blob: 2de1fe65c71bad4cca22aca65db63e278ea76120 [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)) ||
60 (CGF.CurCodeDecl && isa<BlockDecl>(CGF.CurCodeDecl));
61 }
Alexey Bataev3392d762016-02-16 11:18:12 +000062
Alexey Bataev3392d762016-02-16 11:18:12 +000063public:
Alexey Bataev475a7442018-01-12 19:39:11 +000064 OMPLexicalScope(
65 CodeGenFunction &CGF, const OMPExecutableDirective &S,
66 const llvm::Optional<OpenMPDirectiveKind> CapturedRegion = llvm::None,
67 const bool EmitPreInitStmt = true)
Alexey Bataev4ba78a42016-04-27 07:56:03 +000068 : CodeGenFunction::LexicalScope(CGF, S.getSourceRange()),
69 InlinedShareds(CGF) {
Arpith Chacko Jacobfe4890a2017-01-18 20:40:48 +000070 if (EmitPreInitStmt)
71 emitPreInitStmt(CGF, S);
Alexey Bataev475a7442018-01-12 19:39:11 +000072 if (!CapturedRegion.hasValue())
73 return;
74 assert(S.hasAssociatedStmt() &&
75 "Expected associated statement for inlined directive.");
76 const CapturedStmt *CS = S.getCapturedStmt(*CapturedRegion);
Alexey Bataevddf3db92018-04-13 17:31:06 +000077 for (const auto &C : CS->captures()) {
Alexey Bataev475a7442018-01-12 19:39:11 +000078 if (C.capturesVariable() || C.capturesVariableByCopy()) {
79 auto *VD = C.getCapturedVar();
80 assert(VD == VD->getCanonicalDecl() &&
81 "Canonical decl must be captured.");
82 DeclRefExpr DRE(
Bruno Ricci5fc4db72018-12-21 14:10:18 +000083 CGF.getContext(), const_cast<VarDecl *>(VD),
Alexey Bataev475a7442018-01-12 19:39:11 +000084 isCapturedVar(CGF, VD) || (CGF.CapturedStmtInfo &&
85 InlinedShareds.isGlobalVarCaptured(VD)),
Alexey Bataeva9b9cc02018-01-23 18:12:38 +000086 VD->getType().getNonReferenceType(), VK_LValue, C.getLocation());
Alexey Bataev475a7442018-01-12 19:39:11 +000087 InlinedShareds.addPrivate(VD, [&CGF, &DRE]() -> Address {
Akira Hatanakaf139ae32019-12-03 15:17:01 -080088 return CGF.EmitLValue(&DRE).getAddress(CGF);
Alexey Bataev475a7442018-01-12 19:39:11 +000089 });
Alexey Bataev4ba78a42016-04-27 07:56:03 +000090 }
91 }
Alexey Bataev475a7442018-01-12 19:39:11 +000092 (void)InlinedShareds.Privatize();
Alexey Bataev3392d762016-02-16 11:18:12 +000093 }
94};
Alexey Bataev14fa1c62016-03-29 05:34:15 +000095
Arpith Chacko Jacobfe4890a2017-01-18 20:40:48 +000096/// Lexical scope for OpenMP parallel construct, that handles correct codegen
97/// for captured expressions.
98class OMPParallelScope final : public OMPLexicalScope {
99 bool EmitPreInitStmt(const OMPExecutableDirective &S) {
100 OpenMPDirectiveKind Kind = S.getDirectiveKind();
Carlo Bertollib0ff0a62017-04-25 17:52:12 +0000101 return !(isOpenMPTargetExecutionDirective(Kind) ||
102 isOpenMPLoopBoundSharingDirective(Kind)) &&
Arpith Chacko Jacobfe4890a2017-01-18 20:40:48 +0000103 isOpenMPParallelDirective(Kind);
104 }
105
106public:
107 OMPParallelScope(CodeGenFunction &CGF, const OMPExecutableDirective &S)
Alexey Bataev475a7442018-01-12 19:39:11 +0000108 : OMPLexicalScope(CGF, S, /*CapturedRegion=*/llvm::None,
109 EmitPreInitStmt(S)) {}
Arpith Chacko Jacobfe4890a2017-01-18 20:40:48 +0000110};
111
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +0000112/// Lexical scope for OpenMP teams construct, that handles correct codegen
113/// for captured expressions.
114class OMPTeamsScope final : public OMPLexicalScope {
115 bool EmitPreInitStmt(const OMPExecutableDirective &S) {
116 OpenMPDirectiveKind Kind = S.getDirectiveKind();
117 return !isOpenMPTargetExecutionDirective(Kind) &&
118 isOpenMPTeamsDirective(Kind);
119 }
120
121public:
122 OMPTeamsScope(CodeGenFunction &CGF, const OMPExecutableDirective &S)
Alexey Bataev475a7442018-01-12 19:39:11 +0000123 : OMPLexicalScope(CGF, S, /*CapturedRegion=*/llvm::None,
124 EmitPreInitStmt(S)) {}
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +0000125};
126
Alexey Bataev5a3af132016-03-29 08:58:54 +0000127/// Private scope for OpenMP loop-based directives, that supports capturing
128/// of used expression from loop statement.
129class OMPLoopScope : public CodeGenFunction::RunCleanupsScope {
130 void emitPreInitStmt(CodeGenFunction &CGF, const OMPLoopDirective &S) {
Alexey Bataevab4ea222018-03-07 18:17:06 +0000131 CodeGenFunction::OMPMapVars PreCondVars;
Alexey Bataevf71939c2019-09-18 19:24:07 +0000132 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
Alexey Bataevddf3db92018-04-13 17:31:06 +0000133 for (const auto *E : S.counters()) {
Alexey Bataeve83b3e82017-12-08 20:18:58 +0000134 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataevf71939c2019-09-18 19:24:07 +0000135 EmittedAsPrivate.insert(VD->getCanonicalDecl());
Alexey Bataevab4ea222018-03-07 18:17:06 +0000136 (void)PreCondVars.setVarAddr(
137 CGF, VD, CGF.CreateMemTemp(VD->getType().getNonReferenceType()));
Alexey Bataeve83b3e82017-12-08 20:18:58 +0000138 }
Alexey Bataevf71939c2019-09-18 19:24:07 +0000139 // Mark private vars as undefs.
140 for (const auto *C : S.getClausesOfKind<OMPPrivateClause>()) {
141 for (const Expr *IRef : C->varlists()) {
142 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(IRef)->getDecl());
143 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
144 (void)PreCondVars.setVarAddr(
145 CGF, OrigVD,
146 Address(llvm::UndefValue::get(
147 CGF.ConvertTypeForMem(CGF.getContext().getPointerType(
148 OrigVD->getType().getNonReferenceType()))),
149 CGF.getContext().getDeclAlign(OrigVD)));
150 }
151 }
152 }
Alexey Bataevab4ea222018-03-07 18:17:06 +0000153 (void)PreCondVars.apply(CGF);
Alexey Bataevbef93a92019-10-07 18:54:57 +0000154 // Emit init, __range and __end variables for C++ range loops.
155 const Stmt *Body =
156 S.getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers();
157 for (unsigned Cnt = 0; Cnt < S.getCollapsedNumber(); ++Cnt) {
Alexey Bataev8bbf2e32019-11-04 09:59:11 -0500158 Body = OMPLoopDirective::tryToFindNextInnerLoop(
159 Body, /*TryImperfectlyNestedLoops=*/true);
Alexey Bataevbef93a92019-10-07 18:54:57 +0000160 if (auto *For = dyn_cast<ForStmt>(Body)) {
161 Body = For->getBody();
162 } else {
163 assert(isa<CXXForRangeStmt>(Body) &&
Alexey Bataevd457f7e2019-10-07 19:57:40 +0000164 "Expected canonical for loop or range-based for loop.");
Alexey Bataevbef93a92019-10-07 18:54:57 +0000165 auto *CXXFor = cast<CXXForRangeStmt>(Body);
166 if (const Stmt *Init = CXXFor->getInit())
167 CGF.EmitStmt(Init);
168 CGF.EmitStmt(CXXFor->getRangeStmt());
169 CGF.EmitStmt(CXXFor->getEndStmt());
170 Body = CXXFor->getBody();
171 }
172 }
Alexey Bataevddf3db92018-04-13 17:31:06 +0000173 if (const auto *PreInits = cast_or_null<DeclStmt>(S.getPreInits())) {
George Burgess IV00f70bd2018-03-01 05:43:23 +0000174 for (const auto *I : PreInits->decls())
175 CGF.EmitVarDecl(cast<VarDecl>(*I));
Alexey Bataev5a3af132016-03-29 08:58:54 +0000176 }
Alexey Bataevab4ea222018-03-07 18:17:06 +0000177 PreCondVars.restore(CGF);
Alexey Bataev5a3af132016-03-29 08:58:54 +0000178 }
179
180public:
181 OMPLoopScope(CodeGenFunction &CGF, const OMPLoopDirective &S)
182 : CodeGenFunction::RunCleanupsScope(CGF) {
183 emitPreInitStmt(CGF, S);
184 }
185};
186
Alexey Bataeva8a9153a2017-12-29 18:07:07 +0000187class OMPSimdLexicalScope : public CodeGenFunction::LexicalScope {
188 CodeGenFunction::OMPPrivateScope InlinedShareds;
189
190 static bool isCapturedVar(CodeGenFunction &CGF, const VarDecl *VD) {
191 return CGF.LambdaCaptureFields.lookup(VD) ||
192 (CGF.CapturedStmtInfo && CGF.CapturedStmtInfo->lookup(VD)) ||
193 (CGF.CurCodeDecl && isa<BlockDecl>(CGF.CurCodeDecl) &&
194 cast<BlockDecl>(CGF.CurCodeDecl)->capturesVariable(VD));
195 }
196
197public:
198 OMPSimdLexicalScope(CodeGenFunction &CGF, const OMPExecutableDirective &S)
199 : CodeGenFunction::LexicalScope(CGF, S.getSourceRange()),
200 InlinedShareds(CGF) {
201 for (const auto *C : S.clauses()) {
Alexey Bataevddf3db92018-04-13 17:31:06 +0000202 if (const auto *CPI = OMPClauseWithPreInit::get(C)) {
203 if (const auto *PreInit =
204 cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
Alexey Bataeva8a9153a2017-12-29 18:07:07 +0000205 for (const auto *I : PreInit->decls()) {
Alexey Bataevddf3db92018-04-13 17:31:06 +0000206 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
Alexey Bataeva8a9153a2017-12-29 18:07:07 +0000207 CGF.EmitVarDecl(cast<VarDecl>(*I));
Alexey Bataevddf3db92018-04-13 17:31:06 +0000208 } else {
Alexey Bataeva8a9153a2017-12-29 18:07:07 +0000209 CodeGenFunction::AutoVarEmission Emission =
210 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
211 CGF.EmitAutoVarCleanups(Emission);
212 }
213 }
214 }
215 } else if (const auto *UDP = dyn_cast<OMPUseDevicePtrClause>(C)) {
216 for (const Expr *E : UDP->varlists()) {
217 const Decl *D = cast<DeclRefExpr>(E)->getDecl();
218 if (const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
219 CGF.EmitVarDecl(*OED);
220 }
221 }
222 }
223 if (!isOpenMPSimdDirective(S.getDirectiveKind()))
224 CGF.EmitOMPPrivateClause(S, InlinedShareds);
225 if (const auto *TG = dyn_cast<OMPTaskgroupDirective>(&S)) {
226 if (const Expr *E = TG->getReductionRef())
227 CGF.EmitVarDecl(*cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()));
228 }
229 const auto *CS = cast_or_null<CapturedStmt>(S.getAssociatedStmt());
230 while (CS) {
231 for (auto &C : CS->captures()) {
232 if (C.capturesVariable() || C.capturesVariableByCopy()) {
233 auto *VD = C.getCapturedVar();
234 assert(VD == VD->getCanonicalDecl() &&
235 "Canonical decl must be captured.");
Bruno Ricci5fc4db72018-12-21 14:10:18 +0000236 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD),
Alexey Bataeva8a9153a2017-12-29 18:07:07 +0000237 isCapturedVar(CGF, VD) ||
238 (CGF.CapturedStmtInfo &&
239 InlinedShareds.isGlobalVarCaptured(VD)),
240 VD->getType().getNonReferenceType(), VK_LValue,
Alexey Bataeva9b9cc02018-01-23 18:12:38 +0000241 C.getLocation());
Alexey Bataeva8a9153a2017-12-29 18:07:07 +0000242 InlinedShareds.addPrivate(VD, [&CGF, &DRE]() -> Address {
Akira Hatanakaf139ae32019-12-03 15:17:01 -0800243 return CGF.EmitLValue(&DRE).getAddress(CGF);
Alexey Bataeva8a9153a2017-12-29 18:07:07 +0000244 });
245 }
246 }
247 CS = dyn_cast<CapturedStmt>(CS->getCapturedStmt());
248 }
249 (void)InlinedShareds.Privatize();
250 }
251};
252
Alexey Bataev3392d762016-02-16 11:18:12 +0000253} // namespace
254
Alexey Bataevf8365372017-11-17 17:57:25 +0000255static void emitCommonOMPTargetDirective(CodeGenFunction &CGF,
256 const OMPExecutableDirective &S,
257 const RegionCodeGenTy &CodeGen);
258
Alexey Bataevf47c4b42017-09-26 13:47:31 +0000259LValue CodeGenFunction::EmitOMPSharedLValue(const Expr *E) {
Alexey Bataevddf3db92018-04-13 17:31:06 +0000260 if (const auto *OrigDRE = dyn_cast<DeclRefExpr>(E)) {
261 if (const auto *OrigVD = dyn_cast<VarDecl>(OrigDRE->getDecl())) {
Alexey Bataevf47c4b42017-09-26 13:47:31 +0000262 OrigVD = OrigVD->getCanonicalDecl();
263 bool IsCaptured =
264 LambdaCaptureFields.lookup(OrigVD) ||
265 (CapturedStmtInfo && CapturedStmtInfo->lookup(OrigVD)) ||
266 (CurCodeDecl && isa<BlockDecl>(CurCodeDecl));
Bruno Ricci5fc4db72018-12-21 14:10:18 +0000267 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD), IsCaptured,
Alexey Bataevf47c4b42017-09-26 13:47:31 +0000268 OrigDRE->getType(), VK_LValue, OrigDRE->getExprLoc());
269 return EmitLValue(&DRE);
270 }
271 }
272 return EmitLValue(E);
273}
274
Alexey Bataev1189bd02016-01-26 12:20:39 +0000275llvm::Value *CodeGenFunction::getTypeSize(QualType Ty) {
Alexey Bataevddf3db92018-04-13 17:31:06 +0000276 ASTContext &C = getContext();
Alexey Bataev1189bd02016-01-26 12:20:39 +0000277 llvm::Value *Size = nullptr;
278 auto SizeInChars = C.getTypeSizeInChars(Ty);
279 if (SizeInChars.isZero()) {
280 // getTypeSizeInChars() returns 0 for a VLA.
Alexey Bataevddf3db92018-04-13 17:31:06 +0000281 while (const VariableArrayType *VAT = C.getAsVariableArrayType(Ty)) {
282 VlaSizePair VlaSize = getVLASize(VAT);
Sander de Smalen891af03a2018-02-03 13:55:59 +0000283 Ty = VlaSize.Type;
284 Size = Size ? Builder.CreateNUWMul(Size, VlaSize.NumElts)
285 : VlaSize.NumElts;
Alexey Bataev1189bd02016-01-26 12:20:39 +0000286 }
287 SizeInChars = C.getTypeSizeInChars(Ty);
288 if (SizeInChars.isZero())
289 return llvm::ConstantInt::get(SizeTy, /*V=*/0);
Alexey Bataevddf3db92018-04-13 17:31:06 +0000290 return Builder.CreateNUWMul(Size, CGM.getSize(SizeInChars));
291 }
292 return CGM.getSize(SizeInChars);
Alexey Bataev1189bd02016-01-26 12:20:39 +0000293}
294
Alexey Bataev2377fe92015-09-10 08:12:02 +0000295void CodeGenFunction::GenerateOpenMPCapturedVars(
Samuel Antao4af1b7b2015-12-02 17:44:43 +0000296 const CapturedStmt &S, SmallVectorImpl<llvm::Value *> &CapturedVars) {
Alexey Bataev2377fe92015-09-10 08:12:02 +0000297 const RecordDecl *RD = S.getCapturedRecordDecl();
298 auto CurField = RD->field_begin();
299 auto CurCap = S.captures().begin();
300 for (CapturedStmt::const_capture_init_iterator I = S.capture_init_begin(),
301 E = S.capture_init_end();
302 I != E; ++I, ++CurField, ++CurCap) {
303 if (CurField->hasCapturedVLAType()) {
Alexey Bataevddf3db92018-04-13 17:31:06 +0000304 const VariableArrayType *VAT = CurField->getCapturedVLAType();
305 llvm::Value *Val = VLASizeMap[VAT->getSizeExpr()];
Samuel Antaobed3c462015-10-02 16:14:20 +0000306 CapturedVars.push_back(Val);
Alexey Bataevddf3db92018-04-13 17:31:06 +0000307 } else if (CurCap->capturesThis()) {
Alexey Bataev2377fe92015-09-10 08:12:02 +0000308 CapturedVars.push_back(CXXThisValue);
Alexey Bataevddf3db92018-04-13 17:31:06 +0000309 } else if (CurCap->capturesVariableByCopy()) {
Alexey Bataev1e491372018-01-23 18:44:14 +0000310 llvm::Value *CV = EmitLoadOfScalar(EmitLValue(*I), CurCap->getLocation());
Samuel Antao6d004262016-06-16 18:39:34 +0000311
312 // If the field is not a pointer, we need to save the actual value
313 // and load it as a void pointer.
314 if (!CurField->getType()->isAnyPointerType()) {
Alexey Bataevddf3db92018-04-13 17:31:06 +0000315 ASTContext &Ctx = getContext();
316 Address DstAddr = CreateMemTemp(
Samuel Antao6d004262016-06-16 18:39:34 +0000317 Ctx.getUIntPtrType(),
Alexey Bataevddf3db92018-04-13 17:31:06 +0000318 Twine(CurCap->getCapturedVar()->getName(), ".casted"));
Samuel Antao6d004262016-06-16 18:39:34 +0000319 LValue DstLV = MakeAddrLValue(DstAddr, Ctx.getUIntPtrType());
320
Alexey Bataevddf3db92018-04-13 17:31:06 +0000321 llvm::Value *SrcAddrVal = EmitScalarConversion(
Samuel Antao6d004262016-06-16 18:39:34 +0000322 DstAddr.getPointer(), Ctx.getPointerType(Ctx.getUIntPtrType()),
Alexey Bataeva9b9cc02018-01-23 18:12:38 +0000323 Ctx.getPointerType(CurField->getType()), CurCap->getLocation());
Samuel Antao6d004262016-06-16 18:39:34 +0000324 LValue SrcLV =
325 MakeNaturalAlignAddrLValue(SrcAddrVal, CurField->getType());
326
327 // Store the value using the source type pointer.
328 EmitStoreThroughLValue(RValue::get(CV), SrcLV);
329
330 // Load the value using the destination type pointer.
Alexey Bataev1e491372018-01-23 18:44:14 +0000331 CV = EmitLoadOfScalar(DstLV, CurCap->getLocation());
Samuel Antao6d004262016-06-16 18:39:34 +0000332 }
333 CapturedVars.push_back(CV);
334 } else {
Samuel Antao4af1b7b2015-12-02 17:44:43 +0000335 assert(CurCap->capturesVariable() && "Expected capture by reference.");
Akira Hatanakaf139ae32019-12-03 15:17:01 -0800336 CapturedVars.push_back(EmitLValue(*I).getAddress(*this).getPointer());
Samuel Antao4af1b7b2015-12-02 17:44:43 +0000337 }
Alexey Bataev2377fe92015-09-10 08:12:02 +0000338 }
339}
340
Alexey Bataeva9b9cc02018-01-23 18:12:38 +0000341static Address castValueFromUintptr(CodeGenFunction &CGF, SourceLocation Loc,
342 QualType DstType, StringRef Name,
Alexey Bataev06e80f62019-05-23 18:19:54 +0000343 LValue AddrLV) {
Samuel Antao4af1b7b2015-12-02 17:44:43 +0000344 ASTContext &Ctx = CGF.getContext();
345
Alexey Bataevddf3db92018-04-13 17:31:06 +0000346 llvm::Value *CastedPtr = CGF.EmitScalarConversion(
Akira Hatanakaf139ae32019-12-03 15:17:01 -0800347 AddrLV.getAddress(CGF).getPointer(), Ctx.getUIntPtrType(),
Alexey Bataevddf3db92018-04-13 17:31:06 +0000348 Ctx.getPointerType(DstType), Loc);
349 Address TmpAddr =
Samuel Antao4af1b7b2015-12-02 17:44:43 +0000350 CGF.MakeNaturalAlignAddrLValue(CastedPtr, Ctx.getPointerType(DstType))
Akira Hatanakaf139ae32019-12-03 15:17:01 -0800351 .getAddress(CGF);
Samuel Antao4af1b7b2015-12-02 17:44:43 +0000352 return TmpAddr;
353}
354
Alexey Bataevf7ce1662017-04-10 19:16:45 +0000355static QualType getCanonicalParamType(ASTContext &C, QualType T) {
Alexey Bataevddf3db92018-04-13 17:31:06 +0000356 if (T->isLValueReferenceType())
Alexey Bataevf7ce1662017-04-10 19:16:45 +0000357 return C.getLValueReferenceType(
358 getCanonicalParamType(C, T.getNonReferenceType()),
359 /*SpelledAsLValue=*/false);
Alexey Bataevf7ce1662017-04-10 19:16:45 +0000360 if (T->isPointerType())
361 return C.getPointerType(getCanonicalParamType(C, T->getPointeeType()));
Alexey Bataevddf3db92018-04-13 17:31:06 +0000362 if (const ArrayType *A = T->getAsArrayTypeUnsafe()) {
363 if (const auto *VLA = dyn_cast<VariableArrayType>(A))
Alexey Bataev1b48c5e2017-10-24 19:52:31 +0000364 return getCanonicalParamType(C, VLA->getElementType());
Alexey Bataevddf3db92018-04-13 17:31:06 +0000365 if (!A->isVariablyModifiedType())
Alexey Bataev1b48c5e2017-10-24 19:52:31 +0000366 return C.getCanonicalType(T);
367 }
Alexey Bataevf7ce1662017-04-10 19:16:45 +0000368 return C.getCanonicalParamType(T);
369}
370
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000371namespace {
Alexey Bataevc33ba8c2020-01-17 14:05:40 -0500372/// Contains required data for proper outlined function codegen.
373struct FunctionOptions {
374 /// Captured statement for which the function is generated.
375 const CapturedStmt *S = nullptr;
376 /// true if cast to/from UIntPtr is required for variables captured by
377 /// value.
378 const bool UIntPtrCastRequired = true;
379 /// true if only casted arguments must be registered as local args or VLA
380 /// sizes.
381 const bool RegisterCastedArgsOnly = false;
382 /// Name of the generated function.
383 const StringRef FunctionName;
384 /// Location of the non-debug version of the outlined function.
385 SourceLocation Loc;
386 explicit FunctionOptions(const CapturedStmt *S, bool UIntPtrCastRequired,
387 bool RegisterCastedArgsOnly, StringRef FunctionName,
388 SourceLocation Loc)
389 : S(S), UIntPtrCastRequired(UIntPtrCastRequired),
390 RegisterCastedArgsOnly(UIntPtrCastRequired && RegisterCastedArgsOnly),
391 FunctionName(FunctionName), Loc(Loc) {}
392};
393} // namespace
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000394
Alexey Bataeve754b182017-08-09 19:38:53 +0000395static llvm::Function *emitOutlinedFunctionPrologue(
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000396 CodeGenFunction &CGF, FunctionArgList &Args,
Alexey Bataev3b8d5582017-08-08 18:04:06 +0000397 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>>
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000398 &LocalAddrs,
399 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>>
400 &VLASizes,
401 llvm::Value *&CXXThisValue, const FunctionOptions &FO) {
402 const CapturedDecl *CD = FO.S->getCapturedDecl();
403 const RecordDecl *RD = FO.S->getCapturedRecordDecl();
Alexey Bataev2377fe92015-09-10 08:12:02 +0000404 assert(CD->hasBody() && "missing CapturedDecl body");
405
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000406 CXXThisValue = nullptr;
Alexey Bataev2377fe92015-09-10 08:12:02 +0000407 // Build the argument list.
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000408 CodeGenModule &CGM = CGF.CGM;
Alexey Bataev2377fe92015-09-10 08:12:02 +0000409 ASTContext &Ctx = CGM.getContext();
Alexey Bataev3b8d5582017-08-08 18:04:06 +0000410 FunctionArgList TargetArgs;
Alexey Bataev2377fe92015-09-10 08:12:02 +0000411 Args.append(CD->param_begin(),
412 std::next(CD->param_begin(), CD->getContextParamPosition()));
Alexey Bataev3b8d5582017-08-08 18:04:06 +0000413 TargetArgs.append(
414 CD->param_begin(),
415 std::next(CD->param_begin(), CD->getContextParamPosition()));
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000416 auto I = FO.S->captures().begin();
Alexey Bataevb45d43c2017-11-22 16:02:03 +0000417 FunctionDecl *DebugFunctionDecl = nullptr;
418 if (!FO.UIntPtrCastRequired) {
419 FunctionProtoType::ExtProtoInfo EPI;
Jonas Devlieghere64a26302018-11-11 00:56:15 +0000420 QualType FunctionTy = Ctx.getFunctionType(Ctx.VoidTy, llvm::None, EPI);
Alexey Bataevb45d43c2017-11-22 16:02:03 +0000421 DebugFunctionDecl = FunctionDecl::Create(
Stephen Kellyf2ceec42018-08-09 21:08:08 +0000422 Ctx, Ctx.getTranslationUnitDecl(), FO.S->getBeginLoc(),
Jonas Devlieghere64a26302018-11-11 00:56:15 +0000423 SourceLocation(), DeclarationName(), FunctionTy,
424 Ctx.getTrivialTypeSourceInfo(FunctionTy), SC_Static,
425 /*isInlineSpecified=*/false, /*hasWrittenPrototype=*/false);
Alexey Bataevb45d43c2017-11-22 16:02:03 +0000426 }
Alexey Bataevddf3db92018-04-13 17:31:06 +0000427 for (const FieldDecl *FD : RD->fields()) {
Alexey Bataev2377fe92015-09-10 08:12:02 +0000428 QualType ArgType = FD->getType();
429 IdentifierInfo *II = nullptr;
430 VarDecl *CapVar = nullptr;
Samuel Antao4af1b7b2015-12-02 17:44:43 +0000431
432 // If this is a capture by copy and the type is not a pointer, the outlined
433 // function argument type should be uintptr and the value properly casted to
434 // uintptr. This is necessary given that the runtime library is only able to
435 // deal with pointers. We can pass in the same way the VLA type sizes to the
436 // outlined function.
Alexey Bataevddf3db92018-04-13 17:31:06 +0000437 if (FO.UIntPtrCastRequired &&
438 ((I->capturesVariableByCopy() && !ArgType->isAnyPointerType()) ||
439 I->capturesVariableArrayType()))
440 ArgType = Ctx.getUIntPtrType();
Samuel Antao4af1b7b2015-12-02 17:44:43 +0000441
442 if (I->capturesVariable() || I->capturesVariableByCopy()) {
Alexey Bataev2377fe92015-09-10 08:12:02 +0000443 CapVar = I->getCapturedVar();
444 II = CapVar->getIdentifier();
Alexey Bataevddf3db92018-04-13 17:31:06 +0000445 } else if (I->capturesThis()) {
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000446 II = &Ctx.Idents.get("this");
Alexey Bataevddf3db92018-04-13 17:31:06 +0000447 } else {
Alexey Bataev2377fe92015-09-10 08:12:02 +0000448 assert(I->capturesVariableArrayType());
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000449 II = &Ctx.Idents.get("vla");
Alexey Bataev2377fe92015-09-10 08:12:02 +0000450 }
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000451 if (ArgType->isVariablyModifiedType())
Alexey Bataev1b48c5e2017-10-24 19:52:31 +0000452 ArgType = getCanonicalParamType(Ctx, ArgType);
Alexey Bataevb45d43c2017-11-22 16:02:03 +0000453 VarDecl *Arg;
454 if (DebugFunctionDecl && (CapVar || I->capturesThis())) {
455 Arg = ParmVarDecl::Create(
456 Ctx, DebugFunctionDecl,
Stephen Kellyf2ceec42018-08-09 21:08:08 +0000457 CapVar ? CapVar->getBeginLoc() : FD->getBeginLoc(),
Alexey Bataevb45d43c2017-11-22 16:02:03 +0000458 CapVar ? CapVar->getLocation() : FD->getLocation(), II, ArgType,
459 /*TInfo=*/nullptr, SC_None, /*DefArg=*/nullptr);
460 } else {
461 Arg = ImplicitParamDecl::Create(Ctx, /*DC=*/nullptr, FD->getLocation(),
462 II, ArgType, ImplicitParamDecl::Other);
463 }
Alexey Bataev3b8d5582017-08-08 18:04:06 +0000464 Args.emplace_back(Arg);
465 // Do not cast arguments if we emit function with non-original types.
466 TargetArgs.emplace_back(
467 FO.UIntPtrCastRequired
468 ? Arg
469 : CGM.getOpenMPRuntime().translateParameter(FD, Arg));
Alexey Bataev2377fe92015-09-10 08:12:02 +0000470 ++I;
471 }
472 Args.append(
473 std::next(CD->param_begin(), CD->getContextParamPosition() + 1),
474 CD->param_end());
Alexey Bataev3b8d5582017-08-08 18:04:06 +0000475 TargetArgs.append(
476 std::next(CD->param_begin(), CD->getContextParamPosition() + 1),
477 CD->param_end());
Alexey Bataev2377fe92015-09-10 08:12:02 +0000478
479 // Create the function declaration.
Alexey Bataev2377fe92015-09-10 08:12:02 +0000480 const CGFunctionInfo &FuncInfo =
Alexey Bataev3b8d5582017-08-08 18:04:06 +0000481 CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, TargetArgs);
Alexey Bataev2377fe92015-09-10 08:12:02 +0000482 llvm::FunctionType *FuncLLVMTy = CGM.getTypes().GetFunctionType(FuncInfo);
483
Alexey Bataevddf3db92018-04-13 17:31:06 +0000484 auto *F =
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000485 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
486 FO.FunctionName, &CGM.getModule());
Alexey Bataev2377fe92015-09-10 08:12:02 +0000487 CGM.SetInternalFunctionAttributes(CD, F, FuncInfo);
488 if (CD->isNothrow())
Alexey Bataev2c7eee52017-08-04 19:10:54 +0000489 F->setDoesNotThrow();
Alexey Bataevc0f879b2018-04-10 20:10:53 +0000490 F->setDoesNotRecurse();
Alexey Bataev2377fe92015-09-10 08:12:02 +0000491
492 // Generate the function.
Alexey Bataev6e01dc12017-08-14 16:03:47 +0000493 CGF.StartFunction(CD, Ctx.VoidTy, F, FuncInfo, TargetArgs,
Alexey Bataevc33ba8c2020-01-17 14:05:40 -0500494 FO.UIntPtrCastRequired ? FO.Loc : FO.S->getBeginLoc(),
495 FO.UIntPtrCastRequired ? FO.Loc
496 : CD->getBody()->getBeginLoc());
Alexey Bataev2377fe92015-09-10 08:12:02 +0000497 unsigned Cnt = CD->getContextParamPosition();
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000498 I = FO.S->captures().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +0000499 for (const FieldDecl *FD : RD->fields()) {
Alexey Bataev3b8d5582017-08-08 18:04:06 +0000500 // Do not map arguments if we emit function with non-original types.
501 Address LocalAddr(Address::invalid());
502 if (!FO.UIntPtrCastRequired && Args[Cnt] != TargetArgs[Cnt]) {
503 LocalAddr = CGM.getOpenMPRuntime().getParameterAddress(CGF, Args[Cnt],
504 TargetArgs[Cnt]);
505 } else {
506 LocalAddr = CGF.GetAddrOfLocalVar(Args[Cnt]);
507 }
Samuel Antao4af1b7b2015-12-02 17:44:43 +0000508 // If we are capturing a pointer by copy we don't need to do anything, just
509 // use the value that we get from the arguments.
510 if (I->capturesVariableByCopy() && FD->getType()->isAnyPointerType()) {
Samuel Antao403ffd42016-07-27 22:49:49 +0000511 const VarDecl *CurVD = I->getCapturedVar();
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000512 if (!FO.RegisterCastedArgsOnly)
513 LocalAddrs.insert({Args[Cnt], {CurVD, LocalAddr}});
Richard Trieucc3949d2016-02-18 22:34:54 +0000514 ++Cnt;
515 ++I;
Samuel Antao4af1b7b2015-12-02 17:44:43 +0000516 continue;
517 }
518
Ivan A. Kosarev5f8c0ca2017-10-10 09:39:32 +0000519 LValue ArgLVal = CGF.MakeAddrLValue(LocalAddr, Args[Cnt]->getType(),
520 AlignmentSource::Decl);
Alexey Bataev2377fe92015-09-10 08:12:02 +0000521 if (FD->hasCapturedVLAType()) {
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000522 if (FO.UIntPtrCastRequired) {
Alexey Bataeva9b9cc02018-01-23 18:12:38 +0000523 ArgLVal = CGF.MakeAddrLValue(
524 castValueFromUintptr(CGF, I->getLocation(), FD->getType(),
525 Args[Cnt]->getName(), ArgLVal),
526 FD->getType(), AlignmentSource::Decl);
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000527 }
Alexey Bataevddf3db92018-04-13 17:31:06 +0000528 llvm::Value *ExprArg = CGF.EmitLoadOfScalar(ArgLVal, I->getLocation());
529 const VariableArrayType *VAT = FD->getCapturedVLAType();
530 VLASizes.try_emplace(Args[Cnt], VAT->getSizeExpr(), ExprArg);
Alexey Bataev2377fe92015-09-10 08:12:02 +0000531 } else if (I->capturesVariable()) {
Alexey Bataevddf3db92018-04-13 17:31:06 +0000532 const VarDecl *Var = I->getCapturedVar();
Alexey Bataev2377fe92015-09-10 08:12:02 +0000533 QualType VarTy = Var->getType();
Akira Hatanakaf139ae32019-12-03 15:17:01 -0800534 Address ArgAddr = ArgLVal.getAddress(CGF);
Alexey Bataev06e80f62019-05-23 18:19:54 +0000535 if (ArgLVal.getType()->isLValueReferenceType()) {
536 ArgAddr = CGF.EmitLoadOfReference(ArgLVal);
537 } else if (!VarTy->isVariablyModifiedType() || !VarTy->isPointerType()) {
538 assert(ArgLVal.getType()->isPointerType());
539 ArgAddr = CGF.EmitLoadOfPointer(
540 ArgAddr, ArgLVal.getType()->castAs<PointerType>());
Alexey Bataev2377fe92015-09-10 08:12:02 +0000541 }
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000542 if (!FO.RegisterCastedArgsOnly) {
543 LocalAddrs.insert(
544 {Args[Cnt],
545 {Var, Address(ArgAddr.getPointer(), Ctx.getDeclAlign(Var))}});
546 }
Samuel Antao4af1b7b2015-12-02 17:44:43 +0000547 } else if (I->capturesVariableByCopy()) {
548 assert(!FD->getType()->isAnyPointerType() &&
549 "Not expecting a captured pointer.");
Alexey Bataevddf3db92018-04-13 17:31:06 +0000550 const VarDecl *Var = I->getCapturedVar();
Alexey Bataev06e80f62019-05-23 18:19:54 +0000551 LocalAddrs.insert({Args[Cnt],
552 {Var, FO.UIntPtrCastRequired
553 ? castValueFromUintptr(
554 CGF, I->getLocation(), FD->getType(),
555 Args[Cnt]->getName(), ArgLVal)
Akira Hatanakaf139ae32019-12-03 15:17:01 -0800556 : ArgLVal.getAddress(CGF)}});
Alexey Bataev2377fe92015-09-10 08:12:02 +0000557 } else {
558 // If 'this' is captured, load it into CXXThisValue.
559 assert(I->capturesThis());
Alexey Bataev1e491372018-01-23 18:44:14 +0000560 CXXThisValue = CGF.EmitLoadOfScalar(ArgLVal, I->getLocation());
Akira Hatanakaf139ae32019-12-03 15:17:01 -0800561 LocalAddrs.insert({Args[Cnt], {nullptr, ArgLVal.getAddress(CGF)}});
Alexey Bataev2377fe92015-09-10 08:12:02 +0000562 }
Richard Trieucc3949d2016-02-18 22:34:54 +0000563 ++Cnt;
564 ++I;
Alexey Bataev2377fe92015-09-10 08:12:02 +0000565 }
566
Alexey Bataeve754b182017-08-09 19:38:53 +0000567 return F;
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000568}
569
570llvm::Function *
Alexey Bataevc33ba8c2020-01-17 14:05:40 -0500571CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S,
572 SourceLocation Loc) {
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000573 assert(
574 CapturedStmtInfo &&
575 "CapturedStmtInfo should be set when generating the captured function");
576 const CapturedDecl *CD = S.getCapturedDecl();
577 // Build the argument list.
578 bool NeedWrapperFunction =
Amy Huang53539bb2020-01-13 15:54:54 -0800579 getDebugInfo() && CGM.getCodeGenOpts().hasReducedDebugInfo();
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000580 FunctionArgList Args;
Alexey Bataev3b8d5582017-08-08 18:04:06 +0000581 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>> LocalAddrs;
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000582 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>> VLASizes;
Alexey Bataeve754b182017-08-09 19:38:53 +0000583 SmallString<256> Buffer;
584 llvm::raw_svector_ostream Out(Buffer);
585 Out << CapturedStmtInfo->getHelperName();
586 if (NeedWrapperFunction)
587 Out << "_debug__";
Alexey Bataev4aa19052017-08-08 16:45:36 +0000588 FunctionOptions FO(&S, !NeedWrapperFunction, /*RegisterCastedArgsOnly=*/false,
Alexey Bataevc33ba8c2020-01-17 14:05:40 -0500589 Out.str(), Loc);
Alexey Bataeve754b182017-08-09 19:38:53 +0000590 llvm::Function *F = emitOutlinedFunctionPrologue(*this, Args, LocalAddrs,
591 VLASizes, CXXThisValue, FO);
Alexey Bataev06e80f62019-05-23 18:19:54 +0000592 CodeGenFunction::OMPPrivateScope LocalScope(*this);
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000593 for (const auto &LocalAddrPair : LocalAddrs) {
594 if (LocalAddrPair.second.first) {
Alexey Bataev06e80f62019-05-23 18:19:54 +0000595 LocalScope.addPrivate(LocalAddrPair.second.first, [&LocalAddrPair]() {
596 return LocalAddrPair.second.second;
597 });
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000598 }
599 }
Alexey Bataev06e80f62019-05-23 18:19:54 +0000600 (void)LocalScope.Privatize();
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000601 for (const auto &VLASizePair : VLASizes)
602 VLASizeMap[VLASizePair.second.first] = VLASizePair.second.second;
Serge Pavlov3a561452015-12-06 14:32:39 +0000603 PGO.assignRegionCounters(GlobalDecl(CD), F);
Alexey Bataev2377fe92015-09-10 08:12:02 +0000604 CapturedStmtInfo->EmitBody(*this, CD->getBody());
Alexey Bataev06e80f62019-05-23 18:19:54 +0000605 (void)LocalScope.ForceCleanup();
Alexey Bataev2377fe92015-09-10 08:12:02 +0000606 FinishFunction(CD->getBodyRBrace());
Alexey Bataeve754b182017-08-09 19:38:53 +0000607 if (!NeedWrapperFunction)
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000608 return F;
Alexey Bataev2377fe92015-09-10 08:12:02 +0000609
Alexey Bataevefd884d2017-08-04 21:26:25 +0000610 FunctionOptions WrapperFO(&S, /*UIntPtrCastRequired=*/true,
Alexey Bataeve754b182017-08-09 19:38:53 +0000611 /*RegisterCastedArgsOnly=*/true,
Alexey Bataevc33ba8c2020-01-17 14:05:40 -0500612 CapturedStmtInfo->getHelperName(), Loc);
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000613 CodeGenFunction WrapperCGF(CGM, /*suppressNewContext=*/true);
Gheorghe-Teodor Bercead3dcf2f2018-03-14 14:17:45 +0000614 WrapperCGF.CapturedStmtInfo = CapturedStmtInfo;
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000615 Args.clear();
616 LocalAddrs.clear();
617 VLASizes.clear();
618 llvm::Function *WrapperF =
619 emitOutlinedFunctionPrologue(WrapperCGF, Args, LocalAddrs, VLASizes,
Alexey Bataeve754b182017-08-09 19:38:53 +0000620 WrapperCGF.CXXThisValue, WrapperFO);
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000621 llvm::SmallVector<llvm::Value *, 4> CallArgs;
622 for (const auto *Arg : Args) {
623 llvm::Value *CallArg;
624 auto I = LocalAddrs.find(Arg);
625 if (I != LocalAddrs.end()) {
Alexey Bataev7ba57af2017-10-17 16:47:34 +0000626 LValue LV = WrapperCGF.MakeAddrLValue(
627 I->second.second,
628 I->second.first ? I->second.first->getType() : Arg->getType(),
629 AlignmentSource::Decl);
Stephen Kellyf2ceec42018-08-09 21:08:08 +0000630 CallArg = WrapperCGF.EmitLoadOfScalar(LV, S.getBeginLoc());
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000631 } else {
632 auto EI = VLASizes.find(Arg);
Alexey Bataevddf3db92018-04-13 17:31:06 +0000633 if (EI != VLASizes.end()) {
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000634 CallArg = EI->second.second;
Alexey Bataevddf3db92018-04-13 17:31:06 +0000635 } else {
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000636 LValue LV = WrapperCGF.MakeAddrLValue(WrapperCGF.GetAddrOfLocalVar(Arg),
Ivan A. Kosarev5f8c0ca2017-10-10 09:39:32 +0000637 Arg->getType(),
638 AlignmentSource::Decl);
Stephen Kellyf2ceec42018-08-09 21:08:08 +0000639 CallArg = WrapperCGF.EmitLoadOfScalar(LV, S.getBeginLoc());
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000640 }
641 }
Alexey Bataev7ba57af2017-10-17 16:47:34 +0000642 CallArgs.emplace_back(WrapperCGF.EmitFromMemory(CallArg, Arg->getType()));
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000643 }
Alexey Bataevc33ba8c2020-01-17 14:05:40 -0500644 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(WrapperCGF, Loc, F, CallArgs);
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000645 WrapperCGF.FinishFunction();
646 return WrapperF;
Alexey Bataev2377fe92015-09-10 08:12:02 +0000647}
648
Alexey Bataev9959db52014-05-06 10:08:46 +0000649//===----------------------------------------------------------------------===//
650// OpenMP Directive Emission
651//===----------------------------------------------------------------------===//
Alexey Bataev420d45b2015-04-14 05:11:24 +0000652void CodeGenFunction::EmitOMPAggregateAssign(
John McCall7f416cc2015-09-08 08:05:57 +0000653 Address DestAddr, Address SrcAddr, QualType OriginalType,
Alexey Bataevddf3db92018-04-13 17:31:06 +0000654 const llvm::function_ref<void(Address, Address)> CopyGen) {
Alexey Bataev420d45b2015-04-14 05:11:24 +0000655 // Perform element-by-element initialization.
656 QualType ElementTy;
John McCall7f416cc2015-09-08 08:05:57 +0000657
658 // Drill down to the base element type on both arrays.
Alexey Bataevddf3db92018-04-13 17:31:06 +0000659 const ArrayType *ArrayTy = OriginalType->getAsArrayTypeUnsafe();
660 llvm::Value *NumElements = emitArrayLength(ArrayTy, ElementTy, DestAddr);
John McCall7f416cc2015-09-08 08:05:57 +0000661 SrcAddr = Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType());
662
Alexey Bataevddf3db92018-04-13 17:31:06 +0000663 llvm::Value *SrcBegin = SrcAddr.getPointer();
664 llvm::Value *DestBegin = DestAddr.getPointer();
Alexey Bataev420d45b2015-04-14 05:11:24 +0000665 // Cast from pointer to array type to pointer to single element.
Alexey Bataevddf3db92018-04-13 17:31:06 +0000666 llvm::Value *DestEnd = Builder.CreateGEP(DestBegin, NumElements);
Alexey Bataev420d45b2015-04-14 05:11:24 +0000667 // The basic structure here is a while-do loop.
Alexey Bataevddf3db92018-04-13 17:31:06 +0000668 llvm::BasicBlock *BodyBB = createBasicBlock("omp.arraycpy.body");
669 llvm::BasicBlock *DoneBB = createBasicBlock("omp.arraycpy.done");
670 llvm::Value *IsEmpty =
Alexey Bataev420d45b2015-04-14 05:11:24 +0000671 Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arraycpy.isempty");
672 Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000673
Alexey Bataev420d45b2015-04-14 05:11:24 +0000674 // Enter the loop body, making that address the current address.
Alexey Bataevddf3db92018-04-13 17:31:06 +0000675 llvm::BasicBlock *EntryBB = Builder.GetInsertBlock();
Alexey Bataev420d45b2015-04-14 05:11:24 +0000676 EmitBlock(BodyBB);
John McCall7f416cc2015-09-08 08:05:57 +0000677
678 CharUnits ElementSize = getContext().getTypeSizeInChars(ElementTy);
679
680 llvm::PHINode *SrcElementPHI =
681 Builder.CreatePHI(SrcBegin->getType(), 2, "omp.arraycpy.srcElementPast");
682 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
683 Address SrcElementCurrent =
684 Address(SrcElementPHI,
685 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize));
686
687 llvm::PHINode *DestElementPHI =
688 Builder.CreatePHI(DestBegin->getType(), 2, "omp.arraycpy.destElementPast");
689 DestElementPHI->addIncoming(DestBegin, EntryBB);
690 Address DestElementCurrent =
691 Address(DestElementPHI,
692 DestAddr.getAlignment().alignmentOfArrayElement(ElementSize));
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000693
Alexey Bataev420d45b2015-04-14 05:11:24 +0000694 // Emit copy.
695 CopyGen(DestElementCurrent, SrcElementCurrent);
696
697 // Shift the address forward by one element.
Alexey Bataevddf3db92018-04-13 17:31:06 +0000698 llvm::Value *DestElementNext = Builder.CreateConstGEP1_32(
John McCall7f416cc2015-09-08 08:05:57 +0000699 DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
Alexey Bataevddf3db92018-04-13 17:31:06 +0000700 llvm::Value *SrcElementNext = Builder.CreateConstGEP1_32(
John McCall7f416cc2015-09-08 08:05:57 +0000701 SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element");
Alexey Bataev420d45b2015-04-14 05:11:24 +0000702 // Check whether we've reached the end.
Alexey Bataevddf3db92018-04-13 17:31:06 +0000703 llvm::Value *Done =
Alexey Bataev420d45b2015-04-14 05:11:24 +0000704 Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done");
705 Builder.CreateCondBr(Done, DoneBB, BodyBB);
John McCall7f416cc2015-09-08 08:05:57 +0000706 DestElementPHI->addIncoming(DestElementNext, Builder.GetInsertBlock());
707 SrcElementPHI->addIncoming(SrcElementNext, Builder.GetInsertBlock());
Alexey Bataev420d45b2015-04-14 05:11:24 +0000708
709 // Done.
710 EmitBlock(DoneBB, /*IsFinished=*/true);
711}
712
John McCall7f416cc2015-09-08 08:05:57 +0000713void CodeGenFunction::EmitOMPCopy(QualType OriginalType, Address DestAddr,
714 Address SrcAddr, const VarDecl *DestVD,
Alexey Bataev420d45b2015-04-14 05:11:24 +0000715 const VarDecl *SrcVD, const Expr *Copy) {
716 if (OriginalType->isArrayType()) {
Alexey Bataevddf3db92018-04-13 17:31:06 +0000717 const auto *BO = dyn_cast<BinaryOperator>(Copy);
Alexey Bataev420d45b2015-04-14 05:11:24 +0000718 if (BO && BO->getOpcode() == BO_Assign) {
719 // Perform simple memcpy for simple copying.
Ivan A. Kosarev1860b522018-01-25 14:21:55 +0000720 LValue Dest = MakeAddrLValue(DestAddr, OriginalType);
721 LValue Src = MakeAddrLValue(SrcAddr, OriginalType);
722 EmitAggregateAssign(Dest, Src, OriginalType);
Alexey Bataev420d45b2015-04-14 05:11:24 +0000723 } else {
724 // For arrays with complex element types perform element by element
725 // copying.
John McCall7f416cc2015-09-08 08:05:57 +0000726 EmitOMPAggregateAssign(
Alexey Bataev420d45b2015-04-14 05:11:24 +0000727 DestAddr, SrcAddr, OriginalType,
John McCall7f416cc2015-09-08 08:05:57 +0000728 [this, Copy, SrcVD, DestVD](Address DestElement, Address SrcElement) {
Alexey Bataev420d45b2015-04-14 05:11:24 +0000729 // Working with the single array element, so have to remap
730 // destination and source variables to corresponding array
731 // elements.
John McCall7f416cc2015-09-08 08:05:57 +0000732 CodeGenFunction::OMPPrivateScope Remap(*this);
Alexey Bataevddf3db92018-04-13 17:31:06 +0000733 Remap.addPrivate(DestVD, [DestElement]() { return DestElement; });
734 Remap.addPrivate(SrcVD, [SrcElement]() { return SrcElement; });
Alexey Bataev420d45b2015-04-14 05:11:24 +0000735 (void)Remap.Privatize();
John McCall7f416cc2015-09-08 08:05:57 +0000736 EmitIgnoredExpr(Copy);
Alexey Bataev420d45b2015-04-14 05:11:24 +0000737 });
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000738 }
Alexey Bataev420d45b2015-04-14 05:11:24 +0000739 } else {
740 // Remap pseudo source variable to private copy.
John McCall7f416cc2015-09-08 08:05:57 +0000741 CodeGenFunction::OMPPrivateScope Remap(*this);
Alexey Bataevddf3db92018-04-13 17:31:06 +0000742 Remap.addPrivate(SrcVD, [SrcAddr]() { return SrcAddr; });
743 Remap.addPrivate(DestVD, [DestAddr]() { return DestAddr; });
Alexey Bataev420d45b2015-04-14 05:11:24 +0000744 (void)Remap.Privatize();
745 // Emit copying of the whole variable.
John McCall7f416cc2015-09-08 08:05:57 +0000746 EmitIgnoredExpr(Copy);
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000747 }
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000748}
749
Alexey Bataev69c62a92015-04-15 04:52:20 +0000750bool CodeGenFunction::EmitOMPFirstprivateClause(const OMPExecutableDirective &D,
751 OMPPrivateScope &PrivateScope) {
Alexey Bataev8ef31412015-12-18 07:58:25 +0000752 if (!HaveInsertPoint())
753 return false;
Alexey Bataev1af5bd52019-03-05 17:47:18 +0000754 bool DeviceConstTarget =
755 getLangOpts().OpenMPIsDevice &&
756 isOpenMPTargetExecutionDirective(D.getDirectiveKind());
Alexey Bataevcd8b6a22016-02-15 08:07:17 +0000757 bool FirstprivateIsLastprivate = false;
Alexey Bataev46978742020-01-30 10:46:11 -0500758 llvm::DenseMap<const VarDecl *, OpenMPLastprivateModifier> Lastprivates;
Alexey Bataevcd8b6a22016-02-15 08:07:17 +0000759 for (const auto *C : D.getClausesOfKind<OMPLastprivateClause>()) {
760 for (const auto *D : C->varlists())
Alexey Bataev46978742020-01-30 10:46:11 -0500761 Lastprivates.try_emplace(
762 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl())->getCanonicalDecl(),
763 C->getKind());
Alexey Bataevcd8b6a22016-02-15 08:07:17 +0000764 }
Alexey Bataev69c62a92015-04-15 04:52:20 +0000765 llvm::DenseSet<const VarDecl *> EmittedAsFirstprivate;
Alexey Bataev475a7442018-01-12 19:39:11 +0000766 llvm::SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
767 getOpenMPCaptureRegions(CaptureRegions, D.getDirectiveKind());
768 // Force emission of the firstprivate copy if the directive does not emit
769 // outlined function, like omp for, omp simd, omp distribute etc.
770 bool MustEmitFirstprivateCopy =
771 CaptureRegions.size() == 1 && CaptureRegions.back() == OMPD_unknown;
Benjamin Kramerfc600dc2015-08-30 15:12:28 +0000772 for (const auto *C : D.getClausesOfKind<OMPFirstprivateClause>()) {
Alexey Bataev46978742020-01-30 10:46:11 -0500773 const auto *IRef = C->varlist_begin();
774 const auto *InitsRef = C->inits().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +0000775 for (const Expr *IInit : C->private_copies()) {
776 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
Alexey Bataev7ace49d2016-05-17 08:55:33 +0000777 bool ThisFirstprivateIsLastprivate =
778 Lastprivates.count(OrigVD->getCanonicalDecl()) > 0;
Alexey Bataevddf3db92018-04-13 17:31:06 +0000779 const FieldDecl *FD = CapturedStmtInfo->lookup(OrigVD);
Alexey Bataev9c397812019-04-03 17:57:06 +0000780 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
Alexey Bataev475a7442018-01-12 19:39:11 +0000781 if (!MustEmitFirstprivateCopy && !ThisFirstprivateIsLastprivate && FD &&
Alexey Bataev9c397812019-04-03 17:57:06 +0000782 !FD->getType()->isReferenceType() &&
783 (!VD || !VD->hasAttr<OMPAllocateDeclAttr>())) {
Alexey Bataev7ace49d2016-05-17 08:55:33 +0000784 EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl());
785 ++IRef;
786 ++InitsRef;
787 continue;
788 }
Alexey Bataev1af5bd52019-03-05 17:47:18 +0000789 // Do not emit copy for firstprivate constant variables in target regions,
790 // captured by reference.
791 if (DeviceConstTarget && OrigVD->getType().isConstant(getContext()) &&
Alexey Bataev9c397812019-04-03 17:57:06 +0000792 FD && FD->getType()->isReferenceType() &&
793 (!VD || !VD->hasAttr<OMPAllocateDeclAttr>())) {
Alexey Bataev1af5bd52019-03-05 17:47:18 +0000794 (void)CGM.getOpenMPRuntime().registerTargetFirstprivateCopy(*this,
795 OrigVD);
796 ++IRef;
797 ++InitsRef;
798 continue;
799 }
Alexey Bataevcd8b6a22016-02-15 08:07:17 +0000800 FirstprivateIsLastprivate =
Alexey Bataev7ace49d2016-05-17 08:55:33 +0000801 FirstprivateIsLastprivate || ThisFirstprivateIsLastprivate;
Alexey Bataevcd8b6a22016-02-15 08:07:17 +0000802 if (EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl()).second) {
Alexey Bataevddf3db92018-04-13 17:31:06 +0000803 const auto *VDInit =
804 cast<VarDecl>(cast<DeclRefExpr>(*InitsRef)->getDecl());
Alexey Bataev69c62a92015-04-15 04:52:20 +0000805 bool IsRegistered;
Bruno Ricci5fc4db72018-12-21 14:10:18 +0000806 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD),
Alexey Bataev7ace49d2016-05-17 08:55:33 +0000807 /*RefersToEnclosingVariableOrCapture=*/FD != nullptr,
808 (*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc());
Alexey Bataeve0ef04f2019-05-23 22:30:43 +0000809 LValue OriginalLVal;
810 if (!FD) {
811 // Check if the firstprivate variable is just a constant value.
812 ConstantEmission CE = tryEmitAsConstant(&DRE);
813 if (CE && !CE.isReference()) {
814 // Constant value, no need to create a copy.
815 ++IRef;
816 ++InitsRef;
817 continue;
818 }
819 if (CE && CE.isReference()) {
820 OriginalLVal = CE.getReferenceLValue(*this, &DRE);
821 } else {
822 assert(!CE && "Expected non-constant firstprivate.");
823 OriginalLVal = EmitLValue(&DRE);
824 }
825 } else {
826 OriginalLVal = EmitLValue(&DRE);
827 }
Alexey Bataevfeddd642016-04-22 09:05:03 +0000828 QualType Type = VD->getType();
Alexey Bataev1d9c15c2015-05-19 12:31:28 +0000829 if (Type->isArrayType()) {
Alexey Bataev69c62a92015-04-15 04:52:20 +0000830 // Emit VarDecl with copy init for arrays.
831 // Get the address of the original variable captured in current
832 // captured region.
Alexey Bataevddf3db92018-04-13 17:31:06 +0000833 IsRegistered = PrivateScope.addPrivate(
834 OrigVD, [this, VD, Type, OriginalLVal, VDInit]() {
835 AutoVarEmission Emission = EmitAutoVarAlloca(*VD);
836 const Expr *Init = VD->getInit();
837 if (!isa<CXXConstructExpr>(Init) ||
838 isTrivialInitializer(Init)) {
839 // Perform simple memcpy.
840 LValue Dest =
841 MakeAddrLValue(Emission.getAllocatedAddress(), Type);
842 EmitAggregateAssign(Dest, OriginalLVal, Type);
843 } else {
844 EmitOMPAggregateAssign(
Akira Hatanakaf139ae32019-12-03 15:17:01 -0800845 Emission.getAllocatedAddress(),
846 OriginalLVal.getAddress(*this), Type,
Alexey Bataevddf3db92018-04-13 17:31:06 +0000847 [this, VDInit, Init](Address DestElement,
848 Address SrcElement) {
849 // Clean up any temporaries needed by the
850 // initialization.
851 RunCleanupsScope InitScope(*this);
852 // Emit initialization for single element.
853 setAddrOfLocalVar(VDInit, SrcElement);
854 EmitAnyExprToMem(Init, DestElement,
855 Init->getType().getQualifiers(),
856 /*IsInitializer*/ false);
857 LocalDeclMap.erase(VDInit);
858 });
859 }
860 EmitAutoVarCleanups(Emission);
861 return Emission.getAllocatedAddress();
862 });
Alexey Bataev69c62a92015-04-15 04:52:20 +0000863 } else {
Akira Hatanakaf139ae32019-12-03 15:17:01 -0800864 Address OriginalAddr = OriginalLVal.getAddress(*this);
Alexey Bataev46978742020-01-30 10:46:11 -0500865 IsRegistered =
866 PrivateScope.addPrivate(OrigVD, [this, VDInit, OriginalAddr, VD,
867 ThisFirstprivateIsLastprivate,
868 OrigVD, &Lastprivates, IRef]() {
Alexey Bataevddf3db92018-04-13 17:31:06 +0000869 // Emit private VarDecl with copy init.
870 // Remap temp VDInit variable to the address of the original
871 // variable (for proper handling of captured global variables).
872 setAddrOfLocalVar(VDInit, OriginalAddr);
873 EmitDecl(*VD);
874 LocalDeclMap.erase(VDInit);
Alexey Bataev46978742020-01-30 10:46:11 -0500875 if (ThisFirstprivateIsLastprivate &&
876 Lastprivates[OrigVD->getCanonicalDecl()] ==
877 OMPC_LASTPRIVATE_conditional) {
878 // Create/init special variable for lastprivate conditionals.
879 Address VDAddr =
880 CGM.getOpenMPRuntime().emitLastprivateConditionalInit(
881 *this, OrigVD);
882 llvm::Value *V = EmitLoadOfScalar(
883 MakeAddrLValue(GetAddrOfLocalVar(VD), (*IRef)->getType(),
884 AlignmentSource::Decl),
885 (*IRef)->getExprLoc());
886 EmitStoreOfScalar(V,
887 MakeAddrLValue(VDAddr, (*IRef)->getType(),
888 AlignmentSource::Decl));
889 LocalDeclMap.erase(VD);
890 setAddrOfLocalVar(VD, VDAddr);
891 return VDAddr;
892 }
Alexey Bataevddf3db92018-04-13 17:31:06 +0000893 return GetAddrOfLocalVar(VD);
894 });
Alexey Bataev69c62a92015-04-15 04:52:20 +0000895 }
896 assert(IsRegistered &&
897 "firstprivate var already registered as private");
898 // Silence the warning about unused variable.
899 (void)IsRegistered;
900 }
Richard Trieucc3949d2016-02-18 22:34:54 +0000901 ++IRef;
902 ++InitsRef;
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000903 }
904 }
Alexey Bataevcd8b6a22016-02-15 08:07:17 +0000905 return FirstprivateIsLastprivate && !EmittedAsFirstprivate.empty();
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000906}
907
Alexey Bataev03b340a2014-10-21 03:16:40 +0000908void CodeGenFunction::EmitOMPPrivateClause(
909 const OMPExecutableDirective &D,
910 CodeGenFunction::OMPPrivateScope &PrivateScope) {
Alexey Bataev8ef31412015-12-18 07:58:25 +0000911 if (!HaveInsertPoint())
912 return;
Alexey Bataev50a64582015-04-22 12:24:45 +0000913 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
Benjamin Kramerfc600dc2015-08-30 15:12:28 +0000914 for (const auto *C : D.getClausesOfKind<OMPPrivateClause>()) {
Alexey Bataev03b340a2014-10-21 03:16:40 +0000915 auto IRef = C->varlist_begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +0000916 for (const Expr *IInit : C->private_copies()) {
917 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
Alexey Bataev50a64582015-04-22 12:24:45 +0000918 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
Alexey Bataevddf3db92018-04-13 17:31:06 +0000919 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
920 bool IsRegistered = PrivateScope.addPrivate(OrigVD, [this, VD]() {
921 // Emit private VarDecl with copy init.
922 EmitDecl(*VD);
923 return GetAddrOfLocalVar(VD);
924 });
Alexey Bataev50a64582015-04-22 12:24:45 +0000925 assert(IsRegistered && "private var already registered as private");
926 // Silence the warning about unused variable.
927 (void)IsRegistered;
928 }
Alexey Bataev03b340a2014-10-21 03:16:40 +0000929 ++IRef;
930 }
931 }
932}
933
Alexey Bataevf56f98c2015-04-16 05:39:01 +0000934bool CodeGenFunction::EmitOMPCopyinClause(const OMPExecutableDirective &D) {
Alexey Bataev8ef31412015-12-18 07:58:25 +0000935 if (!HaveInsertPoint())
936 return false;
Alexey Bataevf56f98c2015-04-16 05:39:01 +0000937 // threadprivate_var1 = master_threadprivate_var1;
938 // operator=(threadprivate_var2, master_threadprivate_var2);
939 // ...
940 // __kmpc_barrier(&loc, global_tid);
Alexey Bataevf56f98c2015-04-16 05:39:01 +0000941 llvm::DenseSet<const VarDecl *> CopiedVars;
942 llvm::BasicBlock *CopyBegin = nullptr, *CopyEnd = nullptr;
Benjamin Kramerfc600dc2015-08-30 15:12:28 +0000943 for (const auto *C : D.getClausesOfKind<OMPCopyinClause>()) {
Alexey Bataevf56f98c2015-04-16 05:39:01 +0000944 auto IRef = C->varlist_begin();
945 auto ISrcRef = C->source_exprs().begin();
946 auto IDestRef = C->destination_exprs().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +0000947 for (const Expr *AssignOp : C->assignment_ops()) {
948 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
Alexey Bataev1d9c15c2015-05-19 12:31:28 +0000949 QualType Type = VD->getType();
Alexey Bataevf56f98c2015-04-16 05:39:01 +0000950 if (CopiedVars.insert(VD->getCanonicalDecl()).second) {
Samuel Antao9c75cfe2015-07-27 16:38:06 +0000951 // Get the address of the master variable. If we are emitting code with
952 // TLS support, the address is passed from the master as field in the
953 // captured declaration.
John McCall7f416cc2015-09-08 08:05:57 +0000954 Address MasterAddr = Address::invalid();
Samuel Antao9c75cfe2015-07-27 16:38:06 +0000955 if (getLangOpts().OpenMPUseTLS &&
956 getContext().getTargetInfo().isTLSSupported()) {
957 assert(CapturedStmtInfo->lookup(VD) &&
958 "Copyin threadprivates should have been captured!");
Bruno Ricci5fc4db72018-12-21 14:10:18 +0000959 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(VD), true,
960 (*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc());
Akira Hatanakaf139ae32019-12-03 15:17:01 -0800961 MasterAddr = EmitLValue(&DRE).getAddress(*this);
Alexey Bataev2377fe92015-09-10 08:12:02 +0000962 LocalDeclMap.erase(VD);
Samuel Antao9c75cfe2015-07-27 16:38:06 +0000963 } else {
John McCall7f416cc2015-09-08 08:05:57 +0000964 MasterAddr =
965 Address(VD->isStaticLocal() ? CGM.getStaticLocalDeclAddress(VD)
966 : CGM.GetAddrOfGlobal(VD),
967 getContext().getDeclAlign(VD));
Samuel Antao9c75cfe2015-07-27 16:38:06 +0000968 }
Alexey Bataevf56f98c2015-04-16 05:39:01 +0000969 // Get the address of the threadprivate variable.
Akira Hatanakaf139ae32019-12-03 15:17:01 -0800970 Address PrivateAddr = EmitLValue(*IRef).getAddress(*this);
Alexey Bataevf56f98c2015-04-16 05:39:01 +0000971 if (CopiedVars.size() == 1) {
972 // At first check if current thread is a master thread. If it is, no
973 // need to copy data.
974 CopyBegin = createBasicBlock("copyin.not.master");
975 CopyEnd = createBasicBlock("copyin.not.master.end");
976 Builder.CreateCondBr(
977 Builder.CreateICmpNE(
John McCall7f416cc2015-09-08 08:05:57 +0000978 Builder.CreatePtrToInt(MasterAddr.getPointer(), CGM.IntPtrTy),
Alexey Bataevddf3db92018-04-13 17:31:06 +0000979 Builder.CreatePtrToInt(PrivateAddr.getPointer(),
980 CGM.IntPtrTy)),
Alexey Bataevf56f98c2015-04-16 05:39:01 +0000981 CopyBegin, CopyEnd);
982 EmitBlock(CopyBegin);
983 }
Alexey Bataevddf3db92018-04-13 17:31:06 +0000984 const auto *SrcVD =
985 cast<VarDecl>(cast<DeclRefExpr>(*ISrcRef)->getDecl());
986 const auto *DestVD =
987 cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
John McCall7f416cc2015-09-08 08:05:57 +0000988 EmitOMPCopy(Type, PrivateAddr, MasterAddr, DestVD, SrcVD, AssignOp);
Alexey Bataevf56f98c2015-04-16 05:39:01 +0000989 }
990 ++IRef;
991 ++ISrcRef;
992 ++IDestRef;
993 }
994 }
995 if (CopyEnd) {
996 // Exit out of copying procedure for non-master thread.
997 EmitBlock(CopyEnd, /*IsFinished=*/true);
998 return true;
999 }
1000 return false;
1001}
1002
Alexey Bataev38e89532015-04-16 04:54:05 +00001003bool CodeGenFunction::EmitOMPLastprivateClauseInit(
1004 const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001005 if (!HaveInsertPoint())
1006 return false;
Alexey Bataev38e89532015-04-16 04:54:05 +00001007 bool HasAtLeastOneLastprivate = false;
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001008 llvm::DenseSet<const VarDecl *> SIMDLCVs;
1009 if (isOpenMPSimdDirective(D.getDirectiveKind())) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00001010 const auto *LoopDirective = cast<OMPLoopDirective>(&D);
1011 for (const Expr *C : LoopDirective->counters()) {
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001012 SIMDLCVs.insert(
1013 cast<VarDecl>(cast<DeclRefExpr>(C)->getDecl())->getCanonicalDecl());
1014 }
1015 }
Alexey Bataev38e89532015-04-16 04:54:05 +00001016 llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00001017 for (const auto *C : D.getClausesOfKind<OMPLastprivateClause>()) {
Alexey Bataevd130fd12015-05-13 10:23:02 +00001018 HasAtLeastOneLastprivate = true;
Alexey Bataeva8a9153a2017-12-29 18:07:07 +00001019 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) &&
1020 !getLangOpts().OpenMPSimd)
Alexey Bataevf93095a2016-05-05 08:46:22 +00001021 break;
Alexey Bataev46978742020-01-30 10:46:11 -05001022 const auto *IRef = C->varlist_begin();
1023 const auto *IDestRef = C->destination_exprs().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00001024 for (const Expr *IInit : C->private_copies()) {
Alexey Bataev38e89532015-04-16 04:54:05 +00001025 // Keep the address of the original variable for future update at the end
1026 // of the loop.
Alexey Bataevddf3db92018-04-13 17:31:06 +00001027 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
Alexey Bataevf93095a2016-05-05 08:46:22 +00001028 // Taskloops do not require additional initialization, it is done in
1029 // runtime support library.
Alexey Bataev38e89532015-04-16 04:54:05 +00001030 if (AlreadyEmittedVars.insert(OrigVD->getCanonicalDecl()).second) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00001031 const auto *DestVD =
1032 cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
1033 PrivateScope.addPrivate(DestVD, [this, OrigVD, IRef]() {
Bruno Ricci5fc4db72018-12-21 14:10:18 +00001034 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD),
1035 /*RefersToEnclosingVariableOrCapture=*/
1036 CapturedStmtInfo->lookup(OrigVD) != nullptr,
1037 (*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc());
Akira Hatanakaf139ae32019-12-03 15:17:01 -08001038 return EmitLValue(&DRE).getAddress(*this);
Alexey Bataev38e89532015-04-16 04:54:05 +00001039 });
1040 // Check if the variable is also a firstprivate: in this case IInit is
1041 // not generated. Initialization of this variable will happen in codegen
1042 // for 'firstprivate' clause.
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001043 if (IInit && !SIMDLCVs.count(OrigVD->getCanonicalDecl())) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00001044 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
Alexey Bataev46978742020-01-30 10:46:11 -05001045 bool IsRegistered = PrivateScope.addPrivate(OrigVD, [this, VD, C,
1046 OrigVD]() {
1047 if (C->getKind() == OMPC_LASTPRIVATE_conditional) {
1048 Address VDAddr =
1049 CGM.getOpenMPRuntime().emitLastprivateConditionalInit(*this,
1050 OrigVD);
1051 setAddrOfLocalVar(VD, VDAddr);
1052 return VDAddr;
1053 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00001054 // Emit private VarDecl with copy init.
1055 EmitDecl(*VD);
1056 return GetAddrOfLocalVar(VD);
1057 });
Alexey Bataevd130fd12015-05-13 10:23:02 +00001058 assert(IsRegistered &&
1059 "lastprivate var already registered as private");
1060 (void)IsRegistered;
1061 }
Alexey Bataev38e89532015-04-16 04:54:05 +00001062 }
Richard Trieucc3949d2016-02-18 22:34:54 +00001063 ++IRef;
1064 ++IDestRef;
Alexey Bataev38e89532015-04-16 04:54:05 +00001065 }
1066 }
1067 return HasAtLeastOneLastprivate;
1068}
1069
1070void CodeGenFunction::EmitOMPLastprivateClauseFinal(
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001071 const OMPExecutableDirective &D, bool NoFinals,
1072 llvm::Value *IsLastIterCond) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001073 if (!HaveInsertPoint())
1074 return;
Alexey Bataev38e89532015-04-16 04:54:05 +00001075 // Emit following code:
1076 // if (<IsLastIterCond>) {
1077 // orig_var1 = private_orig_var1;
1078 // ...
1079 // orig_varn = private_orig_varn;
1080 // }
Alexey Bataevfc087ec2015-06-16 13:14:42 +00001081 llvm::BasicBlock *ThenBB = nullptr;
1082 llvm::BasicBlock *DoneBB = nullptr;
1083 if (IsLastIterCond) {
Alexey Bataeva58da1a2019-12-27 09:44:43 -05001084 // Emit implicit barrier if at least one lastprivate conditional is found
1085 // and this is not a simd mode.
1086 if (!getLangOpts().OpenMPSimd &&
1087 llvm::any_of(D.getClausesOfKind<OMPLastprivateClause>(),
1088 [](const OMPLastprivateClause *C) {
1089 return C->getKind() == OMPC_LASTPRIVATE_conditional;
1090 })) {
1091 CGM.getOpenMPRuntime().emitBarrierCall(*this, D.getBeginLoc(),
1092 OMPD_unknown,
1093 /*EmitChecks=*/false,
1094 /*ForceSimpleCall=*/true);
1095 }
Alexey Bataevfc087ec2015-06-16 13:14:42 +00001096 ThenBB = createBasicBlock(".omp.lastprivate.then");
1097 DoneBB = createBasicBlock(".omp.lastprivate.done");
1098 Builder.CreateCondBr(IsLastIterCond, ThenBB, DoneBB);
1099 EmitBlock(ThenBB);
1100 }
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001101 llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
1102 llvm::DenseMap<const VarDecl *, const Expr *> LoopCountersAndUpdates;
Alexey Bataevddf3db92018-04-13 17:31:06 +00001103 if (const auto *LoopDirective = dyn_cast<OMPLoopDirective>(&D)) {
Alexey Bataev8ffcc942016-02-18 13:48:15 +00001104 auto IC = LoopDirective->counters().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00001105 for (const Expr *F : LoopDirective->finals()) {
1106 const auto *D =
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001107 cast<VarDecl>(cast<DeclRefExpr>(*IC)->getDecl())->getCanonicalDecl();
1108 if (NoFinals)
1109 AlreadyEmittedVars.insert(D);
1110 else
1111 LoopCountersAndUpdates[D] = F;
Alexey Bataev8ffcc942016-02-18 13:48:15 +00001112 ++IC;
Alexey Bataev7a228ff2015-05-21 07:59:51 +00001113 }
1114 }
Alexey Bataev8ffcc942016-02-18 13:48:15 +00001115 for (const auto *C : D.getClausesOfKind<OMPLastprivateClause>()) {
1116 auto IRef = C->varlist_begin();
1117 auto ISrcRef = C->source_exprs().begin();
1118 auto IDestRef = C->destination_exprs().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00001119 for (const Expr *AssignOp : C->assignment_ops()) {
1120 const auto *PrivateVD =
1121 cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
Alexey Bataev8ffcc942016-02-18 13:48:15 +00001122 QualType Type = PrivateVD->getType();
Alexey Bataevddf3db92018-04-13 17:31:06 +00001123 const auto *CanonicalVD = PrivateVD->getCanonicalDecl();
Alexey Bataev8ffcc942016-02-18 13:48:15 +00001124 if (AlreadyEmittedVars.insert(CanonicalVD).second) {
1125 // If lastprivate variable is a loop control variable for loop-based
1126 // directive, update its value before copyin back to original
1127 // variable.
Alexey Bataevddf3db92018-04-13 17:31:06 +00001128 if (const Expr *FinalExpr = LoopCountersAndUpdates.lookup(CanonicalVD))
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001129 EmitIgnoredExpr(FinalExpr);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001130 const auto *SrcVD =
1131 cast<VarDecl>(cast<DeclRefExpr>(*ISrcRef)->getDecl());
1132 const auto *DestVD =
1133 cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
Alexey Bataev8ffcc942016-02-18 13:48:15 +00001134 // Get the address of the private variable.
1135 Address PrivateAddr = GetAddrOfLocalVar(PrivateVD);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001136 if (const auto *RefTy = PrivateVD->getType()->getAs<ReferenceType>())
Alexey Bataev8ffcc942016-02-18 13:48:15 +00001137 PrivateAddr =
John McCall7f416cc2015-09-08 08:05:57 +00001138 Address(Builder.CreateLoad(PrivateAddr),
1139 getNaturalTypeAlignment(RefTy->getPointeeType()));
Alexey Bataeva58da1a2019-12-27 09:44:43 -05001140 // Store the last value to the private copy in the last iteration.
1141 if (C->getKind() == OMPC_LASTPRIVATE_conditional)
1142 CGM.getOpenMPRuntime().emitLastprivateConditionalFinalUpdate(
1143 *this, MakeAddrLValue(PrivateAddr, (*IRef)->getType()), PrivateVD,
1144 (*IRef)->getExprLoc());
1145 // Get the address of the original variable.
1146 Address OriginalAddr = GetAddrOfLocalVar(DestVD);
Alexey Bataev8ffcc942016-02-18 13:48:15 +00001147 EmitOMPCopy(Type, OriginalAddr, PrivateAddr, DestVD, SrcVD, AssignOp);
Alexey Bataev38e89532015-04-16 04:54:05 +00001148 }
Alexey Bataev8ffcc942016-02-18 13:48:15 +00001149 ++IRef;
1150 ++ISrcRef;
1151 ++IDestRef;
Alexey Bataev38e89532015-04-16 04:54:05 +00001152 }
Alexey Bataevddf3db92018-04-13 17:31:06 +00001153 if (const Expr *PostUpdate = C->getPostUpdateExpr())
Alexey Bataev005248a2016-02-25 05:25:57 +00001154 EmitIgnoredExpr(PostUpdate);
Alexey Bataev38e89532015-04-16 04:54:05 +00001155 }
Alexey Bataev8ffcc942016-02-18 13:48:15 +00001156 if (IsLastIterCond)
Alexey Bataevfc087ec2015-06-16 13:14:42 +00001157 EmitBlock(DoneBB, /*IsFinished=*/true);
Alexey Bataev38e89532015-04-16 04:54:05 +00001158}
1159
Alexey Bataev794ba0d2015-04-10 10:43:45 +00001160void CodeGenFunction::EmitOMPReductionClauseInit(
1161 const OMPExecutableDirective &D,
1162 CodeGenFunction::OMPPrivateScope &PrivateScope) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001163 if (!HaveInsertPoint())
1164 return;
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001165 SmallVector<const Expr *, 4> Shareds;
1166 SmallVector<const Expr *, 4> Privates;
1167 SmallVector<const Expr *, 4> ReductionOps;
1168 SmallVector<const Expr *, 4> LHSs;
1169 SmallVector<const Expr *, 4> RHSs;
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00001170 for (const auto *C : D.getClausesOfKind<OMPReductionClause>()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00001171 auto IPriv = C->privates().begin();
Alexey Bataeva839ddd2016-03-17 10:19:46 +00001172 auto IRed = C->reduction_ops().begin();
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001173 auto ILHS = C->lhs_exprs().begin();
1174 auto IRHS = C->rhs_exprs().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00001175 for (const Expr *Ref : C->varlists()) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001176 Shareds.emplace_back(Ref);
1177 Privates.emplace_back(*IPriv);
1178 ReductionOps.emplace_back(*IRed);
1179 LHSs.emplace_back(*ILHS);
1180 RHSs.emplace_back(*IRHS);
1181 std::advance(IPriv, 1);
1182 std::advance(IRed, 1);
1183 std::advance(ILHS, 1);
1184 std::advance(IRHS, 1);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00001185 }
1186 }
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001187 ReductionCodeGen RedCG(Shareds, Privates, ReductionOps);
1188 unsigned Count = 0;
1189 auto ILHS = LHSs.begin();
1190 auto IRHS = RHSs.begin();
1191 auto IPriv = Privates.begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00001192 for (const Expr *IRef : Shareds) {
1193 const auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*IPriv)->getDecl());
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001194 // Emit private VarDecl with reduction init.
1195 RedCG.emitSharedLValue(*this, Count);
1196 RedCG.emitAggregateType(*this, Count);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001197 AutoVarEmission Emission = EmitAutoVarAlloca(*PrivateVD);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001198 RedCG.emitInitialization(*this, Count, Emission.getAllocatedAddress(),
1199 RedCG.getSharedLValue(Count),
1200 [&Emission](CodeGenFunction &CGF) {
1201 CGF.EmitAutoVarInit(Emission);
1202 return true;
1203 });
1204 EmitAutoVarCleanups(Emission);
1205 Address BaseAddr = RedCG.adjustPrivateAddress(
1206 *this, Count, Emission.getAllocatedAddress());
1207 bool IsRegistered = PrivateScope.addPrivate(
Alexey Bataevddf3db92018-04-13 17:31:06 +00001208 RedCG.getBaseDecl(Count), [BaseAddr]() { return BaseAddr; });
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001209 assert(IsRegistered && "private var already registered as private");
1210 // Silence the warning about unused variable.
1211 (void)IsRegistered;
1212
Alexey Bataevddf3db92018-04-13 17:31:06 +00001213 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
1214 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Jonas Hahnfeld4525c822017-10-23 19:01:35 +00001215 QualType Type = PrivateVD->getType();
1216 bool isaOMPArraySectionExpr = isa<OMPArraySectionExpr>(IRef);
1217 if (isaOMPArraySectionExpr && Type->isVariablyModifiedType()) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001218 // Store the address of the original variable associated with the LHS
1219 // implicit variable.
Akira Hatanakaf139ae32019-12-03 15:17:01 -08001220 PrivateScope.addPrivate(LHSVD, [&RedCG, Count, this]() {
1221 return RedCG.getSharedLValue(Count).getAddress(*this);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001222 });
Alexey Bataevddf3db92018-04-13 17:31:06 +00001223 PrivateScope.addPrivate(
1224 RHSVD, [this, PrivateVD]() { return GetAddrOfLocalVar(PrivateVD); });
Jonas Hahnfeld4525c822017-10-23 19:01:35 +00001225 } else if ((isaOMPArraySectionExpr && Type->isScalarType()) ||
1226 isa<ArraySubscriptExpr>(IRef)) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001227 // Store the address of the original variable associated with the LHS
1228 // implicit variable.
Akira Hatanakaf139ae32019-12-03 15:17:01 -08001229 PrivateScope.addPrivate(LHSVD, [&RedCG, Count, this]() {
1230 return RedCG.getSharedLValue(Count).getAddress(*this);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001231 });
Alexey Bataevddf3db92018-04-13 17:31:06 +00001232 PrivateScope.addPrivate(RHSVD, [this, PrivateVD, RHSVD]() {
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001233 return Builder.CreateElementBitCast(GetAddrOfLocalVar(PrivateVD),
1234 ConvertTypeForMem(RHSVD->getType()),
1235 "rhs.begin");
1236 });
1237 } else {
1238 QualType Type = PrivateVD->getType();
1239 bool IsArray = getContext().getAsArrayType(Type) != nullptr;
Akira Hatanakaf139ae32019-12-03 15:17:01 -08001240 Address OriginalAddr = RedCG.getSharedLValue(Count).getAddress(*this);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001241 // Store the address of the original variable associated with the LHS
1242 // implicit variable.
1243 if (IsArray) {
1244 OriginalAddr = Builder.CreateElementBitCast(
1245 OriginalAddr, ConvertTypeForMem(LHSVD->getType()), "lhs.begin");
1246 }
Alexey Bataevddf3db92018-04-13 17:31:06 +00001247 PrivateScope.addPrivate(LHSVD, [OriginalAddr]() { return OriginalAddr; });
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001248 PrivateScope.addPrivate(
Alexey Bataevddf3db92018-04-13 17:31:06 +00001249 RHSVD, [this, PrivateVD, RHSVD, IsArray]() {
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001250 return IsArray
1251 ? Builder.CreateElementBitCast(
1252 GetAddrOfLocalVar(PrivateVD),
1253 ConvertTypeForMem(RHSVD->getType()), "rhs.begin")
1254 : GetAddrOfLocalVar(PrivateVD);
1255 });
1256 }
1257 ++ILHS;
1258 ++IRHS;
1259 ++IPriv;
1260 ++Count;
1261 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00001262}
1263
1264void CodeGenFunction::EmitOMPReductionClauseFinal(
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00001265 const OMPExecutableDirective &D, const OpenMPDirectiveKind ReductionKind) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001266 if (!HaveInsertPoint())
1267 return;
Alexey Bataevf24e7b12015-10-08 09:10:53 +00001268 llvm::SmallVector<const Expr *, 8> Privates;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00001269 llvm::SmallVector<const Expr *, 8> LHSExprs;
1270 llvm::SmallVector<const Expr *, 8> RHSExprs;
1271 llvm::SmallVector<const Expr *, 8> ReductionOps;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00001272 bool HasAtLeastOneReduction = false;
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00001273 for (const auto *C : D.getClausesOfKind<OMPReductionClause>()) {
Alexey Bataev794ba0d2015-04-10 10:43:45 +00001274 HasAtLeastOneReduction = true;
Alexey Bataevf24e7b12015-10-08 09:10:53 +00001275 Privates.append(C->privates().begin(), C->privates().end());
Alexey Bataev794ba0d2015-04-10 10:43:45 +00001276 LHSExprs.append(C->lhs_exprs().begin(), C->lhs_exprs().end());
1277 RHSExprs.append(C->rhs_exprs().begin(), C->rhs_exprs().end());
1278 ReductionOps.append(C->reduction_ops().begin(), C->reduction_ops().end());
1279 }
1280 if (HasAtLeastOneReduction) {
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00001281 bool WithNowait = D.getSingleClause<OMPNowaitClause>() ||
1282 isOpenMPParallelDirective(D.getDirectiveKind()) ||
Alexey Bataeva8a9153a2017-12-29 18:07:07 +00001283 ReductionKind == OMPD_simd;
1284 bool SimpleReduction = ReductionKind == OMPD_simd;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00001285 // Emit nowait reduction if nowait clause is present or directive is a
1286 // parallel directive (it always has implicit barrier).
1287 CGM.getOpenMPRuntime().emitReduction(
Stephen Kelly1c301dc2018-08-09 21:09:38 +00001288 *this, D.getEndLoc(), Privates, LHSExprs, RHSExprs, ReductionOps,
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00001289 {WithNowait, SimpleReduction, ReductionKind});
Alexey Bataev794ba0d2015-04-10 10:43:45 +00001290 }
1291}
1292
Alexey Bataev61205072016-03-02 04:57:40 +00001293static void emitPostUpdateForReductionClause(
1294 CodeGenFunction &CGF, const OMPExecutableDirective &D,
Alexey Bataevddf3db92018-04-13 17:31:06 +00001295 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
Alexey Bataev61205072016-03-02 04:57:40 +00001296 if (!CGF.HaveInsertPoint())
1297 return;
1298 llvm::BasicBlock *DoneBB = nullptr;
1299 for (const auto *C : D.getClausesOfKind<OMPReductionClause>()) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00001300 if (const Expr *PostUpdate = C->getPostUpdateExpr()) {
Alexey Bataev61205072016-03-02 04:57:40 +00001301 if (!DoneBB) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00001302 if (llvm::Value *Cond = CondGen(CGF)) {
Alexey Bataev61205072016-03-02 04:57:40 +00001303 // If the first post-update expression is found, emit conditional
1304 // block if it was requested.
Alexey Bataevddf3db92018-04-13 17:31:06 +00001305 llvm::BasicBlock *ThenBB = CGF.createBasicBlock(".omp.reduction.pu");
Alexey Bataev61205072016-03-02 04:57:40 +00001306 DoneBB = CGF.createBasicBlock(".omp.reduction.pu.done");
1307 CGF.Builder.CreateCondBr(Cond, ThenBB, DoneBB);
1308 CGF.EmitBlock(ThenBB);
1309 }
1310 }
1311 CGF.EmitIgnoredExpr(PostUpdate);
1312 }
1313 }
1314 if (DoneBB)
1315 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
1316}
1317
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00001318namespace {
1319/// Codegen lambda for appending distribute lower and upper bounds to outlined
1320/// parallel function. This is necessary for combined constructs such as
1321/// 'distribute parallel for'
1322typedef llvm::function_ref<void(CodeGenFunction &,
1323 const OMPExecutableDirective &,
1324 llvm::SmallVectorImpl<llvm::Value *> &)>
1325 CodeGenBoundParametersTy;
1326} // anonymous namespace
1327
Alexey Bataev46978742020-01-30 10:46:11 -05001328static void
1329checkForLastprivateConditionalUpdate(CodeGenFunction &CGF,
1330 const OMPExecutableDirective &S) {
1331 if (CGF.getLangOpts().OpenMP < 50)
1332 return;
1333 llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> PrivateDecls;
1334 for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) {
1335 for (const Expr *Ref : C->varlists()) {
1336 if (!Ref->getType()->isScalarType())
1337 continue;
1338 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1339 if (!DRE)
1340 continue;
1341 PrivateDecls.insert(cast<VarDecl>(DRE->getDecl()));
1342 CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, Ref);
1343 }
1344 }
1345 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) {
1346 for (const Expr *Ref : C->varlists()) {
1347 if (!Ref->getType()->isScalarType())
1348 continue;
1349 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1350 if (!DRE)
1351 continue;
1352 PrivateDecls.insert(cast<VarDecl>(DRE->getDecl()));
1353 CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, Ref);
1354 }
1355 }
1356 for (const auto *C : S.getClausesOfKind<OMPLinearClause>()) {
1357 for (const Expr *Ref : C->varlists()) {
1358 if (!Ref->getType()->isScalarType())
1359 continue;
1360 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1361 if (!DRE)
1362 continue;
1363 PrivateDecls.insert(cast<VarDecl>(DRE->getDecl()));
1364 CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, Ref);
1365 }
1366 }
1367 // Privates should ne analyzed since they are not captured at all.
1368 // Task reductions may be skipped - tasks are ignored.
1369 // Firstprivates do not return value but may be passed by reference - no need
1370 // to check for updated lastprivate conditional.
1371 for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) {
1372 for (const Expr *Ref : C->varlists()) {
1373 if (!Ref->getType()->isScalarType())
1374 continue;
1375 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1376 if (!DRE)
1377 continue;
1378 PrivateDecls.insert(cast<VarDecl>(DRE->getDecl()));
1379 }
1380 }
1381 CGF.CGM.getOpenMPRuntime().checkAndEmitSharedLastprivateConditional(
1382 CGF, S, PrivateDecls);
1383}
1384
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00001385static void emitCommonOMPParallelDirective(
1386 CodeGenFunction &CGF, const OMPExecutableDirective &S,
1387 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
1388 const CodeGenBoundParametersTy &CodeGenBoundParameters) {
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00001389 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
James Y Knight9871db02019-02-05 16:42:33 +00001390 llvm::Function *OutlinedFn =
Alexey Bataevddf3db92018-04-13 17:31:06 +00001391 CGF.CGM.getOpenMPRuntime().emitParallelOutlinedFunction(
1392 S, *CS->getCapturedDecl()->param_begin(), InnermostKind, CodeGen);
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00001393 if (const auto *NumThreadsClause = S.getSingleClause<OMPNumThreadsClause>()) {
Alexey Bataev1d677132015-04-22 13:57:31 +00001394 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001395 llvm::Value *NumThreads =
1396 CGF.EmitScalarExpr(NumThreadsClause->getNumThreads(),
1397 /*IgnoreResultAssign=*/true);
Alexey Bataev1d677132015-04-22 13:57:31 +00001398 CGF.CGM.getOpenMPRuntime().emitNumThreadsClause(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00001399 CGF, NumThreads, NumThreadsClause->getBeginLoc());
Alexey Bataev1d677132015-04-22 13:57:31 +00001400 }
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00001401 if (const auto *ProcBindClause = S.getSingleClause<OMPProcBindClause>()) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001402 CodeGenFunction::RunCleanupsScope ProcBindScope(CGF);
Alexey Bataev7f210c62015-06-18 13:40:03 +00001403 CGF.CGM.getOpenMPRuntime().emitProcBindClause(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00001404 CGF, ProcBindClause->getProcBindKind(), ProcBindClause->getBeginLoc());
Alexey Bataev7f210c62015-06-18 13:40:03 +00001405 }
Alexey Bataev1d677132015-04-22 13:57:31 +00001406 const Expr *IfCond = nullptr;
Alexey Bataev7371aa32015-09-03 08:45:56 +00001407 for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
1408 if (C->getNameModifier() == OMPD_unknown ||
1409 C->getNameModifier() == OMPD_parallel) {
1410 IfCond = C->getCondition();
1411 break;
1412 }
Alexey Bataev1d677132015-04-22 13:57:31 +00001413 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001414
Arpith Chacko Jacobfe4890a2017-01-18 20:40:48 +00001415 OMPParallelScope Scope(CGF, S);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001416 llvm::SmallVector<llvm::Value *, 16> CapturedVars;
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00001417 // Combining 'distribute' with 'for' requires sharing each 'distribute' chunk
1418 // lower and upper bounds with the pragma 'for' chunking mechanism.
1419 // The following lambda takes care of appending the lower and upper bound
1420 // parameters when necessary
1421 CodeGenBoundParameters(CGF, S, CapturedVars);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001422 CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
Stephen Kellyf2ceec42018-08-09 21:08:08 +00001423 CGF.CGM.getOpenMPRuntime().emitParallelCall(CGF, S.getBeginLoc(), OutlinedFn,
Alexey Bataev2377fe92015-09-10 08:12:02 +00001424 CapturedVars, IfCond);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001425}
1426
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00001427static void emitEmptyBoundParameters(CodeGenFunction &,
1428 const OMPExecutableDirective &,
1429 llvm::SmallVectorImpl<llvm::Value *> &) {}
1430
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001431void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) {
Johannes Doerfert10fedd92019-12-26 11:23:38 -06001432 if (llvm::OpenMPIRBuilder *OMPBuilder = CGM.getOpenMPIRBuilder()) {
1433 // Check if we have any if clause associated with the directive.
1434 llvm::Value *IfCond = nullptr;
1435 if (const auto *C = S.getSingleClause<OMPIfClause>())
1436 IfCond = EmitScalarExpr(C->getCondition(),
1437 /*IgnoreResultAssign=*/true);
1438
1439 llvm::Value *NumThreads = nullptr;
1440 if (const auto *NumThreadsClause = S.getSingleClause<OMPNumThreadsClause>())
1441 NumThreads = EmitScalarExpr(NumThreadsClause->getNumThreads(),
1442 /*IgnoreResultAssign=*/true);
1443
1444 ProcBindKind ProcBind = OMP_PROC_BIND_default;
1445 if (const auto *ProcBindClause = S.getSingleClause<OMPProcBindClause>())
1446 ProcBind = ProcBindClause->getProcBindKind();
1447
1448 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
1449
1450 // The cleanup callback that finalizes all variabels at the given location,
1451 // thus calls destructors etc.
1452 auto FiniCB = [this](InsertPointTy IP) {
Fady Ghanimba3f8632020-02-19 13:50:26 -06001453 OMPBuilderCBHelpers::FinalizeOMPRegion(*this, IP);
Johannes Doerfert10fedd92019-12-26 11:23:38 -06001454 };
1455
1456 // Privatization callback that performs appropriate action for
1457 // shared/private/firstprivate/lastprivate/copyin/... variables.
1458 //
1459 // TODO: This defaults to shared right now.
1460 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
1461 llvm::Value &Val, llvm::Value *&ReplVal) {
1462 // The next line is appropriate only for variables (Val) with the
1463 // data-sharing attribute "shared".
1464 ReplVal = &Val;
1465
1466 return CodeGenIP;
1467 };
1468
1469 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
1470 const Stmt *ParallelRegionBodyStmt = CS->getCapturedStmt();
1471
1472 auto BodyGenCB = [ParallelRegionBodyStmt,
1473 this](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
1474 llvm::BasicBlock &ContinuationBB) {
Fady Ghanimba3f8632020-02-19 13:50:26 -06001475 OMPBuilderCBHelpers::OutlinedRegionBodyRAII ORB(*this, AllocaIP,
1476 ContinuationBB);
1477 OMPBuilderCBHelpers::EmitOMPRegionBody(*this, ParallelRegionBodyStmt,
1478 CodeGenIP, ContinuationBB);
Johannes Doerfert10fedd92019-12-26 11:23:38 -06001479 };
1480
1481 CGCapturedStmtInfo CGSI(*CS, CR_OpenMP);
1482 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(*this, &CGSI);
1483 Builder.restoreIP(OMPBuilder->CreateParallel(Builder, BodyGenCB, PrivCB,
1484 FiniCB, IfCond, NumThreads,
1485 ProcBind, S.hasCancel()));
1486 return;
1487 }
1488
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001489 // Emit parallel region as a standalone region.
Alexey Bataevc99042b2018-03-15 18:10:54 +00001490 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataev63cc8e92018-03-20 14:45:59 +00001491 Action.Enter(CGF);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001492 OMPPrivateScope PrivateScope(CGF);
Alexey Bataevf56f98c2015-04-16 05:39:01 +00001493 bool Copyins = CGF.EmitOMPCopyinClause(S);
Alexey Bataevcd8b6a22016-02-15 08:07:17 +00001494 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
1495 if (Copyins) {
Alexey Bataev69c62a92015-04-15 04:52:20 +00001496 // Emit implicit barrier to synchronize threads and avoid data races on
Alexey Bataevcd8b6a22016-02-15 08:07:17 +00001497 // propagation master's thread values of threadprivate variables to local
1498 // instances of that variables of all other implicit threads.
Alexey Bataev25e5b442015-09-15 12:52:43 +00001499 CGF.CGM.getOpenMPRuntime().emitBarrierCall(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00001500 CGF, S.getBeginLoc(), OMPD_unknown, /*EmitChecks=*/false,
Alexey Bataev25e5b442015-09-15 12:52:43 +00001501 /*ForceSimpleCall=*/true);
Alexey Bataev69c62a92015-04-15 04:52:20 +00001502 }
1503 CGF.EmitOMPPrivateClause(S, PrivateScope);
1504 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
1505 (void)PrivateScope.Privatize();
Alexey Bataev475a7442018-01-12 19:39:11 +00001506 CGF.EmitStmt(S.getCapturedStmt(OMPD_parallel)->getCapturedStmt());
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00001507 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001508 };
Alexey Bataev46978742020-01-30 10:46:11 -05001509 {
1510 auto LPCRegion =
1511 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
1512 emitCommonOMPParallelDirective(*this, S, OMPD_parallel, CodeGen,
1513 emitEmptyBoundParameters);
1514 emitPostUpdateForReductionClause(*this, S,
1515 [](CodeGenFunction &) { return nullptr; });
1516 }
1517 // Check for outer lastprivate conditional update.
1518 checkForLastprivateConditionalUpdate(*this, S);
Alexey Bataev9959db52014-05-06 10:08:46 +00001519}
Alexander Musman515ad8c2014-05-22 08:54:05 +00001520
Alexey Bataev8bbf2e32019-11-04 09:59:11 -05001521static void emitBody(CodeGenFunction &CGF, const Stmt *S, const Stmt *NextLoop,
1522 int MaxLevel, int Level = 0) {
1523 assert(Level < MaxLevel && "Too deep lookup during loop body codegen.");
1524 const Stmt *SimplifiedS = S->IgnoreContainers();
1525 if (const auto *CS = dyn_cast<CompoundStmt>(SimplifiedS)) {
1526 PrettyStackTraceLoc CrashInfo(
1527 CGF.getContext().getSourceManager(), CS->getLBracLoc(),
1528 "LLVM IR generation of compound statement ('{}')");
1529
1530 // Keep track of the current cleanup stack depth, including debug scopes.
1531 CodeGenFunction::LexicalScope Scope(CGF, S->getSourceRange());
1532 for (const Stmt *CurStmt : CS->body())
1533 emitBody(CGF, CurStmt, NextLoop, MaxLevel, Level);
1534 return;
1535 }
1536 if (SimplifiedS == NextLoop) {
1537 if (const auto *For = dyn_cast<ForStmt>(SimplifiedS)) {
1538 S = For->getBody();
1539 } else {
1540 assert(isa<CXXForRangeStmt>(SimplifiedS) &&
1541 "Expected canonical for loop or range-based for loop.");
1542 const auto *CXXFor = cast<CXXForRangeStmt>(SimplifiedS);
1543 CGF.EmitStmt(CXXFor->getLoopVarStmt());
1544 S = CXXFor->getBody();
1545 }
1546 if (Level + 1 < MaxLevel) {
1547 NextLoop = OMPLoopDirective::tryToFindNextInnerLoop(
1548 S, /*TryImperfectlyNestedLoops=*/true);
1549 emitBody(CGF, S, NextLoop, MaxLevel, Level + 1);
1550 return;
1551 }
1552 }
1553 CGF.EmitStmt(S);
1554}
1555
Alexey Bataev0f34da12015-07-02 04:17:07 +00001556void CodeGenFunction::EmitOMPLoopBody(const OMPLoopDirective &D,
1557 JumpDest LoopExit) {
Alexander Musmana5f070a2014-10-01 06:03:56 +00001558 RunCleanupsScope BodyScope(*this);
1559 // Update counters values on current iteration.
Alexey Bataevddf3db92018-04-13 17:31:06 +00001560 for (const Expr *UE : D.updates())
1561 EmitIgnoredExpr(UE);
Alexander Musman3276a272015-03-21 10:12:56 +00001562 // Update the linear variables.
Alexey Bataev617db5f2017-12-04 15:38:33 +00001563 // In distribute directives only loop counters may be marked as linear, no
1564 // need to generate the code for them.
1565 if (!isOpenMPDistributeDirective(D.getDirectiveKind())) {
1566 for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00001567 for (const Expr *UE : C->updates())
1568 EmitIgnoredExpr(UE);
Alexey Bataev617db5f2017-12-04 15:38:33 +00001569 }
Alexander Musman3276a272015-03-21 10:12:56 +00001570 }
1571
Alexander Musmana5f070a2014-10-01 06:03:56 +00001572 // On a continue in the body, jump to the end.
Alexey Bataevddf3db92018-04-13 17:31:06 +00001573 JumpDest Continue = getJumpDestInCurrentScope("omp.body.continue");
Alexey Bataev0f34da12015-07-02 04:17:07 +00001574 BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
Alexey Bataevf8be4762019-08-14 19:30:06 +00001575 for (const Expr *E : D.finals_conditions()) {
1576 if (!E)
1577 continue;
1578 // Check that loop counter in non-rectangular nest fits into the iteration
1579 // space.
1580 llvm::BasicBlock *NextBB = createBasicBlock("omp.body.next");
1581 EmitBranchOnBoolExpr(E, NextBB, Continue.getBlock(),
1582 getProfileCount(D.getBody()));
1583 EmitBlock(NextBB);
1584 }
Alexey Bataevbef93a92019-10-07 18:54:57 +00001585 // Emit loop variables for C++ range loops.
1586 const Stmt *Body =
1587 D.getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers();
Alexander Musmana5f070a2014-10-01 06:03:56 +00001588 // Emit loop body.
Alexey Bataev8bbf2e32019-11-04 09:59:11 -05001589 emitBody(*this, Body,
1590 OMPLoopDirective::tryToFindNextInnerLoop(
1591 Body, /*TryImperfectlyNestedLoops=*/true),
1592 D.getCollapsedNumber());
1593
Alexander Musmana5f070a2014-10-01 06:03:56 +00001594 // The end (updates/cleanups).
1595 EmitBlock(Continue.getBlock());
1596 BreakContinueStack.pop_back();
Alexander Musmana5f070a2014-10-01 06:03:56 +00001597}
1598
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001599void CodeGenFunction::EmitOMPInnerLoop(
1600 const Stmt &S, bool RequiresCleanup, const Expr *LoopCond,
1601 const Expr *IncExpr,
Alexey Bataevddf3db92018-04-13 17:31:06 +00001602 const llvm::function_ref<void(CodeGenFunction &)> BodyGen,
1603 const llvm::function_ref<void(CodeGenFunction &)> PostIncGen) {
Alexander Musmand196ef22014-10-07 08:57:09 +00001604 auto LoopExit = getJumpDestInCurrentScope("omp.inner.for.end");
Alexander Musmana5f070a2014-10-01 06:03:56 +00001605
1606 // Start the loop with a block that tests the condition.
Alexander Musmand196ef22014-10-07 08:57:09 +00001607 auto CondBlock = createBasicBlock("omp.inner.for.cond");
Alexander Musmana5f070a2014-10-01 06:03:56 +00001608 EmitBlock(CondBlock);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001609 const SourceRange R = S.getSourceRange();
Amara Emerson652795d2016-11-10 14:44:30 +00001610 LoopStack.push(CondBlock, SourceLocToDebugLoc(R.getBegin()),
1611 SourceLocToDebugLoc(R.getEnd()));
Alexander Musmana5f070a2014-10-01 06:03:56 +00001612
1613 // If there are any cleanups between here and the loop-exit scope,
1614 // create a block to stage a loop exit along.
Alexey Bataevddf3db92018-04-13 17:31:06 +00001615 llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
Alexey Bataev2df54a02015-03-12 08:53:29 +00001616 if (RequiresCleanup)
Alexander Musmand196ef22014-10-07 08:57:09 +00001617 ExitBlock = createBasicBlock("omp.inner.for.cond.cleanup");
Alexander Musmana5f070a2014-10-01 06:03:56 +00001618
Alexey Bataevddf3db92018-04-13 17:31:06 +00001619 llvm::BasicBlock *LoopBody = createBasicBlock("omp.inner.for.body");
Alexander Musmana5f070a2014-10-01 06:03:56 +00001620
Alexey Bataev2df54a02015-03-12 08:53:29 +00001621 // Emit condition.
Justin Bogner66242d62015-04-23 23:06:47 +00001622 EmitBranchOnBoolExpr(LoopCond, LoopBody, ExitBlock, getProfileCount(&S));
Alexander Musmana5f070a2014-10-01 06:03:56 +00001623 if (ExitBlock != LoopExit.getBlock()) {
1624 EmitBlock(ExitBlock);
1625 EmitBranchThroughCleanup(LoopExit);
1626 }
1627
1628 EmitBlock(LoopBody);
Justin Bogner66242d62015-04-23 23:06:47 +00001629 incrementProfileCounter(&S);
Alexander Musmana5f070a2014-10-01 06:03:56 +00001630
1631 // Create a block for the increment.
Alexey Bataevddf3db92018-04-13 17:31:06 +00001632 JumpDest Continue = getJumpDestInCurrentScope("omp.inner.for.inc");
Alexander Musmana5f070a2014-10-01 06:03:56 +00001633 BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
1634
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001635 BodyGen(*this);
Alexander Musmana5f070a2014-10-01 06:03:56 +00001636
1637 // Emit "IV = IV + 1" and a back-edge to the condition block.
1638 EmitBlock(Continue.getBlock());
Alexey Bataev2df54a02015-03-12 08:53:29 +00001639 EmitIgnoredExpr(IncExpr);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001640 PostIncGen(*this);
Alexander Musmana5f070a2014-10-01 06:03:56 +00001641 BreakContinueStack.pop_back();
1642 EmitBranch(CondBlock);
1643 LoopStack.pop();
1644 // Emit the fall-through block.
1645 EmitBlock(LoopExit.getBlock());
1646}
1647
Alexey Bataev8c3edfe2017-08-16 15:58:46 +00001648bool CodeGenFunction::EmitOMPLinearClauseInit(const OMPLoopDirective &D) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001649 if (!HaveInsertPoint())
Alexey Bataev8c3edfe2017-08-16 15:58:46 +00001650 return false;
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001651 // Emit inits for the linear variables.
Alexey Bataev8c3edfe2017-08-16 15:58:46 +00001652 bool HasLinears = false;
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00001653 for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00001654 for (const Expr *Init : C->inits()) {
Alexey Bataev8c3edfe2017-08-16 15:58:46 +00001655 HasLinears = true;
Alexey Bataevddf3db92018-04-13 17:31:06 +00001656 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(Init)->getDecl());
1657 if (const auto *Ref =
1658 dyn_cast<DeclRefExpr>(VD->getInit()->IgnoreImpCasts())) {
Alexey Bataevef549a82016-03-09 09:49:09 +00001659 AutoVarEmission Emission = EmitAutoVarAlloca(*VD);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001660 const auto *OrigVD = cast<VarDecl>(Ref->getDecl());
Bruno Ricci5fc4db72018-12-21 14:10:18 +00001661 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD),
Alexey Bataevef549a82016-03-09 09:49:09 +00001662 CapturedStmtInfo->lookup(OrigVD) != nullptr,
1663 VD->getInit()->getType(), VK_LValue,
1664 VD->getInit()->getExprLoc());
1665 EmitExprAsInit(&DRE, VD, MakeAddrLValue(Emission.getAllocatedAddress(),
1666 VD->getType()),
1667 /*capturedByInit=*/false);
1668 EmitAutoVarCleanups(Emission);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001669 } else {
Alexey Bataevef549a82016-03-09 09:49:09 +00001670 EmitVarDecl(*VD);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001671 }
Alexander Musmana5f070a2014-10-01 06:03:56 +00001672 }
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001673 // Emit the linear steps for the linear clauses.
1674 // If a step is not constant, it is pre-calculated before the loop.
Alexey Bataevddf3db92018-04-13 17:31:06 +00001675 if (const auto *CS = cast_or_null<BinaryOperator>(C->getCalcStep()))
1676 if (const auto *SaveRef = cast<DeclRefExpr>(CS->getLHS())) {
Alexey Bataev3b5b5c42015-06-18 10:10:12 +00001677 EmitVarDecl(*cast<VarDecl>(SaveRef->getDecl()));
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001678 // Emit calculation of the linear step.
Alexey Bataev3b5b5c42015-06-18 10:10:12 +00001679 EmitIgnoredExpr(CS);
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001680 }
Alexander Musmana5f070a2014-10-01 06:03:56 +00001681 }
Alexey Bataev8c3edfe2017-08-16 15:58:46 +00001682 return HasLinears;
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001683}
1684
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001685void CodeGenFunction::EmitOMPLinearClauseFinal(
1686 const OMPLoopDirective &D,
Alexey Bataevddf3db92018-04-13 17:31:06 +00001687 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001688 if (!HaveInsertPoint())
Alexey Bataev8ef31412015-12-18 07:58:25 +00001689 return;
Alexey Bataevef549a82016-03-09 09:49:09 +00001690 llvm::BasicBlock *DoneBB = nullptr;
Alexander Musman3276a272015-03-21 10:12:56 +00001691 // Emit the final values of the linear variables.
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00001692 for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) {
Alexey Bataev39f915b82015-05-08 10:41:21 +00001693 auto IC = C->varlist_begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00001694 for (const Expr *F : C->finals()) {
Alexey Bataevef549a82016-03-09 09:49:09 +00001695 if (!DoneBB) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00001696 if (llvm::Value *Cond = CondGen(*this)) {
Alexey Bataevef549a82016-03-09 09:49:09 +00001697 // If the first post-update expression is found, emit conditional
1698 // block if it was requested.
Alexey Bataevddf3db92018-04-13 17:31:06 +00001699 llvm::BasicBlock *ThenBB = createBasicBlock(".omp.linear.pu");
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001700 DoneBB = createBasicBlock(".omp.linear.pu.done");
1701 Builder.CreateCondBr(Cond, ThenBB, DoneBB);
1702 EmitBlock(ThenBB);
Alexey Bataevef549a82016-03-09 09:49:09 +00001703 }
1704 }
Alexey Bataevddf3db92018-04-13 17:31:06 +00001705 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IC)->getDecl());
Bruno Ricci5fc4db72018-12-21 14:10:18 +00001706 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD),
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001707 CapturedStmtInfo->lookup(OrigVD) != nullptr,
Alexey Bataev39f915b82015-05-08 10:41:21 +00001708 (*IC)->getType(), VK_LValue, (*IC)->getExprLoc());
Akira Hatanakaf139ae32019-12-03 15:17:01 -08001709 Address OrigAddr = EmitLValue(&DRE).getAddress(*this);
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001710 CodeGenFunction::OMPPrivateScope VarScope(*this);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001711 VarScope.addPrivate(OrigVD, [OrigAddr]() { return OrigAddr; });
Alexey Bataev39f915b82015-05-08 10:41:21 +00001712 (void)VarScope.Privatize();
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001713 EmitIgnoredExpr(F);
Alexey Bataev39f915b82015-05-08 10:41:21 +00001714 ++IC;
Alexander Musman3276a272015-03-21 10:12:56 +00001715 }
Alexey Bataevddf3db92018-04-13 17:31:06 +00001716 if (const Expr *PostUpdate = C->getPostUpdateExpr())
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001717 EmitIgnoredExpr(PostUpdate);
Alexander Musman3276a272015-03-21 10:12:56 +00001718 }
Alexey Bataevef549a82016-03-09 09:49:09 +00001719 if (DoneBB)
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001720 EmitBlock(DoneBB, /*IsFinished=*/true);
Alexander Musmana5f070a2014-10-01 06:03:56 +00001721}
1722
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001723static void emitAlignedClause(CodeGenFunction &CGF,
1724 const OMPExecutableDirective &D) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001725 if (!CGF.HaveInsertPoint())
1726 return;
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00001727 for (const auto *Clause : D.getClausesOfKind<OMPAlignedClause>()) {
Erich Keanef7593952019-10-11 14:59:44 +00001728 llvm::APInt ClauseAlignment(64, 0);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001729 if (const Expr *AlignmentExpr = Clause->getAlignment()) {
1730 auto *AlignmentCI =
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001731 cast<llvm::ConstantInt>(CGF.EmitScalarExpr(AlignmentExpr));
Erich Keanef7593952019-10-11 14:59:44 +00001732 ClauseAlignment = AlignmentCI->getValue();
Alexander Musman09184fe2014-09-30 05:29:28 +00001733 }
Alexey Bataevddf3db92018-04-13 17:31:06 +00001734 for (const Expr *E : Clause->varlists()) {
Erich Keanef7593952019-10-11 14:59:44 +00001735 llvm::APInt Alignment(ClauseAlignment);
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001736 if (Alignment == 0) {
1737 // OpenMP [2.8.1, Description]
1738 // If no optional parameter is specified, implementation-defined default
1739 // alignments for SIMD instructions on the target platforms are assumed.
1740 Alignment =
Alexey Bataev00396512015-07-02 03:40:19 +00001741 CGF.getContext()
1742 .toCharUnitsFromBits(CGF.getContext().getOpenMPDefaultSimdAlign(
1743 E->getType()->getPointeeType()))
1744 .getQuantity();
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001745 }
Erich Keanef7593952019-10-11 14:59:44 +00001746 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001747 "alignment is not power of 2");
1748 if (Alignment != 0) {
1749 llvm::Value *PtrValue = CGF.EmitScalarExpr(E);
Fangrui Song1d49eb02020-02-13 16:36:27 -08001750 CGF.emitAlignmentAssumption(
Erich Keanef7593952019-10-11 14:59:44 +00001751 PtrValue, E, /*No second loc needed*/ SourceLocation(),
1752 llvm::ConstantInt::get(CGF.getLLVMContext(), Alignment));
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001753 }
Alexander Musman09184fe2014-09-30 05:29:28 +00001754 }
1755 }
1756}
1757
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001758void CodeGenFunction::EmitOMPPrivateLoopCounters(
1759 const OMPLoopDirective &S, CodeGenFunction::OMPPrivateScope &LoopScope) {
1760 if (!HaveInsertPoint())
Alexey Bataev8ef31412015-12-18 07:58:25 +00001761 return;
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001762 auto I = S.private_counters().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00001763 for (const Expr *E : S.counters()) {
1764 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
1765 const auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl());
Alexey Bataevab4ea222018-03-07 18:17:06 +00001766 // Emit var without initialization.
Alexey Bataevddf3db92018-04-13 17:31:06 +00001767 AutoVarEmission VarEmission = EmitAutoVarAlloca(*PrivateVD);
Alexey Bataevab4ea222018-03-07 18:17:06 +00001768 EmitAutoVarCleanups(VarEmission);
1769 LocalDeclMap.erase(PrivateVD);
1770 (void)LoopScope.addPrivate(VD, [&VarEmission]() {
1771 return VarEmission.getAllocatedAddress();
Alexey Bataev435ad7b2014-10-10 09:48:26 +00001772 });
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001773 if (LocalDeclMap.count(VD) || CapturedStmtInfo->lookup(VD) ||
1774 VD->hasGlobalStorage()) {
Alexey Bataevab4ea222018-03-07 18:17:06 +00001775 (void)LoopScope.addPrivate(PrivateVD, [this, VD, E]() {
Bruno Ricci5fc4db72018-12-21 14:10:18 +00001776 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(VD),
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001777 LocalDeclMap.count(VD) || CapturedStmtInfo->lookup(VD),
1778 E->getType(), VK_LValue, E->getExprLoc());
Akira Hatanakaf139ae32019-12-03 15:17:01 -08001779 return EmitLValue(&DRE).getAddress(*this);
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001780 });
Alexey Bataevab4ea222018-03-07 18:17:06 +00001781 } else {
1782 (void)LoopScope.addPrivate(PrivateVD, [&VarEmission]() {
1783 return VarEmission.getAllocatedAddress();
1784 });
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001785 }
Alexey Bataeva8899172015-08-06 12:30:57 +00001786 ++I;
Alexey Bataev435ad7b2014-10-10 09:48:26 +00001787 }
Alexey Bataevf138fda2018-08-13 19:04:24 +00001788 // Privatize extra loop counters used in loops for ordered(n) clauses.
1789 for (const auto *C : S.getClausesOfKind<OMPOrderedClause>()) {
1790 if (!C->getNumForLoops())
1791 continue;
1792 for (unsigned I = S.getCollapsedNumber(),
1793 E = C->getLoopNumIterations().size();
1794 I < E; ++I) {
Mike Rice0ed46662018-09-20 17:19:41 +00001795 const auto *DRE = cast<DeclRefExpr>(C->getLoopCounter(I));
Alexey Bataevf138fda2018-08-13 19:04:24 +00001796 const auto *VD = cast<VarDecl>(DRE->getDecl());
Alexey Bataev0d8fcdf2019-03-14 20:36:00 +00001797 // Override only those variables that can be captured to avoid re-emission
1798 // of the variables declared within the loops.
1799 if (DRE->refersToEnclosingVariableOrCapture()) {
Alexey Bataevf138fda2018-08-13 19:04:24 +00001800 (void)LoopScope.addPrivate(VD, [this, DRE, VD]() {
1801 return CreateMemTemp(DRE->getType(), VD->getName());
1802 });
1803 }
1804 }
1805 }
Alexey Bataev435ad7b2014-10-10 09:48:26 +00001806}
1807
Alexey Bataev62dbb972015-04-22 11:59:37 +00001808static void emitPreCond(CodeGenFunction &CGF, const OMPLoopDirective &S,
1809 const Expr *Cond, llvm::BasicBlock *TrueBlock,
1810 llvm::BasicBlock *FalseBlock, uint64_t TrueCount) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001811 if (!CGF.HaveInsertPoint())
1812 return;
Alexey Bataev6e8248f2015-06-11 10:53:56 +00001813 {
1814 CodeGenFunction::OMPPrivateScope PreCondScope(CGF);
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001815 CGF.EmitOMPPrivateLoopCounters(S, PreCondScope);
Alexey Bataev6e8248f2015-06-11 10:53:56 +00001816 (void)PreCondScope.Privatize();
Alexey Bataev6e8248f2015-06-11 10:53:56 +00001817 // Get initial values of real counters.
Alexey Bataevddf3db92018-04-13 17:31:06 +00001818 for (const Expr *I : S.inits()) {
Alexey Bataev6e8248f2015-06-11 10:53:56 +00001819 CGF.EmitIgnoredExpr(I);
1820 }
Alexey Bataev62dbb972015-04-22 11:59:37 +00001821 }
Alexey Bataevf8be4762019-08-14 19:30:06 +00001822 // Create temp loop control variables with their init values to support
1823 // non-rectangular loops.
1824 CodeGenFunction::OMPMapVars PreCondVars;
1825 for (const Expr * E: S.dependent_counters()) {
1826 if (!E)
1827 continue;
1828 assert(!E->getType().getNonReferenceType()->isRecordType() &&
1829 "dependent counter must not be an iterator.");
1830 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
1831 Address CounterAddr =
1832 CGF.CreateMemTemp(VD->getType().getNonReferenceType());
1833 (void)PreCondVars.setVarAddr(CGF, VD, CounterAddr);
1834 }
1835 (void)PreCondVars.apply(CGF);
1836 for (const Expr *E : S.dependent_inits()) {
1837 if (!E)
1838 continue;
1839 CGF.EmitIgnoredExpr(E);
1840 }
Alexey Bataev62dbb972015-04-22 11:59:37 +00001841 // Check that loop is executed at least one time.
1842 CGF.EmitBranchOnBoolExpr(Cond, TrueBlock, FalseBlock, TrueCount);
Alexey Bataevf8be4762019-08-14 19:30:06 +00001843 PreCondVars.restore(CGF);
Alexey Bataev62dbb972015-04-22 11:59:37 +00001844}
1845
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001846void CodeGenFunction::EmitOMPLinearClause(
1847 const OMPLoopDirective &D, CodeGenFunction::OMPPrivateScope &PrivateScope) {
1848 if (!HaveInsertPoint())
Alexey Bataev8ef31412015-12-18 07:58:25 +00001849 return;
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001850 llvm::DenseSet<const VarDecl *> SIMDLCVs;
1851 if (isOpenMPSimdDirective(D.getDirectiveKind())) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00001852 const auto *LoopDirective = cast<OMPLoopDirective>(&D);
1853 for (const Expr *C : LoopDirective->counters()) {
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001854 SIMDLCVs.insert(
1855 cast<VarDecl>(cast<DeclRefExpr>(C)->getDecl())->getCanonicalDecl());
1856 }
1857 }
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00001858 for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) {
Alexey Bataevbd9fec12015-08-18 06:47:21 +00001859 auto CurPrivate = C->privates().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00001860 for (const Expr *E : C->varlists()) {
1861 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
1862 const auto *PrivateVD =
Alexey Bataevbd9fec12015-08-18 06:47:21 +00001863 cast<VarDecl>(cast<DeclRefExpr>(*CurPrivate)->getDecl());
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001864 if (!SIMDLCVs.count(VD->getCanonicalDecl())) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00001865 bool IsRegistered = PrivateScope.addPrivate(VD, [this, PrivateVD]() {
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001866 // Emit private VarDecl with copy init.
1867 EmitVarDecl(*PrivateVD);
1868 return GetAddrOfLocalVar(PrivateVD);
1869 });
1870 assert(IsRegistered && "linear var already registered as private");
1871 // Silence the warning about unused variable.
1872 (void)IsRegistered;
Alexey Bataevddf3db92018-04-13 17:31:06 +00001873 } else {
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001874 EmitVarDecl(*PrivateVD);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001875 }
Alexey Bataevbd9fec12015-08-18 06:47:21 +00001876 ++CurPrivate;
Alexander Musman3276a272015-03-21 10:12:56 +00001877 }
1878 }
1879}
1880
Alexey Bataev45bfad52015-08-21 12:19:04 +00001881static void emitSimdlenSafelenClause(CodeGenFunction &CGF,
Alexey Bataeva6f2a142015-12-31 06:52:34 +00001882 const OMPExecutableDirective &D,
1883 bool IsMonotonic) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001884 if (!CGF.HaveInsertPoint())
1885 return;
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00001886 if (const auto *C = D.getSingleClause<OMPSimdlenClause>()) {
Alexey Bataev45bfad52015-08-21 12:19:04 +00001887 RValue Len = CGF.EmitAnyExpr(C->getSimdlen(), AggValueSlot::ignored(),
1888 /*ignoreResult=*/true);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001889 auto *Val = cast<llvm::ConstantInt>(Len.getScalarVal());
Alexey Bataev45bfad52015-08-21 12:19:04 +00001890 CGF.LoopStack.setVectorizeWidth(Val->getZExtValue());
1891 // In presence of finite 'safelen', it may be unsafe to mark all
1892 // the memory instructions parallel, because loop-carried
1893 // dependences of 'safelen' iterations are possible.
Alexey Bataeva6f2a142015-12-31 06:52:34 +00001894 if (!IsMonotonic)
1895 CGF.LoopStack.setParallel(!D.getSingleClause<OMPSafelenClause>());
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00001896 } else if (const auto *C = D.getSingleClause<OMPSafelenClause>()) {
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001897 RValue Len = CGF.EmitAnyExpr(C->getSafelen(), AggValueSlot::ignored(),
1898 /*ignoreResult=*/true);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001899 auto *Val = cast<llvm::ConstantInt>(Len.getScalarVal());
Tyler Nowickida46d0e2015-07-14 23:03:09 +00001900 CGF.LoopStack.setVectorizeWidth(Val->getZExtValue());
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001901 // In presence of finite 'safelen', it may be unsafe to mark all
1902 // the memory instructions parallel, because loop-carried
1903 // dependences of 'safelen' iterations are possible.
Alexey Bataevddf3db92018-04-13 17:31:06 +00001904 CGF.LoopStack.setParallel(/*Enable=*/false);
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001905 }
1906}
1907
Alexey Bataeva6f2a142015-12-31 06:52:34 +00001908void CodeGenFunction::EmitOMPSimdInit(const OMPLoopDirective &D,
1909 bool IsMonotonic) {
Alexey Bataev58e5bdb2015-06-18 04:45:29 +00001910 // Walk clauses and process safelen/lastprivate.
Alexey Bataeva6f2a142015-12-31 06:52:34 +00001911 LoopStack.setParallel(!IsMonotonic);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001912 LoopStack.setVectorizeEnable();
Alexey Bataeva6f2a142015-12-31 06:52:34 +00001913 emitSimdlenSafelenClause(*this, D, IsMonotonic);
Alexey Bataeva7815212020-02-03 12:08:16 -05001914 if (const auto *C = D.getSingleClause<OMPOrderClause>())
1915 if (C->getKind() == OMPC_ORDER_concurrent)
1916 LoopStack.setParallel(/*Enable=*/true);
Alexey Bataev58e5bdb2015-06-18 04:45:29 +00001917}
1918
Alexey Bataevef549a82016-03-09 09:49:09 +00001919void CodeGenFunction::EmitOMPSimdFinal(
1920 const OMPLoopDirective &D,
Alexey Bataevddf3db92018-04-13 17:31:06 +00001921 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001922 if (!HaveInsertPoint())
1923 return;
Alexey Bataevef549a82016-03-09 09:49:09 +00001924 llvm::BasicBlock *DoneBB = nullptr;
Alexey Bataev58e5bdb2015-06-18 04:45:29 +00001925 auto IC = D.counters().begin();
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001926 auto IPC = D.private_counters().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00001927 for (const Expr *F : D.finals()) {
1928 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>((*IC))->getDecl());
1929 const auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>((*IPC))->getDecl());
1930 const auto *CED = dyn_cast<OMPCapturedExprDecl>(OrigVD);
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001931 if (LocalDeclMap.count(OrigVD) || CapturedStmtInfo->lookup(OrigVD) ||
1932 OrigVD->hasGlobalStorage() || CED) {
Alexey Bataevef549a82016-03-09 09:49:09 +00001933 if (!DoneBB) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00001934 if (llvm::Value *Cond = CondGen(*this)) {
Alexey Bataevef549a82016-03-09 09:49:09 +00001935 // If the first post-update expression is found, emit conditional
1936 // block if it was requested.
Alexey Bataevddf3db92018-04-13 17:31:06 +00001937 llvm::BasicBlock *ThenBB = createBasicBlock(".omp.final.then");
Alexey Bataevef549a82016-03-09 09:49:09 +00001938 DoneBB = createBasicBlock(".omp.final.done");
1939 Builder.CreateCondBr(Cond, ThenBB, DoneBB);
1940 EmitBlock(ThenBB);
1941 }
1942 }
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001943 Address OrigAddr = Address::invalid();
Alexey Bataevab4ea222018-03-07 18:17:06 +00001944 if (CED) {
Akira Hatanakaf139ae32019-12-03 15:17:01 -08001945 OrigAddr =
1946 EmitLValue(CED->getInit()->IgnoreImpCasts()).getAddress(*this);
Alexey Bataevab4ea222018-03-07 18:17:06 +00001947 } else {
Bruno Ricci5fc4db72018-12-21 14:10:18 +00001948 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(PrivateVD),
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001949 /*RefersToEnclosingVariableOrCapture=*/false,
1950 (*IPC)->getType(), VK_LValue, (*IPC)->getExprLoc());
Akira Hatanakaf139ae32019-12-03 15:17:01 -08001951 OrigAddr = EmitLValue(&DRE).getAddress(*this);
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001952 }
Alexey Bataev58e5bdb2015-06-18 04:45:29 +00001953 OMPPrivateScope VarScope(*this);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001954 VarScope.addPrivate(OrigVD, [OrigAddr]() { return OrigAddr; });
Alexey Bataev58e5bdb2015-06-18 04:45:29 +00001955 (void)VarScope.Privatize();
1956 EmitIgnoredExpr(F);
1957 }
1958 ++IC;
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001959 ++IPC;
Alexey Bataev58e5bdb2015-06-18 04:45:29 +00001960 }
Alexey Bataevef549a82016-03-09 09:49:09 +00001961 if (DoneBB)
1962 EmitBlock(DoneBB, /*IsFinished=*/true);
Alexey Bataev58e5bdb2015-06-18 04:45:29 +00001963}
1964
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00001965static void emitOMPLoopBodyWithStopPoint(CodeGenFunction &CGF,
1966 const OMPLoopDirective &S,
1967 CodeGenFunction::JumpDest LoopExit) {
1968 CGF.EmitOMPLoopBody(S, LoopExit);
1969 CGF.EmitStopPoint(&S);
Hans Wennborged129ae2017-04-27 17:02:25 +00001970}
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00001971
Alexey Bataeva8a9153a2017-12-29 18:07:07 +00001972/// Emit a helper variable and return corresponding lvalue.
1973static LValue EmitOMPHelperVar(CodeGenFunction &CGF,
1974 const DeclRefExpr *Helper) {
1975 auto VDecl = cast<VarDecl>(Helper->getDecl());
1976 CGF.EmitVarDecl(*VDecl);
1977 return CGF.EmitLValue(Helper);
1978}
1979
Alexey Bataev103f3c9e2019-11-20 15:59:03 -05001980static void emitCommonSimdLoop(CodeGenFunction &CGF, const OMPLoopDirective &S,
1981 const RegionCodeGenTy &SimdInitGen,
1982 const RegionCodeGenTy &BodyCodeGen) {
Alexey Bataev0860db92019-12-19 10:01:10 -05001983 auto &&ThenGen = [&S, &SimdInitGen, &BodyCodeGen](CodeGenFunction &CGF,
1984 PrePostActionTy &) {
1985 CGOpenMPRuntime::NontemporalDeclsRAII NontemporalsRegion(CGF.CGM, S);
Alexey Bataev103f3c9e2019-11-20 15:59:03 -05001986 CodeGenFunction::OMPLocalDeclMapRAII Scope(CGF);
1987 SimdInitGen(CGF);
1988
1989 BodyCodeGen(CGF);
1990 };
1991 auto &&ElseGen = [&BodyCodeGen](CodeGenFunction &CGF, PrePostActionTy &) {
1992 CodeGenFunction::OMPLocalDeclMapRAII Scope(CGF);
1993 CGF.LoopStack.setVectorizeEnable(/*Enable=*/false);
1994
1995 BodyCodeGen(CGF);
1996 };
1997 const Expr *IfCond = nullptr;
Alexey Bataev18789bf2020-02-13 09:21:15 -05001998 if (isOpenMPSimdDirective(S.getDirectiveKind())) {
1999 for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
2000 if (CGF.getLangOpts().OpenMP >= 50 &&
2001 (C->getNameModifier() == OMPD_unknown ||
2002 C->getNameModifier() == OMPD_simd)) {
2003 IfCond = C->getCondition();
2004 break;
2005 }
Alexey Bataev103f3c9e2019-11-20 15:59:03 -05002006 }
2007 }
2008 if (IfCond) {
2009 CGF.CGM.getOpenMPRuntime().emitIfClause(CGF, IfCond, ThenGen, ElseGen);
2010 } else {
2011 RegionCodeGenTy ThenRCG(ThenGen);
2012 ThenRCG(CGF);
2013 }
2014}
2015
Alexey Bataevf8365372017-11-17 17:57:25 +00002016static void emitOMPSimdRegion(CodeGenFunction &CGF, const OMPLoopDirective &S,
2017 PrePostActionTy &Action) {
2018 Action.Enter(CGF);
2019 assert(isOpenMPSimdDirective(S.getDirectiveKind()) &&
2020 "Expected simd directive");
2021 OMPLoopScope PreInitScope(CGF, S);
2022 // if (PreCond) {
2023 // for (IV in 0..LastIteration) BODY;
2024 // <Final counter/linear vars updates>;
2025 // }
2026 //
Alexey Bataeva8a9153a2017-12-29 18:07:07 +00002027 if (isOpenMPDistributeDirective(S.getDirectiveKind()) ||
2028 isOpenMPWorksharingDirective(S.getDirectiveKind()) ||
2029 isOpenMPTaskLoopDirective(S.getDirectiveKind())) {
2030 (void)EmitOMPHelperVar(CGF, cast<DeclRefExpr>(S.getLowerBoundVariable()));
2031 (void)EmitOMPHelperVar(CGF, cast<DeclRefExpr>(S.getUpperBoundVariable()));
2032 }
Alexander Musmana5f070a2014-10-01 06:03:56 +00002033
Alexey Bataevf8365372017-11-17 17:57:25 +00002034 // Emit: if (PreCond) - begin.
2035 // If the condition constant folds and can be elided, avoid emitting the
2036 // whole loop.
2037 bool CondConstant;
2038 llvm::BasicBlock *ContBlock = nullptr;
2039 if (CGF.ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
2040 if (!CondConstant)
2041 return;
2042 } else {
Alexey Bataevddf3db92018-04-13 17:31:06 +00002043 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("simd.if.then");
Alexey Bataevf8365372017-11-17 17:57:25 +00002044 ContBlock = CGF.createBasicBlock("simd.if.end");
2045 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
2046 CGF.getProfileCount(&S));
2047 CGF.EmitBlock(ThenBlock);
2048 CGF.incrementProfileCounter(&S);
2049 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002050
Alexey Bataevf8365372017-11-17 17:57:25 +00002051 // Emit the loop iteration variable.
2052 const Expr *IVExpr = S.getIterationVariable();
Alexey Bataevddf3db92018-04-13 17:31:06 +00002053 const auto *IVDecl = cast<VarDecl>(cast<DeclRefExpr>(IVExpr)->getDecl());
Alexey Bataevf8365372017-11-17 17:57:25 +00002054 CGF.EmitVarDecl(*IVDecl);
2055 CGF.EmitIgnoredExpr(S.getInit());
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002056
Alexey Bataevf8365372017-11-17 17:57:25 +00002057 // Emit the iterations count variable.
2058 // If it is not a variable, Sema decided to calculate iterations count on
2059 // each iteration (e.g., it is foldable into a constant).
Alexey Bataevddf3db92018-04-13 17:31:06 +00002060 if (const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
Alexey Bataevf8365372017-11-17 17:57:25 +00002061 CGF.EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
2062 // Emit calculation of the iterations count.
2063 CGF.EmitIgnoredExpr(S.getCalcLastIteration());
2064 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002065
Alexey Bataevf8365372017-11-17 17:57:25 +00002066 emitAlignedClause(CGF, S);
2067 (void)CGF.EmitOMPLinearClauseInit(S);
2068 {
2069 CodeGenFunction::OMPPrivateScope LoopScope(CGF);
2070 CGF.EmitOMPPrivateLoopCounters(S, LoopScope);
2071 CGF.EmitOMPLinearClause(S, LoopScope);
2072 CGF.EmitOMPPrivateClause(S, LoopScope);
2073 CGF.EmitOMPReductionClauseInit(S, LoopScope);
Alexey Bataeva58da1a2019-12-27 09:44:43 -05002074 CGOpenMPRuntime::LastprivateConditionalRAII LPCRegion(
2075 CGF, S, CGF.EmitLValue(S.getIterationVariable()));
Alexey Bataevf8365372017-11-17 17:57:25 +00002076 bool HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
2077 (void)LoopScope.Privatize();
Alexey Bataev60705422018-10-30 15:50:12 +00002078 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()))
2079 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
Alexey Bataevd08c0562019-11-19 12:07:54 -05002080
Alexey Bataev103f3c9e2019-11-20 15:59:03 -05002081 emitCommonSimdLoop(
2082 CGF, S,
2083 [&S](CodeGenFunction &CGF, PrePostActionTy &) {
2084 CGF.EmitOMPSimdInit(S);
2085 },
2086 [&S, &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) {
2087 CGF.EmitOMPInnerLoop(
2088 S, LoopScope.requiresCleanups(), S.getCond(), S.getInc(),
2089 [&S](CodeGenFunction &CGF) {
2090 CGF.EmitOMPLoopBody(S, CodeGenFunction::JumpDest());
2091 CGF.EmitStopPoint(&S);
2092 },
2093 [](CodeGenFunction &) {});
2094 });
Alexey Bataevddf3db92018-04-13 17:31:06 +00002095 CGF.EmitOMPSimdFinal(S, [](CodeGenFunction &) { return nullptr; });
Alexey Bataevf8365372017-11-17 17:57:25 +00002096 // Emit final copy of the lastprivate variables at the end of loops.
2097 if (HasLastprivateClause)
2098 CGF.EmitOMPLastprivateClauseFinal(S, /*NoFinals=*/true);
2099 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_simd);
Alexey Bataevddf3db92018-04-13 17:31:06 +00002100 emitPostUpdateForReductionClause(CGF, S,
2101 [](CodeGenFunction &) { return nullptr; });
Alexey Bataevf8365372017-11-17 17:57:25 +00002102 }
Alexey Bataevddf3db92018-04-13 17:31:06 +00002103 CGF.EmitOMPLinearClauseFinal(S, [](CodeGenFunction &) { return nullptr; });
Alexey Bataevf8365372017-11-17 17:57:25 +00002104 // Emit: if (PreCond) - end.
2105 if (ContBlock) {
2106 CGF.EmitBranch(ContBlock);
2107 CGF.EmitBlock(ContBlock, true);
2108 }
2109}
2110
2111void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) {
2112 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
2113 emitOMPSimdRegion(CGF, S, Action);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002114 };
Alexey Bataev46978742020-01-30 10:46:11 -05002115 {
2116 auto LPCRegion =
2117 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
2118 OMPLexicalScope Scope(*this, S, OMPD_unknown);
2119 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen);
2120 }
2121 // Check for outer lastprivate conditional update.
2122 checkForLastprivateConditionalUpdate(*this, S);
Alexander Musman515ad8c2014-05-22 08:54:05 +00002123}
2124
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002125void CodeGenFunction::EmitOMPOuterLoop(
2126 bool DynamicOrOrdered, bool IsMonotonic, const OMPLoopDirective &S,
2127 CodeGenFunction::OMPPrivateScope &LoopScope,
2128 const CodeGenFunction::OMPLoopArguments &LoopArgs,
2129 const CodeGenFunction::CodeGenLoopTy &CodeGenLoop,
2130 const CodeGenFunction::CodeGenOrderedTy &CodeGenOrdered) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00002131 CGOpenMPRuntime &RT = CGM.getOpenMPRuntime();
Alexander Musman92bdaab2015-03-12 13:37:50 +00002132
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002133 const Expr *IVExpr = S.getIterationVariable();
2134 const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
2135 const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
2136
Alexey Bataevddf3db92018-04-13 17:31:06 +00002137 JumpDest LoopExit = getJumpDestInCurrentScope("omp.dispatch.end");
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002138
2139 // Start the loop with a block that tests the condition.
Alexey Bataevddf3db92018-04-13 17:31:06 +00002140 llvm::BasicBlock *CondBlock = createBasicBlock("omp.dispatch.cond");
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002141 EmitBlock(CondBlock);
Alexey Bataevddf3db92018-04-13 17:31:06 +00002142 const SourceRange R = S.getSourceRange();
Amara Emerson652795d2016-11-10 14:44:30 +00002143 LoopStack.push(CondBlock, SourceLocToDebugLoc(R.getBegin()),
2144 SourceLocToDebugLoc(R.getEnd()));
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002145
2146 llvm::Value *BoolCondVal = nullptr;
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002147 if (!DynamicOrOrdered) {
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002148 // UB = min(UB, GlobalUB) or
2149 // UB = min(UB, PrevUB) for combined loop sharing constructs (e.g.
2150 // 'distribute parallel for')
2151 EmitIgnoredExpr(LoopArgs.EUB);
Alexander Musman92bdaab2015-03-12 13:37:50 +00002152 // IV = LB
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002153 EmitIgnoredExpr(LoopArgs.Init);
Alexander Musman92bdaab2015-03-12 13:37:50 +00002154 // IV < UB
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002155 BoolCondVal = EvaluateExprAsBool(LoopArgs.Cond);
Alexander Musman92bdaab2015-03-12 13:37:50 +00002156 } else {
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002157 BoolCondVal =
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002158 RT.emitForNext(*this, S.getBeginLoc(), IVSize, IVSigned, LoopArgs.IL,
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002159 LoopArgs.LB, LoopArgs.UB, LoopArgs.ST);
Alexander Musman92bdaab2015-03-12 13:37:50 +00002160 }
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002161
2162 // If there are any cleanups between here and the loop-exit scope,
2163 // create a block to stage a loop exit along.
Alexey Bataevddf3db92018-04-13 17:31:06 +00002164 llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002165 if (LoopScope.requiresCleanups())
2166 ExitBlock = createBasicBlock("omp.dispatch.cleanup");
2167
Alexey Bataevddf3db92018-04-13 17:31:06 +00002168 llvm::BasicBlock *LoopBody = createBasicBlock("omp.dispatch.body");
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002169 Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock);
2170 if (ExitBlock != LoopExit.getBlock()) {
2171 EmitBlock(ExitBlock);
2172 EmitBranchThroughCleanup(LoopExit);
2173 }
2174 EmitBlock(LoopBody);
2175
Alexander Musman92bdaab2015-03-12 13:37:50 +00002176 // Emit "IV = LB" (in case of static schedule, we have already calculated new
2177 // LB for loop condition and emitted it above).
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002178 if (DynamicOrOrdered)
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002179 EmitIgnoredExpr(LoopArgs.Init);
Alexander Musman92bdaab2015-03-12 13:37:50 +00002180
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002181 // Create a block for the increment.
Alexey Bataevddf3db92018-04-13 17:31:06 +00002182 JumpDest Continue = getJumpDestInCurrentScope("omp.dispatch.inc");
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002183 BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
2184
Alexey Bataev103f3c9e2019-11-20 15:59:03 -05002185 emitCommonSimdLoop(
2186 *this, S,
2187 [&S, IsMonotonic](CodeGenFunction &CGF, PrePostActionTy &) {
2188 // Generate !llvm.loop.parallel metadata for loads and stores for loops
2189 // with dynamic/guided scheduling and without ordered clause.
Alexey Bataeva7815212020-02-03 12:08:16 -05002190 if (!isOpenMPSimdDirective(S.getDirectiveKind())) {
Alexey Bataev103f3c9e2019-11-20 15:59:03 -05002191 CGF.LoopStack.setParallel(!IsMonotonic);
Alexey Bataeva7815212020-02-03 12:08:16 -05002192 if (const auto *C = S.getSingleClause<OMPOrderClause>())
2193 if (C->getKind() == OMPC_ORDER_concurrent)
2194 CGF.LoopStack.setParallel(/*Enable=*/true);
2195 } else {
Alexey Bataev103f3c9e2019-11-20 15:59:03 -05002196 CGF.EmitOMPSimdInit(S, IsMonotonic);
Alexey Bataeva7815212020-02-03 12:08:16 -05002197 }
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002198 },
Alexey Bataev103f3c9e2019-11-20 15:59:03 -05002199 [&S, &LoopArgs, LoopExit, &CodeGenLoop, IVSize, IVSigned, &CodeGenOrdered,
2200 &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) {
2201 SourceLocation Loc = S.getBeginLoc();
2202 // when 'distribute' is not combined with a 'for':
2203 // while (idx <= UB) { BODY; ++idx; }
2204 // when 'distribute' is combined with a 'for'
2205 // (e.g. 'distribute parallel for')
2206 // while (idx <= UB) { <CodeGen rest of pragma>; idx += ST; }
2207 CGF.EmitOMPInnerLoop(
2208 S, LoopScope.requiresCleanups(), LoopArgs.Cond, LoopArgs.IncExpr,
2209 [&S, LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
2210 CodeGenLoop(CGF, S, LoopExit);
2211 },
2212 [IVSize, IVSigned, Loc, &CodeGenOrdered](CodeGenFunction &CGF) {
2213 CodeGenOrdered(CGF, Loc, IVSize, IVSigned);
2214 });
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002215 });
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002216
2217 EmitBlock(Continue.getBlock());
2218 BreakContinueStack.pop_back();
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002219 if (!DynamicOrOrdered) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00002220 // Emit "LB = LB + Stride", "UB = UB + Stride".
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002221 EmitIgnoredExpr(LoopArgs.NextLB);
2222 EmitIgnoredExpr(LoopArgs.NextUB);
Alexander Musman92bdaab2015-03-12 13:37:50 +00002223 }
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002224
2225 EmitBranch(CondBlock);
2226 LoopStack.pop();
2227 // Emit the fall-through block.
2228 EmitBlock(LoopExit.getBlock());
2229
2230 // Tell the runtime we are done.
Alexey Bataev957d8562016-11-17 15:12:05 +00002231 auto &&CodeGen = [DynamicOrOrdered, &S](CodeGenFunction &CGF) {
2232 if (!DynamicOrOrdered)
Stephen Kelly1c301dc2018-08-09 21:09:38 +00002233 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
Alexey Bataevf43f7142017-09-06 16:17:35 +00002234 S.getDirectiveKind());
Alexey Bataev957d8562016-11-17 15:12:05 +00002235 };
2236 OMPCancelStack.emitExit(*this, S.getDirectiveKind(), CodeGen);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002237}
2238
2239void CodeGenFunction::EmitOMPForOuterLoop(
Alexey Bataev9ebd7422016-05-10 09:57:36 +00002240 const OpenMPScheduleTy &ScheduleKind, bool IsMonotonic,
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002241 const OMPLoopDirective &S, OMPPrivateScope &LoopScope, bool Ordered,
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002242 const OMPLoopArguments &LoopArgs,
2243 const CodeGenDispatchBoundsTy &CGDispatchBounds) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00002244 CGOpenMPRuntime &RT = CGM.getOpenMPRuntime();
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002245
2246 // Dynamic scheduling of the outer loop (dynamic, guided, auto, runtime).
Alexey Bataev9ebd7422016-05-10 09:57:36 +00002247 const bool DynamicOrOrdered =
2248 Ordered || RT.isDynamic(ScheduleKind.Schedule);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002249
2250 assert((Ordered ||
Alexey Bataev9ebd7422016-05-10 09:57:36 +00002251 !RT.isStaticNonchunked(ScheduleKind.Schedule,
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002252 LoopArgs.Chunk != nullptr)) &&
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002253 "static non-chunked schedule does not need outer loop");
2254
2255 // Emit outer loop.
2256 //
2257 // OpenMP [2.7.1, Loop Construct, Description, table 2-1]
2258 // When schedule(dynamic,chunk_size) is specified, the iterations are
2259 // distributed to threads in the team in chunks as the threads request them.
2260 // Each thread executes a chunk of iterations, then requests another chunk,
2261 // until no chunks remain to be distributed. Each chunk contains chunk_size
2262 // iterations, except for the last chunk to be distributed, which may have
2263 // fewer iterations. When no chunk_size is specified, it defaults to 1.
2264 //
2265 // When schedule(guided,chunk_size) is specified, the iterations are assigned
2266 // to threads in the team in chunks as the executing threads request them.
2267 // Each thread executes a chunk of iterations, then requests another chunk,
2268 // until no chunks remain to be assigned. For a chunk_size of 1, the size of
2269 // each chunk is proportional to the number of unassigned iterations divided
2270 // by the number of threads in the team, decreasing to 1. For a chunk_size
2271 // with value k (greater than 1), the size of each chunk is determined in the
2272 // same way, with the restriction that the chunks do not contain fewer than k
2273 // iterations (except for the last chunk to be assigned, which may have fewer
2274 // than k iterations).
2275 //
2276 // When schedule(auto) is specified, the decision regarding scheduling is
2277 // delegated to the compiler and/or runtime system. The programmer gives the
2278 // implementation the freedom to choose any possible mapping of iterations to
2279 // threads in the team.
2280 //
2281 // When schedule(runtime) is specified, the decision regarding scheduling is
2282 // deferred until run time, and the schedule and chunk size are taken from the
2283 // run-sched-var ICV. If the ICV is set to auto, the schedule is
2284 // implementation defined
2285 //
2286 // while(__kmpc_dispatch_next(&LB, &UB)) {
2287 // idx = LB;
2288 // while (idx <= UB) { BODY; ++idx;
2289 // __kmpc_dispatch_fini_(4|8)[u](); // For ordered loops only.
2290 // } // inner loop
2291 // }
2292 //
2293 // OpenMP [2.7.1, Loop Construct, Description, table 2-1]
2294 // When schedule(static, chunk_size) is specified, iterations are divided into
2295 // chunks of size chunk_size, and the chunks are assigned to the threads in
2296 // the team in a round-robin fashion in the order of the thread number.
2297 //
2298 // while(UB = min(UB, GlobalUB), idx = LB, idx < UB) {
2299 // while (idx <= UB) { BODY; ++idx; } // inner loop
2300 // LB = LB + ST;
2301 // UB = UB + ST;
2302 // }
2303 //
2304
2305 const Expr *IVExpr = S.getIterationVariable();
2306 const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
2307 const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
2308
2309 if (DynamicOrOrdered) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00002310 const std::pair<llvm::Value *, llvm::Value *> DispatchBounds =
2311 CGDispatchBounds(*this, S, LoopArgs.LB, LoopArgs.UB);
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002312 llvm::Value *LBVal = DispatchBounds.first;
2313 llvm::Value *UBVal = DispatchBounds.second;
2314 CGOpenMPRuntime::DispatchRTInput DipatchRTInputValues = {LBVal, UBVal,
2315 LoopArgs.Chunk};
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002316 RT.emitForDispatchInit(*this, S.getBeginLoc(), ScheduleKind, IVSize,
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002317 IVSigned, Ordered, DipatchRTInputValues);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002318 } else {
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00002319 CGOpenMPRuntime::StaticRTInput StaticInit(
2320 IVSize, IVSigned, Ordered, LoopArgs.IL, LoopArgs.LB, LoopArgs.UB,
2321 LoopArgs.ST, LoopArgs.Chunk);
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002322 RT.emitForStaticInit(*this, S.getBeginLoc(), S.getDirectiveKind(),
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00002323 ScheduleKind, StaticInit);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002324 }
2325
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002326 auto &&CodeGenOrdered = [Ordered](CodeGenFunction &CGF, SourceLocation Loc,
2327 const unsigned IVSize,
2328 const bool IVSigned) {
2329 if (Ordered) {
2330 CGF.CGM.getOpenMPRuntime().emitForOrderedIterationEnd(CGF, Loc, IVSize,
2331 IVSigned);
2332 }
2333 };
2334
2335 OMPLoopArguments OuterLoopArgs(LoopArgs.LB, LoopArgs.UB, LoopArgs.ST,
2336 LoopArgs.IL, LoopArgs.Chunk, LoopArgs.EUB);
2337 OuterLoopArgs.IncExpr = S.getInc();
2338 OuterLoopArgs.Init = S.getInit();
2339 OuterLoopArgs.Cond = S.getCond();
2340 OuterLoopArgs.NextLB = S.getNextLowerBound();
2341 OuterLoopArgs.NextUB = S.getNextUpperBound();
2342 EmitOMPOuterLoop(DynamicOrOrdered, IsMonotonic, S, LoopScope, OuterLoopArgs,
2343 emitOMPLoopBodyWithStopPoint, CodeGenOrdered);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002344}
2345
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002346static void emitEmptyOrdered(CodeGenFunction &, SourceLocation Loc,
2347 const unsigned IVSize, const bool IVSigned) {}
2348
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002349void CodeGenFunction::EmitOMPDistributeOuterLoop(
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002350 OpenMPDistScheduleClauseKind ScheduleKind, const OMPLoopDirective &S,
2351 OMPPrivateScope &LoopScope, const OMPLoopArguments &LoopArgs,
2352 const CodeGenLoopTy &CodeGenLoopContent) {
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002353
Alexey Bataevddf3db92018-04-13 17:31:06 +00002354 CGOpenMPRuntime &RT = CGM.getOpenMPRuntime();
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002355
2356 // Emit outer loop.
2357 // Same behavior as a OMPForOuterLoop, except that schedule cannot be
2358 // dynamic
2359 //
2360
2361 const Expr *IVExpr = S.getIterationVariable();
2362 const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
2363 const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
2364
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00002365 CGOpenMPRuntime::StaticRTInput StaticInit(
2366 IVSize, IVSigned, /* Ordered = */ false, LoopArgs.IL, LoopArgs.LB,
2367 LoopArgs.UB, LoopArgs.ST, LoopArgs.Chunk);
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002368 RT.emitDistributeStaticInit(*this, S.getBeginLoc(), ScheduleKind, StaticInit);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002369
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002370 // for combined 'distribute' and 'for' the increment expression of distribute
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00002371 // is stored in DistInc. For 'distribute' alone, it is in Inc.
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002372 Expr *IncExpr;
2373 if (isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()))
2374 IncExpr = S.getDistInc();
2375 else
2376 IncExpr = S.getInc();
2377
2378 // this routine is shared by 'omp distribute parallel for' and
2379 // 'omp distribute': select the right EUB expression depending on the
2380 // directive
2381 OMPLoopArguments OuterLoopArgs;
2382 OuterLoopArgs.LB = LoopArgs.LB;
2383 OuterLoopArgs.UB = LoopArgs.UB;
2384 OuterLoopArgs.ST = LoopArgs.ST;
2385 OuterLoopArgs.IL = LoopArgs.IL;
2386 OuterLoopArgs.Chunk = LoopArgs.Chunk;
2387 OuterLoopArgs.EUB = isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
2388 ? S.getCombinedEnsureUpperBound()
2389 : S.getEnsureUpperBound();
2390 OuterLoopArgs.IncExpr = IncExpr;
2391 OuterLoopArgs.Init = isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
2392 ? S.getCombinedInit()
2393 : S.getInit();
2394 OuterLoopArgs.Cond = isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
2395 ? S.getCombinedCond()
2396 : S.getCond();
2397 OuterLoopArgs.NextLB = isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
2398 ? S.getCombinedNextLowerBound()
2399 : S.getNextLowerBound();
2400 OuterLoopArgs.NextUB = isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
2401 ? S.getCombinedNextUpperBound()
2402 : S.getNextUpperBound();
2403
2404 EmitOMPOuterLoop(/* DynamicOrOrdered = */ false, /* IsMonotonic = */ false, S,
2405 LoopScope, OuterLoopArgs, CodeGenLoopContent,
2406 emitEmptyOrdered);
2407}
2408
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002409static std::pair<LValue, LValue>
2410emitDistributeParallelForInnerBounds(CodeGenFunction &CGF,
2411 const OMPExecutableDirective &S) {
2412 const OMPLoopDirective &LS = cast<OMPLoopDirective>(S);
2413 LValue LB =
2414 EmitOMPHelperVar(CGF, cast<DeclRefExpr>(LS.getLowerBoundVariable()));
2415 LValue UB =
2416 EmitOMPHelperVar(CGF, cast<DeclRefExpr>(LS.getUpperBoundVariable()));
2417
2418 // When composing 'distribute' with 'for' (e.g. as in 'distribute
2419 // parallel for') we need to use the 'distribute'
2420 // chunk lower and upper bounds rather than the whole loop iteration
2421 // space. These are parameters to the outlined function for 'parallel'
2422 // and we copy the bounds of the previous schedule into the
2423 // the current ones.
2424 LValue PrevLB = CGF.EmitLValue(LS.getPrevLowerBoundVariable());
2425 LValue PrevUB = CGF.EmitLValue(LS.getPrevUpperBoundVariable());
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00002426 llvm::Value *PrevLBVal = CGF.EmitLoadOfScalar(
2427 PrevLB, LS.getPrevLowerBoundVariable()->getExprLoc());
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002428 PrevLBVal = CGF.EmitScalarConversion(
2429 PrevLBVal, LS.getPrevLowerBoundVariable()->getType(),
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00002430 LS.getIterationVariable()->getType(),
2431 LS.getPrevLowerBoundVariable()->getExprLoc());
2432 llvm::Value *PrevUBVal = CGF.EmitLoadOfScalar(
2433 PrevUB, LS.getPrevUpperBoundVariable()->getExprLoc());
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002434 PrevUBVal = CGF.EmitScalarConversion(
2435 PrevUBVal, LS.getPrevUpperBoundVariable()->getType(),
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00002436 LS.getIterationVariable()->getType(),
2437 LS.getPrevUpperBoundVariable()->getExprLoc());
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002438
2439 CGF.EmitStoreOfScalar(PrevLBVal, LB);
2440 CGF.EmitStoreOfScalar(PrevUBVal, UB);
2441
2442 return {LB, UB};
2443}
2444
2445/// if the 'for' loop has a dispatch schedule (e.g. dynamic, guided) then
2446/// we need to use the LB and UB expressions generated by the worksharing
2447/// code generation support, whereas in non combined situations we would
2448/// just emit 0 and the LastIteration expression
2449/// This function is necessary due to the difference of the LB and UB
2450/// types for the RT emission routines for 'for_static_init' and
2451/// 'for_dispatch_init'
2452static std::pair<llvm::Value *, llvm::Value *>
2453emitDistributeParallelForDispatchBounds(CodeGenFunction &CGF,
2454 const OMPExecutableDirective &S,
2455 Address LB, Address UB) {
2456 const OMPLoopDirective &LS = cast<OMPLoopDirective>(S);
2457 const Expr *IVExpr = LS.getIterationVariable();
2458 // when implementing a dynamic schedule for a 'for' combined with a
2459 // 'distribute' (e.g. 'distribute parallel for'), the 'for' loop
2460 // is not normalized as each team only executes its own assigned
2461 // distribute chunk
2462 QualType IteratorTy = IVExpr->getType();
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00002463 llvm::Value *LBVal =
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002464 CGF.EmitLoadOfScalar(LB, /*Volatile=*/false, IteratorTy, S.getBeginLoc());
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00002465 llvm::Value *UBVal =
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002466 CGF.EmitLoadOfScalar(UB, /*Volatile=*/false, IteratorTy, S.getBeginLoc());
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002467 return {LBVal, UBVal};
Hans Wennborged129ae2017-04-27 17:02:25 +00002468}
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002469
2470static void emitDistributeParallelForDistributeInnerBoundParams(
2471 CodeGenFunction &CGF, const OMPExecutableDirective &S,
2472 llvm::SmallVectorImpl<llvm::Value *> &CapturedVars) {
2473 const auto &Dir = cast<OMPLoopDirective>(S);
2474 LValue LB =
2475 CGF.EmitLValue(cast<DeclRefExpr>(Dir.getCombinedLowerBoundVariable()));
Akira Hatanakaf139ae32019-12-03 15:17:01 -08002476 llvm::Value *LBCast =
2477 CGF.Builder.CreateIntCast(CGF.Builder.CreateLoad(LB.getAddress(CGF)),
2478 CGF.SizeTy, /*isSigned=*/false);
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002479 CapturedVars.push_back(LBCast);
2480 LValue UB =
2481 CGF.EmitLValue(cast<DeclRefExpr>(Dir.getCombinedUpperBoundVariable()));
2482
Akira Hatanakaf139ae32019-12-03 15:17:01 -08002483 llvm::Value *UBCast =
2484 CGF.Builder.CreateIntCast(CGF.Builder.CreateLoad(UB.getAddress(CGF)),
2485 CGF.SizeTy, /*isSigned=*/false);
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002486 CapturedVars.push_back(UBCast);
Hans Wennborged129ae2017-04-27 17:02:25 +00002487}
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002488
2489static void
2490emitInnerParallelForWhenCombined(CodeGenFunction &CGF,
2491 const OMPLoopDirective &S,
2492 CodeGenFunction::JumpDest LoopExit) {
2493 auto &&CGInlinedWorksharingLoop = [&S](CodeGenFunction &CGF,
Alexey Bataevc99042b2018-03-15 18:10:54 +00002494 PrePostActionTy &Action) {
2495 Action.Enter(CGF);
Alexey Bataevdcb4b8fb2017-11-22 20:19:50 +00002496 bool HasCancel = false;
2497 if (!isOpenMPSimdDirective(S.getDirectiveKind())) {
2498 if (const auto *D = dyn_cast<OMPTeamsDistributeParallelForDirective>(&S))
2499 HasCancel = D->hasCancel();
2500 else if (const auto *D = dyn_cast<OMPDistributeParallelForDirective>(&S))
2501 HasCancel = D->hasCancel();
Alexey Bataev16e79882017-11-22 21:12:03 +00002502 else if (const auto *D =
2503 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&S))
2504 HasCancel = D->hasCancel();
Alexey Bataevdcb4b8fb2017-11-22 20:19:50 +00002505 }
2506 CodeGenFunction::OMPCancelStackRAII CancelRegion(CGF, S.getDirectiveKind(),
2507 HasCancel);
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002508 CGF.EmitOMPWorksharingLoop(S, S.getPrevEnsureUpperBound(),
2509 emitDistributeParallelForInnerBounds,
2510 emitDistributeParallelForDispatchBounds);
2511 };
2512
2513 emitCommonOMPParallelDirective(
Alexey Bataevdcb4b8fb2017-11-22 20:19:50 +00002514 CGF, S,
2515 isOpenMPSimdDirective(S.getDirectiveKind()) ? OMPD_for_simd : OMPD_for,
2516 CGInlinedWorksharingLoop,
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002517 emitDistributeParallelForDistributeInnerBoundParams);
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002518}
2519
Carlo Bertolli9925f152016-06-27 14:55:37 +00002520void CodeGenFunction::EmitOMPDistributeParallelForDirective(
2521 const OMPDistributeParallelForDirective &S) {
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002522 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
2523 CGF.EmitOMPDistributeLoop(S, emitInnerParallelForWhenCombined,
2524 S.getDistInc());
2525 };
Alexey Bataev475a7442018-01-12 19:39:11 +00002526 OMPLexicalScope Scope(*this, S, OMPD_parallel);
Alexey Bataev10a54312017-11-27 16:54:08 +00002527 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_distribute, CodeGen);
Carlo Bertolli9925f152016-06-27 14:55:37 +00002528}
2529
Kelvin Li4a39add2016-07-05 05:00:15 +00002530void CodeGenFunction::EmitOMPDistributeParallelForSimdDirective(
2531 const OMPDistributeParallelForSimdDirective &S) {
Alexey Bataev0b49f9e2017-11-27 19:38:58 +00002532 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
2533 CGF.EmitOMPDistributeLoop(S, emitInnerParallelForWhenCombined,
2534 S.getDistInc());
2535 };
Alexey Bataev475a7442018-01-12 19:39:11 +00002536 OMPLexicalScope Scope(*this, S, OMPD_parallel);
Alexey Bataev0b49f9e2017-11-27 19:38:58 +00002537 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_distribute, CodeGen);
Kelvin Li4a39add2016-07-05 05:00:15 +00002538}
Kelvin Li787f3fc2016-07-06 04:45:38 +00002539
2540void CodeGenFunction::EmitOMPDistributeSimdDirective(
2541 const OMPDistributeSimdDirective &S) {
Alexey Bataev617db5f2017-12-04 15:38:33 +00002542 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
2543 CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc());
2544 };
Alexey Bataev475a7442018-01-12 19:39:11 +00002545 OMPLexicalScope Scope(*this, S, OMPD_unknown);
Alexey Bataev617db5f2017-12-04 15:38:33 +00002546 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen);
Kelvin Li787f3fc2016-07-06 04:45:38 +00002547}
2548
Alexey Bataevf8365372017-11-17 17:57:25 +00002549void CodeGenFunction::EmitOMPTargetSimdDeviceFunction(
2550 CodeGenModule &CGM, StringRef ParentName, const OMPTargetSimdDirective &S) {
2551 // Emit SPMD target parallel for region as a standalone region.
2552 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
2553 emitOMPSimdRegion(CGF, S, Action);
2554 };
2555 llvm::Function *Fn;
2556 llvm::Constant *Addr;
2557 // Emit target region as a standalone region.
2558 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
2559 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
2560 assert(Fn && Addr && "Target device function emission failed.");
2561}
2562
Kelvin Li986330c2016-07-20 22:57:10 +00002563void CodeGenFunction::EmitOMPTargetSimdDirective(
2564 const OMPTargetSimdDirective &S) {
Alexey Bataevf8365372017-11-17 17:57:25 +00002565 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
2566 emitOMPSimdRegion(CGF, S, Action);
2567 };
2568 emitCommonOMPTargetDirective(*this, S, CodeGen);
Kelvin Li986330c2016-07-20 22:57:10 +00002569}
2570
Alexey Bataeva6f2a142015-12-31 06:52:34 +00002571namespace {
2572 struct ScheduleKindModifiersTy {
2573 OpenMPScheduleClauseKind Kind;
2574 OpenMPScheduleClauseModifier M1;
2575 OpenMPScheduleClauseModifier M2;
2576 ScheduleKindModifiersTy(OpenMPScheduleClauseKind Kind,
2577 OpenMPScheduleClauseModifier M1,
2578 OpenMPScheduleClauseModifier M2)
2579 : Kind(Kind), M1(M1), M2(M2) {}
2580 };
2581} // namespace
2582
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002583bool CodeGenFunction::EmitOMPWorksharingLoop(
2584 const OMPLoopDirective &S, Expr *EUB,
2585 const CodeGenLoopBoundsTy &CodeGenLoopBounds,
2586 const CodeGenDispatchBoundsTy &CGDispatchBounds) {
Alexander Musmanc6388682014-12-15 07:07:06 +00002587 // Emit the loop iteration variable.
Alexey Bataevddf3db92018-04-13 17:31:06 +00002588 const auto *IVExpr = cast<DeclRefExpr>(S.getIterationVariable());
2589 const auto *IVDecl = cast<VarDecl>(IVExpr->getDecl());
Alexander Musmanc6388682014-12-15 07:07:06 +00002590 EmitVarDecl(*IVDecl);
2591
2592 // Emit the iterations count variable.
2593 // If it is not a variable, Sema decided to calculate iterations count on each
2594 // iteration (e.g., it is foldable into a constant).
Alexey Bataevddf3db92018-04-13 17:31:06 +00002595 if (const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
Alexander Musmanc6388682014-12-15 07:07:06 +00002596 EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
2597 // Emit calculation of the iterations count.
2598 EmitIgnoredExpr(S.getCalcLastIteration());
2599 }
2600
Alexey Bataevddf3db92018-04-13 17:31:06 +00002601 CGOpenMPRuntime &RT = CGM.getOpenMPRuntime();
Alexander Musmanc6388682014-12-15 07:07:06 +00002602
Alexey Bataev38e89532015-04-16 04:54:05 +00002603 bool HasLastprivateClause;
Alexander Musmanc6388682014-12-15 07:07:06 +00002604 // Check pre-condition.
2605 {
Alexey Bataev5a3af132016-03-29 08:58:54 +00002606 OMPLoopScope PreInitScope(*this, S);
Alexander Musmanc6388682014-12-15 07:07:06 +00002607 // Skip the entire loop if we don't meet the precondition.
Alexey Bataev62dbb972015-04-22 11:59:37 +00002608 // If the condition constant folds and can be elided, avoid emitting the
2609 // whole loop.
2610 bool CondConstant;
2611 llvm::BasicBlock *ContBlock = nullptr;
2612 if (ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
2613 if (!CondConstant)
2614 return false;
2615 } else {
Alexey Bataevddf3db92018-04-13 17:31:06 +00002616 llvm::BasicBlock *ThenBlock = createBasicBlock("omp.precond.then");
Alexey Bataev62dbb972015-04-22 11:59:37 +00002617 ContBlock = createBasicBlock("omp.precond.end");
2618 emitPreCond(*this, S, S.getPreCond(), ThenBlock, ContBlock,
Justin Bogner66242d62015-04-23 23:06:47 +00002619 getProfileCount(&S));
Alexey Bataev62dbb972015-04-22 11:59:37 +00002620 EmitBlock(ThenBlock);
Justin Bogner66242d62015-04-23 23:06:47 +00002621 incrementProfileCounter(&S);
Alexey Bataev62dbb972015-04-22 11:59:37 +00002622 }
Alexey Bataev58e5bdb2015-06-18 04:45:29 +00002623
Alexey Bataevea33dee2018-02-15 23:39:43 +00002624 RunCleanupsScope DoacrossCleanupScope(*this);
Alexey Bataev8b427062016-05-25 12:36:08 +00002625 bool Ordered = false;
Alexey Bataevddf3db92018-04-13 17:31:06 +00002626 if (const auto *OrderedClause = S.getSingleClause<OMPOrderedClause>()) {
Alexey Bataev8b427062016-05-25 12:36:08 +00002627 if (OrderedClause->getNumForLoops())
Alexey Bataevf138fda2018-08-13 19:04:24 +00002628 RT.emitDoacrossInit(*this, S, OrderedClause->getLoopNumIterations());
Alexey Bataev8b427062016-05-25 12:36:08 +00002629 else
2630 Ordered = true;
2631 }
2632
Alexey Bataev5dff95c2016-04-22 03:56:56 +00002633 llvm::DenseSet<const Expr *> EmittedFinals;
Alexey Bataev58e5bdb2015-06-18 04:45:29 +00002634 emitAlignedClause(*this, S);
Alexey Bataev8c3edfe2017-08-16 15:58:46 +00002635 bool HasLinears = EmitOMPLinearClauseInit(S);
Alexey Bataevef549a82016-03-09 09:49:09 +00002636 // Emit helper vars inits.
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002637
2638 std::pair<LValue, LValue> Bounds = CodeGenLoopBounds(*this, S);
2639 LValue LB = Bounds.first;
2640 LValue UB = Bounds.second;
Alexey Bataevef549a82016-03-09 09:49:09 +00002641 LValue ST =
2642 EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getStrideVariable()));
2643 LValue IL =
2644 EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getIsLastIterVariable()));
2645
Alexander Musmanc6388682014-12-15 07:07:06 +00002646 // Emit 'then' code.
2647 {
Alexander Musmanc6388682014-12-15 07:07:06 +00002648 OMPPrivateScope LoopScope(*this);
Alexey Bataev8c3edfe2017-08-16 15:58:46 +00002649 if (EmitOMPFirstprivateClause(S, LoopScope) || HasLinears) {
Alexey Bataev69c62a92015-04-15 04:52:20 +00002650 // Emit implicit barrier to synchronize threads and avoid data races on
Alexey Bataevcd8b6a22016-02-15 08:07:17 +00002651 // initialization of firstprivate variables and post-update of
2652 // lastprivate variables.
Alexey Bataev25e5b442015-09-15 12:52:43 +00002653 CGM.getOpenMPRuntime().emitBarrierCall(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002654 *this, S.getBeginLoc(), OMPD_unknown, /*EmitChecks=*/false,
Alexey Bataev25e5b442015-09-15 12:52:43 +00002655 /*ForceSimpleCall=*/true);
Alexey Bataev69c62a92015-04-15 04:52:20 +00002656 }
Alexey Bataev50a64582015-04-22 12:24:45 +00002657 EmitOMPPrivateClause(S, LoopScope);
Alexey Bataeva58da1a2019-12-27 09:44:43 -05002658 CGOpenMPRuntime::LastprivateConditionalRAII LPCRegion(
2659 *this, S, EmitLValue(S.getIterationVariable()));
Alexey Bataev38e89532015-04-16 04:54:05 +00002660 HasLastprivateClause = EmitOMPLastprivateClauseInit(S, LoopScope);
Alexey Bataev7ebe5fd2015-04-22 13:43:03 +00002661 EmitOMPReductionClauseInit(S, LoopScope);
Alexey Bataev5dff95c2016-04-22 03:56:56 +00002662 EmitOMPPrivateLoopCounters(S, LoopScope);
2663 EmitOMPLinearClause(S, LoopScope);
Alexander Musman7931b982015-03-16 07:14:41 +00002664 (void)LoopScope.Privatize();
Alexey Bataev60705422018-10-30 15:50:12 +00002665 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()))
2666 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*this, S);
Alexander Musmanc6388682014-12-15 07:07:06 +00002667
2668 // Detect the loop schedule kind and chunk.
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00002669 const Expr *ChunkExpr = nullptr;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00002670 OpenMPScheduleTy ScheduleKind;
Alexey Bataevddf3db92018-04-13 17:31:06 +00002671 if (const auto *C = S.getSingleClause<OMPScheduleClause>()) {
Alexey Bataev9ebd7422016-05-10 09:57:36 +00002672 ScheduleKind.Schedule = C->getScheduleKind();
2673 ScheduleKind.M1 = C->getFirstScheduleModifier();
2674 ScheduleKind.M2 = C->getSecondScheduleModifier();
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00002675 ChunkExpr = C->getChunkSize();
Gheorghe-Teodor Bercea8233af92018-09-27 20:29:00 +00002676 } else {
2677 // Default behaviour for schedule clause.
2678 CGM.getOpenMPRuntime().getDefaultScheduleAndChunk(
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00002679 *this, S, ScheduleKind.Schedule, ChunkExpr);
2680 }
2681 bool HasChunkSizeOne = false;
2682 llvm::Value *Chunk = nullptr;
2683 if (ChunkExpr) {
2684 Chunk = EmitScalarExpr(ChunkExpr);
2685 Chunk = EmitScalarConversion(Chunk, ChunkExpr->getType(),
2686 S.getIterationVariable()->getType(),
2687 S.getBeginLoc());
Fangrui Song407659a2018-11-30 23:41:18 +00002688 Expr::EvalResult Result;
2689 if (ChunkExpr->EvaluateAsInt(Result, getContext())) {
2690 llvm::APSInt EvaluatedChunk = Result.Val.getInt();
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00002691 HasChunkSizeOne = (EvaluatedChunk.getLimitedValue() == 1);
Fangrui Song407659a2018-11-30 23:41:18 +00002692 }
Alexey Bataev3392d762016-02-16 11:18:12 +00002693 }
Alexander Musmanc6388682014-12-15 07:07:06 +00002694 const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
2695 const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
Alexey Bataeva6f2a142015-12-31 06:52:34 +00002696 // OpenMP 4.5, 2.7.1 Loop Construct, Description.
2697 // If the static schedule kind is specified or if the ordered clause is
2698 // specified, and if no monotonic modifier is specified, the effect will
2699 // be as if the monotonic modifier was specified.
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00002700 bool StaticChunkedOne = RT.isStaticChunked(ScheduleKind.Schedule,
2701 /* Chunked */ Chunk != nullptr) && HasChunkSizeOne &&
2702 isOpenMPLoopBoundSharingDirective(S.getDirectiveKind());
2703 if ((RT.isStaticNonchunked(ScheduleKind.Schedule,
2704 /* Chunked */ Chunk != nullptr) ||
2705 StaticChunkedOne) &&
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002706 !Ordered) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00002707 JumpDest LoopExit =
Alexey Bataeva6f2a142015-12-31 06:52:34 +00002708 getJumpDestInCurrentScope(createBasicBlock("omp.loop.exit"));
Alexey Bataev103f3c9e2019-11-20 15:59:03 -05002709 emitCommonSimdLoop(
2710 *this, S,
2711 [&S](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataeva7815212020-02-03 12:08:16 -05002712 if (isOpenMPSimdDirective(S.getDirectiveKind())) {
Alexey Bataev103f3c9e2019-11-20 15:59:03 -05002713 CGF.EmitOMPSimdInit(S, /*IsMonotonic=*/true);
Alexey Bataeva7815212020-02-03 12:08:16 -05002714 } else if (const auto *C = S.getSingleClause<OMPOrderClause>()) {
2715 if (C->getKind() == OMPC_ORDER_concurrent)
2716 CGF.LoopStack.setParallel(/*Enable=*/true);
2717 }
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00002718 },
Alexey Bataev103f3c9e2019-11-20 15:59:03 -05002719 [IVSize, IVSigned, Ordered, IL, LB, UB, ST, StaticChunkedOne, Chunk,
2720 &S, ScheduleKind, LoopExit,
2721 &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) {
2722 // OpenMP [2.7.1, Loop Construct, Description, table 2-1]
2723 // When no chunk_size is specified, the iteration space is divided
2724 // into chunks that are approximately equal in size, and at most
2725 // one chunk is distributed to each thread. Note that the size of
2726 // the chunks is unspecified in this case.
2727 CGOpenMPRuntime::StaticRTInput StaticInit(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08002728 IVSize, IVSigned, Ordered, IL.getAddress(CGF),
2729 LB.getAddress(CGF), UB.getAddress(CGF), ST.getAddress(CGF),
Alexey Bataev103f3c9e2019-11-20 15:59:03 -05002730 StaticChunkedOne ? Chunk : nullptr);
2731 CGF.CGM.getOpenMPRuntime().emitForStaticInit(
2732 CGF, S.getBeginLoc(), S.getDirectiveKind(), ScheduleKind,
2733 StaticInit);
2734 // UB = min(UB, GlobalUB);
2735 if (!StaticChunkedOne)
2736 CGF.EmitIgnoredExpr(S.getEnsureUpperBound());
2737 // IV = LB;
2738 CGF.EmitIgnoredExpr(S.getInit());
2739 // For unchunked static schedule generate:
2740 //
2741 // while (idx <= UB) {
2742 // BODY;
2743 // ++idx;
2744 // }
2745 //
2746 // For static schedule with chunk one:
2747 //
2748 // while (IV <= PrevUB) {
2749 // BODY;
2750 // IV += ST;
2751 // }
2752 CGF.EmitOMPInnerLoop(
2753 S, LoopScope.requiresCleanups(),
2754 StaticChunkedOne ? S.getCombinedParForInDistCond()
2755 : S.getCond(),
2756 StaticChunkedOne ? S.getDistInc() : S.getInc(),
2757 [&S, LoopExit](CodeGenFunction &CGF) {
2758 CGF.EmitOMPLoopBody(S, LoopExit);
2759 CGF.EmitStopPoint(&S);
2760 },
2761 [](CodeGenFunction &) {});
2762 });
Alexey Bataev0f34da12015-07-02 04:17:07 +00002763 EmitBlock(LoopExit.getBlock());
Alexander Musmanc6388682014-12-15 07:07:06 +00002764 // Tell the runtime we are done.
Alexey Bataev957d8562016-11-17 15:12:05 +00002765 auto &&CodeGen = [&S](CodeGenFunction &CGF) {
Stephen Kelly1c301dc2018-08-09 21:09:38 +00002766 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
Alexey Bataevf43f7142017-09-06 16:17:35 +00002767 S.getDirectiveKind());
Alexey Bataev957d8562016-11-17 15:12:05 +00002768 };
2769 OMPCancelStack.emitExit(*this, S.getDirectiveKind(), CodeGen);
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002770 } else {
Alexey Bataev9ebd7422016-05-10 09:57:36 +00002771 const bool IsMonotonic =
2772 Ordered || ScheduleKind.Schedule == OMPC_SCHEDULE_static ||
2773 ScheduleKind.Schedule == OMPC_SCHEDULE_unknown ||
2774 ScheduleKind.M1 == OMPC_SCHEDULE_MODIFIER_monotonic ||
2775 ScheduleKind.M2 == OMPC_SCHEDULE_MODIFIER_monotonic;
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002776 // Emit the outer loop, which requests its work chunk [LB..UB] from
2777 // runtime and runs the inner loop to process it.
Akira Hatanakaf139ae32019-12-03 15:17:01 -08002778 const OMPLoopArguments LoopArguments(
2779 LB.getAddress(*this), UB.getAddress(*this), ST.getAddress(*this),
2780 IL.getAddress(*this), Chunk, EUB);
Alexey Bataeva6f2a142015-12-31 06:52:34 +00002781 EmitOMPForOuterLoop(ScheduleKind, IsMonotonic, S, LoopScope, Ordered,
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002782 LoopArguments, CGDispatchBounds);
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002783 }
Alexey Bataev5dff95c2016-04-22 03:56:56 +00002784 if (isOpenMPSimdDirective(S.getDirectiveKind())) {
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002785 EmitOMPSimdFinal(S, [IL, &S](CodeGenFunction &CGF) {
2786 return CGF.Builder.CreateIsNotNull(
2787 CGF.EmitLoadOfScalar(IL, S.getBeginLoc()));
2788 });
Alexey Bataev5dff95c2016-04-22 03:56:56 +00002789 }
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00002790 EmitOMPReductionClauseFinal(
2791 S, /*ReductionKind=*/isOpenMPSimdDirective(S.getDirectiveKind())
2792 ? /*Parallel and Simd*/ OMPD_parallel_for_simd
2793 : /*Parallel only*/ OMPD_parallel);
Alexey Bataev61205072016-03-02 04:57:40 +00002794 // Emit post-update of the reduction variables if IsLastIter != 0.
2795 emitPostUpdateForReductionClause(
Alexey Bataevddf3db92018-04-13 17:31:06 +00002796 *this, S, [IL, &S](CodeGenFunction &CGF) {
Alexey Bataev61205072016-03-02 04:57:40 +00002797 return CGF.Builder.CreateIsNotNull(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002798 CGF.EmitLoadOfScalar(IL, S.getBeginLoc()));
Alexey Bataev61205072016-03-02 04:57:40 +00002799 });
Alexey Bataev38e89532015-04-16 04:54:05 +00002800 // Emit final copy of the lastprivate variables if IsLastIter != 0.
2801 if (HasLastprivateClause)
2802 EmitOMPLastprivateClauseFinal(
Alexey Bataev5dff95c2016-04-22 03:56:56 +00002803 S, isOpenMPSimdDirective(S.getDirectiveKind()),
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002804 Builder.CreateIsNotNull(EmitLoadOfScalar(IL, S.getBeginLoc())));
Alexander Musmanc6388682014-12-15 07:07:06 +00002805 }
Alexey Bataevddf3db92018-04-13 17:31:06 +00002806 EmitOMPLinearClauseFinal(S, [IL, &S](CodeGenFunction &CGF) {
Alexey Bataevef549a82016-03-09 09:49:09 +00002807 return CGF.Builder.CreateIsNotNull(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002808 CGF.EmitLoadOfScalar(IL, S.getBeginLoc()));
Alexey Bataevef549a82016-03-09 09:49:09 +00002809 });
Alexey Bataevea33dee2018-02-15 23:39:43 +00002810 DoacrossCleanupScope.ForceCleanup();
Alexander Musmanc6388682014-12-15 07:07:06 +00002811 // We're now done with the loop, so jump to the continuation block.
Alexey Bataev62dbb972015-04-22 11:59:37 +00002812 if (ContBlock) {
2813 EmitBranch(ContBlock);
Alexey Bataevddf3db92018-04-13 17:31:06 +00002814 EmitBlock(ContBlock, /*IsFinished=*/true);
Alexey Bataev62dbb972015-04-22 11:59:37 +00002815 }
Alexander Musmanc6388682014-12-15 07:07:06 +00002816 }
Alexey Bataev38e89532015-04-16 04:54:05 +00002817 return HasLastprivateClause;
Alexander Musmanc6388682014-12-15 07:07:06 +00002818}
2819
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002820/// The following two functions generate expressions for the loop lower
2821/// and upper bounds in case of static and dynamic (dispatch) schedule
2822/// of the associated 'for' or 'distribute' loop.
2823static std::pair<LValue, LValue>
2824emitForLoopBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00002825 const auto &LS = cast<OMPLoopDirective>(S);
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002826 LValue LB =
2827 EmitOMPHelperVar(CGF, cast<DeclRefExpr>(LS.getLowerBoundVariable()));
2828 LValue UB =
2829 EmitOMPHelperVar(CGF, cast<DeclRefExpr>(LS.getUpperBoundVariable()));
2830 return {LB, UB};
2831}
2832
2833/// When dealing with dispatch schedules (e.g. dynamic, guided) we do not
2834/// consider the lower and upper bound expressions generated by the
2835/// worksharing loop support, but we use 0 and the iteration space size as
2836/// constants
2837static std::pair<llvm::Value *, llvm::Value *>
2838emitDispatchForLoopBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S,
2839 Address LB, Address UB) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00002840 const auto &LS = cast<OMPLoopDirective>(S);
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002841 const Expr *IVExpr = LS.getIterationVariable();
2842 const unsigned IVSize = CGF.getContext().getTypeSize(IVExpr->getType());
2843 llvm::Value *LBVal = CGF.Builder.getIntN(IVSize, 0);
2844 llvm::Value *UBVal = CGF.EmitScalarExpr(LS.getLastIteration());
2845 return {LBVal, UBVal};
2846}
2847
Alexander Musmanc6388682014-12-15 07:07:06 +00002848void CodeGenFunction::EmitOMPForDirective(const OMPForDirective &S) {
Alexey Bataev38e89532015-04-16 04:54:05 +00002849 bool HasLastprivates = false;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002850 auto &&CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF,
2851 PrePostActionTy &) {
Alexey Bataev957d8562016-11-17 15:12:05 +00002852 OMPCancelStackRAII CancelRegion(CGF, OMPD_for, S.hasCancel());
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002853 HasLastprivates = CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(),
2854 emitForLoopBounds,
2855 emitDispatchForLoopBounds);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002856 };
Alexey Bataev3392d762016-02-16 11:18:12 +00002857 {
Alexey Bataev46978742020-01-30 10:46:11 -05002858 auto LPCRegion =
2859 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
Alexey Bataev475a7442018-01-12 19:39:11 +00002860 OMPLexicalScope Scope(*this, S, OMPD_unknown);
Alexey Bataev3392d762016-02-16 11:18:12 +00002861 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_for, CodeGen,
2862 S.hasCancel());
2863 }
Alexander Musmanc6388682014-12-15 07:07:06 +00002864
2865 // Emit an implicit barrier at the end.
Alexey Bataevddf3db92018-04-13 17:31:06 +00002866 if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002867 CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(), OMPD_for);
Alexey Bataev46978742020-01-30 10:46:11 -05002868 // Check for outer lastprivate conditional update.
2869 checkForLastprivateConditionalUpdate(*this, S);
Alexey Bataevf29276e2014-06-18 04:14:57 +00002870}
Alexey Bataevd3f8dd22014-06-25 11:44:49 +00002871
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00002872void CodeGenFunction::EmitOMPForSimdDirective(const OMPForSimdDirective &S) {
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00002873 bool HasLastprivates = false;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002874 auto &&CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF,
2875 PrePostActionTy &) {
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002876 HasLastprivates = CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(),
2877 emitForLoopBounds,
2878 emitDispatchForLoopBounds);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002879 };
Alexey Bataev3392d762016-02-16 11:18:12 +00002880 {
Alexey Bataev46978742020-01-30 10:46:11 -05002881 auto LPCRegion =
2882 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
Alexey Bataev475a7442018-01-12 19:39:11 +00002883 OMPLexicalScope Scope(*this, S, OMPD_unknown);
Alexey Bataev3392d762016-02-16 11:18:12 +00002884 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen);
2885 }
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00002886
2887 // Emit an implicit barrier at the end.
Alexey Bataevddf3db92018-04-13 17:31:06 +00002888 if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002889 CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(), OMPD_for);
Alexey Bataev46978742020-01-30 10:46:11 -05002890 // Check for outer lastprivate conditional update.
2891 checkForLastprivateConditionalUpdate(*this, S);
Alexander Musmanf82886e2014-09-18 05:12:34 +00002892}
2893
Alexey Bataev2df54a02015-03-12 08:53:29 +00002894static LValue createSectionLVal(CodeGenFunction &CGF, QualType Ty,
2895 const Twine &Name,
2896 llvm::Value *Init = nullptr) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00002897 LValue LVal = CGF.MakeAddrLValue(CGF.CreateMemTemp(Ty, Name), Ty);
Alexey Bataev2df54a02015-03-12 08:53:29 +00002898 if (Init)
Akira Hatanaka642f7992016-10-18 19:05:41 +00002899 CGF.EmitStoreThroughLValue(RValue::get(Init), LVal, /*isInit*/ true);
Alexey Bataev2df54a02015-03-12 08:53:29 +00002900 return LVal;
Alexey Bataevd3f8dd22014-06-25 11:44:49 +00002901}
2902
Alexey Bataev3392d762016-02-16 11:18:12 +00002903void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00002904 const Stmt *CapturedStmt = S.getInnermostCapturedStmt()->getCapturedStmt();
2905 const auto *CS = dyn_cast<CompoundStmt>(CapturedStmt);
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002906 bool HasLastprivates = false;
Alexey Bataevddf3db92018-04-13 17:31:06 +00002907 auto &&CodeGen = [&S, CapturedStmt, CS,
2908 &HasLastprivates](CodeGenFunction &CGF, PrePostActionTy &) {
2909 ASTContext &C = CGF.getContext();
2910 QualType KmpInt32Ty =
2911 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002912 // Emit helper vars inits.
2913 LValue LB = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.lb.",
2914 CGF.Builder.getInt32(0));
Alexey Bataevddf3db92018-04-13 17:31:06 +00002915 llvm::ConstantInt *GlobalUBVal = CS != nullptr
2916 ? CGF.Builder.getInt32(CS->size() - 1)
2917 : CGF.Builder.getInt32(0);
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002918 LValue UB =
2919 createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.ub.", GlobalUBVal);
2920 LValue ST = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.st.",
2921 CGF.Builder.getInt32(1));
2922 LValue IL = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.il.",
2923 CGF.Builder.getInt32(0));
2924 // Loop counter.
2925 LValue IV = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.iv.");
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002926 OpaqueValueExpr IVRefExpr(S.getBeginLoc(), KmpInt32Ty, VK_LValue);
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002927 CodeGenFunction::OpaqueValueMapping OpaqueIV(CGF, &IVRefExpr, IV);
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002928 OpaqueValueExpr UBRefExpr(S.getBeginLoc(), KmpInt32Ty, VK_LValue);
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002929 CodeGenFunction::OpaqueValueMapping OpaqueUB(CGF, &UBRefExpr, UB);
2930 // Generate condition for loop.
2931 BinaryOperator Cond(&IVRefExpr, &UBRefExpr, BO_LE, C.BoolTy, VK_RValue,
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002932 OK_Ordinary, S.getBeginLoc(), FPOptions());
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002933 // Increment for loop counter.
2934 UnaryOperator Inc(&IVRefExpr, UO_PreInc, KmpInt32Ty, VK_RValue, OK_Ordinary,
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002935 S.getBeginLoc(), true);
Alexey Bataevddf3db92018-04-13 17:31:06 +00002936 auto &&BodyGen = [CapturedStmt, CS, &S, &IV](CodeGenFunction &CGF) {
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002937 // Iterate through all sections and emit a switch construct:
2938 // switch (IV) {
2939 // case 0:
2940 // <SectionStmt[0]>;
2941 // break;
2942 // ...
2943 // case <NumSection> - 1:
2944 // <SectionStmt[<NumSection> - 1]>;
2945 // break;
2946 // }
2947 // .omp.sections.exit:
Alexey Bataevddf3db92018-04-13 17:31:06 +00002948 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".omp.sections.exit");
2949 llvm::SwitchInst *SwitchStmt =
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002950 CGF.Builder.CreateSwitch(CGF.EmitLoadOfScalar(IV, S.getBeginLoc()),
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00002951 ExitBB, CS == nullptr ? 1 : CS->size());
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002952 if (CS) {
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002953 unsigned CaseNumber = 0;
Alexey Bataevddf3db92018-04-13 17:31:06 +00002954 for (const Stmt *SubStmt : CS->children()) {
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002955 auto CaseBB = CGF.createBasicBlock(".omp.sections.case");
2956 CGF.EmitBlock(CaseBB);
2957 SwitchStmt->addCase(CGF.Builder.getInt32(CaseNumber), CaseBB);
Benjamin Kramer642f1732015-07-02 21:03:14 +00002958 CGF.EmitStmt(SubStmt);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002959 CGF.EmitBranch(ExitBB);
Benjamin Kramer642f1732015-07-02 21:03:14 +00002960 ++CaseNumber;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002961 }
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002962 } else {
Alexey Bataevddf3db92018-04-13 17:31:06 +00002963 llvm::BasicBlock *CaseBB = CGF.createBasicBlock(".omp.sections.case");
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002964 CGF.EmitBlock(CaseBB);
2965 SwitchStmt->addCase(CGF.Builder.getInt32(0), CaseBB);
Alexey Bataevddf3db92018-04-13 17:31:06 +00002966 CGF.EmitStmt(CapturedStmt);
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002967 CGF.EmitBranch(ExitBB);
Alexey Bataev2cb9b952015-04-24 03:37:03 +00002968 }
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002969 CGF.EmitBlock(ExitBB, /*IsFinished=*/true);
Alexey Bataev2df54a02015-03-12 08:53:29 +00002970 };
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002971
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002972 CodeGenFunction::OMPPrivateScope LoopScope(CGF);
2973 if (CGF.EmitOMPFirstprivateClause(S, LoopScope)) {
Alexey Bataev9efc03b2015-04-27 04:34:03 +00002974 // Emit implicit barrier to synchronize threads and avoid data races on
Alexey Bataevcd8b6a22016-02-15 08:07:17 +00002975 // initialization of firstprivate variables and post-update of lastprivate
2976 // variables.
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002977 CGF.CGM.getOpenMPRuntime().emitBarrierCall(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002978 CGF, S.getBeginLoc(), OMPD_unknown, /*EmitChecks=*/false,
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002979 /*ForceSimpleCall=*/true);
Alexey Bataev9efc03b2015-04-27 04:34:03 +00002980 }
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002981 CGF.EmitOMPPrivateClause(S, LoopScope);
Alexey Bataeva58da1a2019-12-27 09:44:43 -05002982 CGOpenMPRuntime::LastprivateConditionalRAII LPCRegion(CGF, S, IV);
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002983 HasLastprivates = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
2984 CGF.EmitOMPReductionClauseInit(S, LoopScope);
2985 (void)LoopScope.Privatize();
Alexey Bataev60705422018-10-30 15:50:12 +00002986 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()))
2987 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
Alexey Bataev2cb9b952015-04-24 03:37:03 +00002988
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002989 // Emit static non-chunked loop.
Alexey Bataev9ebd7422016-05-10 09:57:36 +00002990 OpenMPScheduleTy ScheduleKind;
2991 ScheduleKind.Schedule = OMPC_SCHEDULE_static;
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00002992 CGOpenMPRuntime::StaticRTInput StaticInit(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08002993 /*IVSize=*/32, /*IVSigned=*/true, /*Ordered=*/false, IL.getAddress(CGF),
2994 LB.getAddress(CGF), UB.getAddress(CGF), ST.getAddress(CGF));
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002995 CGF.CGM.getOpenMPRuntime().emitForStaticInit(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002996 CGF, S.getBeginLoc(), S.getDirectiveKind(), ScheduleKind, StaticInit);
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002997 // UB = min(UB, GlobalUB);
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002998 llvm::Value *UBVal = CGF.EmitLoadOfScalar(UB, S.getBeginLoc());
Alexey Bataevddf3db92018-04-13 17:31:06 +00002999 llvm::Value *MinUBGlobalUB = CGF.Builder.CreateSelect(
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003000 CGF.Builder.CreateICmpSLT(UBVal, GlobalUBVal), UBVal, GlobalUBVal);
3001 CGF.EmitStoreOfScalar(MinUBGlobalUB, UB);
3002 // IV = LB;
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003003 CGF.EmitStoreOfScalar(CGF.EmitLoadOfScalar(LB, S.getBeginLoc()), IV);
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003004 // while (idx <= UB) { BODY; ++idx; }
3005 CGF.EmitOMPInnerLoop(S, /*RequiresCleanup=*/false, &Cond, &Inc, BodyGen,
3006 [](CodeGenFunction &) {});
3007 // Tell the runtime we are done.
Alexey Bataev957d8562016-11-17 15:12:05 +00003008 auto &&CodeGen = [&S](CodeGenFunction &CGF) {
Stephen Kelly1c301dc2018-08-09 21:09:38 +00003009 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
Alexey Bataevf43f7142017-09-06 16:17:35 +00003010 S.getDirectiveKind());
Alexey Bataev957d8562016-11-17 15:12:05 +00003011 };
3012 CGF.OMPCancelStack.emitExit(CGF, S.getDirectiveKind(), CodeGen);
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00003013 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel);
Alexey Bataev61205072016-03-02 04:57:40 +00003014 // Emit post-update of the reduction variables if IsLastIter != 0.
Alexey Bataevddf3db92018-04-13 17:31:06 +00003015 emitPostUpdateForReductionClause(CGF, S, [IL, &S](CodeGenFunction &CGF) {
3016 return CGF.Builder.CreateIsNotNull(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003017 CGF.EmitLoadOfScalar(IL, S.getBeginLoc()));
Alexey Bataevddf3db92018-04-13 17:31:06 +00003018 });
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003019
3020 // Emit final copy of the lastprivate variables if IsLastIter != 0.
3021 if (HasLastprivates)
3022 CGF.EmitOMPLastprivateClauseFinal(
Alexey Bataev5dff95c2016-04-22 03:56:56 +00003023 S, /*NoFinals=*/false,
3024 CGF.Builder.CreateIsNotNull(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003025 CGF.EmitLoadOfScalar(IL, S.getBeginLoc())));
Alexey Bataev68adb7d2015-04-14 03:29:22 +00003026 };
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003027
3028 bool HasCancel = false;
3029 if (auto *OSD = dyn_cast<OMPSectionsDirective>(&S))
3030 HasCancel = OSD->hasCancel();
3031 else if (auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&S))
3032 HasCancel = OPSD->hasCancel();
Alexey Bataev957d8562016-11-17 15:12:05 +00003033 OMPCancelStackRAII CancelRegion(*this, S.getDirectiveKind(), HasCancel);
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003034 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_sections, CodeGen,
3035 HasCancel);
3036 // Emit barrier for lastprivates only if 'sections' directive has 'nowait'
3037 // clause. Otherwise the barrier will be generated by the codegen for the
3038 // directive.
3039 if (HasLastprivates && S.getSingleClause<OMPNowaitClause>()) {
Alexey Bataev2cb9b952015-04-24 03:37:03 +00003040 // Emit implicit barrier to synchronize threads and avoid data races on
3041 // initialization of firstprivate variables.
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003042 CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(),
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003043 OMPD_unknown);
Alexey Bataev2cb9b952015-04-24 03:37:03 +00003044 }
Alexey Bataev68adb7d2015-04-14 03:29:22 +00003045}
Alexey Bataev2df54a02015-03-12 08:53:29 +00003046
Alexey Bataev68adb7d2015-04-14 03:29:22 +00003047void CodeGenFunction::EmitOMPSectionsDirective(const OMPSectionsDirective &S) {
Alexey Bataev3392d762016-02-16 11:18:12 +00003048 {
Alexey Bataev46978742020-01-30 10:46:11 -05003049 auto LPCRegion =
3050 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
Alexey Bataev475a7442018-01-12 19:39:11 +00003051 OMPLexicalScope Scope(*this, S, OMPD_unknown);
Alexey Bataev3392d762016-02-16 11:18:12 +00003052 EmitSections(S);
3053 }
Alexey Bataev2df54a02015-03-12 08:53:29 +00003054 // Emit an implicit barrier at the end.
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00003055 if (!S.getSingleClause<OMPNowaitClause>()) {
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003056 CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(),
Alexey Bataev3392d762016-02-16 11:18:12 +00003057 OMPD_sections);
Alexey Bataevf2685682015-03-30 04:30:22 +00003058 }
Alexey Bataev46978742020-01-30 10:46:11 -05003059 // Check for outer lastprivate conditional update.
3060 checkForLastprivateConditionalUpdate(*this, S);
Alexey Bataev2df54a02015-03-12 08:53:29 +00003061}
3062
3063void CodeGenFunction::EmitOMPSectionDirective(const OMPSectionDirective &S) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003064 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataev475a7442018-01-12 19:39:11 +00003065 CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003066 };
Alexey Bataev475a7442018-01-12 19:39:11 +00003067 OMPLexicalScope Scope(*this, S, OMPD_unknown);
Alexey Bataev25e5b442015-09-15 12:52:43 +00003068 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_section, CodeGen,
3069 S.hasCancel());
Alexey Bataev1e0498a2014-06-26 08:21:58 +00003070}
3071
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003072void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &S) {
Alexey Bataeva63048e2015-03-23 06:18:07 +00003073 llvm::SmallVector<const Expr *, 8> CopyprivateVars;
Alexey Bataev420d45b2015-04-14 05:11:24 +00003074 llvm::SmallVector<const Expr *, 8> DestExprs;
Alexey Bataeva63048e2015-03-23 06:18:07 +00003075 llvm::SmallVector<const Expr *, 8> SrcExprs;
Alexey Bataeva63048e2015-03-23 06:18:07 +00003076 llvm::SmallVector<const Expr *, 8> AssignmentOps;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003077 // Check if there are any 'copyprivate' clauses associated with this
Alexey Bataevcd8b6a22016-02-15 08:07:17 +00003078 // 'single' construct.
Alexey Bataeva63048e2015-03-23 06:18:07 +00003079 // Build a list of copyprivate variables along with helper expressions
3080 // (<source>, <destination>, <destination>=<source> expressions)
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00003081 for (const auto *C : S.getClausesOfKind<OMPCopyprivateClause>()) {
Alexey Bataeva63048e2015-03-23 06:18:07 +00003082 CopyprivateVars.append(C->varlists().begin(), C->varlists().end());
Alexey Bataev420d45b2015-04-14 05:11:24 +00003083 DestExprs.append(C->destination_exprs().begin(),
3084 C->destination_exprs().end());
Alexey Bataeva63048e2015-03-23 06:18:07 +00003085 SrcExprs.append(C->source_exprs().begin(), C->source_exprs().end());
Alexey Bataeva63048e2015-03-23 06:18:07 +00003086 AssignmentOps.append(C->assignment_ops().begin(),
3087 C->assignment_ops().end());
3088 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003089 // Emit code for 'single' region along with 'copyprivate' clauses
3090 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
3091 Action.Enter(CGF);
3092 OMPPrivateScope SingleScope(CGF);
3093 (void)CGF.EmitOMPFirstprivateClause(S, SingleScope);
3094 CGF.EmitOMPPrivateClause(S, SingleScope);
3095 (void)SingleScope.Privatize();
Alexey Bataev475a7442018-01-12 19:39:11 +00003096 CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003097 };
Alexey Bataev3392d762016-02-16 11:18:12 +00003098 {
Alexey Bataev46978742020-01-30 10:46:11 -05003099 auto LPCRegion =
3100 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
Alexey Bataev475a7442018-01-12 19:39:11 +00003101 OMPLexicalScope Scope(*this, S, OMPD_unknown);
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003102 CGM.getOpenMPRuntime().emitSingleRegion(*this, CodeGen, S.getBeginLoc(),
Alexey Bataev3392d762016-02-16 11:18:12 +00003103 CopyprivateVars, DestExprs,
3104 SrcExprs, AssignmentOps);
3105 }
3106 // Emit an implicit barrier at the end (to avoid data race on firstprivate
3107 // init or if no 'nowait' clause was specified and no 'copyprivate' clause).
Alexey Bataev417089f2016-02-17 13:19:37 +00003108 if (!S.getSingleClause<OMPNowaitClause>() && CopyprivateVars.empty()) {
Alexey Bataev5521d782015-04-24 04:21:15 +00003109 CGM.getOpenMPRuntime().emitBarrierCall(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003110 *this, S.getBeginLoc(),
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00003111 S.getSingleClause<OMPNowaitClause>() ? OMPD_unknown : OMPD_single);
Alexey Bataevf2685682015-03-30 04:30:22 +00003112 }
Alexey Bataev46978742020-01-30 10:46:11 -05003113 // Check for outer lastprivate conditional update.
3114 checkForLastprivateConditionalUpdate(*this, S);
Alexey Bataevd1e40fb2014-06-26 12:05:45 +00003115}
3116
cchen47d60942019-12-05 13:43:48 -05003117static void emitMaster(CodeGenFunction &CGF, const OMPExecutableDirective &S) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003118 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
3119 Action.Enter(CGF);
Alexey Bataev475a7442018-01-12 19:39:11 +00003120 CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003121 };
cchen47d60942019-12-05 13:43:48 -05003122 CGF.CGM.getOpenMPRuntime().emitMasterRegion(CGF, CodeGen, S.getBeginLoc());
3123}
3124
3125void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &S) {
Fady Ghanim7438059a2020-02-15 00:42:23 -06003126 if (llvm::OpenMPIRBuilder *OMPBuilder = CGM.getOpenMPIRBuilder()) {
3127 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
3128
3129 const CapturedStmt *CS = S.getInnermostCapturedStmt();
3130 const Stmt *MasterRegionBodyStmt = CS->getCapturedStmt();
3131
Fady Ghanim7438059a2020-02-15 00:42:23 -06003132 auto FiniCB = [this](InsertPointTy IP) {
Fady Ghanimba3f8632020-02-19 13:50:26 -06003133 OMPBuilderCBHelpers::FinalizeOMPRegion(*this, IP);
Fady Ghanim7438059a2020-02-15 00:42:23 -06003134 };
3135
Fady Ghanim7438059a2020-02-15 00:42:23 -06003136 auto BodyGenCB = [MasterRegionBodyStmt, this](InsertPointTy AllocaIP,
3137 InsertPointTy CodeGenIP,
3138 llvm::BasicBlock &FiniBB) {
Fady Ghanimba3f8632020-02-19 13:50:26 -06003139 OMPBuilderCBHelpers::InlinedRegionBodyRAII IRB(*this, AllocaIP, FiniBB);
3140 OMPBuilderCBHelpers::EmitOMPRegionBody(*this, MasterRegionBodyStmt,
3141 CodeGenIP, FiniBB);
Fady Ghanim7438059a2020-02-15 00:42:23 -06003142 };
Fady Ghanimba3f8632020-02-19 13:50:26 -06003143
Fady Ghanim7438059a2020-02-15 00:42:23 -06003144 CGCapturedStmtInfo CGSI(*CS, CR_OpenMP);
3145 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(*this, &CGSI);
3146 Builder.restoreIP(OMPBuilder->CreateMaster(Builder, BodyGenCB, FiniCB));
3147
3148 return;
3149 }
Alexey Bataev475a7442018-01-12 19:39:11 +00003150 OMPLexicalScope Scope(*this, S, OMPD_unknown);
cchen47d60942019-12-05 13:43:48 -05003151 emitMaster(*this, S);
Alexander Musman80c22892014-07-17 08:54:58 +00003152}
3153
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003154void CodeGenFunction::EmitOMPCriticalDirective(const OMPCriticalDirective &S) {
Fady Ghanim7438059a2020-02-15 00:42:23 -06003155 if (llvm::OpenMPIRBuilder *OMPBuilder = CGM.getOpenMPIRBuilder()) {
3156 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
3157
3158 const CapturedStmt *CS = S.getInnermostCapturedStmt();
3159 const Stmt *CriticalRegionBodyStmt = CS->getCapturedStmt();
3160 const Expr *Hint = nullptr;
3161 if (const auto *HintClause = S.getSingleClause<OMPHintClause>())
3162 Hint = HintClause->getHint();
3163
3164 // TODO: This is slightly different from what's currently being done in
3165 // clang. Fix the Int32Ty to IntPtrTy (pointer width size) when everything
3166 // about typing is final.
3167 llvm::Value *HintInst = nullptr;
3168 if (Hint)
3169 HintInst =
3170 Builder.CreateIntCast(EmitScalarExpr(Hint), CGM.Int32Ty, false);
3171
Fady Ghanim7438059a2020-02-15 00:42:23 -06003172 auto FiniCB = [this](InsertPointTy IP) {
Fady Ghanimba3f8632020-02-19 13:50:26 -06003173 OMPBuilderCBHelpers::FinalizeOMPRegion(*this, IP);
Fady Ghanim7438059a2020-02-15 00:42:23 -06003174 };
3175
Fady Ghanim7438059a2020-02-15 00:42:23 -06003176 auto BodyGenCB = [CriticalRegionBodyStmt, this](InsertPointTy AllocaIP,
3177 InsertPointTy CodeGenIP,
3178 llvm::BasicBlock &FiniBB) {
Fady Ghanimba3f8632020-02-19 13:50:26 -06003179 OMPBuilderCBHelpers::InlinedRegionBodyRAII IRB(*this, AllocaIP, FiniBB);
3180 OMPBuilderCBHelpers::EmitOMPRegionBody(*this, CriticalRegionBodyStmt,
3181 CodeGenIP, FiniBB);
Fady Ghanim7438059a2020-02-15 00:42:23 -06003182 };
3183
3184 CGCapturedStmtInfo CGSI(*CS, CR_OpenMP);
3185 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(*this, &CGSI);
3186 Builder.restoreIP(OMPBuilder->CreateCritical(
3187 Builder, BodyGenCB, FiniCB, S.getDirectiveName().getAsString(),
3188 HintInst));
3189
3190 return;
3191 }
3192
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003193 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
3194 Action.Enter(CGF);
Alexey Bataev475a7442018-01-12 19:39:11 +00003195 CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003196 };
Alexey Bataevddf3db92018-04-13 17:31:06 +00003197 const Expr *Hint = nullptr;
3198 if (const auto *HintClause = S.getSingleClause<OMPHintClause>())
Alexey Bataevfc57d162015-12-15 10:55:09 +00003199 Hint = HintClause->getHint();
Alexey Bataev475a7442018-01-12 19:39:11 +00003200 OMPLexicalScope Scope(*this, S, OMPD_unknown);
Alexey Bataevfc57d162015-12-15 10:55:09 +00003201 CGM.getOpenMPRuntime().emitCriticalRegion(*this,
3202 S.getDirectiveName().getAsString(),
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003203 CodeGen, S.getBeginLoc(), Hint);
Alexander Musmand9ed09f2014-07-21 09:42:05 +00003204}
3205
Alexey Bataev671605e2015-04-13 05:28:11 +00003206void CodeGenFunction::EmitOMPParallelForDirective(
3207 const OMPParallelForDirective &S) {
3208 // Emit directive as a combined directive that consists of two implicit
3209 // directives: 'parallel' with 'for' directive.
Alexey Bataevc99042b2018-03-15 18:10:54 +00003210 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
3211 Action.Enter(CGF);
Alexey Bataev957d8562016-11-17 15:12:05 +00003212 OMPCancelStackRAII CancelRegion(CGF, OMPD_parallel_for, S.hasCancel());
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003213 CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds,
3214 emitDispatchForLoopBounds);
Alexey Bataev671605e2015-04-13 05:28:11 +00003215 };
Alexey Bataev46978742020-01-30 10:46:11 -05003216 {
3217 auto LPCRegion =
3218 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
3219 emitCommonOMPParallelDirective(*this, S, OMPD_for, CodeGen,
3220 emitEmptyBoundParameters);
3221 }
3222 // Check for outer lastprivate conditional update.
3223 checkForLastprivateConditionalUpdate(*this, S);
Alexey Bataev4acb8592014-07-07 13:01:15 +00003224}
3225
Alexander Musmane4e893b2014-09-23 09:33:00 +00003226void CodeGenFunction::EmitOMPParallelForSimdDirective(
Alexey Bataev3b5b5c42015-06-18 10:10:12 +00003227 const OMPParallelForSimdDirective &S) {
3228 // Emit directive as a combined directive that consists of two implicit
3229 // directives: 'parallel' with 'for' directive.
Alexey Bataevc99042b2018-03-15 18:10:54 +00003230 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
3231 Action.Enter(CGF);
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003232 CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds,
3233 emitDispatchForLoopBounds);
Alexey Bataev3b5b5c42015-06-18 10:10:12 +00003234 };
Alexey Bataev46978742020-01-30 10:46:11 -05003235 {
3236 auto LPCRegion =
3237 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
3238 emitCommonOMPParallelDirective(*this, S, OMPD_simd, CodeGen,
3239 emitEmptyBoundParameters);
3240 }
3241 // Check for outer lastprivate conditional update.
3242 checkForLastprivateConditionalUpdate(*this, S);
Alexander Musmane4e893b2014-09-23 09:33:00 +00003243}
3244
cchen47d60942019-12-05 13:43:48 -05003245void CodeGenFunction::EmitOMPParallelMasterDirective(
3246 const OMPParallelMasterDirective &S) {
3247 // Emit directive as a combined directive that consists of two implicit
3248 // directives: 'parallel' with 'master' directive.
3249 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
3250 Action.Enter(CGF);
3251 OMPPrivateScope PrivateScope(CGF);
3252 bool Copyins = CGF.EmitOMPCopyinClause(S);
3253 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
3254 if (Copyins) {
3255 // Emit implicit barrier to synchronize threads and avoid data races on
3256 // propagation master's thread values of threadprivate variables to local
3257 // instances of that variables of all other implicit threads.
3258 CGF.CGM.getOpenMPRuntime().emitBarrierCall(
3259 CGF, S.getBeginLoc(), OMPD_unknown, /*EmitChecks=*/false,
3260 /*ForceSimpleCall=*/true);
3261 }
3262 CGF.EmitOMPPrivateClause(S, PrivateScope);
3263 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
3264 (void)PrivateScope.Privatize();
3265 emitMaster(CGF, S);
3266 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel);
3267 };
Alexey Bataev46978742020-01-30 10:46:11 -05003268 {
3269 auto LPCRegion =
3270 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
3271 emitCommonOMPParallelDirective(*this, S, OMPD_master, CodeGen,
3272 emitEmptyBoundParameters);
3273 emitPostUpdateForReductionClause(*this, S,
3274 [](CodeGenFunction &) { return nullptr; });
3275 }
3276 // Check for outer lastprivate conditional update.
3277 checkForLastprivateConditionalUpdate(*this, S);
cchen47d60942019-12-05 13:43:48 -05003278}
3279
Alexey Bataev84d0b3e2014-07-08 08:12:03 +00003280void CodeGenFunction::EmitOMPParallelSectionsDirective(
Alexey Bataev68adb7d2015-04-14 03:29:22 +00003281 const OMPParallelSectionsDirective &S) {
3282 // Emit directive as a combined directive that consists of two implicit
3283 // directives: 'parallel' with 'sections' directive.
Alexey Bataevc99042b2018-03-15 18:10:54 +00003284 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
3285 Action.Enter(CGF);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003286 CGF.EmitSections(S);
3287 };
Alexey Bataev46978742020-01-30 10:46:11 -05003288 {
3289 auto LPCRegion =
3290 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
3291 emitCommonOMPParallelDirective(*this, S, OMPD_sections, CodeGen,
3292 emitEmptyBoundParameters);
3293 }
3294 // Check for outer lastprivate conditional update.
3295 checkForLastprivateConditionalUpdate(*this, S);
Alexey Bataev84d0b3e2014-07-08 08:12:03 +00003296}
3297
Alexey Bataev475a7442018-01-12 19:39:11 +00003298void CodeGenFunction::EmitOMPTaskBasedDirective(
3299 const OMPExecutableDirective &S, const OpenMPDirectiveKind CapturedRegion,
3300 const RegionCodeGenTy &BodyGen, const TaskGenTy &TaskGen,
3301 OMPTaskDataTy &Data) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00003302 // Emit outlined function for task construct.
Alexey Bataev475a7442018-01-12 19:39:11 +00003303 const CapturedStmt *CS = S.getCapturedStmt(CapturedRegion);
Alexey Bataevddf3db92018-04-13 17:31:06 +00003304 auto I = CS->getCapturedDecl()->param_begin();
3305 auto PartId = std::next(I);
3306 auto TaskT = std::next(I, 4);
Alexey Bataev24b5bae2016-04-28 09:23:51 +00003307 // Check if the task is final
3308 if (const auto *Clause = S.getSingleClause<OMPFinalClause>()) {
3309 // If the condition constant folds and can be elided, try to avoid emitting
3310 // the condition and the dead arm of the if/else.
Alexey Bataevddf3db92018-04-13 17:31:06 +00003311 const Expr *Cond = Clause->getCondition();
Alexey Bataev24b5bae2016-04-28 09:23:51 +00003312 bool CondConstant;
3313 if (ConstantFoldsToSimpleInteger(Cond, CondConstant))
3314 Data.Final.setInt(CondConstant);
3315 else
3316 Data.Final.setPointer(EvaluateExprAsBool(Cond));
3317 } else {
3318 // By default the task is not final.
3319 Data.Final.setInt(/*IntVal=*/false);
3320 }
Alexey Bataev1e1e2862016-05-10 12:21:02 +00003321 // Check if the task has 'priority' clause.
3322 if (const auto *Clause = S.getSingleClause<OMPPriorityClause>()) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00003323 const Expr *Prio = Clause->getPriority();
Alexey Bataev5140e742016-07-19 04:21:09 +00003324 Data.Priority.setInt(/*IntVal=*/true);
Alexey Bataevad537bb2016-05-30 09:06:50 +00003325 Data.Priority.setPointer(EmitScalarConversion(
3326 EmitScalarExpr(Prio), Prio->getType(),
3327 getContext().getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1),
3328 Prio->getExprLoc()));
Alexey Bataev1e1e2862016-05-10 12:21:02 +00003329 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00003330 // The first function argument for tasks is a thread id, the second one is a
3331 // part id (0 for tied tasks, >=0 for untied task).
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003332 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
3333 // Get list of private variables.
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00003334 for (const auto *C : S.getClausesOfKind<OMPPrivateClause>()) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003335 auto IRef = C->varlist_begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00003336 for (const Expr *IInit : C->private_copies()) {
3337 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003338 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
Alexey Bataev7292c292016-04-25 12:22:29 +00003339 Data.PrivateVars.push_back(*IRef);
3340 Data.PrivateCopies.push_back(IInit);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003341 }
3342 ++IRef;
3343 }
3344 }
3345 EmittedAsPrivate.clear();
3346 // Get list of firstprivate variables.
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00003347 for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003348 auto IRef = C->varlist_begin();
3349 auto IElemInitRef = C->inits().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00003350 for (const Expr *IInit : C->private_copies()) {
3351 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003352 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
Alexey Bataev7292c292016-04-25 12:22:29 +00003353 Data.FirstprivateVars.push_back(*IRef);
3354 Data.FirstprivateCopies.push_back(IInit);
3355 Data.FirstprivateInits.push_back(*IElemInitRef);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003356 }
Richard Trieucc3949d2016-02-18 22:34:54 +00003357 ++IRef;
3358 ++IElemInitRef;
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003359 }
3360 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00003361 // Get list of lastprivate variables (for taskloops).
3362 llvm::DenseMap<const VarDecl *, const DeclRefExpr *> LastprivateDstsOrigs;
3363 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) {
3364 auto IRef = C->varlist_begin();
3365 auto ID = C->destination_exprs().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00003366 for (const Expr *IInit : C->private_copies()) {
3367 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
Alexey Bataevf93095a2016-05-05 08:46:22 +00003368 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
3369 Data.LastprivateVars.push_back(*IRef);
3370 Data.LastprivateCopies.push_back(IInit);
3371 }
3372 LastprivateDstsOrigs.insert(
3373 {cast<VarDecl>(cast<DeclRefExpr>(*ID)->getDecl()),
3374 cast<DeclRefExpr>(*IRef)});
3375 ++IRef;
3376 ++ID;
3377 }
3378 }
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003379 SmallVector<const Expr *, 4> LHSs;
3380 SmallVector<const Expr *, 4> RHSs;
3381 for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) {
3382 auto IPriv = C->privates().begin();
3383 auto IRed = C->reduction_ops().begin();
3384 auto ILHS = C->lhs_exprs().begin();
3385 auto IRHS = C->rhs_exprs().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00003386 for (const Expr *Ref : C->varlists()) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003387 Data.ReductionVars.emplace_back(Ref);
3388 Data.ReductionCopies.emplace_back(*IPriv);
3389 Data.ReductionOps.emplace_back(*IRed);
3390 LHSs.emplace_back(*ILHS);
3391 RHSs.emplace_back(*IRHS);
3392 std::advance(IPriv, 1);
3393 std::advance(IRed, 1);
3394 std::advance(ILHS, 1);
3395 std::advance(IRHS, 1);
3396 }
3397 }
3398 Data.Reductions = CGM.getOpenMPRuntime().emitTaskReductionInit(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003399 *this, S.getBeginLoc(), LHSs, RHSs, Data);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003400 // Build list of dependences.
Alexey Bataev7292c292016-04-25 12:22:29 +00003401 for (const auto *C : S.getClausesOfKind<OMPDependClause>())
Alexey Bataevddf3db92018-04-13 17:31:06 +00003402 for (const Expr *IRef : C->varlists())
Alexey Bataev43a919f2018-04-13 17:48:43 +00003403 Data.Dependences.emplace_back(C->getDependencyKind(), IRef);
Alexey Bataev475a7442018-01-12 19:39:11 +00003404 auto &&CodeGen = [&Data, &S, CS, &BodyGen, &LastprivateDstsOrigs,
3405 CapturedRegion](CodeGenFunction &CGF,
3406 PrePostActionTy &Action) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003407 // Set proper addresses for generated private copies.
Alexey Bataev7292c292016-04-25 12:22:29 +00003408 OMPPrivateScope Scope(CGF);
Alexey Bataevf93095a2016-05-05 08:46:22 +00003409 if (!Data.PrivateVars.empty() || !Data.FirstprivateVars.empty() ||
3410 !Data.LastprivateVars.empty()) {
James Y Knight9871db02019-02-05 16:42:33 +00003411 llvm::FunctionType *CopyFnTy = llvm::FunctionType::get(
3412 CGF.Builder.getVoidTy(), {CGF.Builder.getInt8PtrTy()}, true);
Alexey Bataev3c595a62017-08-14 15:01:03 +00003413 enum { PrivatesParam = 2, CopyFnParam = 3 };
Alexey Bataevddf3db92018-04-13 17:31:06 +00003414 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
3415 CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(CopyFnParam)));
3416 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
3417 CS->getCapturedDecl()->getParam(PrivatesParam)));
Alexey Bataev48591dd2016-04-20 04:01:36 +00003418 // Map privates.
3419 llvm::SmallVector<std::pair<const VarDecl *, Address>, 16> PrivatePtrs;
3420 llvm::SmallVector<llvm::Value *, 16> CallArgs;
3421 CallArgs.push_back(PrivatesPtr);
Alexey Bataevddf3db92018-04-13 17:31:06 +00003422 for (const Expr *E : Data.PrivateVars) {
3423 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev48591dd2016-04-20 04:01:36 +00003424 Address PrivatePtr = CGF.CreateMemTemp(
3425 CGF.getContext().getPointerType(E->getType()), ".priv.ptr.addr");
Alexey Bataevddf3db92018-04-13 17:31:06 +00003426 PrivatePtrs.emplace_back(VD, PrivatePtr);
Alexey Bataev48591dd2016-04-20 04:01:36 +00003427 CallArgs.push_back(PrivatePtr.getPointer());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003428 }
Alexey Bataevddf3db92018-04-13 17:31:06 +00003429 for (const Expr *E : Data.FirstprivateVars) {
3430 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev48591dd2016-04-20 04:01:36 +00003431 Address PrivatePtr =
3432 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()),
3433 ".firstpriv.ptr.addr");
Alexey Bataevddf3db92018-04-13 17:31:06 +00003434 PrivatePtrs.emplace_back(VD, PrivatePtr);
Alexey Bataev48591dd2016-04-20 04:01:36 +00003435 CallArgs.push_back(PrivatePtr.getPointer());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003436 }
Alexey Bataevddf3db92018-04-13 17:31:06 +00003437 for (const Expr *E : Data.LastprivateVars) {
3438 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataevf93095a2016-05-05 08:46:22 +00003439 Address PrivatePtr =
3440 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()),
3441 ".lastpriv.ptr.addr");
Alexey Bataevddf3db92018-04-13 17:31:06 +00003442 PrivatePtrs.emplace_back(VD, PrivatePtr);
Alexey Bataevf93095a2016-05-05 08:46:22 +00003443 CallArgs.push_back(PrivatePtr.getPointer());
3444 }
James Y Knight9871db02019-02-05 16:42:33 +00003445 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
3446 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
Alexey Bataevddf3db92018-04-13 17:31:06 +00003447 for (const auto &Pair : LastprivateDstsOrigs) {
3448 const auto *OrigVD = cast<VarDecl>(Pair.second->getDecl());
Bruno Ricci5fc4db72018-12-21 14:10:18 +00003449 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(OrigVD),
3450 /*RefersToEnclosingVariableOrCapture=*/
3451 CGF.CapturedStmtInfo->lookup(OrigVD) != nullptr,
3452 Pair.second->getType(), VK_LValue,
3453 Pair.second->getExprLoc());
Alexey Bataevf93095a2016-05-05 08:46:22 +00003454 Scope.addPrivate(Pair.first, [&CGF, &DRE]() {
Akira Hatanakaf139ae32019-12-03 15:17:01 -08003455 return CGF.EmitLValue(&DRE).getAddress(CGF);
Alexey Bataevf93095a2016-05-05 08:46:22 +00003456 });
3457 }
Alexey Bataevddf3db92018-04-13 17:31:06 +00003458 for (const auto &Pair : PrivatePtrs) {
Alexey Bataev48591dd2016-04-20 04:01:36 +00003459 Address Replacement(CGF.Builder.CreateLoad(Pair.second),
3460 CGF.getContext().getDeclAlign(Pair.first));
3461 Scope.addPrivate(Pair.first, [Replacement]() { return Replacement; });
3462 }
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003463 }
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003464 if (Data.Reductions) {
Alexey Bataev475a7442018-01-12 19:39:11 +00003465 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003466 ReductionCodeGen RedCG(Data.ReductionVars, Data.ReductionCopies,
3467 Data.ReductionOps);
3468 llvm::Value *ReductionsPtr = CGF.Builder.CreateLoad(
3469 CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(9)));
3470 for (unsigned Cnt = 0, E = Data.ReductionVars.size(); Cnt < E; ++Cnt) {
3471 RedCG.emitSharedLValue(CGF, Cnt);
3472 RedCG.emitAggregateType(CGF, Cnt);
Alexey Bataev2e0cbe502018-03-08 15:24:08 +00003473 // FIXME: This must removed once the runtime library is fixed.
3474 // Emit required threadprivate variables for
Raphael Isemannb23ccec2018-12-10 12:37:46 +00003475 // initializer/combiner/finalizer.
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003476 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
Alexey Bataev2e0cbe502018-03-08 15:24:08 +00003477 RedCG, Cnt);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003478 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003479 CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003480 Replacement =
3481 Address(CGF.EmitScalarConversion(
3482 Replacement.getPointer(), CGF.getContext().VoidPtrTy,
3483 CGF.getContext().getPointerType(
3484 Data.ReductionCopies[Cnt]->getType()),
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00003485 Data.ReductionCopies[Cnt]->getExprLoc()),
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003486 Replacement.getAlignment());
3487 Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement);
3488 Scope.addPrivate(RedCG.getBaseDecl(Cnt),
3489 [Replacement]() { return Replacement; });
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003490 }
3491 }
Alexey Bataev88202be2017-07-27 13:20:36 +00003492 // Privatize all private variables except for in_reduction items.
Alexey Bataev48591dd2016-04-20 04:01:36 +00003493 (void)Scope.Privatize();
Alexey Bataev88202be2017-07-27 13:20:36 +00003494 SmallVector<const Expr *, 4> InRedVars;
3495 SmallVector<const Expr *, 4> InRedPrivs;
3496 SmallVector<const Expr *, 4> InRedOps;
3497 SmallVector<const Expr *, 4> TaskgroupDescriptors;
3498 for (const auto *C : S.getClausesOfKind<OMPInReductionClause>()) {
3499 auto IPriv = C->privates().begin();
3500 auto IRed = C->reduction_ops().begin();
3501 auto ITD = C->taskgroup_descriptors().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00003502 for (const Expr *Ref : C->varlists()) {
Alexey Bataev88202be2017-07-27 13:20:36 +00003503 InRedVars.emplace_back(Ref);
3504 InRedPrivs.emplace_back(*IPriv);
3505 InRedOps.emplace_back(*IRed);
3506 TaskgroupDescriptors.emplace_back(*ITD);
3507 std::advance(IPriv, 1);
3508 std::advance(IRed, 1);
3509 std::advance(ITD, 1);
3510 }
3511 }
3512 // Privatize in_reduction items here, because taskgroup descriptors must be
3513 // privatized earlier.
3514 OMPPrivateScope InRedScope(CGF);
3515 if (!InRedVars.empty()) {
3516 ReductionCodeGen RedCG(InRedVars, InRedPrivs, InRedOps);
3517 for (unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) {
3518 RedCG.emitSharedLValue(CGF, Cnt);
3519 RedCG.emitAggregateType(CGF, Cnt);
3520 // The taskgroup descriptor variable is always implicit firstprivate and
Raphael Isemannb23ccec2018-12-10 12:37:46 +00003521 // privatized already during processing of the firstprivates.
Alexey Bataev2e0cbe502018-03-08 15:24:08 +00003522 // FIXME: This must removed once the runtime library is fixed.
3523 // Emit required threadprivate variables for
Raphael Isemannb23ccec2018-12-10 12:37:46 +00003524 // initializer/combiner/finalizer.
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003525 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
Alexey Bataev2e0cbe502018-03-08 15:24:08 +00003526 RedCG, Cnt);
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00003527 llvm::Value *ReductionsPtr =
3528 CGF.EmitLoadOfScalar(CGF.EmitLValue(TaskgroupDescriptors[Cnt]),
3529 TaskgroupDescriptors[Cnt]->getExprLoc());
Alexey Bataev88202be2017-07-27 13:20:36 +00003530 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003531 CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt));
Alexey Bataev88202be2017-07-27 13:20:36 +00003532 Replacement = Address(
3533 CGF.EmitScalarConversion(
3534 Replacement.getPointer(), CGF.getContext().VoidPtrTy,
3535 CGF.getContext().getPointerType(InRedPrivs[Cnt]->getType()),
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00003536 InRedPrivs[Cnt]->getExprLoc()),
Alexey Bataev88202be2017-07-27 13:20:36 +00003537 Replacement.getAlignment());
3538 Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement);
3539 InRedScope.addPrivate(RedCG.getBaseDecl(Cnt),
3540 [Replacement]() { return Replacement; });
Alexey Bataev88202be2017-07-27 13:20:36 +00003541 }
3542 }
3543 (void)InRedScope.Privatize();
Alexey Bataev48591dd2016-04-20 04:01:36 +00003544
3545 Action.Enter(CGF);
Alexey Bataev7292c292016-04-25 12:22:29 +00003546 BodyGen(CGF);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003547 };
James Y Knight9871db02019-02-05 16:42:33 +00003548 llvm::Function *OutlinedFn = CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
Alexey Bataev7292c292016-04-25 12:22:29 +00003549 S, *I, *PartId, *TaskT, S.getDirectiveKind(), CodeGen, Data.Tied,
3550 Data.NumberOfParts);
Alexey Bataev5bbcead2019-10-14 17:17:41 +00003551 OMPLexicalScope Scope(*this, S, llvm::None,
Alexey Bataev61205822019-12-04 09:50:21 -05003552 !isOpenMPParallelDirective(S.getDirectiveKind()) &&
3553 !isOpenMPSimdDirective(S.getDirectiveKind()));
Alexey Bataev7292c292016-04-25 12:22:29 +00003554 TaskGen(*this, OutlinedFn, Data);
3555}
3556
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003557static ImplicitParamDecl *
3558createImplicitFirstprivateForType(ASTContext &C, OMPTaskDataTy &Data,
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00003559 QualType Ty, CapturedDecl *CD,
3560 SourceLocation Loc) {
3561 auto *OrigVD = ImplicitParamDecl::Create(C, CD, Loc, /*Id=*/nullptr, Ty,
3562 ImplicitParamDecl::Other);
3563 auto *OrigRef = DeclRefExpr::Create(
3564 C, NestedNameSpecifierLoc(), SourceLocation(), OrigVD,
3565 /*RefersToEnclosingVariableOrCapture=*/false, Loc, Ty, VK_LValue);
3566 auto *PrivateVD = ImplicitParamDecl::Create(C, CD, Loc, /*Id=*/nullptr, Ty,
3567 ImplicitParamDecl::Other);
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003568 auto *PrivateRef = DeclRefExpr::Create(
3569 C, NestedNameSpecifierLoc(), SourceLocation(), PrivateVD,
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00003570 /*RefersToEnclosingVariableOrCapture=*/false, Loc, Ty, VK_LValue);
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003571 QualType ElemType = C.getBaseElementType(Ty);
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00003572 auto *InitVD = ImplicitParamDecl::Create(C, CD, Loc, /*Id=*/nullptr, ElemType,
3573 ImplicitParamDecl::Other);
3574 auto *InitRef = DeclRefExpr::Create(
3575 C, NestedNameSpecifierLoc(), SourceLocation(), InitVD,
3576 /*RefersToEnclosingVariableOrCapture=*/false, Loc, ElemType, VK_LValue);
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003577 PrivateVD->setInitStyle(VarDecl::CInit);
3578 PrivateVD->setInit(ImplicitCastExpr::Create(C, ElemType, CK_LValueToRValue,
3579 InitRef, /*BasePath=*/nullptr,
3580 VK_RValue));
3581 Data.FirstprivateVars.emplace_back(OrigRef);
3582 Data.FirstprivateCopies.emplace_back(PrivateRef);
3583 Data.FirstprivateInits.emplace_back(InitRef);
3584 return OrigVD;
3585}
3586
3587void CodeGenFunction::EmitOMPTargetTaskBasedDirective(
3588 const OMPExecutableDirective &S, const RegionCodeGenTy &BodyGen,
3589 OMPTargetDataInfo &InputInfo) {
3590 // Emit outlined function for task construct.
Alexey Bataevddf3db92018-04-13 17:31:06 +00003591 const CapturedStmt *CS = S.getCapturedStmt(OMPD_task);
3592 Address CapturedStruct = GenerateCapturedStmtArgument(*CS);
3593 QualType SharedsTy = getContext().getRecordType(CS->getCapturedRecordDecl());
3594 auto I = CS->getCapturedDecl()->param_begin();
3595 auto PartId = std::next(I);
3596 auto TaskT = std::next(I, 4);
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003597 OMPTaskDataTy Data;
3598 // The task is not final.
3599 Data.Final.setInt(/*IntVal=*/false);
3600 // Get list of firstprivate variables.
3601 for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) {
3602 auto IRef = C->varlist_begin();
3603 auto IElemInitRef = C->inits().begin();
3604 for (auto *IInit : C->private_copies()) {
3605 Data.FirstprivateVars.push_back(*IRef);
3606 Data.FirstprivateCopies.push_back(IInit);
3607 Data.FirstprivateInits.push_back(*IElemInitRef);
3608 ++IRef;
3609 ++IElemInitRef;
3610 }
3611 }
3612 OMPPrivateScope TargetScope(*this);
3613 VarDecl *BPVD = nullptr;
3614 VarDecl *PVD = nullptr;
3615 VarDecl *SVD = nullptr;
3616 if (InputInfo.NumberOfTargetItems > 0) {
3617 auto *CD = CapturedDecl::Create(
3618 getContext(), getContext().getTranslationUnitDecl(), /*NumParams=*/0);
3619 llvm::APInt ArrSize(/*numBits=*/32, InputInfo.NumberOfTargetItems);
3620 QualType BaseAndPointersType = getContext().getConstantArrayType(
Richard Smith772e2662019-10-04 01:25:59 +00003621 getContext().VoidPtrTy, ArrSize, nullptr, ArrayType::Normal,
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003622 /*IndexTypeQuals=*/0);
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00003623 BPVD = createImplicitFirstprivateForType(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003624 getContext(), Data, BaseAndPointersType, CD, S.getBeginLoc());
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00003625 PVD = createImplicitFirstprivateForType(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003626 getContext(), Data, BaseAndPointersType, CD, S.getBeginLoc());
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003627 QualType SizesType = getContext().getConstantArrayType(
Alexey Bataeva90fc662019-06-25 16:00:43 +00003628 getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1),
Richard Smith772e2662019-10-04 01:25:59 +00003629 ArrSize, nullptr, ArrayType::Normal,
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003630 /*IndexTypeQuals=*/0);
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00003631 SVD = createImplicitFirstprivateForType(getContext(), Data, SizesType, CD,
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003632 S.getBeginLoc());
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003633 TargetScope.addPrivate(
3634 BPVD, [&InputInfo]() { return InputInfo.BasePointersArray; });
3635 TargetScope.addPrivate(PVD,
3636 [&InputInfo]() { return InputInfo.PointersArray; });
3637 TargetScope.addPrivate(SVD,
3638 [&InputInfo]() { return InputInfo.SizesArray; });
3639 }
3640 (void)TargetScope.Privatize();
3641 // Build list of dependences.
3642 for (const auto *C : S.getClausesOfKind<OMPDependClause>())
Alexey Bataevddf3db92018-04-13 17:31:06 +00003643 for (const Expr *IRef : C->varlists())
Alexey Bataev43a919f2018-04-13 17:48:43 +00003644 Data.Dependences.emplace_back(C->getDependencyKind(), IRef);
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003645 auto &&CodeGen = [&Data, &S, CS, &BodyGen, BPVD, PVD, SVD,
3646 &InputInfo](CodeGenFunction &CGF, PrePostActionTy &Action) {
3647 // Set proper addresses for generated private copies.
3648 OMPPrivateScope Scope(CGF);
3649 if (!Data.FirstprivateVars.empty()) {
James Y Knight9871db02019-02-05 16:42:33 +00003650 llvm::FunctionType *CopyFnTy = llvm::FunctionType::get(
3651 CGF.Builder.getVoidTy(), {CGF.Builder.getInt8PtrTy()}, true);
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003652 enum { PrivatesParam = 2, CopyFnParam = 3 };
Alexey Bataevddf3db92018-04-13 17:31:06 +00003653 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
3654 CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(CopyFnParam)));
3655 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
3656 CS->getCapturedDecl()->getParam(PrivatesParam)));
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003657 // Map privates.
3658 llvm::SmallVector<std::pair<const VarDecl *, Address>, 16> PrivatePtrs;
3659 llvm::SmallVector<llvm::Value *, 16> CallArgs;
3660 CallArgs.push_back(PrivatesPtr);
Alexey Bataevddf3db92018-04-13 17:31:06 +00003661 for (const Expr *E : Data.FirstprivateVars) {
3662 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003663 Address PrivatePtr =
3664 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()),
3665 ".firstpriv.ptr.addr");
Alexey Bataevddf3db92018-04-13 17:31:06 +00003666 PrivatePtrs.emplace_back(VD, PrivatePtr);
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003667 CallArgs.push_back(PrivatePtr.getPointer());
3668 }
James Y Knight9871db02019-02-05 16:42:33 +00003669 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
3670 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
Alexey Bataevddf3db92018-04-13 17:31:06 +00003671 for (const auto &Pair : PrivatePtrs) {
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003672 Address Replacement(CGF.Builder.CreateLoad(Pair.second),
3673 CGF.getContext().getDeclAlign(Pair.first));
3674 Scope.addPrivate(Pair.first, [Replacement]() { return Replacement; });
3675 }
3676 }
3677 // Privatize all private variables except for in_reduction items.
3678 (void)Scope.Privatize();
Alexey Bataev8451efa2018-01-15 19:06:12 +00003679 if (InputInfo.NumberOfTargetItems > 0) {
3680 InputInfo.BasePointersArray = CGF.Builder.CreateConstArrayGEP(
James Y Knight751fe282019-02-09 22:22:28 +00003681 CGF.GetAddrOfLocalVar(BPVD), /*Index=*/0);
Alexey Bataev8451efa2018-01-15 19:06:12 +00003682 InputInfo.PointersArray = CGF.Builder.CreateConstArrayGEP(
James Y Knight751fe282019-02-09 22:22:28 +00003683 CGF.GetAddrOfLocalVar(PVD), /*Index=*/0);
Alexey Bataev8451efa2018-01-15 19:06:12 +00003684 InputInfo.SizesArray = CGF.Builder.CreateConstArrayGEP(
James Y Knight751fe282019-02-09 22:22:28 +00003685 CGF.GetAddrOfLocalVar(SVD), /*Index=*/0);
Alexey Bataev8451efa2018-01-15 19:06:12 +00003686 }
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003687
3688 Action.Enter(CGF);
Alexey Bataev475a7442018-01-12 19:39:11 +00003689 OMPLexicalScope LexScope(CGF, S, OMPD_task, /*EmitPreInitStmt=*/false);
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003690 BodyGen(CGF);
3691 };
James Y Knight9871db02019-02-05 16:42:33 +00003692 llvm::Function *OutlinedFn = CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003693 S, *I, *PartId, *TaskT, S.getDirectiveKind(), CodeGen, /*Tied=*/true,
3694 Data.NumberOfParts);
3695 llvm::APInt TrueOrFalse(32, S.hasClausesOfKind<OMPNowaitClause>() ? 1 : 0);
3696 IntegerLiteral IfCond(getContext(), TrueOrFalse,
3697 getContext().getIntTypeForBitwidth(32, /*Signed=*/0),
3698 SourceLocation());
3699
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003700 CGM.getOpenMPRuntime().emitTaskCall(*this, S.getBeginLoc(), S, OutlinedFn,
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003701 SharedsTy, CapturedStruct, &IfCond, Data);
3702}
3703
Alexey Bataev7292c292016-04-25 12:22:29 +00003704void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &S) {
3705 // Emit outlined function for task construct.
Alexey Bataev475a7442018-01-12 19:39:11 +00003706 const CapturedStmt *CS = S.getCapturedStmt(OMPD_task);
Alexey Bataevddf3db92018-04-13 17:31:06 +00003707 Address CapturedStruct = GenerateCapturedStmtArgument(*CS);
3708 QualType SharedsTy = getContext().getRecordType(CS->getCapturedRecordDecl());
Alexey Bataev1d677132015-04-22 13:57:31 +00003709 const Expr *IfCond = nullptr;
Alexey Bataev7371aa32015-09-03 08:45:56 +00003710 for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
3711 if (C->getNameModifier() == OMPD_unknown ||
3712 C->getNameModifier() == OMPD_task) {
3713 IfCond = C->getCondition();
3714 break;
3715 }
Alexey Bataev1d677132015-04-22 13:57:31 +00003716 }
Alexey Bataev7292c292016-04-25 12:22:29 +00003717
Alexey Bataev24b5bae2016-04-28 09:23:51 +00003718 OMPTaskDataTy Data;
3719 // Check if we should emit tied or untied task.
3720 Data.Tied = !S.getSingleClause<OMPUntiedClause>();
Alexey Bataev7292c292016-04-25 12:22:29 +00003721 auto &&BodyGen = [CS](CodeGenFunction &CGF, PrePostActionTy &) {
3722 CGF.EmitStmt(CS->getCapturedStmt());
3723 };
Alexey Bataev24b5bae2016-04-28 09:23:51 +00003724 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
James Y Knight9871db02019-02-05 16:42:33 +00003725 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00003726 const OMPTaskDataTy &Data) {
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003727 CGF.CGM.getOpenMPRuntime().emitTaskCall(CGF, S.getBeginLoc(), S, OutlinedFn,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00003728 SharedsTy, CapturedStruct, IfCond,
3729 Data);
Alexey Bataev7292c292016-04-25 12:22:29 +00003730 };
Alexey Bataev46978742020-01-30 10:46:11 -05003731 auto LPCRegion =
3732 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
Alexey Bataev475a7442018-01-12 19:39:11 +00003733 EmitOMPTaskBasedDirective(S, OMPD_task, BodyGen, TaskGen, Data);
Alexey Bataev9c2e8ee2014-07-11 11:25:16 +00003734}
3735
Alexey Bataev9f797f32015-02-05 05:57:51 +00003736void CodeGenFunction::EmitOMPTaskyieldDirective(
3737 const OMPTaskyieldDirective &S) {
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003738 CGM.getOpenMPRuntime().emitTaskyieldCall(*this, S.getBeginLoc());
Alexey Bataev68446b72014-07-18 07:47:19 +00003739}
3740
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00003741void CodeGenFunction::EmitOMPBarrierDirective(const OMPBarrierDirective &S) {
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003742 CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(), OMPD_barrier);
Alexey Bataev4d1dfea2014-07-18 09:11:51 +00003743}
3744
Alexey Bataev8b8e2022015-04-27 05:22:09 +00003745void CodeGenFunction::EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S) {
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003746 CGM.getOpenMPRuntime().emitTaskwaitCall(*this, S.getBeginLoc());
Alexey Bataev2df347a2014-07-18 10:17:07 +00003747}
3748
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00003749void CodeGenFunction::EmitOMPTaskgroupDirective(
3750 const OMPTaskgroupDirective &S) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003751 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
3752 Action.Enter(CGF);
Alexey Bataev3b1b8952017-07-25 15:53:26 +00003753 if (const Expr *E = S.getReductionRef()) {
3754 SmallVector<const Expr *, 4> LHSs;
3755 SmallVector<const Expr *, 4> RHSs;
3756 OMPTaskDataTy Data;
3757 for (const auto *C : S.getClausesOfKind<OMPTaskReductionClause>()) {
3758 auto IPriv = C->privates().begin();
3759 auto IRed = C->reduction_ops().begin();
3760 auto ILHS = C->lhs_exprs().begin();
3761 auto IRHS = C->rhs_exprs().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00003762 for (const Expr *Ref : C->varlists()) {
Alexey Bataev3b1b8952017-07-25 15:53:26 +00003763 Data.ReductionVars.emplace_back(Ref);
3764 Data.ReductionCopies.emplace_back(*IPriv);
3765 Data.ReductionOps.emplace_back(*IRed);
3766 LHSs.emplace_back(*ILHS);
3767 RHSs.emplace_back(*IRHS);
3768 std::advance(IPriv, 1);
3769 std::advance(IRed, 1);
3770 std::advance(ILHS, 1);
3771 std::advance(IRHS, 1);
3772 }
3773 }
3774 llvm::Value *ReductionDesc =
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003775 CGF.CGM.getOpenMPRuntime().emitTaskReductionInit(CGF, S.getBeginLoc(),
Alexey Bataev3b1b8952017-07-25 15:53:26 +00003776 LHSs, RHSs, Data);
3777 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3778 CGF.EmitVarDecl(*VD);
3779 CGF.EmitStoreOfScalar(ReductionDesc, CGF.GetAddrOfLocalVar(VD),
3780 /*Volatile=*/false, E->getType());
3781 }
Alexey Bataev475a7442018-01-12 19:39:11 +00003782 CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00003783 };
Alexey Bataev475a7442018-01-12 19:39:11 +00003784 OMPLexicalScope Scope(*this, S, OMPD_unknown);
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003785 CGM.getOpenMPRuntime().emitTaskgroupRegion(*this, CodeGen, S.getBeginLoc());
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00003786}
3787
Alexey Bataevcc37cc12014-11-20 04:34:54 +00003788void CodeGenFunction::EmitOMPFlushDirective(const OMPFlushDirective &S) {
Alexey Bataeve8e05de2020-02-07 12:22:23 -05003789 llvm::AtomicOrdering AO = S.getSingleClause<OMPFlushClause>()
3790 ? llvm::AtomicOrdering::NotAtomic
3791 : llvm::AtomicOrdering::AcquireRelease;
Alexey Bataevddf3db92018-04-13 17:31:06 +00003792 CGM.getOpenMPRuntime().emitFlush(
3793 *this,
3794 [&S]() -> ArrayRef<const Expr *> {
3795 if (const auto *FlushClause = S.getSingleClause<OMPFlushClause>())
3796 return llvm::makeArrayRef(FlushClause->varlist_begin(),
3797 FlushClause->varlist_end());
3798 return llvm::None;
3799 }(),
Alexey Bataeve8e05de2020-02-07 12:22:23 -05003800 S.getBeginLoc(), AO);
Alexey Bataev6125da92014-07-21 11:26:11 +00003801}
3802
Alexey Bataeve46f0fe2020-03-04 14:37:51 -05003803void CodeGenFunction::EmitOMPDepobjDirective(const OMPDepobjDirective &S) {
3804 const auto *DO = S.getSingleClause<OMPDepobjClause>();
3805 LValue DOLVal = EmitLValue(DO->getDepobj());
3806 if (const auto *DC = S.getSingleClause<OMPDependClause>()) {
3807 SmallVector<std::pair<OpenMPDependClauseKind, const Expr *>, 4>
3808 Dependencies;
3809 for (const Expr *IRef : DC->varlists())
3810 Dependencies.emplace_back(DC->getDependencyKind(), IRef);
3811 Address DepAddr = CGM.getOpenMPRuntime().emitDependClause(
3812 *this, Dependencies, /*ForDepobj=*/true, DC->getBeginLoc());
3813 EmitStoreOfScalar(DepAddr.getPointer(), DOLVal);
Alexey Bataevb27ff4d2020-03-04 16:15:28 -05003814 return;
3815 }
3816 if (const auto *DC = S.getSingleClause<OMPDestroyClause>()) {
3817 CGM.getOpenMPRuntime().emitDestroyClause(*this, DOLVal, DC->getBeginLoc());
3818 return;
Alexey Bataeve46f0fe2020-03-04 14:37:51 -05003819 }
3820}
Alexey Bataevc112e942020-02-28 09:52:15 -05003821
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003822void CodeGenFunction::EmitOMPDistributeLoop(const OMPLoopDirective &S,
3823 const CodeGenLoopTy &CodeGenLoop,
3824 Expr *IncExpr) {
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003825 // Emit the loop iteration variable.
Alexey Bataevddf3db92018-04-13 17:31:06 +00003826 const auto *IVExpr = cast<DeclRefExpr>(S.getIterationVariable());
3827 const auto *IVDecl = cast<VarDecl>(IVExpr->getDecl());
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003828 EmitVarDecl(*IVDecl);
3829
3830 // Emit the iterations count variable.
3831 // If it is not a variable, Sema decided to calculate iterations count on each
3832 // iteration (e.g., it is foldable into a constant).
Alexey Bataevddf3db92018-04-13 17:31:06 +00003833 if (const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003834 EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
3835 // Emit calculation of the iterations count.
3836 EmitIgnoredExpr(S.getCalcLastIteration());
3837 }
3838
Alexey Bataevddf3db92018-04-13 17:31:06 +00003839 CGOpenMPRuntime &RT = CGM.getOpenMPRuntime();
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003840
Carlo Bertolli962bb802017-01-03 18:24:42 +00003841 bool HasLastprivateClause = false;
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003842 // Check pre-condition.
3843 {
Alexey Bataev5a3af132016-03-29 08:58:54 +00003844 OMPLoopScope PreInitScope(*this, S);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003845 // Skip the entire loop if we don't meet the precondition.
3846 // If the condition constant folds and can be elided, avoid emitting the
3847 // whole loop.
3848 bool CondConstant;
3849 llvm::BasicBlock *ContBlock = nullptr;
3850 if (ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
3851 if (!CondConstant)
3852 return;
3853 } else {
Alexey Bataevddf3db92018-04-13 17:31:06 +00003854 llvm::BasicBlock *ThenBlock = createBasicBlock("omp.precond.then");
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003855 ContBlock = createBasicBlock("omp.precond.end");
3856 emitPreCond(*this, S, S.getPreCond(), ThenBlock, ContBlock,
3857 getProfileCount(&S));
3858 EmitBlock(ThenBlock);
3859 incrementProfileCounter(&S);
3860 }
3861
Alexey Bataev617db5f2017-12-04 15:38:33 +00003862 emitAlignedClause(*this, S);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003863 // Emit 'then' code.
3864 {
3865 // Emit helper vars inits.
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003866
3867 LValue LB = EmitOMPHelperVar(
3868 *this, cast<DeclRefExpr>(
3869 (isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
3870 ? S.getCombinedLowerBoundVariable()
3871 : S.getLowerBoundVariable())));
3872 LValue UB = EmitOMPHelperVar(
3873 *this, cast<DeclRefExpr>(
3874 (isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
3875 ? S.getCombinedUpperBoundVariable()
3876 : S.getUpperBoundVariable())));
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003877 LValue ST =
3878 EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getStrideVariable()));
3879 LValue IL =
3880 EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getIsLastIterVariable()));
3881
3882 OMPPrivateScope LoopScope(*this);
Carlo Bertolli962bb802017-01-03 18:24:42 +00003883 if (EmitOMPFirstprivateClause(S, LoopScope)) {
Alexey Bataev617db5f2017-12-04 15:38:33 +00003884 // Emit implicit barrier to synchronize threads and avoid data races
3885 // on initialization of firstprivate variables and post-update of
Carlo Bertolli962bb802017-01-03 18:24:42 +00003886 // lastprivate variables.
3887 CGM.getOpenMPRuntime().emitBarrierCall(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003888 *this, S.getBeginLoc(), OMPD_unknown, /*EmitChecks=*/false,
Alexey Bataev617db5f2017-12-04 15:38:33 +00003889 /*ForceSimpleCall=*/true);
Carlo Bertolli962bb802017-01-03 18:24:42 +00003890 }
3891 EmitOMPPrivateClause(S, LoopScope);
Alexey Bataev617db5f2017-12-04 15:38:33 +00003892 if (isOpenMPSimdDirective(S.getDirectiveKind()) &&
Alexey Bataev999277a2017-12-06 14:31:09 +00003893 !isOpenMPParallelDirective(S.getDirectiveKind()) &&
3894 !isOpenMPTeamsDirective(S.getDirectiveKind()))
Alexey Bataev617db5f2017-12-04 15:38:33 +00003895 EmitOMPReductionClauseInit(S, LoopScope);
Carlo Bertolli962bb802017-01-03 18:24:42 +00003896 HasLastprivateClause = EmitOMPLastprivateClauseInit(S, LoopScope);
Alexey Bataev5dff95c2016-04-22 03:56:56 +00003897 EmitOMPPrivateLoopCounters(S, LoopScope);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003898 (void)LoopScope.Privatize();
Alexey Bataev60705422018-10-30 15:50:12 +00003899 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()))
3900 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*this, S);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003901
3902 // Detect the distribute schedule kind and chunk.
3903 llvm::Value *Chunk = nullptr;
3904 OpenMPDistScheduleClauseKind ScheduleKind = OMPC_DIST_SCHEDULE_unknown;
Alexey Bataevddf3db92018-04-13 17:31:06 +00003905 if (const auto *C = S.getSingleClause<OMPDistScheduleClause>()) {
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003906 ScheduleKind = C->getDistScheduleKind();
Alexey Bataevddf3db92018-04-13 17:31:06 +00003907 if (const Expr *Ch = C->getChunkSize()) {
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003908 Chunk = EmitScalarExpr(Ch);
3909 Chunk = EmitScalarConversion(Chunk, Ch->getType(),
Alexey Bataev617db5f2017-12-04 15:38:33 +00003910 S.getIterationVariable()->getType(),
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003911 S.getBeginLoc());
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003912 }
Gheorghe-Teodor Bercea02650d42018-09-27 19:22:56 +00003913 } else {
3914 // Default behaviour for dist_schedule clause.
3915 CGM.getOpenMPRuntime().getDefaultDistScheduleAndChunk(
3916 *this, S, ScheduleKind, Chunk);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003917 }
3918 const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
3919 const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
3920
3921 // OpenMP [2.10.8, distribute Construct, Description]
3922 // If dist_schedule is specified, kind must be static. If specified,
3923 // iterations are divided into chunks of size chunk_size, chunks are
3924 // assigned to the teams of the league in a round-robin fashion in the
3925 // order of the team number. When no chunk_size is specified, the
3926 // iteration space is divided into chunks that are approximately equal
3927 // in size, and at most one chunk is distributed to each team of the
3928 // league. The size of the chunks is unspecified in this case.
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00003929 bool StaticChunked = RT.isStaticChunked(
3930 ScheduleKind, /* Chunked */ Chunk != nullptr) &&
3931 isOpenMPLoopBoundSharingDirective(S.getDirectiveKind());
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003932 if (RT.isStaticNonchunked(ScheduleKind,
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00003933 /* Chunked */ Chunk != nullptr) ||
3934 StaticChunked) {
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003935 CGOpenMPRuntime::StaticRTInput StaticInit(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08003936 IVSize, IVSigned, /* Ordered = */ false, IL.getAddress(*this),
3937 LB.getAddress(*this), UB.getAddress(*this), ST.getAddress(*this),
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00003938 StaticChunked ? Chunk : nullptr);
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003939 RT.emitDistributeStaticInit(*this, S.getBeginLoc(), ScheduleKind,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003940 StaticInit);
Alexey Bataevddf3db92018-04-13 17:31:06 +00003941 JumpDest LoopExit =
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003942 getJumpDestInCurrentScope(createBasicBlock("omp.loop.exit"));
3943 // UB = min(UB, GlobalUB);
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003944 EmitIgnoredExpr(isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
3945 ? S.getCombinedEnsureUpperBound()
3946 : S.getEnsureUpperBound());
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003947 // IV = LB;
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003948 EmitIgnoredExpr(isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
3949 ? S.getCombinedInit()
3950 : S.getInit());
3951
Alexey Bataevddf3db92018-04-13 17:31:06 +00003952 const Expr *Cond =
3953 isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
3954 ? S.getCombinedCond()
3955 : S.getCond();
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003956
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00003957 if (StaticChunked)
3958 Cond = S.getCombinedDistCond();
3959
3960 // For static unchunked schedules generate:
3961 //
3962 // 1. For distribute alone, codegen
3963 // while (idx <= UB) {
3964 // BODY;
3965 // ++idx;
3966 // }
3967 //
3968 // 2. When combined with 'for' (e.g. as in 'distribute parallel for')
3969 // while (idx <= UB) {
3970 // <CodeGen rest of pragma>(LB, UB);
3971 // idx += ST;
3972 // }
3973 //
3974 // For static chunk one schedule generate:
3975 //
3976 // while (IV <= GlobalUB) {
3977 // <CodeGen rest of pragma>(LB, UB);
3978 // LB += ST;
3979 // UB += ST;
3980 // UB = min(UB, GlobalUB);
3981 // IV = LB;
3982 // }
3983 //
Alexey Bataev779a1802019-12-06 12:21:31 -05003984 emitCommonSimdLoop(
3985 *this, S,
3986 [&S](CodeGenFunction &CGF, PrePostActionTy &) {
3987 if (isOpenMPSimdDirective(S.getDirectiveKind()))
3988 CGF.EmitOMPSimdInit(S, /*IsMonotonic=*/true);
3989 },
3990 [&S, &LoopScope, Cond, IncExpr, LoopExit, &CodeGenLoop,
3991 StaticChunked](CodeGenFunction &CGF, PrePostActionTy &) {
3992 CGF.EmitOMPInnerLoop(
3993 S, LoopScope.requiresCleanups(), Cond, IncExpr,
3994 [&S, LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
3995 CodeGenLoop(CGF, S, LoopExit);
3996 },
3997 [&S, StaticChunked](CodeGenFunction &CGF) {
3998 if (StaticChunked) {
3999 CGF.EmitIgnoredExpr(S.getCombinedNextLowerBound());
4000 CGF.EmitIgnoredExpr(S.getCombinedNextUpperBound());
4001 CGF.EmitIgnoredExpr(S.getCombinedEnsureUpperBound());
4002 CGF.EmitIgnoredExpr(S.getCombinedInit());
4003 }
4004 });
4005 });
Carlo Bertollifc35ad22016-03-07 16:04:49 +00004006 EmitBlock(LoopExit.getBlock());
4007 // Tell the runtime we are done.
Alexey Bataevc33ba8c2020-01-17 14:05:40 -05004008 RT.emitForStaticFinish(*this, S.getEndLoc(), S.getDirectiveKind());
Carlo Bertollifc35ad22016-03-07 16:04:49 +00004009 } else {
4010 // Emit the outer loop, which requests its work chunk [LB..UB] from
4011 // runtime and runs the inner loop to process it.
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00004012 const OMPLoopArguments LoopArguments = {
Akira Hatanakaf139ae32019-12-03 15:17:01 -08004013 LB.getAddress(*this), UB.getAddress(*this), ST.getAddress(*this),
4014 IL.getAddress(*this), Chunk};
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00004015 EmitOMPDistributeOuterLoop(ScheduleKind, S, LoopScope, LoopArguments,
4016 CodeGenLoop);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00004017 }
Alexey Bataev617db5f2017-12-04 15:38:33 +00004018 if (isOpenMPSimdDirective(S.getDirectiveKind())) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00004019 EmitOMPSimdFinal(S, [IL, &S](CodeGenFunction &CGF) {
Alexey Bataev617db5f2017-12-04 15:38:33 +00004020 return CGF.Builder.CreateIsNotNull(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00004021 CGF.EmitLoadOfScalar(IL, S.getBeginLoc()));
Alexey Bataev617db5f2017-12-04 15:38:33 +00004022 });
4023 }
Carlo Bertollibeda2142018-02-22 19:38:14 +00004024 if (isOpenMPSimdDirective(S.getDirectiveKind()) &&
4025 !isOpenMPParallelDirective(S.getDirectiveKind()) &&
4026 !isOpenMPTeamsDirective(S.getDirectiveKind())) {
Jonas Hahnfeld5aaaece2018-10-02 19:12:47 +00004027 EmitOMPReductionClauseFinal(S, OMPD_simd);
Carlo Bertollibeda2142018-02-22 19:38:14 +00004028 // Emit post-update of the reduction variables if IsLastIter != 0.
4029 emitPostUpdateForReductionClause(
Alexey Bataevddf3db92018-04-13 17:31:06 +00004030 *this, S, [IL, &S](CodeGenFunction &CGF) {
Carlo Bertollibeda2142018-02-22 19:38:14 +00004031 return CGF.Builder.CreateIsNotNull(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00004032 CGF.EmitLoadOfScalar(IL, S.getBeginLoc()));
Carlo Bertollibeda2142018-02-22 19:38:14 +00004033 });
Alexey Bataev617db5f2017-12-04 15:38:33 +00004034 }
Carlo Bertolli962bb802017-01-03 18:24:42 +00004035 // Emit final copy of the lastprivate variables if IsLastIter != 0.
Alexey Bataev617db5f2017-12-04 15:38:33 +00004036 if (HasLastprivateClause) {
Carlo Bertolli962bb802017-01-03 18:24:42 +00004037 EmitOMPLastprivateClauseFinal(
4038 S, /*NoFinals=*/false,
Stephen Kellyf2ceec42018-08-09 21:08:08 +00004039 Builder.CreateIsNotNull(EmitLoadOfScalar(IL, S.getBeginLoc())));
Alexey Bataev617db5f2017-12-04 15:38:33 +00004040 }
Carlo Bertollifc35ad22016-03-07 16:04:49 +00004041 }
4042
4043 // We're now done with the loop, so jump to the continuation block.
4044 if (ContBlock) {
4045 EmitBranch(ContBlock);
4046 EmitBlock(ContBlock, true);
4047 }
4048 }
4049}
4050
Carlo Bertolli6200a3d2015-12-14 14:51:25 +00004051void CodeGenFunction::EmitOMPDistributeDirective(
4052 const OMPDistributeDirective &S) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004053 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00004054 CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc());
Carlo Bertollifc35ad22016-03-07 16:04:49 +00004055 };
Alexey Bataev475a7442018-01-12 19:39:11 +00004056 OMPLexicalScope Scope(*this, S, OMPD_unknown);
Alexey Bataev10a54312017-11-27 16:54:08 +00004057 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_distribute, CodeGen);
Carlo Bertolli6200a3d2015-12-14 14:51:25 +00004058}
4059
Alexey Bataev5f600d62015-09-29 03:48:57 +00004060static llvm::Function *emitOutlinedOrderedFunction(CodeGenModule &CGM,
Alexey Bataevc33ba8c2020-01-17 14:05:40 -05004061 const CapturedStmt *S,
4062 SourceLocation Loc) {
Alexey Bataev5f600d62015-09-29 03:48:57 +00004063 CodeGenFunction CGF(CGM, /*suppressNewContext=*/true);
4064 CodeGenFunction::CGCapturedStmtInfo CapStmtInfo;
4065 CGF.CapturedStmtInfo = &CapStmtInfo;
Alexey Bataevc33ba8c2020-01-17 14:05:40 -05004066 llvm::Function *Fn = CGF.GenerateOpenMPCapturedStmtFunction(*S, Loc);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00004067 Fn->setDoesNotRecurse();
Alexey Bataev5f600d62015-09-29 03:48:57 +00004068 return Fn;
4069}
4070
Alexey Bataev98eb6e32015-04-22 11:15:40 +00004071void CodeGenFunction::EmitOMPOrderedDirective(const OMPOrderedDirective &S) {
Alexey Bataev475a7442018-01-12 19:39:11 +00004072 if (S.hasClausesOfKind<OMPDependClause>()) {
4073 assert(!S.getAssociatedStmt() &&
4074 "No associated statement must be in ordered depend construct.");
Alexey Bataev8b427062016-05-25 12:36:08 +00004075 for (const auto *DC : S.getClausesOfKind<OMPDependClause>())
4076 CGM.getOpenMPRuntime().emitDoacrossOrdered(*this, DC);
Alexey Bataev8ef31412015-12-18 07:58:25 +00004077 return;
Alexey Bataev8b427062016-05-25 12:36:08 +00004078 }
Alexey Bataevddf3db92018-04-13 17:31:06 +00004079 const auto *C = S.getSingleClause<OMPSIMDClause>();
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004080 auto &&CodeGen = [&S, C, this](CodeGenFunction &CGF,
4081 PrePostActionTy &Action) {
Alexey Bataev475a7442018-01-12 19:39:11 +00004082 const CapturedStmt *CS = S.getInnermostCapturedStmt();
Alexey Bataev5f600d62015-09-29 03:48:57 +00004083 if (C) {
Alexey Bataev5f600d62015-09-29 03:48:57 +00004084 llvm::SmallVector<llvm::Value *, 16> CapturedVars;
4085 CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
Alexey Bataevc33ba8c2020-01-17 14:05:40 -05004086 llvm::Function *OutlinedFn =
4087 emitOutlinedOrderedFunction(CGM, CS, S.getBeginLoc());
Stephen Kellyf2ceec42018-08-09 21:08:08 +00004088 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, S.getBeginLoc(),
Alexey Bataev3c595a62017-08-14 15:01:03 +00004089 OutlinedFn, CapturedVars);
Alexey Bataev5f600d62015-09-29 03:48:57 +00004090 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004091 Action.Enter(CGF);
Alexey Bataev475a7442018-01-12 19:39:11 +00004092 CGF.EmitStmt(CS->getCapturedStmt());
Alexey Bataev5f600d62015-09-29 03:48:57 +00004093 }
Alexey Bataev98eb6e32015-04-22 11:15:40 +00004094 };
Alexey Bataev475a7442018-01-12 19:39:11 +00004095 OMPLexicalScope Scope(*this, S, OMPD_unknown);
Stephen Kellyf2ceec42018-08-09 21:08:08 +00004096 CGM.getOpenMPRuntime().emitOrderedRegion(*this, CodeGen, S.getBeginLoc(), !C);
Alexey Bataev9fb6e642014-07-22 06:45:04 +00004097}
4098
Alexey Bataevb57056f2015-01-22 06:17:56 +00004099static llvm::Value *convertToScalarValue(CodeGenFunction &CGF, RValue Val,
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00004100 QualType SrcType, QualType DestType,
4101 SourceLocation Loc) {
Alexey Bataevb57056f2015-01-22 06:17:56 +00004102 assert(CGF.hasScalarEvaluationKind(DestType) &&
4103 "DestType must have scalar evaluation kind.");
4104 assert(!Val.isAggregate() && "Must be a scalar or complex.");
Alexey Bataevddf3db92018-04-13 17:31:06 +00004105 return Val.isScalar() ? CGF.EmitScalarConversion(Val.getScalarVal(), SrcType,
4106 DestType, Loc)
4107 : CGF.EmitComplexToScalarConversion(
4108 Val.getComplexVal(), SrcType, DestType, Loc);
Alexey Bataevb57056f2015-01-22 06:17:56 +00004109}
4110
4111static CodeGenFunction::ComplexPairTy
4112convertToComplexValue(CodeGenFunction &CGF, RValue Val, QualType SrcType,
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00004113 QualType DestType, SourceLocation Loc) {
Alexey Bataevb57056f2015-01-22 06:17:56 +00004114 assert(CGF.getEvaluationKind(DestType) == TEK_Complex &&
4115 "DestType must have complex evaluation kind.");
4116 CodeGenFunction::ComplexPairTy ComplexVal;
4117 if (Val.isScalar()) {
4118 // Convert the input element to the element type of the complex.
Alexey Bataevddf3db92018-04-13 17:31:06 +00004119 QualType DestElementType =
4120 DestType->castAs<ComplexType>()->getElementType();
4121 llvm::Value *ScalarVal = CGF.EmitScalarConversion(
4122 Val.getScalarVal(), SrcType, DestElementType, Loc);
Alexey Bataevb57056f2015-01-22 06:17:56 +00004123 ComplexVal = CodeGenFunction::ComplexPairTy(
4124 ScalarVal, llvm::Constant::getNullValue(ScalarVal->getType()));
4125 } else {
4126 assert(Val.isComplex() && "Must be a scalar or complex.");
Alexey Bataevddf3db92018-04-13 17:31:06 +00004127 QualType SrcElementType = SrcType->castAs<ComplexType>()->getElementType();
4128 QualType DestElementType =
4129 DestType->castAs<ComplexType>()->getElementType();
Alexey Bataevb57056f2015-01-22 06:17:56 +00004130 ComplexVal.first = CGF.EmitScalarConversion(
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00004131 Val.getComplexVal().first, SrcElementType, DestElementType, Loc);
Alexey Bataevb57056f2015-01-22 06:17:56 +00004132 ComplexVal.second = CGF.EmitScalarConversion(
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00004133 Val.getComplexVal().second, SrcElementType, DestElementType, Loc);
Alexey Bataevb57056f2015-01-22 06:17:56 +00004134 }
4135 return ComplexVal;
4136}
4137
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004138static void emitSimpleAtomicStore(CodeGenFunction &CGF, llvm::AtomicOrdering AO,
Alexey Bataev5e018f92015-04-23 06:35:10 +00004139 LValue LVal, RValue RVal) {
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004140 if (LVal.isGlobalReg())
Alexey Bataev5e018f92015-04-23 06:35:10 +00004141 CGF.EmitStoreThroughGlobalRegLValue(RVal, LVal);
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004142 else
4143 CGF.EmitAtomicStore(RVal, LVal, AO, LVal.isVolatile(), /*isInit=*/false);
4144}
4145
4146static RValue emitSimpleAtomicLoad(CodeGenFunction &CGF,
4147 llvm::AtomicOrdering AO, LValue LVal,
4148 SourceLocation Loc) {
4149 if (LVal.isGlobalReg())
4150 return CGF.EmitLoadOfLValue(LVal, Loc);
4151 return CGF.EmitAtomicLoad(
4152 LVal, Loc, llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO),
4153 LVal.isVolatile());
Alexey Bataev5e018f92015-04-23 06:35:10 +00004154}
4155
Alexey Bataev8524d152016-01-21 12:35:58 +00004156void CodeGenFunction::emitOMPSimpleStore(LValue LVal, RValue RVal,
4157 QualType RValTy, SourceLocation Loc) {
4158 switch (getEvaluationKind(LVal.getType())) {
Alexey Bataev5e018f92015-04-23 06:35:10 +00004159 case TEK_Scalar:
Alexey Bataev8524d152016-01-21 12:35:58 +00004160 EmitStoreThroughLValue(RValue::get(convertToScalarValue(
4161 *this, RVal, RValTy, LVal.getType(), Loc)),
4162 LVal);
Alexey Bataev5e018f92015-04-23 06:35:10 +00004163 break;
4164 case TEK_Complex:
Alexey Bataev8524d152016-01-21 12:35:58 +00004165 EmitStoreOfComplex(
4166 convertToComplexValue(*this, RVal, RValTy, LVal.getType(), Loc), LVal,
Alexey Bataev5e018f92015-04-23 06:35:10 +00004167 /*isInit=*/false);
4168 break;
4169 case TEK_Aggregate:
4170 llvm_unreachable("Must be a scalar or complex.");
4171 }
4172}
4173
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004174static void emitOMPAtomicReadExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO,
Alexey Bataevb57056f2015-01-22 06:17:56 +00004175 const Expr *X, const Expr *V,
4176 SourceLocation Loc) {
4177 // v = x;
4178 assert(V->isLValue() && "V of 'omp atomic read' is not lvalue");
4179 assert(X->isLValue() && "X of 'omp atomic read' is not lvalue");
4180 LValue XLValue = CGF.EmitLValue(X);
4181 LValue VLValue = CGF.EmitLValue(V);
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004182 RValue Res = emitSimpleAtomicLoad(CGF, AO, XLValue, Loc);
4183 // OpenMP, 2.17.7, atomic Construct
4184 // If the read or capture clause is specified and the acquire, acq_rel, or
4185 // seq_cst clause is specified then the strong flush on exit from the atomic
4186 // operation is also an acquire flush.
4187 switch (AO) {
4188 case llvm::AtomicOrdering::Acquire:
4189 case llvm::AtomicOrdering::AcquireRelease:
4190 case llvm::AtomicOrdering::SequentiallyConsistent:
4191 CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc,
4192 llvm::AtomicOrdering::Acquire);
4193 break;
4194 case llvm::AtomicOrdering::Monotonic:
4195 case llvm::AtomicOrdering::Release:
4196 break;
4197 case llvm::AtomicOrdering::NotAtomic:
4198 case llvm::AtomicOrdering::Unordered:
4199 llvm_unreachable("Unexpected ordering.");
4200 }
Alexey Bataev8524d152016-01-21 12:35:58 +00004201 CGF.emitOMPSimpleStore(VLValue, Res, X->getType().getNonReferenceType(), Loc);
Alexey Bataevf117f2c2020-01-28 11:19:45 -05004202 CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, V);
Alexey Bataevb57056f2015-01-22 06:17:56 +00004203}
4204
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004205static void emitOMPAtomicWriteExpr(CodeGenFunction &CGF,
4206 llvm::AtomicOrdering AO, const Expr *X,
4207 const Expr *E, SourceLocation Loc) {
Alexey Bataevb8329262015-02-27 06:33:30 +00004208 // x = expr;
4209 assert(X->isLValue() && "X of 'omp atomic write' is not lvalue");
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004210 emitSimpleAtomicStore(CGF, AO, CGF.EmitLValue(X), CGF.EmitAnyExpr(E));
Alexey Bataevf117f2c2020-01-28 11:19:45 -05004211 CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, X);
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004212 // OpenMP, 2.17.7, atomic Construct
4213 // If the write, update, or capture clause is specified and the release,
4214 // acq_rel, or seq_cst clause is specified then the strong flush on entry to
4215 // the atomic operation is also a release flush.
4216 switch (AO) {
4217 case llvm::AtomicOrdering::Release:
4218 case llvm::AtomicOrdering::AcquireRelease:
4219 case llvm::AtomicOrdering::SequentiallyConsistent:
4220 CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc,
4221 llvm::AtomicOrdering::Release);
4222 break;
4223 case llvm::AtomicOrdering::Acquire:
4224 case llvm::AtomicOrdering::Monotonic:
4225 break;
4226 case llvm::AtomicOrdering::NotAtomic:
4227 case llvm::AtomicOrdering::Unordered:
4228 llvm_unreachable("Unexpected ordering.");
4229 }
Alexey Bataevb8329262015-02-27 06:33:30 +00004230}
4231
Benjamin Kramer439ee9d2015-05-01 13:59:53 +00004232static std::pair<bool, RValue> emitOMPAtomicRMW(CodeGenFunction &CGF, LValue X,
4233 RValue Update,
4234 BinaryOperatorKind BO,
4235 llvm::AtomicOrdering AO,
4236 bool IsXLHSInRHSPart) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00004237 ASTContext &Context = CGF.getContext();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004238 // Allow atomicrmw only if 'x' and 'update' are integer values, lvalue for 'x'
Alexey Bataevb4505a72015-03-30 05:20:59 +00004239 // expression is simple and atomic is allowed for the given type for the
4240 // target platform.
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004241 if (BO == BO_Comma || !Update.isScalar() ||
Akira Hatanakaf139ae32019-12-03 15:17:01 -08004242 !Update.getScalarVal()->getType()->isIntegerTy() || !X.isSimple() ||
4243 (!isa<llvm::ConstantInt>(Update.getScalarVal()) &&
4244 (Update.getScalarVal()->getType() !=
4245 X.getAddress(CGF).getElementType())) ||
4246 !X.getAddress(CGF).getElementType()->isIntegerTy() ||
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004247 !Context.getTargetInfo().hasBuiltinAtomic(
4248 Context.getTypeSize(X.getType()), Context.toBits(X.getAlignment())))
Alexey Bataev5e018f92015-04-23 06:35:10 +00004249 return std::make_pair(false, RValue::get(nullptr));
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004250
4251 llvm::AtomicRMWInst::BinOp RMWOp;
4252 switch (BO) {
4253 case BO_Add:
4254 RMWOp = llvm::AtomicRMWInst::Add;
4255 break;
4256 case BO_Sub:
4257 if (!IsXLHSInRHSPart)
Alexey Bataev5e018f92015-04-23 06:35:10 +00004258 return std::make_pair(false, RValue::get(nullptr));
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004259 RMWOp = llvm::AtomicRMWInst::Sub;
4260 break;
4261 case BO_And:
4262 RMWOp = llvm::AtomicRMWInst::And;
4263 break;
4264 case BO_Or:
4265 RMWOp = llvm::AtomicRMWInst::Or;
4266 break;
4267 case BO_Xor:
4268 RMWOp = llvm::AtomicRMWInst::Xor;
4269 break;
4270 case BO_LT:
4271 RMWOp = X.getType()->hasSignedIntegerRepresentation()
4272 ? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Min
4273 : llvm::AtomicRMWInst::Max)
4274 : (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMin
4275 : llvm::AtomicRMWInst::UMax);
4276 break;
4277 case BO_GT:
4278 RMWOp = X.getType()->hasSignedIntegerRepresentation()
4279 ? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Max
4280 : llvm::AtomicRMWInst::Min)
4281 : (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMax
4282 : llvm::AtomicRMWInst::UMin);
4283 break;
Alexey Bataev5e018f92015-04-23 06:35:10 +00004284 case BO_Assign:
4285 RMWOp = llvm::AtomicRMWInst::Xchg;
4286 break;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004287 case BO_Mul:
4288 case BO_Div:
4289 case BO_Rem:
4290 case BO_Shl:
4291 case BO_Shr:
4292 case BO_LAnd:
4293 case BO_LOr:
Alexey Bataev5e018f92015-04-23 06:35:10 +00004294 return std::make_pair(false, RValue::get(nullptr));
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004295 case BO_PtrMemD:
4296 case BO_PtrMemI:
4297 case BO_LE:
4298 case BO_GE:
4299 case BO_EQ:
4300 case BO_NE:
Richard Smithc70f1d62017-12-14 15:16:18 +00004301 case BO_Cmp:
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004302 case BO_AddAssign:
4303 case BO_SubAssign:
4304 case BO_AndAssign:
4305 case BO_OrAssign:
4306 case BO_XorAssign:
4307 case BO_MulAssign:
4308 case BO_DivAssign:
4309 case BO_RemAssign:
4310 case BO_ShlAssign:
4311 case BO_ShrAssign:
4312 case BO_Comma:
4313 llvm_unreachable("Unsupported atomic update operation");
4314 }
Alexey Bataevddf3db92018-04-13 17:31:06 +00004315 llvm::Value *UpdateVal = Update.getScalarVal();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004316 if (auto *IC = dyn_cast<llvm::ConstantInt>(UpdateVal)) {
4317 UpdateVal = CGF.Builder.CreateIntCast(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08004318 IC, X.getAddress(CGF).getElementType(),
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004319 X.getType()->hasSignedIntegerRepresentation());
4320 }
Alexey Bataevddf3db92018-04-13 17:31:06 +00004321 llvm::Value *Res =
Akira Hatanakaf139ae32019-12-03 15:17:01 -08004322 CGF.Builder.CreateAtomicRMW(RMWOp, X.getPointer(CGF), UpdateVal, AO);
Alexey Bataev5e018f92015-04-23 06:35:10 +00004323 return std::make_pair(true, RValue::get(Res));
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004324}
4325
Alexey Bataev5e018f92015-04-23 06:35:10 +00004326std::pair<bool, RValue> CodeGenFunction::EmitOMPAtomicSimpleUpdateExpr(
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004327 LValue X, RValue E, BinaryOperatorKind BO, bool IsXLHSInRHSPart,
4328 llvm::AtomicOrdering AO, SourceLocation Loc,
Alexey Bataevddf3db92018-04-13 17:31:06 +00004329 const llvm::function_ref<RValue(RValue)> CommonGen) {
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004330 // Update expressions are allowed to have the following forms:
4331 // x binop= expr; -> xrval + expr;
4332 // x++, ++x -> xrval + 1;
4333 // x--, --x -> xrval - 1;
4334 // x = x binop expr; -> xrval binop expr
4335 // x = expr Op x; - > expr binop xrval;
Alexey Bataev5e018f92015-04-23 06:35:10 +00004336 auto Res = emitOMPAtomicRMW(*this, X, E, BO, AO, IsXLHSInRHSPart);
4337 if (!Res.first) {
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004338 if (X.isGlobalReg()) {
4339 // Emit an update expression: 'xrval' binop 'expr' or 'expr' binop
4340 // 'xrval'.
4341 EmitStoreThroughLValue(CommonGen(EmitLoadOfLValue(X, Loc)), X);
4342 } else {
4343 // Perform compare-and-swap procedure.
4344 EmitAtomicUpdate(X, AO, CommonGen, X.getType().isVolatileQualified());
Alexey Bataevb4505a72015-03-30 05:20:59 +00004345 }
4346 }
Alexey Bataev5e018f92015-04-23 06:35:10 +00004347 return Res;
Alexey Bataevb4505a72015-03-30 05:20:59 +00004348}
4349
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004350static void emitOMPAtomicUpdateExpr(CodeGenFunction &CGF,
4351 llvm::AtomicOrdering AO, const Expr *X,
4352 const Expr *E, const Expr *UE,
4353 bool IsXLHSInRHSPart, SourceLocation Loc) {
Alexey Bataevb4505a72015-03-30 05:20:59 +00004354 assert(isa<BinaryOperator>(UE->IgnoreImpCasts()) &&
4355 "Update expr in 'atomic update' must be a binary operator.");
Alexey Bataevddf3db92018-04-13 17:31:06 +00004356 const auto *BOUE = cast<BinaryOperator>(UE->IgnoreImpCasts());
Alexey Bataevb4505a72015-03-30 05:20:59 +00004357 // Update expressions are allowed to have the following forms:
4358 // x binop= expr; -> xrval + expr;
4359 // x++, ++x -> xrval + 1;
4360 // x--, --x -> xrval - 1;
4361 // x = x binop expr; -> xrval binop expr
4362 // x = expr Op x; - > expr binop xrval;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004363 assert(X->isLValue() && "X of 'omp atomic update' is not lvalue");
Alexey Bataevb4505a72015-03-30 05:20:59 +00004364 LValue XLValue = CGF.EmitLValue(X);
4365 RValue ExprRValue = CGF.EmitAnyExpr(E);
Alexey Bataevddf3db92018-04-13 17:31:06 +00004366 const auto *LHS = cast<OpaqueValueExpr>(BOUE->getLHS()->IgnoreImpCasts());
4367 const auto *RHS = cast<OpaqueValueExpr>(BOUE->getRHS()->IgnoreImpCasts());
4368 const OpaqueValueExpr *XRValExpr = IsXLHSInRHSPart ? LHS : RHS;
4369 const OpaqueValueExpr *ERValExpr = IsXLHSInRHSPart ? RHS : LHS;
4370 auto &&Gen = [&CGF, UE, ExprRValue, XRValExpr, ERValExpr](RValue XRValue) {
4371 CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue);
4372 CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, XRValue);
4373 return CGF.EmitAnyExpr(UE);
4374 };
Alexey Bataev5e018f92015-04-23 06:35:10 +00004375 (void)CGF.EmitOMPAtomicSimpleUpdateExpr(
4376 XLValue, ExprRValue, BOUE->getOpcode(), IsXLHSInRHSPart, AO, Loc, Gen);
Alexey Bataevf117f2c2020-01-28 11:19:45 -05004377 CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, X);
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004378 // OpenMP, 2.17.7, atomic Construct
4379 // If the write, update, or capture clause is specified and the release,
4380 // acq_rel, or seq_cst clause is specified then the strong flush on entry to
4381 // the atomic operation is also a release flush.
4382 switch (AO) {
4383 case llvm::AtomicOrdering::Release:
4384 case llvm::AtomicOrdering::AcquireRelease:
4385 case llvm::AtomicOrdering::SequentiallyConsistent:
4386 CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc,
4387 llvm::AtomicOrdering::Release);
4388 break;
4389 case llvm::AtomicOrdering::Acquire:
4390 case llvm::AtomicOrdering::Monotonic:
4391 break;
4392 case llvm::AtomicOrdering::NotAtomic:
4393 case llvm::AtomicOrdering::Unordered:
4394 llvm_unreachable("Unexpected ordering.");
4395 }
Alexey Bataev5e018f92015-04-23 06:35:10 +00004396}
4397
4398static RValue convertToType(CodeGenFunction &CGF, RValue Value,
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00004399 QualType SourceType, QualType ResType,
4400 SourceLocation Loc) {
Alexey Bataev5e018f92015-04-23 06:35:10 +00004401 switch (CGF.getEvaluationKind(ResType)) {
4402 case TEK_Scalar:
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00004403 return RValue::get(
4404 convertToScalarValue(CGF, Value, SourceType, ResType, Loc));
Alexey Bataev5e018f92015-04-23 06:35:10 +00004405 case TEK_Complex: {
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00004406 auto Res = convertToComplexValue(CGF, Value, SourceType, ResType, Loc);
Alexey Bataev5e018f92015-04-23 06:35:10 +00004407 return RValue::getComplex(Res.first, Res.second);
4408 }
4409 case TEK_Aggregate:
4410 break;
4411 }
4412 llvm_unreachable("Must be a scalar or complex.");
4413}
4414
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004415static void emitOMPAtomicCaptureExpr(CodeGenFunction &CGF,
4416 llvm::AtomicOrdering AO,
Alexey Bataev5e018f92015-04-23 06:35:10 +00004417 bool IsPostfixUpdate, const Expr *V,
4418 const Expr *X, const Expr *E,
4419 const Expr *UE, bool IsXLHSInRHSPart,
4420 SourceLocation Loc) {
4421 assert(X->isLValue() && "X of 'omp atomic capture' is not lvalue");
4422 assert(V->isLValue() && "V of 'omp atomic capture' is not lvalue");
4423 RValue NewVVal;
4424 LValue VLValue = CGF.EmitLValue(V);
4425 LValue XLValue = CGF.EmitLValue(X);
4426 RValue ExprRValue = CGF.EmitAnyExpr(E);
Alexey Bataev5e018f92015-04-23 06:35:10 +00004427 QualType NewVValType;
4428 if (UE) {
4429 // 'x' is updated with some additional value.
4430 assert(isa<BinaryOperator>(UE->IgnoreImpCasts()) &&
4431 "Update expr in 'atomic capture' must be a binary operator.");
Alexey Bataevddf3db92018-04-13 17:31:06 +00004432 const auto *BOUE = cast<BinaryOperator>(UE->IgnoreImpCasts());
Alexey Bataev5e018f92015-04-23 06:35:10 +00004433 // Update expressions are allowed to have the following forms:
4434 // x binop= expr; -> xrval + expr;
4435 // x++, ++x -> xrval + 1;
4436 // x--, --x -> xrval - 1;
4437 // x = x binop expr; -> xrval binop expr
4438 // x = expr Op x; - > expr binop xrval;
Alexey Bataevddf3db92018-04-13 17:31:06 +00004439 const auto *LHS = cast<OpaqueValueExpr>(BOUE->getLHS()->IgnoreImpCasts());
4440 const auto *RHS = cast<OpaqueValueExpr>(BOUE->getRHS()->IgnoreImpCasts());
4441 const OpaqueValueExpr *XRValExpr = IsXLHSInRHSPart ? LHS : RHS;
Alexey Bataev5e018f92015-04-23 06:35:10 +00004442 NewVValType = XRValExpr->getType();
Alexey Bataevddf3db92018-04-13 17:31:06 +00004443 const OpaqueValueExpr *ERValExpr = IsXLHSInRHSPart ? RHS : LHS;
Alexey Bataev5e018f92015-04-23 06:35:10 +00004444 auto &&Gen = [&CGF, &NewVVal, UE, ExprRValue, XRValExpr, ERValExpr,
Alexey Bataevddf3db92018-04-13 17:31:06 +00004445 IsPostfixUpdate](RValue XRValue) {
Alexey Bataev5e018f92015-04-23 06:35:10 +00004446 CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue);
4447 CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, XRValue);
4448 RValue Res = CGF.EmitAnyExpr(UE);
4449 NewVVal = IsPostfixUpdate ? XRValue : Res;
4450 return Res;
4451 };
4452 auto Res = CGF.EmitOMPAtomicSimpleUpdateExpr(
4453 XLValue, ExprRValue, BOUE->getOpcode(), IsXLHSInRHSPart, AO, Loc, Gen);
Alexey Bataevf117f2c2020-01-28 11:19:45 -05004454 CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, X);
Alexey Bataev5e018f92015-04-23 06:35:10 +00004455 if (Res.first) {
4456 // 'atomicrmw' instruction was generated.
4457 if (IsPostfixUpdate) {
4458 // Use old value from 'atomicrmw'.
4459 NewVVal = Res.second;
4460 } else {
4461 // 'atomicrmw' does not provide new value, so evaluate it using old
4462 // value of 'x'.
4463 CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue);
4464 CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, Res.second);
4465 NewVVal = CGF.EmitAnyExpr(UE);
4466 }
4467 }
4468 } else {
4469 // 'x' is simply rewritten with some 'expr'.
4470 NewVValType = X->getType().getNonReferenceType();
4471 ExprRValue = convertToType(CGF, ExprRValue, E->getType(),
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00004472 X->getType().getNonReferenceType(), Loc);
Alexey Bataevddf3db92018-04-13 17:31:06 +00004473 auto &&Gen = [&NewVVal, ExprRValue](RValue XRValue) {
Alexey Bataev5e018f92015-04-23 06:35:10 +00004474 NewVVal = XRValue;
4475 return ExprRValue;
4476 };
4477 // Try to perform atomicrmw xchg, otherwise simple exchange.
4478 auto Res = CGF.EmitOMPAtomicSimpleUpdateExpr(
4479 XLValue, ExprRValue, /*BO=*/BO_Assign, /*IsXLHSInRHSPart=*/false, AO,
4480 Loc, Gen);
Alexey Bataevf117f2c2020-01-28 11:19:45 -05004481 CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, X);
Alexey Bataev5e018f92015-04-23 06:35:10 +00004482 if (Res.first) {
4483 // 'atomicrmw' instruction was generated.
4484 NewVVal = IsPostfixUpdate ? Res.second : ExprRValue;
4485 }
4486 }
4487 // Emit post-update store to 'v' of old/new 'x' value.
Alexey Bataev8524d152016-01-21 12:35:58 +00004488 CGF.emitOMPSimpleStore(VLValue, NewVVal, NewVValType, Loc);
Alexey Bataevf117f2c2020-01-28 11:19:45 -05004489 CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, V);
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004490 // OpenMP, 2.17.7, atomic Construct
4491 // If the write, update, or capture clause is specified and the release,
4492 // acq_rel, or seq_cst clause is specified then the strong flush on entry to
4493 // the atomic operation is also a release flush.
4494 // If the read or capture clause is specified and the acquire, acq_rel, or
4495 // seq_cst clause is specified then the strong flush on exit from the atomic
4496 // operation is also an acquire flush.
4497 switch (AO) {
4498 case llvm::AtomicOrdering::Release:
4499 CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc,
4500 llvm::AtomicOrdering::Release);
4501 break;
4502 case llvm::AtomicOrdering::Acquire:
4503 CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc,
4504 llvm::AtomicOrdering::Acquire);
4505 break;
4506 case llvm::AtomicOrdering::AcquireRelease:
4507 case llvm::AtomicOrdering::SequentiallyConsistent:
4508 CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc,
4509 llvm::AtomicOrdering::AcquireRelease);
4510 break;
4511 case llvm::AtomicOrdering::Monotonic:
4512 break;
4513 case llvm::AtomicOrdering::NotAtomic:
4514 case llvm::AtomicOrdering::Unordered:
4515 llvm_unreachable("Unexpected ordering.");
4516 }
Alexey Bataevb4505a72015-03-30 05:20:59 +00004517}
4518
Alexey Bataevddf3db92018-04-13 17:31:06 +00004519static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004520 llvm::AtomicOrdering AO, bool IsPostfixUpdate,
Alexey Bataev5e018f92015-04-23 06:35:10 +00004521 const Expr *X, const Expr *V, const Expr *E,
4522 const Expr *UE, bool IsXLHSInRHSPart,
4523 SourceLocation Loc) {
Alexey Bataevb57056f2015-01-22 06:17:56 +00004524 switch (Kind) {
4525 case OMPC_read:
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004526 emitOMPAtomicReadExpr(CGF, AO, X, V, Loc);
Alexey Bataevb57056f2015-01-22 06:17:56 +00004527 break;
4528 case OMPC_write:
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004529 emitOMPAtomicWriteExpr(CGF, AO, X, E, Loc);
Alexey Bataevb8329262015-02-27 06:33:30 +00004530 break;
Alexey Bataevb4505a72015-03-30 05:20:59 +00004531 case OMPC_unknown:
Alexey Bataevb57056f2015-01-22 06:17:56 +00004532 case OMPC_update:
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004533 emitOMPAtomicUpdateExpr(CGF, AO, X, E, UE, IsXLHSInRHSPart, Loc);
Alexey Bataevb4505a72015-03-30 05:20:59 +00004534 break;
Alexey Bataevb57056f2015-01-22 06:17:56 +00004535 case OMPC_capture:
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004536 emitOMPAtomicCaptureExpr(CGF, AO, IsPostfixUpdate, V, X, E, UE,
Alexey Bataev5e018f92015-04-23 06:35:10 +00004537 IsXLHSInRHSPart, Loc);
4538 break;
Alexey Bataevb57056f2015-01-22 06:17:56 +00004539 case OMPC_if:
4540 case OMPC_final:
4541 case OMPC_num_threads:
4542 case OMPC_private:
4543 case OMPC_firstprivate:
4544 case OMPC_lastprivate:
4545 case OMPC_reduction:
Alexey Bataev169d96a2017-07-18 20:17:46 +00004546 case OMPC_task_reduction:
Alexey Bataevfa312f32017-07-21 18:48:21 +00004547 case OMPC_in_reduction:
Alexey Bataevb57056f2015-01-22 06:17:56 +00004548 case OMPC_safelen:
Alexey Bataev66b15b52015-08-21 11:14:16 +00004549 case OMPC_simdlen:
Alexey Bataev9cc10fc2019-03-12 18:52:33 +00004550 case OMPC_allocator:
Alexey Bataeve04483e2019-03-27 14:14:31 +00004551 case OMPC_allocate:
Alexey Bataevb57056f2015-01-22 06:17:56 +00004552 case OMPC_collapse:
4553 case OMPC_default:
4554 case OMPC_seq_cst:
Alexey Bataevea9166b2020-02-06 16:30:23 -05004555 case OMPC_acq_rel:
Alexey Bataev04a830f2020-02-10 14:30:39 -05004556 case OMPC_acquire:
Alexey Bataev95598342020-02-10 15:49:05 -05004557 case OMPC_release:
Alexey Bataev9a8defc2020-02-11 11:10:43 -05004558 case OMPC_relaxed:
Alexey Bataevb57056f2015-01-22 06:17:56 +00004559 case OMPC_shared:
4560 case OMPC_linear:
4561 case OMPC_aligned:
4562 case OMPC_copyin:
4563 case OMPC_copyprivate:
4564 case OMPC_flush:
Alexey Bataevc112e942020-02-28 09:52:15 -05004565 case OMPC_depobj:
Alexey Bataevb57056f2015-01-22 06:17:56 +00004566 case OMPC_proc_bind:
4567 case OMPC_schedule:
4568 case OMPC_ordered:
4569 case OMPC_nowait:
4570 case OMPC_untied:
4571 case OMPC_threadprivate:
Alexey Bataev1c2cfbc2015-06-23 14:25:19 +00004572 case OMPC_depend:
Alexey Bataevb57056f2015-01-22 06:17:56 +00004573 case OMPC_mergeable:
Michael Wonge710d542015-08-07 16:16:36 +00004574 case OMPC_device:
Alexey Bataev346265e2015-09-25 10:37:12 +00004575 case OMPC_threads:
Alexey Bataevd14d1e62015-09-28 06:39:35 +00004576 case OMPC_simd:
Kelvin Li0bff7af2015-11-23 05:32:03 +00004577 case OMPC_map:
Kelvin Li099bb8c2015-11-24 20:50:12 +00004578 case OMPC_num_teams:
Kelvin Lia15fb1a2015-11-27 18:47:36 +00004579 case OMPC_thread_limit:
Alexey Bataeva0569352015-12-01 10:17:31 +00004580 case OMPC_priority:
Alexey Bataev1fd4aed2015-12-07 12:52:51 +00004581 case OMPC_grainsize:
Alexey Bataevb825de12015-12-07 10:51:44 +00004582 case OMPC_nogroup:
Alexey Bataev382967a2015-12-08 12:06:20 +00004583 case OMPC_num_tasks:
Alexey Bataev28c75412015-12-15 08:19:24 +00004584 case OMPC_hint:
Carlo Bertollib4adf552016-01-15 18:50:31 +00004585 case OMPC_dist_schedule:
Arpith Chacko Jacob3cf89042016-01-26 16:37:23 +00004586 case OMPC_defaultmap:
Alexey Bataeve48a5fc2016-04-12 05:28:34 +00004587 case OMPC_uniform:
Samuel Antao661c0902016-05-26 17:39:58 +00004588 case OMPC_to:
Samuel Antaoec172c62016-05-26 17:49:04 +00004589 case OMPC_from:
Carlo Bertolli2404b172016-07-13 15:37:16 +00004590 case OMPC_use_device_ptr:
Carlo Bertolli70594e92016-07-13 17:16:49 +00004591 case OMPC_is_device_ptr:
Kelvin Li1408f912018-09-26 04:28:39 +00004592 case OMPC_unified_address:
Alexey Bataev94c50642018-10-01 14:26:31 +00004593 case OMPC_unified_shared_memory:
Patrick Lyster6bdf63b2018-10-03 20:07:58 +00004594 case OMPC_reverse_offload:
Patrick Lyster3fe9e392018-10-11 14:41:10 +00004595 case OMPC_dynamic_allocators:
Patrick Lyster7a2a27c2018-11-02 12:18:11 +00004596 case OMPC_atomic_default_mem_order:
Alexey Bataev729e2422019-08-23 16:11:14 +00004597 case OMPC_device_type:
Alexey Bataevdba792c2019-09-23 18:13:31 +00004598 case OMPC_match:
Alexey Bataevb6e70842019-12-16 15:54:17 -05004599 case OMPC_nontemporal:
Alexey Bataevcb8e6912020-01-31 16:09:26 -05004600 case OMPC_order:
Alexey Bataev375437a2020-03-02 14:21:20 -05004601 case OMPC_destroy:
Alexey Bataevb57056f2015-01-22 06:17:56 +00004602 llvm_unreachable("Clause is not allowed in 'omp atomic'.");
4603 }
4604}
4605
4606void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &S) {
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004607 llvm::AtomicOrdering AO = llvm::AtomicOrdering::Monotonic;
Alexey Bataev2d4f80f2020-02-11 15:15:21 -05004608 bool MemOrderingSpecified = false;
4609 if (S.getSingleClause<OMPSeqCstClause>()) {
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004610 AO = llvm::AtomicOrdering::SequentiallyConsistent;
Alexey Bataev2d4f80f2020-02-11 15:15:21 -05004611 MemOrderingSpecified = true;
4612 } else if (S.getSingleClause<OMPAcqRelClause>()) {
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004613 AO = llvm::AtomicOrdering::AcquireRelease;
Alexey Bataev2d4f80f2020-02-11 15:15:21 -05004614 MemOrderingSpecified = true;
4615 } else if (S.getSingleClause<OMPAcquireClause>()) {
Alexey Bataev04a830f2020-02-10 14:30:39 -05004616 AO = llvm::AtomicOrdering::Acquire;
Alexey Bataev2d4f80f2020-02-11 15:15:21 -05004617 MemOrderingSpecified = true;
4618 } else if (S.getSingleClause<OMPReleaseClause>()) {
Alexey Bataev95598342020-02-10 15:49:05 -05004619 AO = llvm::AtomicOrdering::Release;
Alexey Bataev2d4f80f2020-02-11 15:15:21 -05004620 MemOrderingSpecified = true;
4621 } else if (S.getSingleClause<OMPRelaxedClause>()) {
Alexey Bataev9a8defc2020-02-11 11:10:43 -05004622 AO = llvm::AtomicOrdering::Monotonic;
Alexey Bataev2d4f80f2020-02-11 15:15:21 -05004623 MemOrderingSpecified = true;
4624 }
Alexey Bataevb57056f2015-01-22 06:17:56 +00004625 OpenMPClauseKind Kind = OMPC_unknown;
Alexey Bataevddf3db92018-04-13 17:31:06 +00004626 for (const OMPClause *C : S.clauses()) {
Alexey Bataev9a8defc2020-02-11 11:10:43 -05004627 // Find first clause (skip seq_cst|acq_rel|aqcuire|release|relaxed clause,
4628 // if it is first).
Alexey Bataevea9166b2020-02-06 16:30:23 -05004629 if (C->getClauseKind() != OMPC_seq_cst &&
Alexey Bataev04a830f2020-02-10 14:30:39 -05004630 C->getClauseKind() != OMPC_acq_rel &&
Alexey Bataev95598342020-02-10 15:49:05 -05004631 C->getClauseKind() != OMPC_acquire &&
Alexey Bataev9a8defc2020-02-11 11:10:43 -05004632 C->getClauseKind() != OMPC_release &&
4633 C->getClauseKind() != OMPC_relaxed) {
Alexey Bataevb57056f2015-01-22 06:17:56 +00004634 Kind = C->getClauseKind();
4635 break;
4636 }
4637 }
Alexey Bataev2d4f80f2020-02-11 15:15:21 -05004638 if (!MemOrderingSpecified) {
4639 llvm::AtomicOrdering DefaultOrder =
4640 CGM.getOpenMPRuntime().getDefaultMemoryOrdering();
4641 if (DefaultOrder == llvm::AtomicOrdering::Monotonic ||
4642 DefaultOrder == llvm::AtomicOrdering::SequentiallyConsistent ||
4643 (DefaultOrder == llvm::AtomicOrdering::AcquireRelease &&
4644 Kind == OMPC_capture)) {
4645 AO = DefaultOrder;
4646 } else if (DefaultOrder == llvm::AtomicOrdering::AcquireRelease) {
4647 if (Kind == OMPC_unknown || Kind == OMPC_update || Kind == OMPC_write) {
4648 AO = llvm::AtomicOrdering::Release;
4649 } else if (Kind == OMPC_read) {
4650 assert(Kind == OMPC_read && "Unexpected atomic kind.");
4651 AO = llvm::AtomicOrdering::Acquire;
4652 }
4653 }
4654 }
Alexey Bataev10fec572015-03-11 04:48:56 +00004655
Alexey Bataevddf3db92018-04-13 17:31:06 +00004656 const Stmt *CS = S.getInnermostCapturedStmt()->IgnoreContainers();
Bill Wendling7c44da22018-10-31 03:48:47 +00004657 if (const auto *FE = dyn_cast<FullExpr>(CS))
4658 enterFullExpression(FE);
Alexey Bataev5e018f92015-04-23 06:35:10 +00004659 // Processing for statements under 'atomic capture'.
4660 if (const auto *Compound = dyn_cast<CompoundStmt>(CS)) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00004661 for (const Stmt *C : Compound->body()) {
Bill Wendling7c44da22018-10-31 03:48:47 +00004662 if (const auto *FE = dyn_cast<FullExpr>(C))
4663 enterFullExpression(FE);
Alexey Bataev5e018f92015-04-23 06:35:10 +00004664 }
4665 }
Alexey Bataev10fec572015-03-11 04:48:56 +00004666
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004667 auto &&CodeGen = [&S, Kind, AO, CS](CodeGenFunction &CGF,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004668 PrePostActionTy &) {
Alexey Bataev33c56402015-12-14 09:26:19 +00004669 CGF.EmitStopPoint(CS);
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004670 emitOMPAtomicExpr(CGF, Kind, AO, S.isPostfixUpdate(), S.getX(), S.getV(),
4671 S.getExpr(), S.getUpdateExpr(), S.isXLHSInRHSPart(),
4672 S.getBeginLoc());
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00004673 };
Alexey Bataev475a7442018-01-12 19:39:11 +00004674 OMPLexicalScope Scope(*this, S, OMPD_unknown);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00004675 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_atomic, CodeGen);
Alexey Bataev0162e452014-07-22 10:10:35 +00004676}
4677
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00004678static void emitCommonOMPTargetDirective(CodeGenFunction &CGF,
4679 const OMPExecutableDirective &S,
4680 const RegionCodeGenTy &CodeGen) {
4681 assert(isOpenMPTargetExecutionDirective(S.getDirectiveKind()));
4682 CodeGenModule &CGM = CGF.CGM;
Samuel Antaobed3c462015-10-02 16:14:20 +00004683
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00004684 // On device emit this construct as inlined code.
4685 if (CGM.getLangOpts().OpenMPIsDevice) {
4686 OMPLexicalScope Scope(CGF, S, OMPD_target);
4687 CGM.getOpenMPRuntime().emitInlinedDirective(
4688 CGF, OMPD_target, [&S](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataev4ac68a22018-05-16 15:08:32 +00004689 CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00004690 });
4691 return;
4692 }
4693
Alexey Bataev46978742020-01-30 10:46:11 -05004694 auto LPCRegion =
4695 CGOpenMPRuntime::LastprivateConditionalRAII::disable(CGF, S);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004696 llvm::Function *Fn = nullptr;
4697 llvm::Constant *FnID = nullptr;
Samuel Antaobed3c462015-10-02 16:14:20 +00004698
Samuel Antaobed3c462015-10-02 16:14:20 +00004699 const Expr *IfCond = nullptr;
Arpith Chacko Jacobfe4890a2017-01-18 20:40:48 +00004700 // Check for the at most one if clause associated with the target region.
4701 for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
4702 if (C->getNameModifier() == OMPD_unknown ||
4703 C->getNameModifier() == OMPD_target) {
4704 IfCond = C->getCondition();
4705 break;
4706 }
Samuel Antaobed3c462015-10-02 16:14:20 +00004707 }
4708
4709 // Check if we have any device clause associated with the directive.
4710 const Expr *Device = nullptr;
Alexey Bataevddf3db92018-04-13 17:31:06 +00004711 if (auto *C = S.getSingleClause<OMPDeviceClause>())
Samuel Antaobed3c462015-10-02 16:14:20 +00004712 Device = C->getDevice();
Samuel Antaobed3c462015-10-02 16:14:20 +00004713
Samuel Antaoee8fb302016-01-06 13:42:12 +00004714 // Check if we have an if clause whose conditional always evaluates to false
4715 // or if we do not have any targets specified. If so the target region is not
4716 // an offload entry point.
4717 bool IsOffloadEntry = true;
4718 if (IfCond) {
4719 bool Val;
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00004720 if (CGF.ConstantFoldsToSimpleInteger(IfCond, Val) && !Val)
Samuel Antaoee8fb302016-01-06 13:42:12 +00004721 IsOffloadEntry = false;
4722 }
4723 if (CGM.getLangOpts().OMPTargetTriples.empty())
4724 IsOffloadEntry = false;
4725
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00004726 assert(CGF.CurFuncDecl && "No parent declaration for target region!");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004727 StringRef ParentName;
4728 // In case we have Ctors/Dtors we use the complete type variant to produce
4729 // the mangling of the device outlined kernel.
Alexey Bataevddf3db92018-04-13 17:31:06 +00004730 if (const auto *D = dyn_cast<CXXConstructorDecl>(CGF.CurFuncDecl))
Samuel Antaoee8fb302016-01-06 13:42:12 +00004731 ParentName = CGM.getMangledName(GlobalDecl(D, Ctor_Complete));
Alexey Bataevddf3db92018-04-13 17:31:06 +00004732 else if (const auto *D = dyn_cast<CXXDestructorDecl>(CGF.CurFuncDecl))
Samuel Antaoee8fb302016-01-06 13:42:12 +00004733 ParentName = CGM.getMangledName(GlobalDecl(D, Dtor_Complete));
4734 else
4735 ParentName =
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00004736 CGM.getMangledName(GlobalDecl(cast<FunctionDecl>(CGF.CurFuncDecl)));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004737
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00004738 // Emit target region as a standalone region.
4739 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(S, ParentName, Fn, FnID,
4740 IsOffloadEntry, CodeGen);
Alexey Bataev8451efa2018-01-15 19:06:12 +00004741 OMPLexicalScope Scope(CGF, S, OMPD_task);
Alexey Bataevec7946e2019-09-23 14:06:51 +00004742 auto &&SizeEmitter =
4743 [IsOffloadEntry](CodeGenFunction &CGF,
4744 const OMPLoopDirective &D) -> llvm::Value * {
4745 if (IsOffloadEntry) {
4746 OMPLoopScope(CGF, D);
4747 // Emit calculation of the iterations count.
4748 llvm::Value *NumIterations = CGF.EmitScalarExpr(D.getNumIterations());
4749 NumIterations = CGF.Builder.CreateIntCast(NumIterations, CGF.Int64Ty,
4750 /*isSigned=*/false);
4751 return NumIterations;
4752 }
4753 return nullptr;
Alexey Bataev7bb33532019-01-07 21:30:43 +00004754 };
Alexey Bataevec7946e2019-09-23 14:06:51 +00004755 CGM.getOpenMPRuntime().emitTargetCall(CGF, S, Fn, FnID, IfCond, Device,
4756 SizeEmitter);
Alexey Bataev0bd520b2014-09-19 08:19:49 +00004757}
4758
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00004759static void emitTargetRegion(CodeGenFunction &CGF, const OMPTargetDirective &S,
4760 PrePostActionTy &Action) {
Alexey Bataev63cc8e92018-03-20 14:45:59 +00004761 Action.Enter(CGF);
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00004762 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
4763 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
4764 CGF.EmitOMPPrivateClause(S, PrivateScope);
4765 (void)PrivateScope.Privatize();
Alexey Bataev60705422018-10-30 15:50:12 +00004766 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()))
4767 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00004768
Alexey Bataev475a7442018-01-12 19:39:11 +00004769 CGF.EmitStmt(S.getCapturedStmt(OMPD_target)->getCapturedStmt());
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00004770}
4771
4772void CodeGenFunction::EmitOMPTargetDeviceFunction(CodeGenModule &CGM,
4773 StringRef ParentName,
4774 const OMPTargetDirective &S) {
4775 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
4776 emitTargetRegion(CGF, S, Action);
4777 };
4778 llvm::Function *Fn;
4779 llvm::Constant *Addr;
4780 // Emit target region as a standalone region.
4781 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
4782 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
4783 assert(Fn && Addr && "Target device function emission failed.");
4784}
4785
4786void CodeGenFunction::EmitOMPTargetDirective(const OMPTargetDirective &S) {
4787 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
4788 emitTargetRegion(CGF, S, Action);
4789 };
4790 emitCommonOMPTargetDirective(*this, S, CodeGen);
4791}
4792
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00004793static void emitCommonOMPTeamsDirective(CodeGenFunction &CGF,
4794 const OMPExecutableDirective &S,
4795 OpenMPDirectiveKind InnermostKind,
4796 const RegionCodeGenTy &CodeGen) {
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00004797 const CapturedStmt *CS = S.getCapturedStmt(OMPD_teams);
James Y Knight9871db02019-02-05 16:42:33 +00004798 llvm::Function *OutlinedFn =
Alexey Bataevddf3db92018-04-13 17:31:06 +00004799 CGF.CGM.getOpenMPRuntime().emitTeamsOutlinedFunction(
4800 S, *CS->getCapturedDecl()->param_begin(), InnermostKind, CodeGen);
Samuel Antaob68e2db2016-03-03 16:20:23 +00004801
Alexey Bataevddf3db92018-04-13 17:31:06 +00004802 const auto *NT = S.getSingleClause<OMPNumTeamsClause>();
4803 const auto *TL = S.getSingleClause<OMPThreadLimitClause>();
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00004804 if (NT || TL) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00004805 const Expr *NumTeams = NT ? NT->getNumTeams() : nullptr;
4806 const Expr *ThreadLimit = TL ? TL->getThreadLimit() : nullptr;
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00004807
Carlo Bertollic6872252016-04-04 15:55:02 +00004808 CGF.CGM.getOpenMPRuntime().emitNumTeamsClause(CGF, NumTeams, ThreadLimit,
Stephen Kellyf2ceec42018-08-09 21:08:08 +00004809 S.getBeginLoc());
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00004810 }
4811
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00004812 OMPTeamsScope Scope(CGF, S);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004813 llvm::SmallVector<llvm::Value *, 16> CapturedVars;
4814 CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
Stephen Kellyf2ceec42018-08-09 21:08:08 +00004815 CGF.CGM.getOpenMPRuntime().emitTeamsCall(CGF, S, S.getBeginLoc(), OutlinedFn,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00004816 CapturedVars);
4817}
4818
4819void CodeGenFunction::EmitOMPTeamsDirective(const OMPTeamsDirective &S) {
Kelvin Li51336dd2016-12-15 17:55:32 +00004820 // Emit teams region as a standalone region.
Alexey Bataevc99042b2018-03-15 18:10:54 +00004821 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataev63cc8e92018-03-20 14:45:59 +00004822 Action.Enter(CGF);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00004823 OMPPrivateScope PrivateScope(CGF);
Carlo Bertolli6ad7b5a2016-03-03 22:09:40 +00004824 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
4825 CGF.EmitOMPPrivateClause(S, PrivateScope);
Arpith Chacko Jacobfc711b12017-02-16 16:48:49 +00004826 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00004827 (void)PrivateScope.Privatize();
Alexey Bataev475a7442018-01-12 19:39:11 +00004828 CGF.EmitStmt(S.getCapturedStmt(OMPD_teams)->getCapturedStmt());
Arpith Chacko Jacobfc711b12017-02-16 16:48:49 +00004829 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00004830 };
Alexey Bataev2139ed62017-11-16 18:20:21 +00004831 emitCommonOMPTeamsDirective(*this, S, OMPD_distribute, CodeGen);
Alexey Bataevddf3db92018-04-13 17:31:06 +00004832 emitPostUpdateForReductionClause(*this, S,
4833 [](CodeGenFunction &) { return nullptr; });
Alexey Bataev13314bf2014-10-09 04:18:56 +00004834}
Alexey Bataev6d4ed052015-07-01 06:57:41 +00004835
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00004836static void emitTargetTeamsRegion(CodeGenFunction &CGF, PrePostActionTy &Action,
4837 const OMPTargetTeamsDirective &S) {
4838 auto *CS = S.getCapturedStmt(OMPD_teams);
4839 Action.Enter(CGF);
Alexey Bataevf9fc42e2017-11-22 14:25:55 +00004840 // Emit teams region as a standalone region.
4841 auto &&CodeGen = [&S, CS](CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataev63cc8e92018-03-20 14:45:59 +00004842 Action.Enter(CGF);
Alexey Bataevf9fc42e2017-11-22 14:25:55 +00004843 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
4844 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
4845 CGF.EmitOMPPrivateClause(S, PrivateScope);
4846 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
4847 (void)PrivateScope.Privatize();
Alexey Bataev60705422018-10-30 15:50:12 +00004848 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()))
4849 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00004850 CGF.EmitStmt(CS->getCapturedStmt());
Alexey Bataevf9fc42e2017-11-22 14:25:55 +00004851 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00004852 };
4853 emitCommonOMPTeamsDirective(CGF, S, OMPD_teams, CodeGen);
Alexey Bataevddf3db92018-04-13 17:31:06 +00004854 emitPostUpdateForReductionClause(CGF, S,
4855 [](CodeGenFunction &) { return nullptr; });
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00004856}
4857
4858void CodeGenFunction::EmitOMPTargetTeamsDeviceFunction(
4859 CodeGenModule &CGM, StringRef ParentName,
4860 const OMPTargetTeamsDirective &S) {
4861 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
4862 emitTargetTeamsRegion(CGF, Action, S);
4863 };
4864 llvm::Function *Fn;
4865 llvm::Constant *Addr;
4866 // Emit target region as a standalone region.
4867 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
4868 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
4869 assert(Fn && Addr && "Target device function emission failed.");
4870}
4871
4872void CodeGenFunction::EmitOMPTargetTeamsDirective(
4873 const OMPTargetTeamsDirective &S) {
4874 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
4875 emitTargetTeamsRegion(CGF, Action, S);
4876 };
4877 emitCommonOMPTargetDirective(*this, S, CodeGen);
4878}
4879
Alexey Bataevdfa430f2017-12-08 15:03:50 +00004880static void
4881emitTargetTeamsDistributeRegion(CodeGenFunction &CGF, PrePostActionTy &Action,
4882 const OMPTargetTeamsDistributeDirective &S) {
4883 Action.Enter(CGF);
4884 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
4885 CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc());
4886 };
4887
4888 // Emit teams region as a standalone region.
4889 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
Alexey Bataevc99042b2018-03-15 18:10:54 +00004890 PrePostActionTy &Action) {
Alexey Bataev63cc8e92018-03-20 14:45:59 +00004891 Action.Enter(CGF);
Alexey Bataevdfa430f2017-12-08 15:03:50 +00004892 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
4893 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
4894 (void)PrivateScope.Privatize();
4895 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute,
4896 CodeGenDistribute);
4897 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
4898 };
4899 emitCommonOMPTeamsDirective(CGF, S, OMPD_distribute, CodeGen);
4900 emitPostUpdateForReductionClause(CGF, S,
4901 [](CodeGenFunction &) { return nullptr; });
4902}
4903
4904void CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction(
4905 CodeGenModule &CGM, StringRef ParentName,
4906 const OMPTargetTeamsDistributeDirective &S) {
4907 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
4908 emitTargetTeamsDistributeRegion(CGF, Action, S);
4909 };
4910 llvm::Function *Fn;
4911 llvm::Constant *Addr;
4912 // Emit target region as a standalone region.
4913 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
4914 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
4915 assert(Fn && Addr && "Target device function emission failed.");
4916}
4917
4918void CodeGenFunction::EmitOMPTargetTeamsDistributeDirective(
4919 const OMPTargetTeamsDistributeDirective &S) {
4920 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
4921 emitTargetTeamsDistributeRegion(CGF, Action, S);
4922 };
4923 emitCommonOMPTargetDirective(*this, S, CodeGen);
4924}
4925
Alexey Bataevfbe17fb2017-12-13 19:45:06 +00004926static void emitTargetTeamsDistributeSimdRegion(
4927 CodeGenFunction &CGF, PrePostActionTy &Action,
4928 const OMPTargetTeamsDistributeSimdDirective &S) {
4929 Action.Enter(CGF);
4930 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
4931 CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc());
4932 };
4933
4934 // Emit teams region as a standalone region.
4935 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
Alexey Bataevc99042b2018-03-15 18:10:54 +00004936 PrePostActionTy &Action) {
Alexey Bataev63cc8e92018-03-20 14:45:59 +00004937 Action.Enter(CGF);
Alexey Bataevfbe17fb2017-12-13 19:45:06 +00004938 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
4939 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
4940 (void)PrivateScope.Privatize();
4941 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute,
4942 CodeGenDistribute);
4943 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
4944 };
4945 emitCommonOMPTeamsDirective(CGF, S, OMPD_distribute_simd, CodeGen);
4946 emitPostUpdateForReductionClause(CGF, S,
4947 [](CodeGenFunction &) { return nullptr; });
4948}
4949
4950void CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction(
4951 CodeGenModule &CGM, StringRef ParentName,
4952 const OMPTargetTeamsDistributeSimdDirective &S) {
4953 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
4954 emitTargetTeamsDistributeSimdRegion(CGF, Action, S);
4955 };
4956 llvm::Function *Fn;
4957 llvm::Constant *Addr;
4958 // Emit target region as a standalone region.
4959 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
4960 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
4961 assert(Fn && Addr && "Target device function emission failed.");
4962}
4963
4964void CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDirective(
4965 const OMPTargetTeamsDistributeSimdDirective &S) {
4966 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
4967 emitTargetTeamsDistributeSimdRegion(CGF, Action, S);
4968 };
4969 emitCommonOMPTargetDirective(*this, S, CodeGen);
4970}
4971
Carlo Bertolliba1487b2017-10-04 14:12:09 +00004972void CodeGenFunction::EmitOMPTeamsDistributeDirective(
4973 const OMPTeamsDistributeDirective &S) {
4974
4975 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
4976 CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc());
4977 };
4978
4979 // Emit teams region as a standalone region.
4980 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
Alexey Bataevc99042b2018-03-15 18:10:54 +00004981 PrePostActionTy &Action) {
Alexey Bataev63cc8e92018-03-20 14:45:59 +00004982 Action.Enter(CGF);
Carlo Bertolliba1487b2017-10-04 14:12:09 +00004983 OMPPrivateScope PrivateScope(CGF);
4984 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
4985 (void)PrivateScope.Privatize();
4986 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute,
4987 CodeGenDistribute);
4988 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
4989 };
Alexey Bataev95c6dd42017-11-29 15:14:16 +00004990 emitCommonOMPTeamsDirective(*this, S, OMPD_distribute, CodeGen);
Carlo Bertolliba1487b2017-10-04 14:12:09 +00004991 emitPostUpdateForReductionClause(*this, S,
4992 [](CodeGenFunction &) { return nullptr; });
4993}
4994
Alexey Bataev999277a2017-12-06 14:31:09 +00004995void CodeGenFunction::EmitOMPTeamsDistributeSimdDirective(
4996 const OMPTeamsDistributeSimdDirective &S) {
4997 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
4998 CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc());
4999 };
5000
5001 // Emit teams region as a standalone region.
5002 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
Alexey Bataevc99042b2018-03-15 18:10:54 +00005003 PrePostActionTy &Action) {
Alexey Bataev63cc8e92018-03-20 14:45:59 +00005004 Action.Enter(CGF);
Alexey Bataev999277a2017-12-06 14:31:09 +00005005 OMPPrivateScope PrivateScope(CGF);
5006 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
5007 (void)PrivateScope.Privatize();
5008 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_simd,
5009 CodeGenDistribute);
5010 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
5011 };
5012 emitCommonOMPTeamsDirective(*this, S, OMPD_distribute_simd, CodeGen);
5013 emitPostUpdateForReductionClause(*this, S,
5014 [](CodeGenFunction &) { return nullptr; });
5015}
5016
Carlo Bertolli62fae152017-11-20 20:46:39 +00005017void CodeGenFunction::EmitOMPTeamsDistributeParallelForDirective(
5018 const OMPTeamsDistributeParallelForDirective &S) {
5019 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
5020 CGF.EmitOMPDistributeLoop(S, emitInnerParallelForWhenCombined,
5021 S.getDistInc());
5022 };
5023
5024 // Emit teams region as a standalone region.
5025 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
Alexey Bataevc99042b2018-03-15 18:10:54 +00005026 PrePostActionTy &Action) {
Alexey Bataev63cc8e92018-03-20 14:45:59 +00005027 Action.Enter(CGF);
Carlo Bertolli62fae152017-11-20 20:46:39 +00005028 OMPPrivateScope PrivateScope(CGF);
5029 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
5030 (void)PrivateScope.Privatize();
Alexey Bataev10a54312017-11-27 16:54:08 +00005031 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute,
5032 CodeGenDistribute);
Carlo Bertolli62fae152017-11-20 20:46:39 +00005033 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
5034 };
5035 emitCommonOMPTeamsDirective(*this, S, OMPD_distribute_parallel_for, CodeGen);
5036 emitPostUpdateForReductionClause(*this, S,
5037 [](CodeGenFunction &) { return nullptr; });
5038}
5039
Carlo Bertolli56a2aa42017-12-04 20:57:19 +00005040void CodeGenFunction::EmitOMPTeamsDistributeParallelForSimdDirective(
5041 const OMPTeamsDistributeParallelForSimdDirective &S) {
5042 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
5043 CGF.EmitOMPDistributeLoop(S, emitInnerParallelForWhenCombined,
5044 S.getDistInc());
5045 };
5046
5047 // Emit teams region as a standalone region.
5048 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
Alexey Bataevc99042b2018-03-15 18:10:54 +00005049 PrePostActionTy &Action) {
Alexey Bataev63cc8e92018-03-20 14:45:59 +00005050 Action.Enter(CGF);
Carlo Bertolli56a2aa42017-12-04 20:57:19 +00005051 OMPPrivateScope PrivateScope(CGF);
5052 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
5053 (void)PrivateScope.Privatize();
5054 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(
5055 CGF, OMPD_distribute, CodeGenDistribute, /*HasCancel=*/false);
5056 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
5057 };
Alexey Bataev0b978942019-12-11 15:26:38 -05005058 emitCommonOMPTeamsDirective(*this, S, OMPD_distribute_parallel_for_simd,
5059 CodeGen);
Carlo Bertolli56a2aa42017-12-04 20:57:19 +00005060 emitPostUpdateForReductionClause(*this, S,
5061 [](CodeGenFunction &) { return nullptr; });
5062}
5063
Carlo Bertolli52978c32018-01-03 21:12:44 +00005064static void emitTargetTeamsDistributeParallelForRegion(
5065 CodeGenFunction &CGF, const OMPTargetTeamsDistributeParallelForDirective &S,
5066 PrePostActionTy &Action) {
Carlo Bertolli79712092018-02-28 20:48:35 +00005067 Action.Enter(CGF);
Carlo Bertolli52978c32018-01-03 21:12:44 +00005068 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
5069 CGF.EmitOMPDistributeLoop(S, emitInnerParallelForWhenCombined,
5070 S.getDistInc());
5071 };
5072
5073 // Emit teams region as a standalone region.
5074 auto &&CodeGenTeams = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
Alexey Bataevc99042b2018-03-15 18:10:54 +00005075 PrePostActionTy &Action) {
Alexey Bataev63cc8e92018-03-20 14:45:59 +00005076 Action.Enter(CGF);
Carlo Bertolli52978c32018-01-03 21:12:44 +00005077 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
5078 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
5079 (void)PrivateScope.Privatize();
5080 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(
5081 CGF, OMPD_distribute, CodeGenDistribute, /*HasCancel=*/false);
5082 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
5083 };
5084
5085 emitCommonOMPTeamsDirective(CGF, S, OMPD_distribute_parallel_for,
5086 CodeGenTeams);
5087 emitPostUpdateForReductionClause(CGF, S,
5088 [](CodeGenFunction &) { return nullptr; });
5089}
5090
5091void CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction(
5092 CodeGenModule &CGM, StringRef ParentName,
5093 const OMPTargetTeamsDistributeParallelForDirective &S) {
5094 // Emit SPMD target teams distribute parallel for region as a standalone
5095 // region.
5096 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5097 emitTargetTeamsDistributeParallelForRegion(CGF, S, Action);
5098 };
5099 llvm::Function *Fn;
5100 llvm::Constant *Addr;
5101 // Emit target region as a standalone region.
5102 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
5103 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
5104 assert(Fn && Addr && "Target device function emission failed.");
5105}
5106
5107void CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDirective(
5108 const OMPTargetTeamsDistributeParallelForDirective &S) {
5109 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5110 emitTargetTeamsDistributeParallelForRegion(CGF, S, Action);
5111 };
5112 emitCommonOMPTargetDirective(*this, S, CodeGen);
5113}
5114
Alexey Bataev647dd842018-01-15 20:59:40 +00005115static void emitTargetTeamsDistributeParallelForSimdRegion(
5116 CodeGenFunction &CGF,
5117 const OMPTargetTeamsDistributeParallelForSimdDirective &S,
5118 PrePostActionTy &Action) {
Carlo Bertolli79712092018-02-28 20:48:35 +00005119 Action.Enter(CGF);
Alexey Bataev647dd842018-01-15 20:59:40 +00005120 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
5121 CGF.EmitOMPDistributeLoop(S, emitInnerParallelForWhenCombined,
5122 S.getDistInc());
5123 };
5124
5125 // Emit teams region as a standalone region.
5126 auto &&CodeGenTeams = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
Alexey Bataevc99042b2018-03-15 18:10:54 +00005127 PrePostActionTy &Action) {
Alexey Bataev63cc8e92018-03-20 14:45:59 +00005128 Action.Enter(CGF);
Alexey Bataev647dd842018-01-15 20:59:40 +00005129 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
5130 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
5131 (void)PrivateScope.Privatize();
5132 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(
5133 CGF, OMPD_distribute, CodeGenDistribute, /*HasCancel=*/false);
5134 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
5135 };
5136
5137 emitCommonOMPTeamsDirective(CGF, S, OMPD_distribute_parallel_for_simd,
5138 CodeGenTeams);
5139 emitPostUpdateForReductionClause(CGF, S,
5140 [](CodeGenFunction &) { return nullptr; });
5141}
5142
5143void CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(
5144 CodeGenModule &CGM, StringRef ParentName,
5145 const OMPTargetTeamsDistributeParallelForSimdDirective &S) {
5146 // Emit SPMD target teams distribute parallel for simd region as a standalone
5147 // region.
5148 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5149 emitTargetTeamsDistributeParallelForSimdRegion(CGF, S, Action);
5150 };
5151 llvm::Function *Fn;
5152 llvm::Constant *Addr;
5153 // Emit target region as a standalone region.
5154 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
5155 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
5156 assert(Fn && Addr && "Target device function emission failed.");
5157}
5158
5159void CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForSimdDirective(
5160 const OMPTargetTeamsDistributeParallelForSimdDirective &S) {
5161 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5162 emitTargetTeamsDistributeParallelForSimdRegion(CGF, S, Action);
5163 };
5164 emitCommonOMPTargetDirective(*this, S, CodeGen);
5165}
5166
Alexey Bataev6d4ed052015-07-01 06:57:41 +00005167void CodeGenFunction::EmitOMPCancellationPointDirective(
5168 const OMPCancellationPointDirective &S) {
Stephen Kellyf2ceec42018-08-09 21:08:08 +00005169 CGM.getOpenMPRuntime().emitCancellationPointCall(*this, S.getBeginLoc(),
Alexey Bataev0f34da12015-07-02 04:17:07 +00005170 S.getCancelRegion());
Alexey Bataev6d4ed052015-07-01 06:57:41 +00005171}
5172
Alexey Bataev80909872015-07-02 11:25:17 +00005173void CodeGenFunction::EmitOMPCancelDirective(const OMPCancelDirective &S) {
Alexey Bataev87933c72015-09-18 08:07:34 +00005174 const Expr *IfCond = nullptr;
5175 for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
5176 if (C->getNameModifier() == OMPD_unknown ||
5177 C->getNameModifier() == OMPD_cancel) {
5178 IfCond = C->getCondition();
5179 break;
5180 }
5181 }
Johannes Doerfert10fedd92019-12-26 11:23:38 -06005182 if (llvm::OpenMPIRBuilder *OMPBuilder = CGM.getOpenMPIRBuilder()) {
5183 // TODO: This check is necessary as we only generate `omp parallel` through
5184 // the OpenMPIRBuilder for now.
5185 if (S.getCancelRegion() == OMPD_parallel) {
5186 llvm::Value *IfCondition = nullptr;
5187 if (IfCond)
5188 IfCondition = EmitScalarExpr(IfCond,
5189 /*IgnoreResultAssign=*/true);
5190 return Builder.restoreIP(
5191 OMPBuilder->CreateCancel(Builder, IfCondition, S.getCancelRegion()));
5192 }
5193 }
5194
Stephen Kellyf2ceec42018-08-09 21:08:08 +00005195 CGM.getOpenMPRuntime().emitCancelCall(*this, S.getBeginLoc(), IfCond,
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00005196 S.getCancelRegion());
Alexey Bataev80909872015-07-02 11:25:17 +00005197}
5198
Alexey Bataev81c7ea02015-07-03 09:56:58 +00005199CodeGenFunction::JumpDest
5200CodeGenFunction::getOMPCancelDestination(OpenMPDirectiveKind Kind) {
Alexey Bataev957d8562016-11-17 15:12:05 +00005201 if (Kind == OMPD_parallel || Kind == OMPD_task ||
Alexey Bataeve0ca4792020-02-12 16:12:53 -05005202 Kind == OMPD_target_parallel || Kind == OMPD_taskloop ||
5203 Kind == OMPD_master_taskloop || Kind == OMPD_parallel_master_taskloop)
Alexey Bataev81c7ea02015-07-03 09:56:58 +00005204 return ReturnBlock;
Alexey Bataev25e5b442015-09-15 12:52:43 +00005205 assert(Kind == OMPD_for || Kind == OMPD_section || Kind == OMPD_sections ||
Alexey Bataev957d8562016-11-17 15:12:05 +00005206 Kind == OMPD_parallel_sections || Kind == OMPD_parallel_for ||
5207 Kind == OMPD_distribute_parallel_for ||
Alexey Bataevdcb4b8fb2017-11-22 20:19:50 +00005208 Kind == OMPD_target_parallel_for ||
Alexey Bataev16e79882017-11-22 21:12:03 +00005209 Kind == OMPD_teams_distribute_parallel_for ||
5210 Kind == OMPD_target_teams_distribute_parallel_for);
Alexey Bataev957d8562016-11-17 15:12:05 +00005211 return OMPCancelStack.getExitBlock();
Alexey Bataev81c7ea02015-07-03 09:56:58 +00005212}
Michael Wong65f367f2015-07-21 13:44:28 +00005213
Samuel Antaocc10b852016-07-28 14:23:26 +00005214void CodeGenFunction::EmitOMPUseDevicePtrClause(
5215 const OMPClause &NC, OMPPrivateScope &PrivateScope,
5216 const llvm::DenseMap<const ValueDecl *, Address> &CaptureDeviceAddrMap) {
5217 const auto &C = cast<OMPUseDevicePtrClause>(NC);
5218 auto OrigVarIt = C.varlist_begin();
5219 auto InitIt = C.inits().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00005220 for (const Expr *PvtVarIt : C.private_copies()) {
5221 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*OrigVarIt)->getDecl());
5222 const auto *InitVD = cast<VarDecl>(cast<DeclRefExpr>(*InitIt)->getDecl());
5223 const auto *PvtVD = cast<VarDecl>(cast<DeclRefExpr>(PvtVarIt)->getDecl());
Samuel Antaocc10b852016-07-28 14:23:26 +00005224
5225 // In order to identify the right initializer we need to match the
5226 // declaration used by the mapping logic. In some cases we may get
5227 // OMPCapturedExprDecl that refers to the original declaration.
5228 const ValueDecl *MatchingVD = OrigVD;
Alexey Bataevddf3db92018-04-13 17:31:06 +00005229 if (const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
Samuel Antaocc10b852016-07-28 14:23:26 +00005230 // OMPCapturedExprDecl are used to privative fields of the current
5231 // structure.
Alexey Bataevddf3db92018-04-13 17:31:06 +00005232 const auto *ME = cast<MemberExpr>(OED->getInit());
Samuel Antaocc10b852016-07-28 14:23:26 +00005233 assert(isa<CXXThisExpr>(ME->getBase()) &&
5234 "Base should be the current struct!");
5235 MatchingVD = ME->getMemberDecl();
5236 }
5237
5238 // If we don't have information about the current list item, move on to
5239 // the next one.
5240 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
5241 if (InitAddrIt == CaptureDeviceAddrMap.end())
5242 continue;
5243
Alexey Bataevddf3db92018-04-13 17:31:06 +00005244 bool IsRegistered = PrivateScope.addPrivate(OrigVD, [this, OrigVD,
5245 InitAddrIt, InitVD,
5246 PvtVD]() {
Samuel Antaocc10b852016-07-28 14:23:26 +00005247 // Initialize the temporary initialization variable with the address we
5248 // get from the runtime library. We have to cast the source address
5249 // because it is always a void *. References are materialized in the
5250 // privatization scope, so the initialization here disregards the fact
5251 // the original variable is a reference.
5252 QualType AddrQTy =
5253 getContext().getPointerType(OrigVD->getType().getNonReferenceType());
5254 llvm::Type *AddrTy = ConvertTypeForMem(AddrQTy);
5255 Address InitAddr = Builder.CreateBitCast(InitAddrIt->second, AddrTy);
5256 setAddrOfLocalVar(InitVD, InitAddr);
5257
5258 // Emit private declaration, it will be initialized by the value we
5259 // declaration we just added to the local declarations map.
5260 EmitDecl(*PvtVD);
5261
5262 // The initialization variables reached its purpose in the emission
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00005263 // of the previous declaration, so we don't need it anymore.
Samuel Antaocc10b852016-07-28 14:23:26 +00005264 LocalDeclMap.erase(InitVD);
5265
5266 // Return the address of the private variable.
5267 return GetAddrOfLocalVar(PvtVD);
5268 });
5269 assert(IsRegistered && "firstprivate var already registered as private");
5270 // Silence the warning about unused variable.
5271 (void)IsRegistered;
5272
5273 ++OrigVarIt;
5274 ++InitIt;
5275 }
5276}
5277
Michael Wong65f367f2015-07-21 13:44:28 +00005278// Generate the instructions for '#pragma omp target data' directive.
5279void CodeGenFunction::EmitOMPTargetDataDirective(
5280 const OMPTargetDataDirective &S) {
Samuel Antaocc10b852016-07-28 14:23:26 +00005281 CGOpenMPRuntime::TargetDataInfo Info(/*RequiresDevicePointerInfo=*/true);
5282
5283 // Create a pre/post action to signal the privatization of the device pointer.
5284 // This action can be replaced by the OpenMP runtime code generation to
5285 // deactivate privatization.
5286 bool PrivatizeDevicePointers = false;
5287 class DevicePointerPrivActionTy : public PrePostActionTy {
5288 bool &PrivatizeDevicePointers;
5289
5290 public:
5291 explicit DevicePointerPrivActionTy(bool &PrivatizeDevicePointers)
5292 : PrePostActionTy(), PrivatizeDevicePointers(PrivatizeDevicePointers) {}
5293 void Enter(CodeGenFunction &CGF) override {
5294 PrivatizeDevicePointers = true;
5295 }
Samuel Antaodf158d52016-04-27 22:58:19 +00005296 };
Samuel Antaocc10b852016-07-28 14:23:26 +00005297 DevicePointerPrivActionTy PrivAction(PrivatizeDevicePointers);
5298
5299 auto &&CodeGen = [&S, &Info, &PrivatizeDevicePointers](
Alexey Bataev475a7442018-01-12 19:39:11 +00005300 CodeGenFunction &CGF, PrePostActionTy &Action) {
Samuel Antaocc10b852016-07-28 14:23:26 +00005301 auto &&InnermostCodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataev475a7442018-01-12 19:39:11 +00005302 CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
Samuel Antaocc10b852016-07-28 14:23:26 +00005303 };
5304
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00005305 // Codegen that selects whether to generate the privatization code or not.
Samuel Antaocc10b852016-07-28 14:23:26 +00005306 auto &&PrivCodeGen = [&S, &Info, &PrivatizeDevicePointers,
5307 &InnermostCodeGen](CodeGenFunction &CGF,
5308 PrePostActionTy &Action) {
5309 RegionCodeGenTy RCG(InnermostCodeGen);
5310 PrivatizeDevicePointers = false;
5311
5312 // Call the pre-action to change the status of PrivatizeDevicePointers if
5313 // needed.
5314 Action.Enter(CGF);
5315
5316 if (PrivatizeDevicePointers) {
5317 OMPPrivateScope PrivateScope(CGF);
5318 // Emit all instances of the use_device_ptr clause.
5319 for (const auto *C : S.getClausesOfKind<OMPUseDevicePtrClause>())
5320 CGF.EmitOMPUseDevicePtrClause(*C, PrivateScope,
5321 Info.CaptureDeviceAddrMap);
5322 (void)PrivateScope.Privatize();
5323 RCG(CGF);
Alexey Bataevddf3db92018-04-13 17:31:06 +00005324 } else {
Samuel Antaocc10b852016-07-28 14:23:26 +00005325 RCG(CGF);
Alexey Bataevddf3db92018-04-13 17:31:06 +00005326 }
Samuel Antaocc10b852016-07-28 14:23:26 +00005327 };
5328
5329 // Forward the provided action to the privatization codegen.
5330 RegionCodeGenTy PrivRCG(PrivCodeGen);
5331 PrivRCG.setAction(Action);
5332
5333 // Notwithstanding the body of the region is emitted as inlined directive,
5334 // we don't use an inline scope as changes in the references inside the
5335 // region are expected to be visible outside, so we do not privative them.
5336 OMPLexicalScope Scope(CGF, S);
5337 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_target_data,
5338 PrivRCG);
5339 };
5340
5341 RegionCodeGenTy RCG(CodeGen);
Samuel Antaodf158d52016-04-27 22:58:19 +00005342
5343 // If we don't have target devices, don't bother emitting the data mapping
5344 // code.
5345 if (CGM.getLangOpts().OMPTargetTriples.empty()) {
Samuel Antaocc10b852016-07-28 14:23:26 +00005346 RCG(*this);
Samuel Antaodf158d52016-04-27 22:58:19 +00005347 return;
5348 }
5349
5350 // Check if we have any if clause associated with the directive.
5351 const Expr *IfCond = nullptr;
Alexey Bataevddf3db92018-04-13 17:31:06 +00005352 if (const auto *C = S.getSingleClause<OMPIfClause>())
Samuel Antaodf158d52016-04-27 22:58:19 +00005353 IfCond = C->getCondition();
5354
5355 // Check if we have any device clause associated with the directive.
5356 const Expr *Device = nullptr;
Alexey Bataevddf3db92018-04-13 17:31:06 +00005357 if (const auto *C = S.getSingleClause<OMPDeviceClause>())
Samuel Antaodf158d52016-04-27 22:58:19 +00005358 Device = C->getDevice();
5359
Samuel Antaocc10b852016-07-28 14:23:26 +00005360 // Set the action to signal privatization of device pointers.
5361 RCG.setAction(PrivAction);
5362
5363 // Emit region code.
5364 CGM.getOpenMPRuntime().emitTargetDataCalls(*this, S, IfCond, Device, RCG,
5365 Info);
Michael Wong65f367f2015-07-21 13:44:28 +00005366}
Alexey Bataev49f6e782015-12-01 04:18:41 +00005367
Samuel Antaodf67fc42016-01-19 19:15:56 +00005368void CodeGenFunction::EmitOMPTargetEnterDataDirective(
5369 const OMPTargetEnterDataDirective &S) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00005370 // If we don't have target devices, don't bother emitting the data mapping
5371 // code.
5372 if (CGM.getLangOpts().OMPTargetTriples.empty())
5373 return;
5374
5375 // Check if we have any if clause associated with the directive.
5376 const Expr *IfCond = nullptr;
Alexey Bataevddf3db92018-04-13 17:31:06 +00005377 if (const auto *C = S.getSingleClause<OMPIfClause>())
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00005378 IfCond = C->getCondition();
5379
5380 // Check if we have any device clause associated with the directive.
5381 const Expr *Device = nullptr;
Alexey Bataevddf3db92018-04-13 17:31:06 +00005382 if (const auto *C = S.getSingleClause<OMPDeviceClause>())
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00005383 Device = C->getDevice();
5384
Alexey Bataev475a7442018-01-12 19:39:11 +00005385 OMPLexicalScope Scope(*this, S, OMPD_task);
Alexey Bataevd2202ca2017-12-27 17:58:32 +00005386 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*this, S, IfCond, Device);
Samuel Antaodf67fc42016-01-19 19:15:56 +00005387}
5388
Samuel Antao72590762016-01-19 20:04:50 +00005389void CodeGenFunction::EmitOMPTargetExitDataDirective(
5390 const OMPTargetExitDataDirective &S) {
Samuel Antao8dd66282016-04-27 23:14:30 +00005391 // If we don't have target devices, don't bother emitting the data mapping
5392 // code.
5393 if (CGM.getLangOpts().OMPTargetTriples.empty())
5394 return;
5395
5396 // Check if we have any if clause associated with the directive.
5397 const Expr *IfCond = nullptr;
Alexey Bataevddf3db92018-04-13 17:31:06 +00005398 if (const auto *C = S.getSingleClause<OMPIfClause>())
Samuel Antao8dd66282016-04-27 23:14:30 +00005399 IfCond = C->getCondition();
5400
5401 // Check if we have any device clause associated with the directive.
5402 const Expr *Device = nullptr;
Alexey Bataevddf3db92018-04-13 17:31:06 +00005403 if (const auto *C = S.getSingleClause<OMPDeviceClause>())
Samuel Antao8dd66282016-04-27 23:14:30 +00005404 Device = C->getDevice();
5405
Alexey Bataev475a7442018-01-12 19:39:11 +00005406 OMPLexicalScope Scope(*this, S, OMPD_task);
Alexey Bataevd2202ca2017-12-27 17:58:32 +00005407 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*this, S, IfCond, Device);
Samuel Antao72590762016-01-19 20:04:50 +00005408}
5409
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00005410static void emitTargetParallelRegion(CodeGenFunction &CGF,
5411 const OMPTargetParallelDirective &S,
5412 PrePostActionTy &Action) {
5413 // Get the captured statement associated with the 'parallel' region.
Alexey Bataevddf3db92018-04-13 17:31:06 +00005414 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00005415 Action.Enter(CGF);
Alexey Bataevc99042b2018-03-15 18:10:54 +00005416 auto &&CodeGen = [&S, CS](CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataev63cc8e92018-03-20 14:45:59 +00005417 Action.Enter(CGF);
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005418 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
5419 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
5420 CGF.EmitOMPPrivateClause(S, PrivateScope);
5421 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
5422 (void)PrivateScope.Privatize();
Alexey Bataev60705422018-10-30 15:50:12 +00005423 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()))
5424 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00005425 // TODO: Add support for clauses.
5426 CGF.EmitStmt(CS->getCapturedStmt());
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005427 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel);
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00005428 };
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00005429 emitCommonOMPParallelDirective(CGF, S, OMPD_parallel, CodeGen,
5430 emitEmptyBoundParameters);
Alexey Bataevddf3db92018-04-13 17:31:06 +00005431 emitPostUpdateForReductionClause(CGF, S,
5432 [](CodeGenFunction &) { return nullptr; });
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00005433}
5434
5435void CodeGenFunction::EmitOMPTargetParallelDeviceFunction(
5436 CodeGenModule &CGM, StringRef ParentName,
5437 const OMPTargetParallelDirective &S) {
5438 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5439 emitTargetParallelRegion(CGF, S, Action);
5440 };
5441 llvm::Function *Fn;
5442 llvm::Constant *Addr;
5443 // Emit target region as a standalone region.
5444 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
5445 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
5446 assert(Fn && Addr && "Target device function emission failed.");
5447}
5448
Arpith Chacko Jacobe955b3d2016-01-26 18:48:41 +00005449void CodeGenFunction::EmitOMPTargetParallelDirective(
5450 const OMPTargetParallelDirective &S) {
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00005451 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5452 emitTargetParallelRegion(CGF, S, Action);
5453 };
5454 emitCommonOMPTargetDirective(*this, S, CodeGen);
Arpith Chacko Jacobe955b3d2016-01-26 18:48:41 +00005455}
5456
Alexey Bataevfb0ebec2017-11-08 20:16:14 +00005457static void emitTargetParallelForRegion(CodeGenFunction &CGF,
5458 const OMPTargetParallelForDirective &S,
5459 PrePostActionTy &Action) {
5460 Action.Enter(CGF);
5461 // Emit directive as a combined directive that consists of two implicit
5462 // directives: 'parallel' with 'for' directive.
Alexey Bataevc99042b2018-03-15 18:10:54 +00005463 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5464 Action.Enter(CGF);
Alexey Bataev2139ed62017-11-16 18:20:21 +00005465 CodeGenFunction::OMPCancelStackRAII CancelRegion(
5466 CGF, OMPD_target_parallel_for, S.hasCancel());
Alexey Bataevfb0ebec2017-11-08 20:16:14 +00005467 CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds,
5468 emitDispatchForLoopBounds);
5469 };
5470 emitCommonOMPParallelDirective(CGF, S, OMPD_for, CodeGen,
5471 emitEmptyBoundParameters);
5472}
5473
5474void CodeGenFunction::EmitOMPTargetParallelForDeviceFunction(
5475 CodeGenModule &CGM, StringRef ParentName,
5476 const OMPTargetParallelForDirective &S) {
5477 // Emit SPMD target parallel for region as a standalone region.
5478 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5479 emitTargetParallelForRegion(CGF, S, Action);
5480 };
5481 llvm::Function *Fn;
5482 llvm::Constant *Addr;
5483 // Emit target region as a standalone region.
5484 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
5485 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
5486 assert(Fn && Addr && "Target device function emission failed.");
5487}
5488
Arpith Chacko Jacob05bebb52016-02-03 15:46:42 +00005489void CodeGenFunction::EmitOMPTargetParallelForDirective(
5490 const OMPTargetParallelForDirective &S) {
Alexey Bataevfb0ebec2017-11-08 20:16:14 +00005491 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5492 emitTargetParallelForRegion(CGF, S, Action);
5493 };
5494 emitCommonOMPTargetDirective(*this, S, CodeGen);
Arpith Chacko Jacob05bebb52016-02-03 15:46:42 +00005495}
5496
Alexey Bataev5d7edca2017-11-09 17:32:15 +00005497static void
5498emitTargetParallelForSimdRegion(CodeGenFunction &CGF,
5499 const OMPTargetParallelForSimdDirective &S,
5500 PrePostActionTy &Action) {
5501 Action.Enter(CGF);
5502 // Emit directive as a combined directive that consists of two implicit
5503 // directives: 'parallel' with 'for' directive.
Alexey Bataevc99042b2018-03-15 18:10:54 +00005504 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5505 Action.Enter(CGF);
Alexey Bataev5d7edca2017-11-09 17:32:15 +00005506 CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds,
5507 emitDispatchForLoopBounds);
5508 };
5509 emitCommonOMPParallelDirective(CGF, S, OMPD_simd, CodeGen,
5510 emitEmptyBoundParameters);
5511}
5512
5513void CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction(
5514 CodeGenModule &CGM, StringRef ParentName,
5515 const OMPTargetParallelForSimdDirective &S) {
5516 // Emit SPMD target parallel for region as a standalone region.
5517 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5518 emitTargetParallelForSimdRegion(CGF, S, Action);
5519 };
5520 llvm::Function *Fn;
5521 llvm::Constant *Addr;
5522 // Emit target region as a standalone region.
5523 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
5524 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
5525 assert(Fn && Addr && "Target device function emission failed.");
5526}
5527
5528void CodeGenFunction::EmitOMPTargetParallelForSimdDirective(
5529 const OMPTargetParallelForSimdDirective &S) {
5530 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5531 emitTargetParallelForSimdRegion(CGF, S, Action);
5532 };
5533 emitCommonOMPTargetDirective(*this, S, CodeGen);
5534}
5535
Alexey Bataev7292c292016-04-25 12:22:29 +00005536/// Emit a helper variable and return corresponding lvalue.
5537static void mapParam(CodeGenFunction &CGF, const DeclRefExpr *Helper,
5538 const ImplicitParamDecl *PVD,
5539 CodeGenFunction::OMPPrivateScope &Privates) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00005540 const auto *VDecl = cast<VarDecl>(Helper->getDecl());
5541 Privates.addPrivate(VDecl,
5542 [&CGF, PVD]() { return CGF.GetAddrOfLocalVar(PVD); });
Alexey Bataev7292c292016-04-25 12:22:29 +00005543}
5544
5545void CodeGenFunction::EmitOMPTaskLoopBasedDirective(const OMPLoopDirective &S) {
5546 assert(isOpenMPTaskLoopDirective(S.getDirectiveKind()));
5547 // Emit outlined function for task construct.
Alexey Bataev475a7442018-01-12 19:39:11 +00005548 const CapturedStmt *CS = S.getCapturedStmt(OMPD_taskloop);
Alexey Bataevddf3db92018-04-13 17:31:06 +00005549 Address CapturedStruct = GenerateCapturedStmtArgument(*CS);
5550 QualType SharedsTy = getContext().getRecordType(CS->getCapturedRecordDecl());
Alexey Bataev7292c292016-04-25 12:22:29 +00005551 const Expr *IfCond = nullptr;
5552 for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
5553 if (C->getNameModifier() == OMPD_unknown ||
5554 C->getNameModifier() == OMPD_taskloop) {
5555 IfCond = C->getCondition();
5556 break;
5557 }
5558 }
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005559
5560 OMPTaskDataTy Data;
5561 // Check if taskloop must be emitted without taskgroup.
5562 Data.Nogroup = S.getSingleClause<OMPNogroupClause>();
Alexey Bataev7292c292016-04-25 12:22:29 +00005563 // TODO: Check if we should emit tied or untied task.
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005564 Data.Tied = true;
5565 // Set scheduling for taskloop
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005566 if (const auto* Clause = S.getSingleClause<OMPGrainsizeClause>()) {
5567 // grainsize clause
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005568 Data.Schedule.setInt(/*IntVal=*/false);
5569 Data.Schedule.setPointer(EmitScalarExpr(Clause->getGrainsize()));
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005570 } else if (const auto* Clause = S.getSingleClause<OMPNumTasksClause>()) {
5571 // num_tasks clause
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005572 Data.Schedule.setInt(/*IntVal=*/true);
5573 Data.Schedule.setPointer(EmitScalarExpr(Clause->getNumTasks()));
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005574 }
Alexey Bataev7292c292016-04-25 12:22:29 +00005575
5576 auto &&BodyGen = [CS, &S](CodeGenFunction &CGF, PrePostActionTy &) {
5577 // if (PreCond) {
5578 // for (IV in 0..LastIteration) BODY;
5579 // <Final counter/linear vars updates>;
5580 // }
5581 //
5582
5583 // Emit: if (PreCond) - begin.
5584 // If the condition constant folds and can be elided, avoid emitting the
5585 // whole loop.
5586 bool CondConstant;
5587 llvm::BasicBlock *ContBlock = nullptr;
5588 OMPLoopScope PreInitScope(CGF, S);
5589 if (CGF.ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
5590 if (!CondConstant)
5591 return;
5592 } else {
Alexey Bataevddf3db92018-04-13 17:31:06 +00005593 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("taskloop.if.then");
Alexey Bataev7292c292016-04-25 12:22:29 +00005594 ContBlock = CGF.createBasicBlock("taskloop.if.end");
5595 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
5596 CGF.getProfileCount(&S));
5597 CGF.EmitBlock(ThenBlock);
5598 CGF.incrementProfileCounter(&S);
5599 }
5600
Alexey Bataev61205822019-12-04 09:50:21 -05005601 (void)CGF.EmitOMPLinearClauseInit(S);
Alexey Bataev1e73ef32016-04-28 12:14:51 +00005602
Alexey Bataev7292c292016-04-25 12:22:29 +00005603 OMPPrivateScope LoopScope(CGF);
5604 // Emit helper vars inits.
5605 enum { LowerBound = 5, UpperBound, Stride, LastIter };
5606 auto *I = CS->getCapturedDecl()->param_begin();
5607 auto *LBP = std::next(I, LowerBound);
5608 auto *UBP = std::next(I, UpperBound);
5609 auto *STP = std::next(I, Stride);
5610 auto *LIP = std::next(I, LastIter);
5611 mapParam(CGF, cast<DeclRefExpr>(S.getLowerBoundVariable()), *LBP,
5612 LoopScope);
5613 mapParam(CGF, cast<DeclRefExpr>(S.getUpperBoundVariable()), *UBP,
5614 LoopScope);
5615 mapParam(CGF, cast<DeclRefExpr>(S.getStrideVariable()), *STP, LoopScope);
5616 mapParam(CGF, cast<DeclRefExpr>(S.getIsLastIterVariable()), *LIP,
5617 LoopScope);
5618 CGF.EmitOMPPrivateLoopCounters(S, LoopScope);
Alexey Bataev14a388f2019-10-25 10:27:13 -04005619 CGF.EmitOMPLinearClause(S, LoopScope);
Alexey Bataevf93095a2016-05-05 08:46:22 +00005620 bool HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
Alexey Bataev7292c292016-04-25 12:22:29 +00005621 (void)LoopScope.Privatize();
5622 // Emit the loop iteration variable.
5623 const Expr *IVExpr = S.getIterationVariable();
Alexey Bataevddf3db92018-04-13 17:31:06 +00005624 const auto *IVDecl = cast<VarDecl>(cast<DeclRefExpr>(IVExpr)->getDecl());
Alexey Bataev7292c292016-04-25 12:22:29 +00005625 CGF.EmitVarDecl(*IVDecl);
5626 CGF.EmitIgnoredExpr(S.getInit());
5627
5628 // Emit the iterations count variable.
5629 // If it is not a variable, Sema decided to calculate iterations count on
5630 // each iteration (e.g., it is foldable into a constant).
Alexey Bataevddf3db92018-04-13 17:31:06 +00005631 if (const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
Alexey Bataev7292c292016-04-25 12:22:29 +00005632 CGF.EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
5633 // Emit calculation of the iterations count.
5634 CGF.EmitIgnoredExpr(S.getCalcLastIteration());
5635 }
5636
Alexey Bataev61205822019-12-04 09:50:21 -05005637 {
5638 OMPLexicalScope Scope(CGF, S, OMPD_taskloop, /*EmitPreInitStmt=*/false);
5639 emitCommonSimdLoop(
5640 CGF, S,
5641 [&S](CodeGenFunction &CGF, PrePostActionTy &) {
5642 if (isOpenMPSimdDirective(S.getDirectiveKind()))
5643 CGF.EmitOMPSimdInit(S);
5644 },
5645 [&S, &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) {
5646 CGF.EmitOMPInnerLoop(
5647 S, LoopScope.requiresCleanups(), S.getCond(), S.getInc(),
5648 [&S](CodeGenFunction &CGF) {
5649 CGF.EmitOMPLoopBody(S, CodeGenFunction::JumpDest());
5650 CGF.EmitStopPoint(&S);
5651 },
5652 [](CodeGenFunction &) {});
5653 });
5654 }
Alexey Bataev7292c292016-04-25 12:22:29 +00005655 // Emit: if (PreCond) - end.
5656 if (ContBlock) {
5657 CGF.EmitBranch(ContBlock);
5658 CGF.EmitBlock(ContBlock, true);
5659 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00005660 // Emit final copy of the lastprivate variables if IsLastIter != 0.
5661 if (HasLastprivateClause) {
5662 CGF.EmitOMPLastprivateClauseFinal(
5663 S, isOpenMPSimdDirective(S.getDirectiveKind()),
5664 CGF.Builder.CreateIsNotNull(CGF.EmitLoadOfScalar(
5665 CGF.GetAddrOfLocalVar(*LIP), /*Volatile=*/false,
Stephen Kellyf2ceec42018-08-09 21:08:08 +00005666 (*LIP)->getType(), S.getBeginLoc())));
Alexey Bataevf93095a2016-05-05 08:46:22 +00005667 }
Alexey Bataev14a388f2019-10-25 10:27:13 -04005668 CGF.EmitOMPLinearClauseFinal(S, [LIP, &S](CodeGenFunction &CGF) {
5669 return CGF.Builder.CreateIsNotNull(
5670 CGF.EmitLoadOfScalar(CGF.GetAddrOfLocalVar(*LIP), /*Volatile=*/false,
5671 (*LIP)->getType(), S.getBeginLoc()));
5672 });
Alexey Bataev7292c292016-04-25 12:22:29 +00005673 };
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005674 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
James Y Knight9871db02019-02-05 16:42:33 +00005675 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005676 const OMPTaskDataTy &Data) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00005677 auto &&CodeGen = [&S, OutlinedFn, SharedsTy, CapturedStruct, IfCond,
5678 &Data](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataev7292c292016-04-25 12:22:29 +00005679 OMPLoopScope PreInitScope(CGF, S);
Stephen Kellyf2ceec42018-08-09 21:08:08 +00005680 CGF.CGM.getOpenMPRuntime().emitTaskLoopCall(CGF, S.getBeginLoc(), S,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005681 OutlinedFn, SharedsTy,
5682 CapturedStruct, IfCond, Data);
Alexey Bataev7292c292016-04-25 12:22:29 +00005683 };
5684 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_taskloop,
5685 CodeGen);
5686 };
Alexey Bataev475a7442018-01-12 19:39:11 +00005687 if (Data.Nogroup) {
5688 EmitOMPTaskBasedDirective(S, OMPD_taskloop, BodyGen, TaskGen, Data);
5689 } else {
Alexey Bataev33446032017-07-12 18:09:32 +00005690 CGM.getOpenMPRuntime().emitTaskgroupRegion(
5691 *this,
5692 [&S, &BodyGen, &TaskGen, &Data](CodeGenFunction &CGF,
5693 PrePostActionTy &Action) {
5694 Action.Enter(CGF);
Alexey Bataev475a7442018-01-12 19:39:11 +00005695 CGF.EmitOMPTaskBasedDirective(S, OMPD_taskloop, BodyGen, TaskGen,
5696 Data);
Alexey Bataev33446032017-07-12 18:09:32 +00005697 },
Stephen Kellyf2ceec42018-08-09 21:08:08 +00005698 S.getBeginLoc());
Alexey Bataev33446032017-07-12 18:09:32 +00005699 }
Alexey Bataev7292c292016-04-25 12:22:29 +00005700}
5701
Alexey Bataev49f6e782015-12-01 04:18:41 +00005702void CodeGenFunction::EmitOMPTaskLoopDirective(const OMPTaskLoopDirective &S) {
Alexey Bataev46978742020-01-30 10:46:11 -05005703 auto LPCRegion =
5704 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
Alexey Bataev7292c292016-04-25 12:22:29 +00005705 EmitOMPTaskLoopBasedDirective(S);
Alexey Bataev49f6e782015-12-01 04:18:41 +00005706}
5707
Alexey Bataev0a6ed842015-12-03 09:40:15 +00005708void CodeGenFunction::EmitOMPTaskLoopSimdDirective(
5709 const OMPTaskLoopSimdDirective &S) {
Alexey Bataev46978742020-01-30 10:46:11 -05005710 auto LPCRegion =
5711 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
Alexey Bataev61205822019-12-04 09:50:21 -05005712 OMPLexicalScope Scope(*this, S);
Alexey Bataev1e73ef32016-04-28 12:14:51 +00005713 EmitOMPTaskLoopBasedDirective(S);
Alexey Bataev0a6ed842015-12-03 09:40:15 +00005714}
Samuel Antao686c70c2016-05-26 17:30:50 +00005715
Alexey Bataev60e51c42019-10-10 20:13:02 +00005716void CodeGenFunction::EmitOMPMasterTaskLoopDirective(
5717 const OMPMasterTaskLoopDirective &S) {
5718 auto &&CodeGen = [this, &S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5719 Action.Enter(CGF);
5720 EmitOMPTaskLoopBasedDirective(S);
5721 };
Alexey Bataev46978742020-01-30 10:46:11 -05005722 auto LPCRegion =
5723 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
Alexey Bataev60e51c42019-10-10 20:13:02 +00005724 OMPLexicalScope Scope(*this, S, llvm::None, /*EmitPreInitStmt=*/false);
5725 CGM.getOpenMPRuntime().emitMasterRegion(*this, CodeGen, S.getBeginLoc());
5726}
5727
Alexey Bataevb8552ab2019-10-18 16:47:35 +00005728void CodeGenFunction::EmitOMPMasterTaskLoopSimdDirective(
5729 const OMPMasterTaskLoopSimdDirective &S) {
5730 auto &&CodeGen = [this, &S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5731 Action.Enter(CGF);
5732 EmitOMPTaskLoopBasedDirective(S);
5733 };
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 Bataevb8552ab2019-10-18 16:47:35 +00005737 CGM.getOpenMPRuntime().emitMasterRegion(*this, CodeGen, S.getBeginLoc());
5738}
5739
Alexey Bataev5bbcead2019-10-14 17:17:41 +00005740void CodeGenFunction::EmitOMPParallelMasterTaskLoopDirective(
5741 const OMPParallelMasterTaskLoopDirective &S) {
5742 auto &&CodeGen = [this, &S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5743 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
5744 PrePostActionTy &Action) {
5745 Action.Enter(CGF);
5746 CGF.EmitOMPTaskLoopBasedDirective(S);
5747 };
Alexey Bataev18789bf2020-02-13 09:21:15 -05005748 OMPLexicalScope Scope(CGF, S, OMPD_parallel, /*EmitPreInitStmt=*/false);
Alexey Bataev5bbcead2019-10-14 17:17:41 +00005749 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
5750 S.getBeginLoc());
5751 };
Alexey Bataev46978742020-01-30 10:46:11 -05005752 auto LPCRegion =
5753 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
Alexey Bataev5bbcead2019-10-14 17:17:41 +00005754 emitCommonOMPParallelDirective(*this, S, OMPD_master_taskloop, CodeGen,
5755 emitEmptyBoundParameters);
5756}
5757
Alexey Bataev14a388f2019-10-25 10:27:13 -04005758void CodeGenFunction::EmitOMPParallelMasterTaskLoopSimdDirective(
5759 const OMPParallelMasterTaskLoopSimdDirective &S) {
5760 auto &&CodeGen = [this, &S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5761 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
5762 PrePostActionTy &Action) {
5763 Action.Enter(CGF);
5764 CGF.EmitOMPTaskLoopBasedDirective(S);
5765 };
5766 OMPLexicalScope Scope(CGF, S, OMPD_parallel, /*EmitPreInitStmt=*/false);
5767 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
5768 S.getBeginLoc());
5769 };
Alexey Bataev46978742020-01-30 10:46:11 -05005770 auto LPCRegion =
5771 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
Alexey Bataev14a388f2019-10-25 10:27:13 -04005772 emitCommonOMPParallelDirective(*this, S, OMPD_master_taskloop_simd, CodeGen,
5773 emitEmptyBoundParameters);
5774}
5775
Samuel Antao686c70c2016-05-26 17:30:50 +00005776// Generate the instructions for '#pragma omp target update' directive.
5777void CodeGenFunction::EmitOMPTargetUpdateDirective(
5778 const OMPTargetUpdateDirective &S) {
Samuel Antao8d2d7302016-05-26 18:30:22 +00005779 // If we don't have target devices, don't bother emitting the data mapping
5780 // code.
5781 if (CGM.getLangOpts().OMPTargetTriples.empty())
5782 return;
5783
5784 // Check if we have any if clause associated with the directive.
5785 const Expr *IfCond = nullptr;
Alexey Bataevddf3db92018-04-13 17:31:06 +00005786 if (const auto *C = S.getSingleClause<OMPIfClause>())
Samuel Antao8d2d7302016-05-26 18:30:22 +00005787 IfCond = C->getCondition();
5788
5789 // Check if we have any device clause associated with the directive.
5790 const Expr *Device = nullptr;
Alexey Bataevddf3db92018-04-13 17:31:06 +00005791 if (const auto *C = S.getSingleClause<OMPDeviceClause>())
Samuel Antao8d2d7302016-05-26 18:30:22 +00005792 Device = C->getDevice();
5793
Alexey Bataev475a7442018-01-12 19:39:11 +00005794 OMPLexicalScope Scope(*this, S, OMPD_task);
Alexey Bataevd2202ca2017-12-27 17:58:32 +00005795 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*this, S, IfCond, Device);
Samuel Antao686c70c2016-05-26 17:30:50 +00005796}
Alexey Bataeva8a9153a2017-12-29 18:07:07 +00005797
5798void CodeGenFunction::EmitSimpleOMPExecutableDirective(
5799 const OMPExecutableDirective &D) {
5800 if (!D.hasAssociatedStmt() || !D.getAssociatedStmt())
5801 return;
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08005802 auto &&CodeGen = [&D](CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataeva8a9153a2017-12-29 18:07:07 +00005803 if (isOpenMPSimdDirective(D.getDirectiveKind())) {
5804 emitOMPSimdRegion(CGF, cast<OMPLoopDirective>(D), Action);
5805 } else {
Alexey Bataev6ab5bb12018-10-29 15:01:58 +00005806 OMPPrivateScope LoopGlobals(CGF);
Alexey Bataeva8a9153a2017-12-29 18:07:07 +00005807 if (const auto *LD = dyn_cast<OMPLoopDirective>(&D)) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00005808 for (const Expr *E : LD->counters()) {
Simon Pilgrim93431f92020-01-11 16:00:17 +00005809 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev6ab5bb12018-10-29 15:01:58 +00005810 if (!VD->hasLocalStorage() && !CGF.LocalDeclMap.count(VD)) {
5811 LValue GlobLVal = CGF.EmitLValue(E);
5812 LoopGlobals.addPrivate(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08005813 VD, [&GlobLVal, &CGF]() { return GlobLVal.getAddress(CGF); });
Alexey Bataev6ab5bb12018-10-29 15:01:58 +00005814 }
Bjorn Pettersson6c2d83b2018-10-30 08:49:26 +00005815 if (isa<OMPCapturedExprDecl>(VD)) {
Alexey Bataeva8a9153a2017-12-29 18:07:07 +00005816 // Emit only those that were not explicitly referenced in clauses.
5817 if (!CGF.LocalDeclMap.count(VD))
5818 CGF.EmitVarDecl(*VD);
5819 }
5820 }
Alexey Bataevf138fda2018-08-13 19:04:24 +00005821 for (const auto *C : D.getClausesOfKind<OMPOrderedClause>()) {
5822 if (!C->getNumForLoops())
5823 continue;
5824 for (unsigned I = LD->getCollapsedNumber(),
5825 E = C->getLoopNumIterations().size();
5826 I < E; ++I) {
5827 if (const auto *VD = dyn_cast<OMPCapturedExprDecl>(
Mike Rice0ed46662018-09-20 17:19:41 +00005828 cast<DeclRefExpr>(C->getLoopCounter(I))->getDecl())) {
Alexey Bataevf138fda2018-08-13 19:04:24 +00005829 // Emit only those that were not explicitly referenced in clauses.
5830 if (!CGF.LocalDeclMap.count(VD))
5831 CGF.EmitVarDecl(*VD);
5832 }
5833 }
5834 }
Alexey Bataeva8a9153a2017-12-29 18:07:07 +00005835 }
Alexey Bataev6ab5bb12018-10-29 15:01:58 +00005836 LoopGlobals.Privatize();
Alexey Bataev475a7442018-01-12 19:39:11 +00005837 CGF.EmitStmt(D.getInnermostCapturedStmt()->getCapturedStmt());
Alexey Bataeva8a9153a2017-12-29 18:07:07 +00005838 }
5839 };
Alexey Bataev46978742020-01-30 10:46:11 -05005840 {
5841 auto LPCRegion =
5842 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, D);
5843 OMPSimdLexicalScope Scope(*this, D);
5844 CGM.getOpenMPRuntime().emitInlinedDirective(
5845 *this,
5846 isOpenMPSimdDirective(D.getDirectiveKind()) ? OMPD_simd
5847 : D.getDirectiveKind(),
5848 CodeGen);
5849 }
5850 // Check for outer lastprivate conditional update.
5851 checkForLastprivateConditionalUpdate(*this, D);
Alexey Bataeva8a9153a2017-12-29 18:07:07 +00005852}