blob: d7115e00836c8f094ecee28c1e97dedb0f15a3c6 [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) {
1453 CGBuilderTy::InsertPointGuard IPG(Builder);
1454 assert(IP.getBlock()->end() != IP.getPoint() &&
1455 "OpenMP IR Builder should cause terminated block!");
1456 llvm::BasicBlock *IPBB = IP.getBlock();
1457 llvm::BasicBlock *DestBB = IPBB->splitBasicBlock(IP.getPoint());
1458 IPBB->getTerminator()->eraseFromParent();
1459 Builder.SetInsertPoint(IPBB);
1460 CodeGenFunction::JumpDest Dest = getJumpDestInCurrentScope(DestBB);
1461 EmitBranchThroughCleanup(Dest);
1462 };
1463
1464 // Privatization callback that performs appropriate action for
1465 // shared/private/firstprivate/lastprivate/copyin/... variables.
1466 //
1467 // TODO: This defaults to shared right now.
1468 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
1469 llvm::Value &Val, llvm::Value *&ReplVal) {
1470 // The next line is appropriate only for variables (Val) with the
1471 // data-sharing attribute "shared".
1472 ReplVal = &Val;
1473
1474 return CodeGenIP;
1475 };
1476
1477 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
1478 const Stmt *ParallelRegionBodyStmt = CS->getCapturedStmt();
1479
1480 auto BodyGenCB = [ParallelRegionBodyStmt,
1481 this](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
1482 llvm::BasicBlock &ContinuationBB) {
1483 auto OldAllocaIP = AllocaInsertPt;
1484 AllocaInsertPt = &*AllocaIP.getPoint();
1485
1486 auto OldReturnBlock = ReturnBlock;
1487 ReturnBlock = getJumpDestInCurrentScope(&ContinuationBB);
1488
1489 llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock();
1490 CodeGenIPBB->splitBasicBlock(CodeGenIP.getPoint());
1491 llvm::Instruction *CodeGenIPBBTI = CodeGenIPBB->getTerminator();
1492 CodeGenIPBBTI->removeFromParent();
1493
1494 Builder.SetInsertPoint(CodeGenIPBB);
1495
1496 EmitStmt(ParallelRegionBodyStmt);
1497
1498 Builder.Insert(CodeGenIPBBTI);
1499
1500 AllocaInsertPt = OldAllocaIP;
1501 ReturnBlock = OldReturnBlock;
1502 };
1503
1504 CGCapturedStmtInfo CGSI(*CS, CR_OpenMP);
1505 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(*this, &CGSI);
1506 Builder.restoreIP(OMPBuilder->CreateParallel(Builder, BodyGenCB, PrivCB,
1507 FiniCB, IfCond, NumThreads,
1508 ProcBind, S.hasCancel()));
1509 return;
1510 }
1511
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001512 // Emit parallel region as a standalone region.
Alexey Bataevc99042b2018-03-15 18:10:54 +00001513 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataev63cc8e92018-03-20 14:45:59 +00001514 Action.Enter(CGF);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001515 OMPPrivateScope PrivateScope(CGF);
Alexey Bataevf56f98c2015-04-16 05:39:01 +00001516 bool Copyins = CGF.EmitOMPCopyinClause(S);
Alexey Bataevcd8b6a22016-02-15 08:07:17 +00001517 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
1518 if (Copyins) {
Alexey Bataev69c62a92015-04-15 04:52:20 +00001519 // Emit implicit barrier to synchronize threads and avoid data races on
Alexey Bataevcd8b6a22016-02-15 08:07:17 +00001520 // propagation master's thread values of threadprivate variables to local
1521 // instances of that variables of all other implicit threads.
Alexey Bataev25e5b442015-09-15 12:52:43 +00001522 CGF.CGM.getOpenMPRuntime().emitBarrierCall(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00001523 CGF, S.getBeginLoc(), OMPD_unknown, /*EmitChecks=*/false,
Alexey Bataev25e5b442015-09-15 12:52:43 +00001524 /*ForceSimpleCall=*/true);
Alexey Bataev69c62a92015-04-15 04:52:20 +00001525 }
1526 CGF.EmitOMPPrivateClause(S, PrivateScope);
1527 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
1528 (void)PrivateScope.Privatize();
Alexey Bataev475a7442018-01-12 19:39:11 +00001529 CGF.EmitStmt(S.getCapturedStmt(OMPD_parallel)->getCapturedStmt());
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00001530 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001531 };
Alexey Bataev46978742020-01-30 10:46:11 -05001532 {
1533 auto LPCRegion =
1534 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
1535 emitCommonOMPParallelDirective(*this, S, OMPD_parallel, CodeGen,
1536 emitEmptyBoundParameters);
1537 emitPostUpdateForReductionClause(*this, S,
1538 [](CodeGenFunction &) { return nullptr; });
1539 }
1540 // Check for outer lastprivate conditional update.
1541 checkForLastprivateConditionalUpdate(*this, S);
Alexey Bataev9959db52014-05-06 10:08:46 +00001542}
Alexander Musman515ad8c2014-05-22 08:54:05 +00001543
Alexey Bataev8bbf2e32019-11-04 09:59:11 -05001544static void emitBody(CodeGenFunction &CGF, const Stmt *S, const Stmt *NextLoop,
1545 int MaxLevel, int Level = 0) {
1546 assert(Level < MaxLevel && "Too deep lookup during loop body codegen.");
1547 const Stmt *SimplifiedS = S->IgnoreContainers();
1548 if (const auto *CS = dyn_cast<CompoundStmt>(SimplifiedS)) {
1549 PrettyStackTraceLoc CrashInfo(
1550 CGF.getContext().getSourceManager(), CS->getLBracLoc(),
1551 "LLVM IR generation of compound statement ('{}')");
1552
1553 // Keep track of the current cleanup stack depth, including debug scopes.
1554 CodeGenFunction::LexicalScope Scope(CGF, S->getSourceRange());
1555 for (const Stmt *CurStmt : CS->body())
1556 emitBody(CGF, CurStmt, NextLoop, MaxLevel, Level);
1557 return;
1558 }
1559 if (SimplifiedS == NextLoop) {
1560 if (const auto *For = dyn_cast<ForStmt>(SimplifiedS)) {
1561 S = For->getBody();
1562 } else {
1563 assert(isa<CXXForRangeStmt>(SimplifiedS) &&
1564 "Expected canonical for loop or range-based for loop.");
1565 const auto *CXXFor = cast<CXXForRangeStmt>(SimplifiedS);
1566 CGF.EmitStmt(CXXFor->getLoopVarStmt());
1567 S = CXXFor->getBody();
1568 }
1569 if (Level + 1 < MaxLevel) {
1570 NextLoop = OMPLoopDirective::tryToFindNextInnerLoop(
1571 S, /*TryImperfectlyNestedLoops=*/true);
1572 emitBody(CGF, S, NextLoop, MaxLevel, Level + 1);
1573 return;
1574 }
1575 }
1576 CGF.EmitStmt(S);
1577}
1578
Alexey Bataev0f34da12015-07-02 04:17:07 +00001579void CodeGenFunction::EmitOMPLoopBody(const OMPLoopDirective &D,
1580 JumpDest LoopExit) {
Alexander Musmana5f070a2014-10-01 06:03:56 +00001581 RunCleanupsScope BodyScope(*this);
1582 // Update counters values on current iteration.
Alexey Bataevddf3db92018-04-13 17:31:06 +00001583 for (const Expr *UE : D.updates())
1584 EmitIgnoredExpr(UE);
Alexander Musman3276a272015-03-21 10:12:56 +00001585 // Update the linear variables.
Alexey Bataev617db5f2017-12-04 15:38:33 +00001586 // In distribute directives only loop counters may be marked as linear, no
1587 // need to generate the code for them.
1588 if (!isOpenMPDistributeDirective(D.getDirectiveKind())) {
1589 for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00001590 for (const Expr *UE : C->updates())
1591 EmitIgnoredExpr(UE);
Alexey Bataev617db5f2017-12-04 15:38:33 +00001592 }
Alexander Musman3276a272015-03-21 10:12:56 +00001593 }
1594
Alexander Musmana5f070a2014-10-01 06:03:56 +00001595 // On a continue in the body, jump to the end.
Alexey Bataevddf3db92018-04-13 17:31:06 +00001596 JumpDest Continue = getJumpDestInCurrentScope("omp.body.continue");
Alexey Bataev0f34da12015-07-02 04:17:07 +00001597 BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
Alexey Bataevf8be4762019-08-14 19:30:06 +00001598 for (const Expr *E : D.finals_conditions()) {
1599 if (!E)
1600 continue;
1601 // Check that loop counter in non-rectangular nest fits into the iteration
1602 // space.
1603 llvm::BasicBlock *NextBB = createBasicBlock("omp.body.next");
1604 EmitBranchOnBoolExpr(E, NextBB, Continue.getBlock(),
1605 getProfileCount(D.getBody()));
1606 EmitBlock(NextBB);
1607 }
Alexey Bataevbef93a92019-10-07 18:54:57 +00001608 // Emit loop variables for C++ range loops.
1609 const Stmt *Body =
1610 D.getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers();
Alexander Musmana5f070a2014-10-01 06:03:56 +00001611 // Emit loop body.
Alexey Bataev8bbf2e32019-11-04 09:59:11 -05001612 emitBody(*this, Body,
1613 OMPLoopDirective::tryToFindNextInnerLoop(
1614 Body, /*TryImperfectlyNestedLoops=*/true),
1615 D.getCollapsedNumber());
1616
Alexander Musmana5f070a2014-10-01 06:03:56 +00001617 // The end (updates/cleanups).
1618 EmitBlock(Continue.getBlock());
1619 BreakContinueStack.pop_back();
Alexander Musmana5f070a2014-10-01 06:03:56 +00001620}
1621
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001622void CodeGenFunction::EmitOMPInnerLoop(
1623 const Stmt &S, bool RequiresCleanup, const Expr *LoopCond,
1624 const Expr *IncExpr,
Alexey Bataevddf3db92018-04-13 17:31:06 +00001625 const llvm::function_ref<void(CodeGenFunction &)> BodyGen,
1626 const llvm::function_ref<void(CodeGenFunction &)> PostIncGen) {
Alexander Musmand196ef22014-10-07 08:57:09 +00001627 auto LoopExit = getJumpDestInCurrentScope("omp.inner.for.end");
Alexander Musmana5f070a2014-10-01 06:03:56 +00001628
1629 // Start the loop with a block that tests the condition.
Alexander Musmand196ef22014-10-07 08:57:09 +00001630 auto CondBlock = createBasicBlock("omp.inner.for.cond");
Alexander Musmana5f070a2014-10-01 06:03:56 +00001631 EmitBlock(CondBlock);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001632 const SourceRange R = S.getSourceRange();
Amara Emerson652795d2016-11-10 14:44:30 +00001633 LoopStack.push(CondBlock, SourceLocToDebugLoc(R.getBegin()),
1634 SourceLocToDebugLoc(R.getEnd()));
Alexander Musmana5f070a2014-10-01 06:03:56 +00001635
1636 // If there are any cleanups between here and the loop-exit scope,
1637 // create a block to stage a loop exit along.
Alexey Bataevddf3db92018-04-13 17:31:06 +00001638 llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
Alexey Bataev2df54a02015-03-12 08:53:29 +00001639 if (RequiresCleanup)
Alexander Musmand196ef22014-10-07 08:57:09 +00001640 ExitBlock = createBasicBlock("omp.inner.for.cond.cleanup");
Alexander Musmana5f070a2014-10-01 06:03:56 +00001641
Alexey Bataevddf3db92018-04-13 17:31:06 +00001642 llvm::BasicBlock *LoopBody = createBasicBlock("omp.inner.for.body");
Alexander Musmana5f070a2014-10-01 06:03:56 +00001643
Alexey Bataev2df54a02015-03-12 08:53:29 +00001644 // Emit condition.
Justin Bogner66242d62015-04-23 23:06:47 +00001645 EmitBranchOnBoolExpr(LoopCond, LoopBody, ExitBlock, getProfileCount(&S));
Alexander Musmana5f070a2014-10-01 06:03:56 +00001646 if (ExitBlock != LoopExit.getBlock()) {
1647 EmitBlock(ExitBlock);
1648 EmitBranchThroughCleanup(LoopExit);
1649 }
1650
1651 EmitBlock(LoopBody);
Justin Bogner66242d62015-04-23 23:06:47 +00001652 incrementProfileCounter(&S);
Alexander Musmana5f070a2014-10-01 06:03:56 +00001653
1654 // Create a block for the increment.
Alexey Bataevddf3db92018-04-13 17:31:06 +00001655 JumpDest Continue = getJumpDestInCurrentScope("omp.inner.for.inc");
Alexander Musmana5f070a2014-10-01 06:03:56 +00001656 BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
1657
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001658 BodyGen(*this);
Alexander Musmana5f070a2014-10-01 06:03:56 +00001659
1660 // Emit "IV = IV + 1" and a back-edge to the condition block.
1661 EmitBlock(Continue.getBlock());
Alexey Bataev2df54a02015-03-12 08:53:29 +00001662 EmitIgnoredExpr(IncExpr);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001663 PostIncGen(*this);
Alexander Musmana5f070a2014-10-01 06:03:56 +00001664 BreakContinueStack.pop_back();
1665 EmitBranch(CondBlock);
1666 LoopStack.pop();
1667 // Emit the fall-through block.
1668 EmitBlock(LoopExit.getBlock());
1669}
1670
Alexey Bataev8c3edfe2017-08-16 15:58:46 +00001671bool CodeGenFunction::EmitOMPLinearClauseInit(const OMPLoopDirective &D) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001672 if (!HaveInsertPoint())
Alexey Bataev8c3edfe2017-08-16 15:58:46 +00001673 return false;
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001674 // Emit inits for the linear variables.
Alexey Bataev8c3edfe2017-08-16 15:58:46 +00001675 bool HasLinears = false;
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00001676 for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00001677 for (const Expr *Init : C->inits()) {
Alexey Bataev8c3edfe2017-08-16 15:58:46 +00001678 HasLinears = true;
Alexey Bataevddf3db92018-04-13 17:31:06 +00001679 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(Init)->getDecl());
1680 if (const auto *Ref =
1681 dyn_cast<DeclRefExpr>(VD->getInit()->IgnoreImpCasts())) {
Alexey Bataevef549a82016-03-09 09:49:09 +00001682 AutoVarEmission Emission = EmitAutoVarAlloca(*VD);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001683 const auto *OrigVD = cast<VarDecl>(Ref->getDecl());
Bruno Ricci5fc4db72018-12-21 14:10:18 +00001684 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD),
Alexey Bataevef549a82016-03-09 09:49:09 +00001685 CapturedStmtInfo->lookup(OrigVD) != nullptr,
1686 VD->getInit()->getType(), VK_LValue,
1687 VD->getInit()->getExprLoc());
1688 EmitExprAsInit(&DRE, VD, MakeAddrLValue(Emission.getAllocatedAddress(),
1689 VD->getType()),
1690 /*capturedByInit=*/false);
1691 EmitAutoVarCleanups(Emission);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001692 } else {
Alexey Bataevef549a82016-03-09 09:49:09 +00001693 EmitVarDecl(*VD);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001694 }
Alexander Musmana5f070a2014-10-01 06:03:56 +00001695 }
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001696 // Emit the linear steps for the linear clauses.
1697 // If a step is not constant, it is pre-calculated before the loop.
Alexey Bataevddf3db92018-04-13 17:31:06 +00001698 if (const auto *CS = cast_or_null<BinaryOperator>(C->getCalcStep()))
1699 if (const auto *SaveRef = cast<DeclRefExpr>(CS->getLHS())) {
Alexey Bataev3b5b5c42015-06-18 10:10:12 +00001700 EmitVarDecl(*cast<VarDecl>(SaveRef->getDecl()));
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001701 // Emit calculation of the linear step.
Alexey Bataev3b5b5c42015-06-18 10:10:12 +00001702 EmitIgnoredExpr(CS);
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001703 }
Alexander Musmana5f070a2014-10-01 06:03:56 +00001704 }
Alexey Bataev8c3edfe2017-08-16 15:58:46 +00001705 return HasLinears;
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001706}
1707
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001708void CodeGenFunction::EmitOMPLinearClauseFinal(
1709 const OMPLoopDirective &D,
Alexey Bataevddf3db92018-04-13 17:31:06 +00001710 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001711 if (!HaveInsertPoint())
Alexey Bataev8ef31412015-12-18 07:58:25 +00001712 return;
Alexey Bataevef549a82016-03-09 09:49:09 +00001713 llvm::BasicBlock *DoneBB = nullptr;
Alexander Musman3276a272015-03-21 10:12:56 +00001714 // Emit the final values of the linear variables.
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00001715 for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) {
Alexey Bataev39f915b82015-05-08 10:41:21 +00001716 auto IC = C->varlist_begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00001717 for (const Expr *F : C->finals()) {
Alexey Bataevef549a82016-03-09 09:49:09 +00001718 if (!DoneBB) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00001719 if (llvm::Value *Cond = CondGen(*this)) {
Alexey Bataevef549a82016-03-09 09:49:09 +00001720 // If the first post-update expression is found, emit conditional
1721 // block if it was requested.
Alexey Bataevddf3db92018-04-13 17:31:06 +00001722 llvm::BasicBlock *ThenBB = createBasicBlock(".omp.linear.pu");
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001723 DoneBB = createBasicBlock(".omp.linear.pu.done");
1724 Builder.CreateCondBr(Cond, ThenBB, DoneBB);
1725 EmitBlock(ThenBB);
Alexey Bataevef549a82016-03-09 09:49:09 +00001726 }
1727 }
Alexey Bataevddf3db92018-04-13 17:31:06 +00001728 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IC)->getDecl());
Bruno Ricci5fc4db72018-12-21 14:10:18 +00001729 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD),
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001730 CapturedStmtInfo->lookup(OrigVD) != nullptr,
Alexey Bataev39f915b82015-05-08 10:41:21 +00001731 (*IC)->getType(), VK_LValue, (*IC)->getExprLoc());
Akira Hatanakaf139ae32019-12-03 15:17:01 -08001732 Address OrigAddr = EmitLValue(&DRE).getAddress(*this);
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001733 CodeGenFunction::OMPPrivateScope VarScope(*this);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001734 VarScope.addPrivate(OrigVD, [OrigAddr]() { return OrigAddr; });
Alexey Bataev39f915b82015-05-08 10:41:21 +00001735 (void)VarScope.Privatize();
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001736 EmitIgnoredExpr(F);
Alexey Bataev39f915b82015-05-08 10:41:21 +00001737 ++IC;
Alexander Musman3276a272015-03-21 10:12:56 +00001738 }
Alexey Bataevddf3db92018-04-13 17:31:06 +00001739 if (const Expr *PostUpdate = C->getPostUpdateExpr())
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001740 EmitIgnoredExpr(PostUpdate);
Alexander Musman3276a272015-03-21 10:12:56 +00001741 }
Alexey Bataevef549a82016-03-09 09:49:09 +00001742 if (DoneBB)
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001743 EmitBlock(DoneBB, /*IsFinished=*/true);
Alexander Musmana5f070a2014-10-01 06:03:56 +00001744}
1745
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001746static void emitAlignedClause(CodeGenFunction &CGF,
1747 const OMPExecutableDirective &D) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001748 if (!CGF.HaveInsertPoint())
1749 return;
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00001750 for (const auto *Clause : D.getClausesOfKind<OMPAlignedClause>()) {
Erich Keanef7593952019-10-11 14:59:44 +00001751 llvm::APInt ClauseAlignment(64, 0);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001752 if (const Expr *AlignmentExpr = Clause->getAlignment()) {
1753 auto *AlignmentCI =
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001754 cast<llvm::ConstantInt>(CGF.EmitScalarExpr(AlignmentExpr));
Erich Keanef7593952019-10-11 14:59:44 +00001755 ClauseAlignment = AlignmentCI->getValue();
Alexander Musman09184fe2014-09-30 05:29:28 +00001756 }
Alexey Bataevddf3db92018-04-13 17:31:06 +00001757 for (const Expr *E : Clause->varlists()) {
Erich Keanef7593952019-10-11 14:59:44 +00001758 llvm::APInt Alignment(ClauseAlignment);
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001759 if (Alignment == 0) {
1760 // OpenMP [2.8.1, Description]
1761 // If no optional parameter is specified, implementation-defined default
1762 // alignments for SIMD instructions on the target platforms are assumed.
1763 Alignment =
Alexey Bataev00396512015-07-02 03:40:19 +00001764 CGF.getContext()
1765 .toCharUnitsFromBits(CGF.getContext().getOpenMPDefaultSimdAlign(
1766 E->getType()->getPointeeType()))
1767 .getQuantity();
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001768 }
Erich Keanef7593952019-10-11 14:59:44 +00001769 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001770 "alignment is not power of 2");
1771 if (Alignment != 0) {
1772 llvm::Value *PtrValue = CGF.EmitScalarExpr(E);
Fangrui Song1d49eb02020-02-13 16:36:27 -08001773 CGF.emitAlignmentAssumption(
Erich Keanef7593952019-10-11 14:59:44 +00001774 PtrValue, E, /*No second loc needed*/ SourceLocation(),
1775 llvm::ConstantInt::get(CGF.getLLVMContext(), Alignment));
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001776 }
Alexander Musman09184fe2014-09-30 05:29:28 +00001777 }
1778 }
1779}
1780
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001781void CodeGenFunction::EmitOMPPrivateLoopCounters(
1782 const OMPLoopDirective &S, CodeGenFunction::OMPPrivateScope &LoopScope) {
1783 if (!HaveInsertPoint())
Alexey Bataev8ef31412015-12-18 07:58:25 +00001784 return;
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001785 auto I = S.private_counters().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00001786 for (const Expr *E : S.counters()) {
1787 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
1788 const auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl());
Alexey Bataevab4ea222018-03-07 18:17:06 +00001789 // Emit var without initialization.
Alexey Bataevddf3db92018-04-13 17:31:06 +00001790 AutoVarEmission VarEmission = EmitAutoVarAlloca(*PrivateVD);
Alexey Bataevab4ea222018-03-07 18:17:06 +00001791 EmitAutoVarCleanups(VarEmission);
1792 LocalDeclMap.erase(PrivateVD);
1793 (void)LoopScope.addPrivate(VD, [&VarEmission]() {
1794 return VarEmission.getAllocatedAddress();
Alexey Bataev435ad7b2014-10-10 09:48:26 +00001795 });
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001796 if (LocalDeclMap.count(VD) || CapturedStmtInfo->lookup(VD) ||
1797 VD->hasGlobalStorage()) {
Alexey Bataevab4ea222018-03-07 18:17:06 +00001798 (void)LoopScope.addPrivate(PrivateVD, [this, VD, E]() {
Bruno Ricci5fc4db72018-12-21 14:10:18 +00001799 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(VD),
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001800 LocalDeclMap.count(VD) || CapturedStmtInfo->lookup(VD),
1801 E->getType(), VK_LValue, E->getExprLoc());
Akira Hatanakaf139ae32019-12-03 15:17:01 -08001802 return EmitLValue(&DRE).getAddress(*this);
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001803 });
Alexey Bataevab4ea222018-03-07 18:17:06 +00001804 } else {
1805 (void)LoopScope.addPrivate(PrivateVD, [&VarEmission]() {
1806 return VarEmission.getAllocatedAddress();
1807 });
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001808 }
Alexey Bataeva8899172015-08-06 12:30:57 +00001809 ++I;
Alexey Bataev435ad7b2014-10-10 09:48:26 +00001810 }
Alexey Bataevf138fda2018-08-13 19:04:24 +00001811 // Privatize extra loop counters used in loops for ordered(n) clauses.
1812 for (const auto *C : S.getClausesOfKind<OMPOrderedClause>()) {
1813 if (!C->getNumForLoops())
1814 continue;
1815 for (unsigned I = S.getCollapsedNumber(),
1816 E = C->getLoopNumIterations().size();
1817 I < E; ++I) {
Mike Rice0ed46662018-09-20 17:19:41 +00001818 const auto *DRE = cast<DeclRefExpr>(C->getLoopCounter(I));
Alexey Bataevf138fda2018-08-13 19:04:24 +00001819 const auto *VD = cast<VarDecl>(DRE->getDecl());
Alexey Bataev0d8fcdf2019-03-14 20:36:00 +00001820 // Override only those variables that can be captured to avoid re-emission
1821 // of the variables declared within the loops.
1822 if (DRE->refersToEnclosingVariableOrCapture()) {
Alexey Bataevf138fda2018-08-13 19:04:24 +00001823 (void)LoopScope.addPrivate(VD, [this, DRE, VD]() {
1824 return CreateMemTemp(DRE->getType(), VD->getName());
1825 });
1826 }
1827 }
1828 }
Alexey Bataev435ad7b2014-10-10 09:48:26 +00001829}
1830
Alexey Bataev62dbb972015-04-22 11:59:37 +00001831static void emitPreCond(CodeGenFunction &CGF, const OMPLoopDirective &S,
1832 const Expr *Cond, llvm::BasicBlock *TrueBlock,
1833 llvm::BasicBlock *FalseBlock, uint64_t TrueCount) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001834 if (!CGF.HaveInsertPoint())
1835 return;
Alexey Bataev6e8248f2015-06-11 10:53:56 +00001836 {
1837 CodeGenFunction::OMPPrivateScope PreCondScope(CGF);
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001838 CGF.EmitOMPPrivateLoopCounters(S, PreCondScope);
Alexey Bataev6e8248f2015-06-11 10:53:56 +00001839 (void)PreCondScope.Privatize();
Alexey Bataev6e8248f2015-06-11 10:53:56 +00001840 // Get initial values of real counters.
Alexey Bataevddf3db92018-04-13 17:31:06 +00001841 for (const Expr *I : S.inits()) {
Alexey Bataev6e8248f2015-06-11 10:53:56 +00001842 CGF.EmitIgnoredExpr(I);
1843 }
Alexey Bataev62dbb972015-04-22 11:59:37 +00001844 }
Alexey Bataevf8be4762019-08-14 19:30:06 +00001845 // Create temp loop control variables with their init values to support
1846 // non-rectangular loops.
1847 CodeGenFunction::OMPMapVars PreCondVars;
1848 for (const Expr * E: S.dependent_counters()) {
1849 if (!E)
1850 continue;
1851 assert(!E->getType().getNonReferenceType()->isRecordType() &&
1852 "dependent counter must not be an iterator.");
1853 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
1854 Address CounterAddr =
1855 CGF.CreateMemTemp(VD->getType().getNonReferenceType());
1856 (void)PreCondVars.setVarAddr(CGF, VD, CounterAddr);
1857 }
1858 (void)PreCondVars.apply(CGF);
1859 for (const Expr *E : S.dependent_inits()) {
1860 if (!E)
1861 continue;
1862 CGF.EmitIgnoredExpr(E);
1863 }
Alexey Bataev62dbb972015-04-22 11:59:37 +00001864 // Check that loop is executed at least one time.
1865 CGF.EmitBranchOnBoolExpr(Cond, TrueBlock, FalseBlock, TrueCount);
Alexey Bataevf8be4762019-08-14 19:30:06 +00001866 PreCondVars.restore(CGF);
Alexey Bataev62dbb972015-04-22 11:59:37 +00001867}
1868
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001869void CodeGenFunction::EmitOMPLinearClause(
1870 const OMPLoopDirective &D, CodeGenFunction::OMPPrivateScope &PrivateScope) {
1871 if (!HaveInsertPoint())
Alexey Bataev8ef31412015-12-18 07:58:25 +00001872 return;
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001873 llvm::DenseSet<const VarDecl *> SIMDLCVs;
1874 if (isOpenMPSimdDirective(D.getDirectiveKind())) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00001875 const auto *LoopDirective = cast<OMPLoopDirective>(&D);
1876 for (const Expr *C : LoopDirective->counters()) {
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001877 SIMDLCVs.insert(
1878 cast<VarDecl>(cast<DeclRefExpr>(C)->getDecl())->getCanonicalDecl());
1879 }
1880 }
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00001881 for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) {
Alexey Bataevbd9fec12015-08-18 06:47:21 +00001882 auto CurPrivate = C->privates().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00001883 for (const Expr *E : C->varlists()) {
1884 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
1885 const auto *PrivateVD =
Alexey Bataevbd9fec12015-08-18 06:47:21 +00001886 cast<VarDecl>(cast<DeclRefExpr>(*CurPrivate)->getDecl());
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001887 if (!SIMDLCVs.count(VD->getCanonicalDecl())) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00001888 bool IsRegistered = PrivateScope.addPrivate(VD, [this, PrivateVD]() {
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001889 // Emit private VarDecl with copy init.
1890 EmitVarDecl(*PrivateVD);
1891 return GetAddrOfLocalVar(PrivateVD);
1892 });
1893 assert(IsRegistered && "linear var already registered as private");
1894 // Silence the warning about unused variable.
1895 (void)IsRegistered;
Alexey Bataevddf3db92018-04-13 17:31:06 +00001896 } else {
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001897 EmitVarDecl(*PrivateVD);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001898 }
Alexey Bataevbd9fec12015-08-18 06:47:21 +00001899 ++CurPrivate;
Alexander Musman3276a272015-03-21 10:12:56 +00001900 }
1901 }
1902}
1903
Alexey Bataev45bfad52015-08-21 12:19:04 +00001904static void emitSimdlenSafelenClause(CodeGenFunction &CGF,
Alexey Bataeva6f2a142015-12-31 06:52:34 +00001905 const OMPExecutableDirective &D,
1906 bool IsMonotonic) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001907 if (!CGF.HaveInsertPoint())
1908 return;
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00001909 if (const auto *C = D.getSingleClause<OMPSimdlenClause>()) {
Alexey Bataev45bfad52015-08-21 12:19:04 +00001910 RValue Len = CGF.EmitAnyExpr(C->getSimdlen(), AggValueSlot::ignored(),
1911 /*ignoreResult=*/true);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001912 auto *Val = cast<llvm::ConstantInt>(Len.getScalarVal());
Alexey Bataev45bfad52015-08-21 12:19:04 +00001913 CGF.LoopStack.setVectorizeWidth(Val->getZExtValue());
1914 // In presence of finite 'safelen', it may be unsafe to mark all
1915 // the memory instructions parallel, because loop-carried
1916 // dependences of 'safelen' iterations are possible.
Alexey Bataeva6f2a142015-12-31 06:52:34 +00001917 if (!IsMonotonic)
1918 CGF.LoopStack.setParallel(!D.getSingleClause<OMPSafelenClause>());
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00001919 } else if (const auto *C = D.getSingleClause<OMPSafelenClause>()) {
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001920 RValue Len = CGF.EmitAnyExpr(C->getSafelen(), AggValueSlot::ignored(),
1921 /*ignoreResult=*/true);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001922 auto *Val = cast<llvm::ConstantInt>(Len.getScalarVal());
Tyler Nowickida46d0e2015-07-14 23:03:09 +00001923 CGF.LoopStack.setVectorizeWidth(Val->getZExtValue());
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001924 // In presence of finite 'safelen', it may be unsafe to mark all
1925 // the memory instructions parallel, because loop-carried
1926 // dependences of 'safelen' iterations are possible.
Alexey Bataevddf3db92018-04-13 17:31:06 +00001927 CGF.LoopStack.setParallel(/*Enable=*/false);
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001928 }
1929}
1930
Alexey Bataeva6f2a142015-12-31 06:52:34 +00001931void CodeGenFunction::EmitOMPSimdInit(const OMPLoopDirective &D,
1932 bool IsMonotonic) {
Alexey Bataev58e5bdb2015-06-18 04:45:29 +00001933 // Walk clauses and process safelen/lastprivate.
Alexey Bataeva6f2a142015-12-31 06:52:34 +00001934 LoopStack.setParallel(!IsMonotonic);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001935 LoopStack.setVectorizeEnable();
Alexey Bataeva6f2a142015-12-31 06:52:34 +00001936 emitSimdlenSafelenClause(*this, D, IsMonotonic);
Alexey Bataeva7815212020-02-03 12:08:16 -05001937 if (const auto *C = D.getSingleClause<OMPOrderClause>())
1938 if (C->getKind() == OMPC_ORDER_concurrent)
1939 LoopStack.setParallel(/*Enable=*/true);
Alexey Bataev58e5bdb2015-06-18 04:45:29 +00001940}
1941
Alexey Bataevef549a82016-03-09 09:49:09 +00001942void CodeGenFunction::EmitOMPSimdFinal(
1943 const OMPLoopDirective &D,
Alexey Bataevddf3db92018-04-13 17:31:06 +00001944 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001945 if (!HaveInsertPoint())
1946 return;
Alexey Bataevef549a82016-03-09 09:49:09 +00001947 llvm::BasicBlock *DoneBB = nullptr;
Alexey Bataev58e5bdb2015-06-18 04:45:29 +00001948 auto IC = D.counters().begin();
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001949 auto IPC = D.private_counters().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00001950 for (const Expr *F : D.finals()) {
1951 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>((*IC))->getDecl());
1952 const auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>((*IPC))->getDecl());
1953 const auto *CED = dyn_cast<OMPCapturedExprDecl>(OrigVD);
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001954 if (LocalDeclMap.count(OrigVD) || CapturedStmtInfo->lookup(OrigVD) ||
1955 OrigVD->hasGlobalStorage() || CED) {
Alexey Bataevef549a82016-03-09 09:49:09 +00001956 if (!DoneBB) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00001957 if (llvm::Value *Cond = CondGen(*this)) {
Alexey Bataevef549a82016-03-09 09:49:09 +00001958 // If the first post-update expression is found, emit conditional
1959 // block if it was requested.
Alexey Bataevddf3db92018-04-13 17:31:06 +00001960 llvm::BasicBlock *ThenBB = createBasicBlock(".omp.final.then");
Alexey Bataevef549a82016-03-09 09:49:09 +00001961 DoneBB = createBasicBlock(".omp.final.done");
1962 Builder.CreateCondBr(Cond, ThenBB, DoneBB);
1963 EmitBlock(ThenBB);
1964 }
1965 }
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001966 Address OrigAddr = Address::invalid();
Alexey Bataevab4ea222018-03-07 18:17:06 +00001967 if (CED) {
Akira Hatanakaf139ae32019-12-03 15:17:01 -08001968 OrigAddr =
1969 EmitLValue(CED->getInit()->IgnoreImpCasts()).getAddress(*this);
Alexey Bataevab4ea222018-03-07 18:17:06 +00001970 } else {
Bruno Ricci5fc4db72018-12-21 14:10:18 +00001971 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(PrivateVD),
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001972 /*RefersToEnclosingVariableOrCapture=*/false,
1973 (*IPC)->getType(), VK_LValue, (*IPC)->getExprLoc());
Akira Hatanakaf139ae32019-12-03 15:17:01 -08001974 OrigAddr = EmitLValue(&DRE).getAddress(*this);
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001975 }
Alexey Bataev58e5bdb2015-06-18 04:45:29 +00001976 OMPPrivateScope VarScope(*this);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001977 VarScope.addPrivate(OrigVD, [OrigAddr]() { return OrigAddr; });
Alexey Bataev58e5bdb2015-06-18 04:45:29 +00001978 (void)VarScope.Privatize();
1979 EmitIgnoredExpr(F);
1980 }
1981 ++IC;
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001982 ++IPC;
Alexey Bataev58e5bdb2015-06-18 04:45:29 +00001983 }
Alexey Bataevef549a82016-03-09 09:49:09 +00001984 if (DoneBB)
1985 EmitBlock(DoneBB, /*IsFinished=*/true);
Alexey Bataev58e5bdb2015-06-18 04:45:29 +00001986}
1987
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00001988static void emitOMPLoopBodyWithStopPoint(CodeGenFunction &CGF,
1989 const OMPLoopDirective &S,
1990 CodeGenFunction::JumpDest LoopExit) {
1991 CGF.EmitOMPLoopBody(S, LoopExit);
1992 CGF.EmitStopPoint(&S);
Hans Wennborged129ae2017-04-27 17:02:25 +00001993}
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00001994
Alexey Bataeva8a9153a2017-12-29 18:07:07 +00001995/// Emit a helper variable and return corresponding lvalue.
1996static LValue EmitOMPHelperVar(CodeGenFunction &CGF,
1997 const DeclRefExpr *Helper) {
1998 auto VDecl = cast<VarDecl>(Helper->getDecl());
1999 CGF.EmitVarDecl(*VDecl);
2000 return CGF.EmitLValue(Helper);
2001}
2002
Alexey Bataev103f3c9e2019-11-20 15:59:03 -05002003static void emitCommonSimdLoop(CodeGenFunction &CGF, const OMPLoopDirective &S,
2004 const RegionCodeGenTy &SimdInitGen,
2005 const RegionCodeGenTy &BodyCodeGen) {
Alexey Bataev0860db92019-12-19 10:01:10 -05002006 auto &&ThenGen = [&S, &SimdInitGen, &BodyCodeGen](CodeGenFunction &CGF,
2007 PrePostActionTy &) {
2008 CGOpenMPRuntime::NontemporalDeclsRAII NontemporalsRegion(CGF.CGM, S);
Alexey Bataev103f3c9e2019-11-20 15:59:03 -05002009 CodeGenFunction::OMPLocalDeclMapRAII Scope(CGF);
2010 SimdInitGen(CGF);
2011
2012 BodyCodeGen(CGF);
2013 };
2014 auto &&ElseGen = [&BodyCodeGen](CodeGenFunction &CGF, PrePostActionTy &) {
2015 CodeGenFunction::OMPLocalDeclMapRAII Scope(CGF);
2016 CGF.LoopStack.setVectorizeEnable(/*Enable=*/false);
2017
2018 BodyCodeGen(CGF);
2019 };
2020 const Expr *IfCond = nullptr;
Alexey Bataev18789bf2020-02-13 09:21:15 -05002021 if (isOpenMPSimdDirective(S.getDirectiveKind())) {
2022 for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
2023 if (CGF.getLangOpts().OpenMP >= 50 &&
2024 (C->getNameModifier() == OMPD_unknown ||
2025 C->getNameModifier() == OMPD_simd)) {
2026 IfCond = C->getCondition();
2027 break;
2028 }
Alexey Bataev103f3c9e2019-11-20 15:59:03 -05002029 }
2030 }
2031 if (IfCond) {
2032 CGF.CGM.getOpenMPRuntime().emitIfClause(CGF, IfCond, ThenGen, ElseGen);
2033 } else {
2034 RegionCodeGenTy ThenRCG(ThenGen);
2035 ThenRCG(CGF);
2036 }
2037}
2038
Alexey Bataevf8365372017-11-17 17:57:25 +00002039static void emitOMPSimdRegion(CodeGenFunction &CGF, const OMPLoopDirective &S,
2040 PrePostActionTy &Action) {
2041 Action.Enter(CGF);
2042 assert(isOpenMPSimdDirective(S.getDirectiveKind()) &&
2043 "Expected simd directive");
2044 OMPLoopScope PreInitScope(CGF, S);
2045 // if (PreCond) {
2046 // for (IV in 0..LastIteration) BODY;
2047 // <Final counter/linear vars updates>;
2048 // }
2049 //
Alexey Bataeva8a9153a2017-12-29 18:07:07 +00002050 if (isOpenMPDistributeDirective(S.getDirectiveKind()) ||
2051 isOpenMPWorksharingDirective(S.getDirectiveKind()) ||
2052 isOpenMPTaskLoopDirective(S.getDirectiveKind())) {
2053 (void)EmitOMPHelperVar(CGF, cast<DeclRefExpr>(S.getLowerBoundVariable()));
2054 (void)EmitOMPHelperVar(CGF, cast<DeclRefExpr>(S.getUpperBoundVariable()));
2055 }
Alexander Musmana5f070a2014-10-01 06:03:56 +00002056
Alexey Bataevf8365372017-11-17 17:57:25 +00002057 // Emit: if (PreCond) - begin.
2058 // If the condition constant folds and can be elided, avoid emitting the
2059 // whole loop.
2060 bool CondConstant;
2061 llvm::BasicBlock *ContBlock = nullptr;
2062 if (CGF.ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
2063 if (!CondConstant)
2064 return;
2065 } else {
Alexey Bataevddf3db92018-04-13 17:31:06 +00002066 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("simd.if.then");
Alexey Bataevf8365372017-11-17 17:57:25 +00002067 ContBlock = CGF.createBasicBlock("simd.if.end");
2068 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
2069 CGF.getProfileCount(&S));
2070 CGF.EmitBlock(ThenBlock);
2071 CGF.incrementProfileCounter(&S);
2072 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002073
Alexey Bataevf8365372017-11-17 17:57:25 +00002074 // Emit the loop iteration variable.
2075 const Expr *IVExpr = S.getIterationVariable();
Alexey Bataevddf3db92018-04-13 17:31:06 +00002076 const auto *IVDecl = cast<VarDecl>(cast<DeclRefExpr>(IVExpr)->getDecl());
Alexey Bataevf8365372017-11-17 17:57:25 +00002077 CGF.EmitVarDecl(*IVDecl);
2078 CGF.EmitIgnoredExpr(S.getInit());
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002079
Alexey Bataevf8365372017-11-17 17:57:25 +00002080 // Emit the iterations count variable.
2081 // If it is not a variable, Sema decided to calculate iterations count on
2082 // each iteration (e.g., it is foldable into a constant).
Alexey Bataevddf3db92018-04-13 17:31:06 +00002083 if (const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
Alexey Bataevf8365372017-11-17 17:57:25 +00002084 CGF.EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
2085 // Emit calculation of the iterations count.
2086 CGF.EmitIgnoredExpr(S.getCalcLastIteration());
2087 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002088
Alexey Bataevf8365372017-11-17 17:57:25 +00002089 emitAlignedClause(CGF, S);
2090 (void)CGF.EmitOMPLinearClauseInit(S);
2091 {
2092 CodeGenFunction::OMPPrivateScope LoopScope(CGF);
2093 CGF.EmitOMPPrivateLoopCounters(S, LoopScope);
2094 CGF.EmitOMPLinearClause(S, LoopScope);
2095 CGF.EmitOMPPrivateClause(S, LoopScope);
2096 CGF.EmitOMPReductionClauseInit(S, LoopScope);
Alexey Bataeva58da1a2019-12-27 09:44:43 -05002097 CGOpenMPRuntime::LastprivateConditionalRAII LPCRegion(
2098 CGF, S, CGF.EmitLValue(S.getIterationVariable()));
Alexey Bataevf8365372017-11-17 17:57:25 +00002099 bool HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
2100 (void)LoopScope.Privatize();
Alexey Bataev60705422018-10-30 15:50:12 +00002101 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()))
2102 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
Alexey Bataevd08c0562019-11-19 12:07:54 -05002103
Alexey Bataev103f3c9e2019-11-20 15:59:03 -05002104 emitCommonSimdLoop(
2105 CGF, S,
2106 [&S](CodeGenFunction &CGF, PrePostActionTy &) {
2107 CGF.EmitOMPSimdInit(S);
2108 },
2109 [&S, &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) {
2110 CGF.EmitOMPInnerLoop(
2111 S, LoopScope.requiresCleanups(), S.getCond(), S.getInc(),
2112 [&S](CodeGenFunction &CGF) {
2113 CGF.EmitOMPLoopBody(S, CodeGenFunction::JumpDest());
2114 CGF.EmitStopPoint(&S);
2115 },
2116 [](CodeGenFunction &) {});
2117 });
Alexey Bataevddf3db92018-04-13 17:31:06 +00002118 CGF.EmitOMPSimdFinal(S, [](CodeGenFunction &) { return nullptr; });
Alexey Bataevf8365372017-11-17 17:57:25 +00002119 // Emit final copy of the lastprivate variables at the end of loops.
2120 if (HasLastprivateClause)
2121 CGF.EmitOMPLastprivateClauseFinal(S, /*NoFinals=*/true);
2122 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_simd);
Alexey Bataevddf3db92018-04-13 17:31:06 +00002123 emitPostUpdateForReductionClause(CGF, S,
2124 [](CodeGenFunction &) { return nullptr; });
Alexey Bataevf8365372017-11-17 17:57:25 +00002125 }
Alexey Bataevddf3db92018-04-13 17:31:06 +00002126 CGF.EmitOMPLinearClauseFinal(S, [](CodeGenFunction &) { return nullptr; });
Alexey Bataevf8365372017-11-17 17:57:25 +00002127 // Emit: if (PreCond) - end.
2128 if (ContBlock) {
2129 CGF.EmitBranch(ContBlock);
2130 CGF.EmitBlock(ContBlock, true);
2131 }
2132}
2133
2134void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) {
2135 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
2136 emitOMPSimdRegion(CGF, S, Action);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002137 };
Alexey Bataev46978742020-01-30 10:46:11 -05002138 {
2139 auto LPCRegion =
2140 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
2141 OMPLexicalScope Scope(*this, S, OMPD_unknown);
2142 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen);
2143 }
2144 // Check for outer lastprivate conditional update.
2145 checkForLastprivateConditionalUpdate(*this, S);
Alexander Musman515ad8c2014-05-22 08:54:05 +00002146}
2147
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002148void CodeGenFunction::EmitOMPOuterLoop(
2149 bool DynamicOrOrdered, bool IsMonotonic, const OMPLoopDirective &S,
2150 CodeGenFunction::OMPPrivateScope &LoopScope,
2151 const CodeGenFunction::OMPLoopArguments &LoopArgs,
2152 const CodeGenFunction::CodeGenLoopTy &CodeGenLoop,
2153 const CodeGenFunction::CodeGenOrderedTy &CodeGenOrdered) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00002154 CGOpenMPRuntime &RT = CGM.getOpenMPRuntime();
Alexander Musman92bdaab2015-03-12 13:37:50 +00002155
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002156 const Expr *IVExpr = S.getIterationVariable();
2157 const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
2158 const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
2159
Alexey Bataevddf3db92018-04-13 17:31:06 +00002160 JumpDest LoopExit = getJumpDestInCurrentScope("omp.dispatch.end");
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002161
2162 // Start the loop with a block that tests the condition.
Alexey Bataevddf3db92018-04-13 17:31:06 +00002163 llvm::BasicBlock *CondBlock = createBasicBlock("omp.dispatch.cond");
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002164 EmitBlock(CondBlock);
Alexey Bataevddf3db92018-04-13 17:31:06 +00002165 const SourceRange R = S.getSourceRange();
Amara Emerson652795d2016-11-10 14:44:30 +00002166 LoopStack.push(CondBlock, SourceLocToDebugLoc(R.getBegin()),
2167 SourceLocToDebugLoc(R.getEnd()));
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002168
2169 llvm::Value *BoolCondVal = nullptr;
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002170 if (!DynamicOrOrdered) {
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002171 // UB = min(UB, GlobalUB) or
2172 // UB = min(UB, PrevUB) for combined loop sharing constructs (e.g.
2173 // 'distribute parallel for')
2174 EmitIgnoredExpr(LoopArgs.EUB);
Alexander Musman92bdaab2015-03-12 13:37:50 +00002175 // IV = LB
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002176 EmitIgnoredExpr(LoopArgs.Init);
Alexander Musman92bdaab2015-03-12 13:37:50 +00002177 // IV < UB
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002178 BoolCondVal = EvaluateExprAsBool(LoopArgs.Cond);
Alexander Musman92bdaab2015-03-12 13:37:50 +00002179 } else {
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002180 BoolCondVal =
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002181 RT.emitForNext(*this, S.getBeginLoc(), IVSize, IVSigned, LoopArgs.IL,
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002182 LoopArgs.LB, LoopArgs.UB, LoopArgs.ST);
Alexander Musman92bdaab2015-03-12 13:37:50 +00002183 }
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002184
2185 // If there are any cleanups between here and the loop-exit scope,
2186 // create a block to stage a loop exit along.
Alexey Bataevddf3db92018-04-13 17:31:06 +00002187 llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002188 if (LoopScope.requiresCleanups())
2189 ExitBlock = createBasicBlock("omp.dispatch.cleanup");
2190
Alexey Bataevddf3db92018-04-13 17:31:06 +00002191 llvm::BasicBlock *LoopBody = createBasicBlock("omp.dispatch.body");
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002192 Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock);
2193 if (ExitBlock != LoopExit.getBlock()) {
2194 EmitBlock(ExitBlock);
2195 EmitBranchThroughCleanup(LoopExit);
2196 }
2197 EmitBlock(LoopBody);
2198
Alexander Musman92bdaab2015-03-12 13:37:50 +00002199 // Emit "IV = LB" (in case of static schedule, we have already calculated new
2200 // LB for loop condition and emitted it above).
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002201 if (DynamicOrOrdered)
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002202 EmitIgnoredExpr(LoopArgs.Init);
Alexander Musman92bdaab2015-03-12 13:37:50 +00002203
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002204 // Create a block for the increment.
Alexey Bataevddf3db92018-04-13 17:31:06 +00002205 JumpDest Continue = getJumpDestInCurrentScope("omp.dispatch.inc");
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002206 BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
2207
Alexey Bataev103f3c9e2019-11-20 15:59:03 -05002208 emitCommonSimdLoop(
2209 *this, S,
2210 [&S, IsMonotonic](CodeGenFunction &CGF, PrePostActionTy &) {
2211 // Generate !llvm.loop.parallel metadata for loads and stores for loops
2212 // with dynamic/guided scheduling and without ordered clause.
Alexey Bataeva7815212020-02-03 12:08:16 -05002213 if (!isOpenMPSimdDirective(S.getDirectiveKind())) {
Alexey Bataev103f3c9e2019-11-20 15:59:03 -05002214 CGF.LoopStack.setParallel(!IsMonotonic);
Alexey Bataeva7815212020-02-03 12:08:16 -05002215 if (const auto *C = S.getSingleClause<OMPOrderClause>())
2216 if (C->getKind() == OMPC_ORDER_concurrent)
2217 CGF.LoopStack.setParallel(/*Enable=*/true);
2218 } else {
Alexey Bataev103f3c9e2019-11-20 15:59:03 -05002219 CGF.EmitOMPSimdInit(S, IsMonotonic);
Alexey Bataeva7815212020-02-03 12:08:16 -05002220 }
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002221 },
Alexey Bataev103f3c9e2019-11-20 15:59:03 -05002222 [&S, &LoopArgs, LoopExit, &CodeGenLoop, IVSize, IVSigned, &CodeGenOrdered,
2223 &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) {
2224 SourceLocation Loc = S.getBeginLoc();
2225 // when 'distribute' is not combined with a 'for':
2226 // while (idx <= UB) { BODY; ++idx; }
2227 // when 'distribute' is combined with a 'for'
2228 // (e.g. 'distribute parallel for')
2229 // while (idx <= UB) { <CodeGen rest of pragma>; idx += ST; }
2230 CGF.EmitOMPInnerLoop(
2231 S, LoopScope.requiresCleanups(), LoopArgs.Cond, LoopArgs.IncExpr,
2232 [&S, LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
2233 CodeGenLoop(CGF, S, LoopExit);
2234 },
2235 [IVSize, IVSigned, Loc, &CodeGenOrdered](CodeGenFunction &CGF) {
2236 CodeGenOrdered(CGF, Loc, IVSize, IVSigned);
2237 });
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002238 });
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002239
2240 EmitBlock(Continue.getBlock());
2241 BreakContinueStack.pop_back();
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002242 if (!DynamicOrOrdered) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00002243 // Emit "LB = LB + Stride", "UB = UB + Stride".
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002244 EmitIgnoredExpr(LoopArgs.NextLB);
2245 EmitIgnoredExpr(LoopArgs.NextUB);
Alexander Musman92bdaab2015-03-12 13:37:50 +00002246 }
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002247
2248 EmitBranch(CondBlock);
2249 LoopStack.pop();
2250 // Emit the fall-through block.
2251 EmitBlock(LoopExit.getBlock());
2252
2253 // Tell the runtime we are done.
Alexey Bataev957d8562016-11-17 15:12:05 +00002254 auto &&CodeGen = [DynamicOrOrdered, &S](CodeGenFunction &CGF) {
2255 if (!DynamicOrOrdered)
Stephen Kelly1c301dc2018-08-09 21:09:38 +00002256 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
Alexey Bataevf43f7142017-09-06 16:17:35 +00002257 S.getDirectiveKind());
Alexey Bataev957d8562016-11-17 15:12:05 +00002258 };
2259 OMPCancelStack.emitExit(*this, S.getDirectiveKind(), CodeGen);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002260}
2261
2262void CodeGenFunction::EmitOMPForOuterLoop(
Alexey Bataev9ebd7422016-05-10 09:57:36 +00002263 const OpenMPScheduleTy &ScheduleKind, bool IsMonotonic,
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002264 const OMPLoopDirective &S, OMPPrivateScope &LoopScope, bool Ordered,
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002265 const OMPLoopArguments &LoopArgs,
2266 const CodeGenDispatchBoundsTy &CGDispatchBounds) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00002267 CGOpenMPRuntime &RT = CGM.getOpenMPRuntime();
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002268
2269 // Dynamic scheduling of the outer loop (dynamic, guided, auto, runtime).
Alexey Bataev9ebd7422016-05-10 09:57:36 +00002270 const bool DynamicOrOrdered =
2271 Ordered || RT.isDynamic(ScheduleKind.Schedule);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002272
2273 assert((Ordered ||
Alexey Bataev9ebd7422016-05-10 09:57:36 +00002274 !RT.isStaticNonchunked(ScheduleKind.Schedule,
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002275 LoopArgs.Chunk != nullptr)) &&
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002276 "static non-chunked schedule does not need outer loop");
2277
2278 // Emit outer loop.
2279 //
2280 // OpenMP [2.7.1, Loop Construct, Description, table 2-1]
2281 // When schedule(dynamic,chunk_size) is specified, the iterations are
2282 // distributed to threads in the team in chunks as the threads request them.
2283 // Each thread executes a chunk of iterations, then requests another chunk,
2284 // until no chunks remain to be distributed. Each chunk contains chunk_size
2285 // iterations, except for the last chunk to be distributed, which may have
2286 // fewer iterations. When no chunk_size is specified, it defaults to 1.
2287 //
2288 // When schedule(guided,chunk_size) is specified, the iterations are assigned
2289 // to threads in the team in chunks as the executing threads request them.
2290 // Each thread executes a chunk of iterations, then requests another chunk,
2291 // until no chunks remain to be assigned. For a chunk_size of 1, the size of
2292 // each chunk is proportional to the number of unassigned iterations divided
2293 // by the number of threads in the team, decreasing to 1. For a chunk_size
2294 // with value k (greater than 1), the size of each chunk is determined in the
2295 // same way, with the restriction that the chunks do not contain fewer than k
2296 // iterations (except for the last chunk to be assigned, which may have fewer
2297 // than k iterations).
2298 //
2299 // When schedule(auto) is specified, the decision regarding scheduling is
2300 // delegated to the compiler and/or runtime system. The programmer gives the
2301 // implementation the freedom to choose any possible mapping of iterations to
2302 // threads in the team.
2303 //
2304 // When schedule(runtime) is specified, the decision regarding scheduling is
2305 // deferred until run time, and the schedule and chunk size are taken from the
2306 // run-sched-var ICV. If the ICV is set to auto, the schedule is
2307 // implementation defined
2308 //
2309 // while(__kmpc_dispatch_next(&LB, &UB)) {
2310 // idx = LB;
2311 // while (idx <= UB) { BODY; ++idx;
2312 // __kmpc_dispatch_fini_(4|8)[u](); // For ordered loops only.
2313 // } // inner loop
2314 // }
2315 //
2316 // OpenMP [2.7.1, Loop Construct, Description, table 2-1]
2317 // When schedule(static, chunk_size) is specified, iterations are divided into
2318 // chunks of size chunk_size, and the chunks are assigned to the threads in
2319 // the team in a round-robin fashion in the order of the thread number.
2320 //
2321 // while(UB = min(UB, GlobalUB), idx = LB, idx < UB) {
2322 // while (idx <= UB) { BODY; ++idx; } // inner loop
2323 // LB = LB + ST;
2324 // UB = UB + ST;
2325 // }
2326 //
2327
2328 const Expr *IVExpr = S.getIterationVariable();
2329 const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
2330 const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
2331
2332 if (DynamicOrOrdered) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00002333 const std::pair<llvm::Value *, llvm::Value *> DispatchBounds =
2334 CGDispatchBounds(*this, S, LoopArgs.LB, LoopArgs.UB);
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002335 llvm::Value *LBVal = DispatchBounds.first;
2336 llvm::Value *UBVal = DispatchBounds.second;
2337 CGOpenMPRuntime::DispatchRTInput DipatchRTInputValues = {LBVal, UBVal,
2338 LoopArgs.Chunk};
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002339 RT.emitForDispatchInit(*this, S.getBeginLoc(), ScheduleKind, IVSize,
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002340 IVSigned, Ordered, DipatchRTInputValues);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002341 } else {
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00002342 CGOpenMPRuntime::StaticRTInput StaticInit(
2343 IVSize, IVSigned, Ordered, LoopArgs.IL, LoopArgs.LB, LoopArgs.UB,
2344 LoopArgs.ST, LoopArgs.Chunk);
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002345 RT.emitForStaticInit(*this, S.getBeginLoc(), S.getDirectiveKind(),
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00002346 ScheduleKind, StaticInit);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002347 }
2348
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002349 auto &&CodeGenOrdered = [Ordered](CodeGenFunction &CGF, SourceLocation Loc,
2350 const unsigned IVSize,
2351 const bool IVSigned) {
2352 if (Ordered) {
2353 CGF.CGM.getOpenMPRuntime().emitForOrderedIterationEnd(CGF, Loc, IVSize,
2354 IVSigned);
2355 }
2356 };
2357
2358 OMPLoopArguments OuterLoopArgs(LoopArgs.LB, LoopArgs.UB, LoopArgs.ST,
2359 LoopArgs.IL, LoopArgs.Chunk, LoopArgs.EUB);
2360 OuterLoopArgs.IncExpr = S.getInc();
2361 OuterLoopArgs.Init = S.getInit();
2362 OuterLoopArgs.Cond = S.getCond();
2363 OuterLoopArgs.NextLB = S.getNextLowerBound();
2364 OuterLoopArgs.NextUB = S.getNextUpperBound();
2365 EmitOMPOuterLoop(DynamicOrOrdered, IsMonotonic, S, LoopScope, OuterLoopArgs,
2366 emitOMPLoopBodyWithStopPoint, CodeGenOrdered);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002367}
2368
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002369static void emitEmptyOrdered(CodeGenFunction &, SourceLocation Loc,
2370 const unsigned IVSize, const bool IVSigned) {}
2371
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002372void CodeGenFunction::EmitOMPDistributeOuterLoop(
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002373 OpenMPDistScheduleClauseKind ScheduleKind, const OMPLoopDirective &S,
2374 OMPPrivateScope &LoopScope, const OMPLoopArguments &LoopArgs,
2375 const CodeGenLoopTy &CodeGenLoopContent) {
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002376
Alexey Bataevddf3db92018-04-13 17:31:06 +00002377 CGOpenMPRuntime &RT = CGM.getOpenMPRuntime();
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002378
2379 // Emit outer loop.
2380 // Same behavior as a OMPForOuterLoop, except that schedule cannot be
2381 // dynamic
2382 //
2383
2384 const Expr *IVExpr = S.getIterationVariable();
2385 const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
2386 const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
2387
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00002388 CGOpenMPRuntime::StaticRTInput StaticInit(
2389 IVSize, IVSigned, /* Ordered = */ false, LoopArgs.IL, LoopArgs.LB,
2390 LoopArgs.UB, LoopArgs.ST, LoopArgs.Chunk);
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002391 RT.emitDistributeStaticInit(*this, S.getBeginLoc(), ScheduleKind, StaticInit);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002392
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002393 // for combined 'distribute' and 'for' the increment expression of distribute
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00002394 // is stored in DistInc. For 'distribute' alone, it is in Inc.
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002395 Expr *IncExpr;
2396 if (isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()))
2397 IncExpr = S.getDistInc();
2398 else
2399 IncExpr = S.getInc();
2400
2401 // this routine is shared by 'omp distribute parallel for' and
2402 // 'omp distribute': select the right EUB expression depending on the
2403 // directive
2404 OMPLoopArguments OuterLoopArgs;
2405 OuterLoopArgs.LB = LoopArgs.LB;
2406 OuterLoopArgs.UB = LoopArgs.UB;
2407 OuterLoopArgs.ST = LoopArgs.ST;
2408 OuterLoopArgs.IL = LoopArgs.IL;
2409 OuterLoopArgs.Chunk = LoopArgs.Chunk;
2410 OuterLoopArgs.EUB = isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
2411 ? S.getCombinedEnsureUpperBound()
2412 : S.getEnsureUpperBound();
2413 OuterLoopArgs.IncExpr = IncExpr;
2414 OuterLoopArgs.Init = isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
2415 ? S.getCombinedInit()
2416 : S.getInit();
2417 OuterLoopArgs.Cond = isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
2418 ? S.getCombinedCond()
2419 : S.getCond();
2420 OuterLoopArgs.NextLB = isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
2421 ? S.getCombinedNextLowerBound()
2422 : S.getNextLowerBound();
2423 OuterLoopArgs.NextUB = isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
2424 ? S.getCombinedNextUpperBound()
2425 : S.getNextUpperBound();
2426
2427 EmitOMPOuterLoop(/* DynamicOrOrdered = */ false, /* IsMonotonic = */ false, S,
2428 LoopScope, OuterLoopArgs, CodeGenLoopContent,
2429 emitEmptyOrdered);
2430}
2431
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002432static std::pair<LValue, LValue>
2433emitDistributeParallelForInnerBounds(CodeGenFunction &CGF,
2434 const OMPExecutableDirective &S) {
2435 const OMPLoopDirective &LS = cast<OMPLoopDirective>(S);
2436 LValue LB =
2437 EmitOMPHelperVar(CGF, cast<DeclRefExpr>(LS.getLowerBoundVariable()));
2438 LValue UB =
2439 EmitOMPHelperVar(CGF, cast<DeclRefExpr>(LS.getUpperBoundVariable()));
2440
2441 // When composing 'distribute' with 'for' (e.g. as in 'distribute
2442 // parallel for') we need to use the 'distribute'
2443 // chunk lower and upper bounds rather than the whole loop iteration
2444 // space. These are parameters to the outlined function for 'parallel'
2445 // and we copy the bounds of the previous schedule into the
2446 // the current ones.
2447 LValue PrevLB = CGF.EmitLValue(LS.getPrevLowerBoundVariable());
2448 LValue PrevUB = CGF.EmitLValue(LS.getPrevUpperBoundVariable());
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00002449 llvm::Value *PrevLBVal = CGF.EmitLoadOfScalar(
2450 PrevLB, LS.getPrevLowerBoundVariable()->getExprLoc());
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002451 PrevLBVal = CGF.EmitScalarConversion(
2452 PrevLBVal, LS.getPrevLowerBoundVariable()->getType(),
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00002453 LS.getIterationVariable()->getType(),
2454 LS.getPrevLowerBoundVariable()->getExprLoc());
2455 llvm::Value *PrevUBVal = CGF.EmitLoadOfScalar(
2456 PrevUB, LS.getPrevUpperBoundVariable()->getExprLoc());
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002457 PrevUBVal = CGF.EmitScalarConversion(
2458 PrevUBVal, LS.getPrevUpperBoundVariable()->getType(),
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00002459 LS.getIterationVariable()->getType(),
2460 LS.getPrevUpperBoundVariable()->getExprLoc());
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002461
2462 CGF.EmitStoreOfScalar(PrevLBVal, LB);
2463 CGF.EmitStoreOfScalar(PrevUBVal, UB);
2464
2465 return {LB, UB};
2466}
2467
2468/// if the 'for' loop has a dispatch schedule (e.g. dynamic, guided) then
2469/// we need to use the LB and UB expressions generated by the worksharing
2470/// code generation support, whereas in non combined situations we would
2471/// just emit 0 and the LastIteration expression
2472/// This function is necessary due to the difference of the LB and UB
2473/// types for the RT emission routines for 'for_static_init' and
2474/// 'for_dispatch_init'
2475static std::pair<llvm::Value *, llvm::Value *>
2476emitDistributeParallelForDispatchBounds(CodeGenFunction &CGF,
2477 const OMPExecutableDirective &S,
2478 Address LB, Address UB) {
2479 const OMPLoopDirective &LS = cast<OMPLoopDirective>(S);
2480 const Expr *IVExpr = LS.getIterationVariable();
2481 // when implementing a dynamic schedule for a 'for' combined with a
2482 // 'distribute' (e.g. 'distribute parallel for'), the 'for' loop
2483 // is not normalized as each team only executes its own assigned
2484 // distribute chunk
2485 QualType IteratorTy = IVExpr->getType();
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00002486 llvm::Value *LBVal =
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002487 CGF.EmitLoadOfScalar(LB, /*Volatile=*/false, IteratorTy, S.getBeginLoc());
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00002488 llvm::Value *UBVal =
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002489 CGF.EmitLoadOfScalar(UB, /*Volatile=*/false, IteratorTy, S.getBeginLoc());
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002490 return {LBVal, UBVal};
Hans Wennborged129ae2017-04-27 17:02:25 +00002491}
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002492
2493static void emitDistributeParallelForDistributeInnerBoundParams(
2494 CodeGenFunction &CGF, const OMPExecutableDirective &S,
2495 llvm::SmallVectorImpl<llvm::Value *> &CapturedVars) {
2496 const auto &Dir = cast<OMPLoopDirective>(S);
2497 LValue LB =
2498 CGF.EmitLValue(cast<DeclRefExpr>(Dir.getCombinedLowerBoundVariable()));
Akira Hatanakaf139ae32019-12-03 15:17:01 -08002499 llvm::Value *LBCast =
2500 CGF.Builder.CreateIntCast(CGF.Builder.CreateLoad(LB.getAddress(CGF)),
2501 CGF.SizeTy, /*isSigned=*/false);
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002502 CapturedVars.push_back(LBCast);
2503 LValue UB =
2504 CGF.EmitLValue(cast<DeclRefExpr>(Dir.getCombinedUpperBoundVariable()));
2505
Akira Hatanakaf139ae32019-12-03 15:17:01 -08002506 llvm::Value *UBCast =
2507 CGF.Builder.CreateIntCast(CGF.Builder.CreateLoad(UB.getAddress(CGF)),
2508 CGF.SizeTy, /*isSigned=*/false);
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002509 CapturedVars.push_back(UBCast);
Hans Wennborged129ae2017-04-27 17:02:25 +00002510}
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002511
2512static void
2513emitInnerParallelForWhenCombined(CodeGenFunction &CGF,
2514 const OMPLoopDirective &S,
2515 CodeGenFunction::JumpDest LoopExit) {
2516 auto &&CGInlinedWorksharingLoop = [&S](CodeGenFunction &CGF,
Alexey Bataevc99042b2018-03-15 18:10:54 +00002517 PrePostActionTy &Action) {
2518 Action.Enter(CGF);
Alexey Bataevdcb4b8fb2017-11-22 20:19:50 +00002519 bool HasCancel = false;
2520 if (!isOpenMPSimdDirective(S.getDirectiveKind())) {
2521 if (const auto *D = dyn_cast<OMPTeamsDistributeParallelForDirective>(&S))
2522 HasCancel = D->hasCancel();
2523 else if (const auto *D = dyn_cast<OMPDistributeParallelForDirective>(&S))
2524 HasCancel = D->hasCancel();
Alexey Bataev16e79882017-11-22 21:12:03 +00002525 else if (const auto *D =
2526 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&S))
2527 HasCancel = D->hasCancel();
Alexey Bataevdcb4b8fb2017-11-22 20:19:50 +00002528 }
2529 CodeGenFunction::OMPCancelStackRAII CancelRegion(CGF, S.getDirectiveKind(),
2530 HasCancel);
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002531 CGF.EmitOMPWorksharingLoop(S, S.getPrevEnsureUpperBound(),
2532 emitDistributeParallelForInnerBounds,
2533 emitDistributeParallelForDispatchBounds);
2534 };
2535
2536 emitCommonOMPParallelDirective(
Alexey Bataevdcb4b8fb2017-11-22 20:19:50 +00002537 CGF, S,
2538 isOpenMPSimdDirective(S.getDirectiveKind()) ? OMPD_for_simd : OMPD_for,
2539 CGInlinedWorksharingLoop,
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002540 emitDistributeParallelForDistributeInnerBoundParams);
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002541}
2542
Carlo Bertolli9925f152016-06-27 14:55:37 +00002543void CodeGenFunction::EmitOMPDistributeParallelForDirective(
2544 const OMPDistributeParallelForDirective &S) {
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002545 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
2546 CGF.EmitOMPDistributeLoop(S, emitInnerParallelForWhenCombined,
2547 S.getDistInc());
2548 };
Alexey Bataev475a7442018-01-12 19:39:11 +00002549 OMPLexicalScope Scope(*this, S, OMPD_parallel);
Alexey Bataev10a54312017-11-27 16:54:08 +00002550 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_distribute, CodeGen);
Carlo Bertolli9925f152016-06-27 14:55:37 +00002551}
2552
Kelvin Li4a39add2016-07-05 05:00:15 +00002553void CodeGenFunction::EmitOMPDistributeParallelForSimdDirective(
2554 const OMPDistributeParallelForSimdDirective &S) {
Alexey Bataev0b49f9e2017-11-27 19:38:58 +00002555 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
2556 CGF.EmitOMPDistributeLoop(S, emitInnerParallelForWhenCombined,
2557 S.getDistInc());
2558 };
Alexey Bataev475a7442018-01-12 19:39:11 +00002559 OMPLexicalScope Scope(*this, S, OMPD_parallel);
Alexey Bataev0b49f9e2017-11-27 19:38:58 +00002560 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_distribute, CodeGen);
Kelvin Li4a39add2016-07-05 05:00:15 +00002561}
Kelvin Li787f3fc2016-07-06 04:45:38 +00002562
2563void CodeGenFunction::EmitOMPDistributeSimdDirective(
2564 const OMPDistributeSimdDirective &S) {
Alexey Bataev617db5f2017-12-04 15:38:33 +00002565 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
2566 CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc());
2567 };
Alexey Bataev475a7442018-01-12 19:39:11 +00002568 OMPLexicalScope Scope(*this, S, OMPD_unknown);
Alexey Bataev617db5f2017-12-04 15:38:33 +00002569 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen);
Kelvin Li787f3fc2016-07-06 04:45:38 +00002570}
2571
Alexey Bataevf8365372017-11-17 17:57:25 +00002572void CodeGenFunction::EmitOMPTargetSimdDeviceFunction(
2573 CodeGenModule &CGM, StringRef ParentName, const OMPTargetSimdDirective &S) {
2574 // Emit SPMD target parallel for region as a standalone region.
2575 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
2576 emitOMPSimdRegion(CGF, S, Action);
2577 };
2578 llvm::Function *Fn;
2579 llvm::Constant *Addr;
2580 // Emit target region as a standalone region.
2581 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
2582 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
2583 assert(Fn && Addr && "Target device function emission failed.");
2584}
2585
Kelvin Li986330c2016-07-20 22:57:10 +00002586void CodeGenFunction::EmitOMPTargetSimdDirective(
2587 const OMPTargetSimdDirective &S) {
Alexey Bataevf8365372017-11-17 17:57:25 +00002588 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
2589 emitOMPSimdRegion(CGF, S, Action);
2590 };
2591 emitCommonOMPTargetDirective(*this, S, CodeGen);
Kelvin Li986330c2016-07-20 22:57:10 +00002592}
2593
Alexey Bataeva6f2a142015-12-31 06:52:34 +00002594namespace {
2595 struct ScheduleKindModifiersTy {
2596 OpenMPScheduleClauseKind Kind;
2597 OpenMPScheduleClauseModifier M1;
2598 OpenMPScheduleClauseModifier M2;
2599 ScheduleKindModifiersTy(OpenMPScheduleClauseKind Kind,
2600 OpenMPScheduleClauseModifier M1,
2601 OpenMPScheduleClauseModifier M2)
2602 : Kind(Kind), M1(M1), M2(M2) {}
2603 };
2604} // namespace
2605
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002606bool CodeGenFunction::EmitOMPWorksharingLoop(
2607 const OMPLoopDirective &S, Expr *EUB,
2608 const CodeGenLoopBoundsTy &CodeGenLoopBounds,
2609 const CodeGenDispatchBoundsTy &CGDispatchBounds) {
Alexander Musmanc6388682014-12-15 07:07:06 +00002610 // Emit the loop iteration variable.
Alexey Bataevddf3db92018-04-13 17:31:06 +00002611 const auto *IVExpr = cast<DeclRefExpr>(S.getIterationVariable());
2612 const auto *IVDecl = cast<VarDecl>(IVExpr->getDecl());
Alexander Musmanc6388682014-12-15 07:07:06 +00002613 EmitVarDecl(*IVDecl);
2614
2615 // Emit the iterations count variable.
2616 // If it is not a variable, Sema decided to calculate iterations count on each
2617 // iteration (e.g., it is foldable into a constant).
Alexey Bataevddf3db92018-04-13 17:31:06 +00002618 if (const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
Alexander Musmanc6388682014-12-15 07:07:06 +00002619 EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
2620 // Emit calculation of the iterations count.
2621 EmitIgnoredExpr(S.getCalcLastIteration());
2622 }
2623
Alexey Bataevddf3db92018-04-13 17:31:06 +00002624 CGOpenMPRuntime &RT = CGM.getOpenMPRuntime();
Alexander Musmanc6388682014-12-15 07:07:06 +00002625
Alexey Bataev38e89532015-04-16 04:54:05 +00002626 bool HasLastprivateClause;
Alexander Musmanc6388682014-12-15 07:07:06 +00002627 // Check pre-condition.
2628 {
Alexey Bataev5a3af132016-03-29 08:58:54 +00002629 OMPLoopScope PreInitScope(*this, S);
Alexander Musmanc6388682014-12-15 07:07:06 +00002630 // Skip the entire loop if we don't meet the precondition.
Alexey Bataev62dbb972015-04-22 11:59:37 +00002631 // If the condition constant folds and can be elided, avoid emitting the
2632 // whole loop.
2633 bool CondConstant;
2634 llvm::BasicBlock *ContBlock = nullptr;
2635 if (ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
2636 if (!CondConstant)
2637 return false;
2638 } else {
Alexey Bataevddf3db92018-04-13 17:31:06 +00002639 llvm::BasicBlock *ThenBlock = createBasicBlock("omp.precond.then");
Alexey Bataev62dbb972015-04-22 11:59:37 +00002640 ContBlock = createBasicBlock("omp.precond.end");
2641 emitPreCond(*this, S, S.getPreCond(), ThenBlock, ContBlock,
Justin Bogner66242d62015-04-23 23:06:47 +00002642 getProfileCount(&S));
Alexey Bataev62dbb972015-04-22 11:59:37 +00002643 EmitBlock(ThenBlock);
Justin Bogner66242d62015-04-23 23:06:47 +00002644 incrementProfileCounter(&S);
Alexey Bataev62dbb972015-04-22 11:59:37 +00002645 }
Alexey Bataev58e5bdb2015-06-18 04:45:29 +00002646
Alexey Bataevea33dee2018-02-15 23:39:43 +00002647 RunCleanupsScope DoacrossCleanupScope(*this);
Alexey Bataev8b427062016-05-25 12:36:08 +00002648 bool Ordered = false;
Alexey Bataevddf3db92018-04-13 17:31:06 +00002649 if (const auto *OrderedClause = S.getSingleClause<OMPOrderedClause>()) {
Alexey Bataev8b427062016-05-25 12:36:08 +00002650 if (OrderedClause->getNumForLoops())
Alexey Bataevf138fda2018-08-13 19:04:24 +00002651 RT.emitDoacrossInit(*this, S, OrderedClause->getLoopNumIterations());
Alexey Bataev8b427062016-05-25 12:36:08 +00002652 else
2653 Ordered = true;
2654 }
2655
Alexey Bataev5dff95c2016-04-22 03:56:56 +00002656 llvm::DenseSet<const Expr *> EmittedFinals;
Alexey Bataev58e5bdb2015-06-18 04:45:29 +00002657 emitAlignedClause(*this, S);
Alexey Bataev8c3edfe2017-08-16 15:58:46 +00002658 bool HasLinears = EmitOMPLinearClauseInit(S);
Alexey Bataevef549a82016-03-09 09:49:09 +00002659 // Emit helper vars inits.
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002660
2661 std::pair<LValue, LValue> Bounds = CodeGenLoopBounds(*this, S);
2662 LValue LB = Bounds.first;
2663 LValue UB = Bounds.second;
Alexey Bataevef549a82016-03-09 09:49:09 +00002664 LValue ST =
2665 EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getStrideVariable()));
2666 LValue IL =
2667 EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getIsLastIterVariable()));
2668
Alexander Musmanc6388682014-12-15 07:07:06 +00002669 // Emit 'then' code.
2670 {
Alexander Musmanc6388682014-12-15 07:07:06 +00002671 OMPPrivateScope LoopScope(*this);
Alexey Bataev8c3edfe2017-08-16 15:58:46 +00002672 if (EmitOMPFirstprivateClause(S, LoopScope) || HasLinears) {
Alexey Bataev69c62a92015-04-15 04:52:20 +00002673 // Emit implicit barrier to synchronize threads and avoid data races on
Alexey Bataevcd8b6a22016-02-15 08:07:17 +00002674 // initialization of firstprivate variables and post-update of
2675 // lastprivate variables.
Alexey Bataev25e5b442015-09-15 12:52:43 +00002676 CGM.getOpenMPRuntime().emitBarrierCall(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002677 *this, S.getBeginLoc(), OMPD_unknown, /*EmitChecks=*/false,
Alexey Bataev25e5b442015-09-15 12:52:43 +00002678 /*ForceSimpleCall=*/true);
Alexey Bataev69c62a92015-04-15 04:52:20 +00002679 }
Alexey Bataev50a64582015-04-22 12:24:45 +00002680 EmitOMPPrivateClause(S, LoopScope);
Alexey Bataeva58da1a2019-12-27 09:44:43 -05002681 CGOpenMPRuntime::LastprivateConditionalRAII LPCRegion(
2682 *this, S, EmitLValue(S.getIterationVariable()));
Alexey Bataev38e89532015-04-16 04:54:05 +00002683 HasLastprivateClause = EmitOMPLastprivateClauseInit(S, LoopScope);
Alexey Bataev7ebe5fd2015-04-22 13:43:03 +00002684 EmitOMPReductionClauseInit(S, LoopScope);
Alexey Bataev5dff95c2016-04-22 03:56:56 +00002685 EmitOMPPrivateLoopCounters(S, LoopScope);
2686 EmitOMPLinearClause(S, LoopScope);
Alexander Musman7931b982015-03-16 07:14:41 +00002687 (void)LoopScope.Privatize();
Alexey Bataev60705422018-10-30 15:50:12 +00002688 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()))
2689 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*this, S);
Alexander Musmanc6388682014-12-15 07:07:06 +00002690
2691 // Detect the loop schedule kind and chunk.
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00002692 const Expr *ChunkExpr = nullptr;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00002693 OpenMPScheduleTy ScheduleKind;
Alexey Bataevddf3db92018-04-13 17:31:06 +00002694 if (const auto *C = S.getSingleClause<OMPScheduleClause>()) {
Alexey Bataev9ebd7422016-05-10 09:57:36 +00002695 ScheduleKind.Schedule = C->getScheduleKind();
2696 ScheduleKind.M1 = C->getFirstScheduleModifier();
2697 ScheduleKind.M2 = C->getSecondScheduleModifier();
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00002698 ChunkExpr = C->getChunkSize();
Gheorghe-Teodor Bercea8233af92018-09-27 20:29:00 +00002699 } else {
2700 // Default behaviour for schedule clause.
2701 CGM.getOpenMPRuntime().getDefaultScheduleAndChunk(
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00002702 *this, S, ScheduleKind.Schedule, ChunkExpr);
2703 }
2704 bool HasChunkSizeOne = false;
2705 llvm::Value *Chunk = nullptr;
2706 if (ChunkExpr) {
2707 Chunk = EmitScalarExpr(ChunkExpr);
2708 Chunk = EmitScalarConversion(Chunk, ChunkExpr->getType(),
2709 S.getIterationVariable()->getType(),
2710 S.getBeginLoc());
Fangrui Song407659a2018-11-30 23:41:18 +00002711 Expr::EvalResult Result;
2712 if (ChunkExpr->EvaluateAsInt(Result, getContext())) {
2713 llvm::APSInt EvaluatedChunk = Result.Val.getInt();
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00002714 HasChunkSizeOne = (EvaluatedChunk.getLimitedValue() == 1);
Fangrui Song407659a2018-11-30 23:41:18 +00002715 }
Alexey Bataev3392d762016-02-16 11:18:12 +00002716 }
Alexander Musmanc6388682014-12-15 07:07:06 +00002717 const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
2718 const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
Alexey Bataeva6f2a142015-12-31 06:52:34 +00002719 // OpenMP 4.5, 2.7.1 Loop Construct, Description.
2720 // If the static schedule kind is specified or if the ordered clause is
2721 // specified, and if no monotonic modifier is specified, the effect will
2722 // be as if the monotonic modifier was specified.
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00002723 bool StaticChunkedOne = RT.isStaticChunked(ScheduleKind.Schedule,
2724 /* Chunked */ Chunk != nullptr) && HasChunkSizeOne &&
2725 isOpenMPLoopBoundSharingDirective(S.getDirectiveKind());
2726 if ((RT.isStaticNonchunked(ScheduleKind.Schedule,
2727 /* Chunked */ Chunk != nullptr) ||
2728 StaticChunkedOne) &&
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002729 !Ordered) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00002730 JumpDest LoopExit =
Alexey Bataeva6f2a142015-12-31 06:52:34 +00002731 getJumpDestInCurrentScope(createBasicBlock("omp.loop.exit"));
Alexey Bataev103f3c9e2019-11-20 15:59:03 -05002732 emitCommonSimdLoop(
2733 *this, S,
2734 [&S](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataeva7815212020-02-03 12:08:16 -05002735 if (isOpenMPSimdDirective(S.getDirectiveKind())) {
Alexey Bataev103f3c9e2019-11-20 15:59:03 -05002736 CGF.EmitOMPSimdInit(S, /*IsMonotonic=*/true);
Alexey Bataeva7815212020-02-03 12:08:16 -05002737 } else if (const auto *C = S.getSingleClause<OMPOrderClause>()) {
2738 if (C->getKind() == OMPC_ORDER_concurrent)
2739 CGF.LoopStack.setParallel(/*Enable=*/true);
2740 }
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00002741 },
Alexey Bataev103f3c9e2019-11-20 15:59:03 -05002742 [IVSize, IVSigned, Ordered, IL, LB, UB, ST, StaticChunkedOne, Chunk,
2743 &S, ScheduleKind, LoopExit,
2744 &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) {
2745 // OpenMP [2.7.1, Loop Construct, Description, table 2-1]
2746 // When no chunk_size is specified, the iteration space is divided
2747 // into chunks that are approximately equal in size, and at most
2748 // one chunk is distributed to each thread. Note that the size of
2749 // the chunks is unspecified in this case.
2750 CGOpenMPRuntime::StaticRTInput StaticInit(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08002751 IVSize, IVSigned, Ordered, IL.getAddress(CGF),
2752 LB.getAddress(CGF), UB.getAddress(CGF), ST.getAddress(CGF),
Alexey Bataev103f3c9e2019-11-20 15:59:03 -05002753 StaticChunkedOne ? Chunk : nullptr);
2754 CGF.CGM.getOpenMPRuntime().emitForStaticInit(
2755 CGF, S.getBeginLoc(), S.getDirectiveKind(), ScheduleKind,
2756 StaticInit);
2757 // UB = min(UB, GlobalUB);
2758 if (!StaticChunkedOne)
2759 CGF.EmitIgnoredExpr(S.getEnsureUpperBound());
2760 // IV = LB;
2761 CGF.EmitIgnoredExpr(S.getInit());
2762 // For unchunked static schedule generate:
2763 //
2764 // while (idx <= UB) {
2765 // BODY;
2766 // ++idx;
2767 // }
2768 //
2769 // For static schedule with chunk one:
2770 //
2771 // while (IV <= PrevUB) {
2772 // BODY;
2773 // IV += ST;
2774 // }
2775 CGF.EmitOMPInnerLoop(
2776 S, LoopScope.requiresCleanups(),
2777 StaticChunkedOne ? S.getCombinedParForInDistCond()
2778 : S.getCond(),
2779 StaticChunkedOne ? S.getDistInc() : S.getInc(),
2780 [&S, LoopExit](CodeGenFunction &CGF) {
2781 CGF.EmitOMPLoopBody(S, LoopExit);
2782 CGF.EmitStopPoint(&S);
2783 },
2784 [](CodeGenFunction &) {});
2785 });
Alexey Bataev0f34da12015-07-02 04:17:07 +00002786 EmitBlock(LoopExit.getBlock());
Alexander Musmanc6388682014-12-15 07:07:06 +00002787 // Tell the runtime we are done.
Alexey Bataev957d8562016-11-17 15:12:05 +00002788 auto &&CodeGen = [&S](CodeGenFunction &CGF) {
Stephen Kelly1c301dc2018-08-09 21:09:38 +00002789 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
Alexey Bataevf43f7142017-09-06 16:17:35 +00002790 S.getDirectiveKind());
Alexey Bataev957d8562016-11-17 15:12:05 +00002791 };
2792 OMPCancelStack.emitExit(*this, S.getDirectiveKind(), CodeGen);
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002793 } else {
Alexey Bataev9ebd7422016-05-10 09:57:36 +00002794 const bool IsMonotonic =
2795 Ordered || ScheduleKind.Schedule == OMPC_SCHEDULE_static ||
2796 ScheduleKind.Schedule == OMPC_SCHEDULE_unknown ||
2797 ScheduleKind.M1 == OMPC_SCHEDULE_MODIFIER_monotonic ||
2798 ScheduleKind.M2 == OMPC_SCHEDULE_MODIFIER_monotonic;
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002799 // Emit the outer loop, which requests its work chunk [LB..UB] from
2800 // runtime and runs the inner loop to process it.
Akira Hatanakaf139ae32019-12-03 15:17:01 -08002801 const OMPLoopArguments LoopArguments(
2802 LB.getAddress(*this), UB.getAddress(*this), ST.getAddress(*this),
2803 IL.getAddress(*this), Chunk, EUB);
Alexey Bataeva6f2a142015-12-31 06:52:34 +00002804 EmitOMPForOuterLoop(ScheduleKind, IsMonotonic, S, LoopScope, Ordered,
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002805 LoopArguments, CGDispatchBounds);
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002806 }
Alexey Bataev5dff95c2016-04-22 03:56:56 +00002807 if (isOpenMPSimdDirective(S.getDirectiveKind())) {
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002808 EmitOMPSimdFinal(S, [IL, &S](CodeGenFunction &CGF) {
2809 return CGF.Builder.CreateIsNotNull(
2810 CGF.EmitLoadOfScalar(IL, S.getBeginLoc()));
2811 });
Alexey Bataev5dff95c2016-04-22 03:56:56 +00002812 }
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00002813 EmitOMPReductionClauseFinal(
2814 S, /*ReductionKind=*/isOpenMPSimdDirective(S.getDirectiveKind())
2815 ? /*Parallel and Simd*/ OMPD_parallel_for_simd
2816 : /*Parallel only*/ OMPD_parallel);
Alexey Bataev61205072016-03-02 04:57:40 +00002817 // Emit post-update of the reduction variables if IsLastIter != 0.
2818 emitPostUpdateForReductionClause(
Alexey Bataevddf3db92018-04-13 17:31:06 +00002819 *this, S, [IL, &S](CodeGenFunction &CGF) {
Alexey Bataev61205072016-03-02 04:57:40 +00002820 return CGF.Builder.CreateIsNotNull(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002821 CGF.EmitLoadOfScalar(IL, S.getBeginLoc()));
Alexey Bataev61205072016-03-02 04:57:40 +00002822 });
Alexey Bataev38e89532015-04-16 04:54:05 +00002823 // Emit final copy of the lastprivate variables if IsLastIter != 0.
2824 if (HasLastprivateClause)
2825 EmitOMPLastprivateClauseFinal(
Alexey Bataev5dff95c2016-04-22 03:56:56 +00002826 S, isOpenMPSimdDirective(S.getDirectiveKind()),
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002827 Builder.CreateIsNotNull(EmitLoadOfScalar(IL, S.getBeginLoc())));
Alexander Musmanc6388682014-12-15 07:07:06 +00002828 }
Alexey Bataevddf3db92018-04-13 17:31:06 +00002829 EmitOMPLinearClauseFinal(S, [IL, &S](CodeGenFunction &CGF) {
Alexey Bataevef549a82016-03-09 09:49:09 +00002830 return CGF.Builder.CreateIsNotNull(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002831 CGF.EmitLoadOfScalar(IL, S.getBeginLoc()));
Alexey Bataevef549a82016-03-09 09:49:09 +00002832 });
Alexey Bataevea33dee2018-02-15 23:39:43 +00002833 DoacrossCleanupScope.ForceCleanup();
Alexander Musmanc6388682014-12-15 07:07:06 +00002834 // We're now done with the loop, so jump to the continuation block.
Alexey Bataev62dbb972015-04-22 11:59:37 +00002835 if (ContBlock) {
2836 EmitBranch(ContBlock);
Alexey Bataevddf3db92018-04-13 17:31:06 +00002837 EmitBlock(ContBlock, /*IsFinished=*/true);
Alexey Bataev62dbb972015-04-22 11:59:37 +00002838 }
Alexander Musmanc6388682014-12-15 07:07:06 +00002839 }
Alexey Bataev38e89532015-04-16 04:54:05 +00002840 return HasLastprivateClause;
Alexander Musmanc6388682014-12-15 07:07:06 +00002841}
2842
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002843/// The following two functions generate expressions for the loop lower
2844/// and upper bounds in case of static and dynamic (dispatch) schedule
2845/// of the associated 'for' or 'distribute' loop.
2846static std::pair<LValue, LValue>
2847emitForLoopBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00002848 const auto &LS = cast<OMPLoopDirective>(S);
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002849 LValue LB =
2850 EmitOMPHelperVar(CGF, cast<DeclRefExpr>(LS.getLowerBoundVariable()));
2851 LValue UB =
2852 EmitOMPHelperVar(CGF, cast<DeclRefExpr>(LS.getUpperBoundVariable()));
2853 return {LB, UB};
2854}
2855
2856/// When dealing with dispatch schedules (e.g. dynamic, guided) we do not
2857/// consider the lower and upper bound expressions generated by the
2858/// worksharing loop support, but we use 0 and the iteration space size as
2859/// constants
2860static std::pair<llvm::Value *, llvm::Value *>
2861emitDispatchForLoopBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S,
2862 Address LB, Address UB) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00002863 const auto &LS = cast<OMPLoopDirective>(S);
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002864 const Expr *IVExpr = LS.getIterationVariable();
2865 const unsigned IVSize = CGF.getContext().getTypeSize(IVExpr->getType());
2866 llvm::Value *LBVal = CGF.Builder.getIntN(IVSize, 0);
2867 llvm::Value *UBVal = CGF.EmitScalarExpr(LS.getLastIteration());
2868 return {LBVal, UBVal};
2869}
2870
Alexander Musmanc6388682014-12-15 07:07:06 +00002871void CodeGenFunction::EmitOMPForDirective(const OMPForDirective &S) {
Alexey Bataev38e89532015-04-16 04:54:05 +00002872 bool HasLastprivates = false;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002873 auto &&CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF,
2874 PrePostActionTy &) {
Alexey Bataev957d8562016-11-17 15:12:05 +00002875 OMPCancelStackRAII CancelRegion(CGF, OMPD_for, S.hasCancel());
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_for, CodeGen,
2885 S.hasCancel());
2886 }
Alexander Musmanc6388682014-12-15 07:07:06 +00002887
2888 // Emit an implicit barrier at the end.
Alexey Bataevddf3db92018-04-13 17:31:06 +00002889 if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002890 CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(), OMPD_for);
Alexey Bataev46978742020-01-30 10:46:11 -05002891 // Check for outer lastprivate conditional update.
2892 checkForLastprivateConditionalUpdate(*this, S);
Alexey Bataevf29276e2014-06-18 04:14:57 +00002893}
Alexey Bataevd3f8dd22014-06-25 11:44:49 +00002894
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00002895void CodeGenFunction::EmitOMPForSimdDirective(const OMPForSimdDirective &S) {
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00002896 bool HasLastprivates = false;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002897 auto &&CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF,
2898 PrePostActionTy &) {
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002899 HasLastprivates = CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(),
2900 emitForLoopBounds,
2901 emitDispatchForLoopBounds);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002902 };
Alexey Bataev3392d762016-02-16 11:18:12 +00002903 {
Alexey Bataev46978742020-01-30 10:46:11 -05002904 auto LPCRegion =
2905 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
Alexey Bataev475a7442018-01-12 19:39:11 +00002906 OMPLexicalScope Scope(*this, S, OMPD_unknown);
Alexey Bataev3392d762016-02-16 11:18:12 +00002907 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen);
2908 }
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00002909
2910 // Emit an implicit barrier at the end.
Alexey Bataevddf3db92018-04-13 17:31:06 +00002911 if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002912 CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(), OMPD_for);
Alexey Bataev46978742020-01-30 10:46:11 -05002913 // Check for outer lastprivate conditional update.
2914 checkForLastprivateConditionalUpdate(*this, S);
Alexander Musmanf82886e2014-09-18 05:12:34 +00002915}
2916
Alexey Bataev2df54a02015-03-12 08:53:29 +00002917static LValue createSectionLVal(CodeGenFunction &CGF, QualType Ty,
2918 const Twine &Name,
2919 llvm::Value *Init = nullptr) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00002920 LValue LVal = CGF.MakeAddrLValue(CGF.CreateMemTemp(Ty, Name), Ty);
Alexey Bataev2df54a02015-03-12 08:53:29 +00002921 if (Init)
Akira Hatanaka642f7992016-10-18 19:05:41 +00002922 CGF.EmitStoreThroughLValue(RValue::get(Init), LVal, /*isInit*/ true);
Alexey Bataev2df54a02015-03-12 08:53:29 +00002923 return LVal;
Alexey Bataevd3f8dd22014-06-25 11:44:49 +00002924}
2925
Alexey Bataev3392d762016-02-16 11:18:12 +00002926void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00002927 const Stmt *CapturedStmt = S.getInnermostCapturedStmt()->getCapturedStmt();
2928 const auto *CS = dyn_cast<CompoundStmt>(CapturedStmt);
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002929 bool HasLastprivates = false;
Alexey Bataevddf3db92018-04-13 17:31:06 +00002930 auto &&CodeGen = [&S, CapturedStmt, CS,
2931 &HasLastprivates](CodeGenFunction &CGF, PrePostActionTy &) {
2932 ASTContext &C = CGF.getContext();
2933 QualType KmpInt32Ty =
2934 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002935 // Emit helper vars inits.
2936 LValue LB = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.lb.",
2937 CGF.Builder.getInt32(0));
Alexey Bataevddf3db92018-04-13 17:31:06 +00002938 llvm::ConstantInt *GlobalUBVal = CS != nullptr
2939 ? CGF.Builder.getInt32(CS->size() - 1)
2940 : CGF.Builder.getInt32(0);
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002941 LValue UB =
2942 createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.ub.", GlobalUBVal);
2943 LValue ST = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.st.",
2944 CGF.Builder.getInt32(1));
2945 LValue IL = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.il.",
2946 CGF.Builder.getInt32(0));
2947 // Loop counter.
2948 LValue IV = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.iv.");
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002949 OpaqueValueExpr IVRefExpr(S.getBeginLoc(), KmpInt32Ty, VK_LValue);
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002950 CodeGenFunction::OpaqueValueMapping OpaqueIV(CGF, &IVRefExpr, IV);
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002951 OpaqueValueExpr UBRefExpr(S.getBeginLoc(), KmpInt32Ty, VK_LValue);
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002952 CodeGenFunction::OpaqueValueMapping OpaqueUB(CGF, &UBRefExpr, UB);
2953 // Generate condition for loop.
2954 BinaryOperator Cond(&IVRefExpr, &UBRefExpr, BO_LE, C.BoolTy, VK_RValue,
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002955 OK_Ordinary, S.getBeginLoc(), FPOptions());
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002956 // Increment for loop counter.
2957 UnaryOperator Inc(&IVRefExpr, UO_PreInc, KmpInt32Ty, VK_RValue, OK_Ordinary,
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002958 S.getBeginLoc(), true);
Alexey Bataevddf3db92018-04-13 17:31:06 +00002959 auto &&BodyGen = [CapturedStmt, CS, &S, &IV](CodeGenFunction &CGF) {
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002960 // Iterate through all sections and emit a switch construct:
2961 // switch (IV) {
2962 // case 0:
2963 // <SectionStmt[0]>;
2964 // break;
2965 // ...
2966 // case <NumSection> - 1:
2967 // <SectionStmt[<NumSection> - 1]>;
2968 // break;
2969 // }
2970 // .omp.sections.exit:
Alexey Bataevddf3db92018-04-13 17:31:06 +00002971 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".omp.sections.exit");
2972 llvm::SwitchInst *SwitchStmt =
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002973 CGF.Builder.CreateSwitch(CGF.EmitLoadOfScalar(IV, S.getBeginLoc()),
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00002974 ExitBB, CS == nullptr ? 1 : CS->size());
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002975 if (CS) {
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002976 unsigned CaseNumber = 0;
Alexey Bataevddf3db92018-04-13 17:31:06 +00002977 for (const Stmt *SubStmt : CS->children()) {
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002978 auto CaseBB = CGF.createBasicBlock(".omp.sections.case");
2979 CGF.EmitBlock(CaseBB);
2980 SwitchStmt->addCase(CGF.Builder.getInt32(CaseNumber), CaseBB);
Benjamin Kramer642f1732015-07-02 21:03:14 +00002981 CGF.EmitStmt(SubStmt);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002982 CGF.EmitBranch(ExitBB);
Benjamin Kramer642f1732015-07-02 21:03:14 +00002983 ++CaseNumber;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002984 }
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002985 } else {
Alexey Bataevddf3db92018-04-13 17:31:06 +00002986 llvm::BasicBlock *CaseBB = CGF.createBasicBlock(".omp.sections.case");
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002987 CGF.EmitBlock(CaseBB);
2988 SwitchStmt->addCase(CGF.Builder.getInt32(0), CaseBB);
Alexey Bataevddf3db92018-04-13 17:31:06 +00002989 CGF.EmitStmt(CapturedStmt);
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002990 CGF.EmitBranch(ExitBB);
Alexey Bataev2cb9b952015-04-24 03:37:03 +00002991 }
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002992 CGF.EmitBlock(ExitBB, /*IsFinished=*/true);
Alexey Bataev2df54a02015-03-12 08:53:29 +00002993 };
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002994
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002995 CodeGenFunction::OMPPrivateScope LoopScope(CGF);
2996 if (CGF.EmitOMPFirstprivateClause(S, LoopScope)) {
Alexey Bataev9efc03b2015-04-27 04:34:03 +00002997 // Emit implicit barrier to synchronize threads and avoid data races on
Alexey Bataevcd8b6a22016-02-15 08:07:17 +00002998 // initialization of firstprivate variables and post-update of lastprivate
2999 // variables.
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003000 CGF.CGM.getOpenMPRuntime().emitBarrierCall(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003001 CGF, S.getBeginLoc(), OMPD_unknown, /*EmitChecks=*/false,
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003002 /*ForceSimpleCall=*/true);
Alexey Bataev9efc03b2015-04-27 04:34:03 +00003003 }
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003004 CGF.EmitOMPPrivateClause(S, LoopScope);
Alexey Bataeva58da1a2019-12-27 09:44:43 -05003005 CGOpenMPRuntime::LastprivateConditionalRAII LPCRegion(CGF, S, IV);
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003006 HasLastprivates = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
3007 CGF.EmitOMPReductionClauseInit(S, LoopScope);
3008 (void)LoopScope.Privatize();
Alexey Bataev60705422018-10-30 15:50:12 +00003009 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()))
3010 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
Alexey Bataev2cb9b952015-04-24 03:37:03 +00003011
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003012 // Emit static non-chunked loop.
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003013 OpenMPScheduleTy ScheduleKind;
3014 ScheduleKind.Schedule = OMPC_SCHEDULE_static;
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003015 CGOpenMPRuntime::StaticRTInput StaticInit(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08003016 /*IVSize=*/32, /*IVSigned=*/true, /*Ordered=*/false, IL.getAddress(CGF),
3017 LB.getAddress(CGF), UB.getAddress(CGF), ST.getAddress(CGF));
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003018 CGF.CGM.getOpenMPRuntime().emitForStaticInit(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003019 CGF, S.getBeginLoc(), S.getDirectiveKind(), ScheduleKind, StaticInit);
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003020 // UB = min(UB, GlobalUB);
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003021 llvm::Value *UBVal = CGF.EmitLoadOfScalar(UB, S.getBeginLoc());
Alexey Bataevddf3db92018-04-13 17:31:06 +00003022 llvm::Value *MinUBGlobalUB = CGF.Builder.CreateSelect(
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003023 CGF.Builder.CreateICmpSLT(UBVal, GlobalUBVal), UBVal, GlobalUBVal);
3024 CGF.EmitStoreOfScalar(MinUBGlobalUB, UB);
3025 // IV = LB;
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003026 CGF.EmitStoreOfScalar(CGF.EmitLoadOfScalar(LB, S.getBeginLoc()), IV);
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003027 // while (idx <= UB) { BODY; ++idx; }
3028 CGF.EmitOMPInnerLoop(S, /*RequiresCleanup=*/false, &Cond, &Inc, BodyGen,
3029 [](CodeGenFunction &) {});
3030 // Tell the runtime we are done.
Alexey Bataev957d8562016-11-17 15:12:05 +00003031 auto &&CodeGen = [&S](CodeGenFunction &CGF) {
Stephen Kelly1c301dc2018-08-09 21:09:38 +00003032 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
Alexey Bataevf43f7142017-09-06 16:17:35 +00003033 S.getDirectiveKind());
Alexey Bataev957d8562016-11-17 15:12:05 +00003034 };
3035 CGF.OMPCancelStack.emitExit(CGF, S.getDirectiveKind(), CodeGen);
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00003036 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel);
Alexey Bataev61205072016-03-02 04:57:40 +00003037 // Emit post-update of the reduction variables if IsLastIter != 0.
Alexey Bataevddf3db92018-04-13 17:31:06 +00003038 emitPostUpdateForReductionClause(CGF, S, [IL, &S](CodeGenFunction &CGF) {
3039 return CGF.Builder.CreateIsNotNull(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003040 CGF.EmitLoadOfScalar(IL, S.getBeginLoc()));
Alexey Bataevddf3db92018-04-13 17:31:06 +00003041 });
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003042
3043 // Emit final copy of the lastprivate variables if IsLastIter != 0.
3044 if (HasLastprivates)
3045 CGF.EmitOMPLastprivateClauseFinal(
Alexey Bataev5dff95c2016-04-22 03:56:56 +00003046 S, /*NoFinals=*/false,
3047 CGF.Builder.CreateIsNotNull(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003048 CGF.EmitLoadOfScalar(IL, S.getBeginLoc())));
Alexey Bataev68adb7d2015-04-14 03:29:22 +00003049 };
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003050
3051 bool HasCancel = false;
3052 if (auto *OSD = dyn_cast<OMPSectionsDirective>(&S))
3053 HasCancel = OSD->hasCancel();
3054 else if (auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&S))
3055 HasCancel = OPSD->hasCancel();
Alexey Bataev957d8562016-11-17 15:12:05 +00003056 OMPCancelStackRAII CancelRegion(*this, S.getDirectiveKind(), HasCancel);
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003057 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_sections, CodeGen,
3058 HasCancel);
3059 // Emit barrier for lastprivates only if 'sections' directive has 'nowait'
3060 // clause. Otherwise the barrier will be generated by the codegen for the
3061 // directive.
3062 if (HasLastprivates && S.getSingleClause<OMPNowaitClause>()) {
Alexey Bataev2cb9b952015-04-24 03:37:03 +00003063 // Emit implicit barrier to synchronize threads and avoid data races on
3064 // initialization of firstprivate variables.
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003065 CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(),
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003066 OMPD_unknown);
Alexey Bataev2cb9b952015-04-24 03:37:03 +00003067 }
Alexey Bataev68adb7d2015-04-14 03:29:22 +00003068}
Alexey Bataev2df54a02015-03-12 08:53:29 +00003069
Alexey Bataev68adb7d2015-04-14 03:29:22 +00003070void CodeGenFunction::EmitOMPSectionsDirective(const OMPSectionsDirective &S) {
Alexey Bataev3392d762016-02-16 11:18:12 +00003071 {
Alexey Bataev46978742020-01-30 10:46:11 -05003072 auto LPCRegion =
3073 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
Alexey Bataev475a7442018-01-12 19:39:11 +00003074 OMPLexicalScope Scope(*this, S, OMPD_unknown);
Alexey Bataev3392d762016-02-16 11:18:12 +00003075 EmitSections(S);
3076 }
Alexey Bataev2df54a02015-03-12 08:53:29 +00003077 // Emit an implicit barrier at the end.
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00003078 if (!S.getSingleClause<OMPNowaitClause>()) {
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003079 CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(),
Alexey Bataev3392d762016-02-16 11:18:12 +00003080 OMPD_sections);
Alexey Bataevf2685682015-03-30 04:30:22 +00003081 }
Alexey Bataev46978742020-01-30 10:46:11 -05003082 // Check for outer lastprivate conditional update.
3083 checkForLastprivateConditionalUpdate(*this, S);
Alexey Bataev2df54a02015-03-12 08:53:29 +00003084}
3085
3086void CodeGenFunction::EmitOMPSectionDirective(const OMPSectionDirective &S) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003087 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataev475a7442018-01-12 19:39:11 +00003088 CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003089 };
Alexey Bataev475a7442018-01-12 19:39:11 +00003090 OMPLexicalScope Scope(*this, S, OMPD_unknown);
Alexey Bataev25e5b442015-09-15 12:52:43 +00003091 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_section, CodeGen,
3092 S.hasCancel());
Alexey Bataev1e0498a2014-06-26 08:21:58 +00003093}
3094
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003095void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &S) {
Alexey Bataeva63048e2015-03-23 06:18:07 +00003096 llvm::SmallVector<const Expr *, 8> CopyprivateVars;
Alexey Bataev420d45b2015-04-14 05:11:24 +00003097 llvm::SmallVector<const Expr *, 8> DestExprs;
Alexey Bataeva63048e2015-03-23 06:18:07 +00003098 llvm::SmallVector<const Expr *, 8> SrcExprs;
Alexey Bataeva63048e2015-03-23 06:18:07 +00003099 llvm::SmallVector<const Expr *, 8> AssignmentOps;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003100 // Check if there are any 'copyprivate' clauses associated with this
Alexey Bataevcd8b6a22016-02-15 08:07:17 +00003101 // 'single' construct.
Alexey Bataeva63048e2015-03-23 06:18:07 +00003102 // Build a list of copyprivate variables along with helper expressions
3103 // (<source>, <destination>, <destination>=<source> expressions)
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00003104 for (const auto *C : S.getClausesOfKind<OMPCopyprivateClause>()) {
Alexey Bataeva63048e2015-03-23 06:18:07 +00003105 CopyprivateVars.append(C->varlists().begin(), C->varlists().end());
Alexey Bataev420d45b2015-04-14 05:11:24 +00003106 DestExprs.append(C->destination_exprs().begin(),
3107 C->destination_exprs().end());
Alexey Bataeva63048e2015-03-23 06:18:07 +00003108 SrcExprs.append(C->source_exprs().begin(), C->source_exprs().end());
Alexey Bataeva63048e2015-03-23 06:18:07 +00003109 AssignmentOps.append(C->assignment_ops().begin(),
3110 C->assignment_ops().end());
3111 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003112 // Emit code for 'single' region along with 'copyprivate' clauses
3113 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
3114 Action.Enter(CGF);
3115 OMPPrivateScope SingleScope(CGF);
3116 (void)CGF.EmitOMPFirstprivateClause(S, SingleScope);
3117 CGF.EmitOMPPrivateClause(S, SingleScope);
3118 (void)SingleScope.Privatize();
Alexey Bataev475a7442018-01-12 19:39:11 +00003119 CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003120 };
Alexey Bataev3392d762016-02-16 11:18:12 +00003121 {
Alexey Bataev46978742020-01-30 10:46:11 -05003122 auto LPCRegion =
3123 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
Alexey Bataev475a7442018-01-12 19:39:11 +00003124 OMPLexicalScope Scope(*this, S, OMPD_unknown);
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003125 CGM.getOpenMPRuntime().emitSingleRegion(*this, CodeGen, S.getBeginLoc(),
Alexey Bataev3392d762016-02-16 11:18:12 +00003126 CopyprivateVars, DestExprs,
3127 SrcExprs, AssignmentOps);
3128 }
3129 // Emit an implicit barrier at the end (to avoid data race on firstprivate
3130 // init or if no 'nowait' clause was specified and no 'copyprivate' clause).
Alexey Bataev417089f2016-02-17 13:19:37 +00003131 if (!S.getSingleClause<OMPNowaitClause>() && CopyprivateVars.empty()) {
Alexey Bataev5521d782015-04-24 04:21:15 +00003132 CGM.getOpenMPRuntime().emitBarrierCall(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003133 *this, S.getBeginLoc(),
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00003134 S.getSingleClause<OMPNowaitClause>() ? OMPD_unknown : OMPD_single);
Alexey Bataevf2685682015-03-30 04:30:22 +00003135 }
Alexey Bataev46978742020-01-30 10:46:11 -05003136 // Check for outer lastprivate conditional update.
3137 checkForLastprivateConditionalUpdate(*this, S);
Alexey Bataevd1e40fb2014-06-26 12:05:45 +00003138}
3139
cchen47d60942019-12-05 13:43:48 -05003140static void emitMaster(CodeGenFunction &CGF, const OMPExecutableDirective &S) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003141 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
3142 Action.Enter(CGF);
Alexey Bataev475a7442018-01-12 19:39:11 +00003143 CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003144 };
cchen47d60942019-12-05 13:43:48 -05003145 CGF.CGM.getOpenMPRuntime().emitMasterRegion(CGF, CodeGen, S.getBeginLoc());
3146}
3147
3148void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &S) {
Fady Ghanim7438059a2020-02-15 00:42:23 -06003149 if (llvm::OpenMPIRBuilder *OMPBuilder = CGM.getOpenMPIRBuilder()) {
3150 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
3151
3152 const CapturedStmt *CS = S.getInnermostCapturedStmt();
3153 const Stmt *MasterRegionBodyStmt = CS->getCapturedStmt();
3154
3155 // TODO: Replace with a generic helper function for finalization
3156 auto FiniCB = [this](InsertPointTy IP) {
3157 CGBuilderTy::InsertPointGuard IPG(Builder);
3158 assert(IP.getBlock()->end() != IP.getPoint() &&
3159 "OpenMP IR Builder should cause terminated block!");
3160
3161 llvm::BasicBlock *IPBB = IP.getBlock();
3162 llvm::BasicBlock *DestBB = IPBB->getUniqueSuccessor();
3163 assert(DestBB && "Finalization block should have one successor!");
3164
3165 // erase and replace with cleanup branch.
3166 IPBB->getTerminator()->eraseFromParent();
3167 Builder.SetInsertPoint(IPBB);
3168 CodeGenFunction::JumpDest Dest = getJumpDestInCurrentScope(DestBB);
3169 EmitBranchThroughCleanup(Dest);
3170 };
3171
3172 // TODO: Replace with a generic helper function for emitting body
3173 auto BodyGenCB = [MasterRegionBodyStmt, this](InsertPointTy AllocaIP,
3174 InsertPointTy CodeGenIP,
3175 llvm::BasicBlock &FiniBB) {
3176 // Alloca insertion block should be in the entry block of the containing
3177 // function So it expects an empty AllocaIP in which case will reuse the
3178 // old alloca insertion point, or a new AllocaIP in the same block as the
3179 // old one
3180 assert((!AllocaIP.isSet() ||
3181 AllocaInsertPt->getParent() == AllocaIP.getBlock()) &&
3182 "Insertion point should be in the entry block of containing "
3183 "function!");
3184 auto OldAllocaIP = AllocaInsertPt;
3185 if (AllocaIP.isSet())
3186 AllocaInsertPt = &*AllocaIP.getPoint();
3187 auto OldReturnBlock = ReturnBlock;
3188 ReturnBlock = getJumpDestInCurrentScope(&FiniBB);
3189
3190 llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock();
3191 if (llvm::Instruction *CodeGenIPBBTI = CodeGenIPBB->getTerminator())
3192 CodeGenIPBBTI->eraseFromParent();
3193
3194 Builder.SetInsertPoint(CodeGenIPBB);
3195
3196 EmitStmt(MasterRegionBodyStmt);
3197
3198 if (Builder.saveIP().isSet())
3199 Builder.CreateBr(&FiniBB);
3200
3201 AllocaInsertPt = OldAllocaIP;
3202 ReturnBlock = OldReturnBlock;
3203 };
3204 CGCapturedStmtInfo CGSI(*CS, CR_OpenMP);
3205 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(*this, &CGSI);
3206 Builder.restoreIP(OMPBuilder->CreateMaster(Builder, BodyGenCB, FiniCB));
3207
3208 return;
3209 }
Alexey Bataev475a7442018-01-12 19:39:11 +00003210 OMPLexicalScope Scope(*this, S, OMPD_unknown);
cchen47d60942019-12-05 13:43:48 -05003211 emitMaster(*this, S);
Alexander Musman80c22892014-07-17 08:54:58 +00003212}
3213
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003214void CodeGenFunction::EmitOMPCriticalDirective(const OMPCriticalDirective &S) {
Fady Ghanim7438059a2020-02-15 00:42:23 -06003215 if (llvm::OpenMPIRBuilder *OMPBuilder = CGM.getOpenMPIRBuilder()) {
3216 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
3217
3218 const CapturedStmt *CS = S.getInnermostCapturedStmt();
3219 const Stmt *CriticalRegionBodyStmt = CS->getCapturedStmt();
3220 const Expr *Hint = nullptr;
3221 if (const auto *HintClause = S.getSingleClause<OMPHintClause>())
3222 Hint = HintClause->getHint();
3223
3224 // TODO: This is slightly different from what's currently being done in
3225 // clang. Fix the Int32Ty to IntPtrTy (pointer width size) when everything
3226 // about typing is final.
3227 llvm::Value *HintInst = nullptr;
3228 if (Hint)
3229 HintInst =
3230 Builder.CreateIntCast(EmitScalarExpr(Hint), CGM.Int32Ty, false);
3231
3232 // TODO: Replace with a generic helper function for finalization
3233 auto FiniCB = [this](InsertPointTy IP) {
3234 CGBuilderTy::InsertPointGuard IPG(Builder);
3235 assert(IP.getBlock()->end() != IP.getPoint() &&
3236 "OpenMP IR Builder should cause terminated block!");
3237 llvm::BasicBlock *IPBB = IP.getBlock();
3238 llvm::BasicBlock *DestBB = IPBB->getUniqueSuccessor();
3239 assert(DestBB && "Finalization block should have one successor!");
3240
3241 // erase and replace with cleanup branch.
3242 IPBB->getTerminator()->eraseFromParent();
3243 Builder.SetInsertPoint(IPBB);
3244 CodeGenFunction::JumpDest Dest = getJumpDestInCurrentScope(DestBB);
3245 EmitBranchThroughCleanup(Dest);
3246 };
3247
3248 // TODO: Replace with a generic helper function for emitting body
3249 auto BodyGenCB = [CriticalRegionBodyStmt, this](InsertPointTy AllocaIP,
3250 InsertPointTy CodeGenIP,
3251 llvm::BasicBlock &FiniBB) {
3252 // Alloca insertion block should be in the entry block of the containing
3253 // function So it expects an empty AllocaIP in which case will reuse the
3254 // old alloca insertion point, or a new AllocaIP in the same block as the
3255 // old one
3256 assert((!AllocaIP.isSet() ||
3257 AllocaInsertPt->getParent() == AllocaIP.getBlock()) &&
3258 "Insertion point should be in the entry block of containing "
3259 "function!");
3260 auto OldAllocaIP = AllocaInsertPt;
3261 if (AllocaIP.isSet())
3262 AllocaInsertPt = &*AllocaIP.getPoint();
3263 auto OldReturnBlock = ReturnBlock;
3264 ReturnBlock = getJumpDestInCurrentScope(&FiniBB);
3265
3266 llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock();
3267 if (llvm::Instruction *CodeGenIPBBTI = CodeGenIPBB->getTerminator())
3268 CodeGenIPBBTI->eraseFromParent();
3269
3270 Builder.SetInsertPoint(CodeGenIPBB);
3271
3272 EmitStmt(CriticalRegionBodyStmt);
3273
3274 if (Builder.saveIP().isSet())
3275 Builder.CreateBr(&FiniBB);
3276
3277 AllocaInsertPt = OldAllocaIP;
3278 ReturnBlock = OldReturnBlock;
3279 };
3280
3281 CGCapturedStmtInfo CGSI(*CS, CR_OpenMP);
3282 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(*this, &CGSI);
3283 Builder.restoreIP(OMPBuilder->CreateCritical(
3284 Builder, BodyGenCB, FiniCB, S.getDirectiveName().getAsString(),
3285 HintInst));
3286
3287 return;
3288 }
3289
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003290 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
3291 Action.Enter(CGF);
Alexey Bataev475a7442018-01-12 19:39:11 +00003292 CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003293 };
Alexey Bataevddf3db92018-04-13 17:31:06 +00003294 const Expr *Hint = nullptr;
3295 if (const auto *HintClause = S.getSingleClause<OMPHintClause>())
Alexey Bataevfc57d162015-12-15 10:55:09 +00003296 Hint = HintClause->getHint();
Alexey Bataev475a7442018-01-12 19:39:11 +00003297 OMPLexicalScope Scope(*this, S, OMPD_unknown);
Alexey Bataevfc57d162015-12-15 10:55:09 +00003298 CGM.getOpenMPRuntime().emitCriticalRegion(*this,
3299 S.getDirectiveName().getAsString(),
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003300 CodeGen, S.getBeginLoc(), Hint);
Alexander Musmand9ed09f2014-07-21 09:42:05 +00003301}
3302
Alexey Bataev671605e2015-04-13 05:28:11 +00003303void CodeGenFunction::EmitOMPParallelForDirective(
3304 const OMPParallelForDirective &S) {
3305 // Emit directive as a combined directive that consists of two implicit
3306 // directives: 'parallel' with 'for' directive.
Alexey Bataevc99042b2018-03-15 18:10:54 +00003307 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
3308 Action.Enter(CGF);
Alexey Bataev957d8562016-11-17 15:12:05 +00003309 OMPCancelStackRAII CancelRegion(CGF, OMPD_parallel_for, S.hasCancel());
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003310 CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds,
3311 emitDispatchForLoopBounds);
Alexey Bataev671605e2015-04-13 05:28:11 +00003312 };
Alexey Bataev46978742020-01-30 10:46:11 -05003313 {
3314 auto LPCRegion =
3315 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
3316 emitCommonOMPParallelDirective(*this, S, OMPD_for, CodeGen,
3317 emitEmptyBoundParameters);
3318 }
3319 // Check for outer lastprivate conditional update.
3320 checkForLastprivateConditionalUpdate(*this, S);
Alexey Bataev4acb8592014-07-07 13:01:15 +00003321}
3322
Alexander Musmane4e893b2014-09-23 09:33:00 +00003323void CodeGenFunction::EmitOMPParallelForSimdDirective(
Alexey Bataev3b5b5c42015-06-18 10:10:12 +00003324 const OMPParallelForSimdDirective &S) {
3325 // Emit directive as a combined directive that consists of two implicit
3326 // directives: 'parallel' with 'for' directive.
Alexey Bataevc99042b2018-03-15 18:10:54 +00003327 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
3328 Action.Enter(CGF);
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003329 CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds,
3330 emitDispatchForLoopBounds);
Alexey Bataev3b5b5c42015-06-18 10:10:12 +00003331 };
Alexey Bataev46978742020-01-30 10:46:11 -05003332 {
3333 auto LPCRegion =
3334 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
3335 emitCommonOMPParallelDirective(*this, S, OMPD_simd, CodeGen,
3336 emitEmptyBoundParameters);
3337 }
3338 // Check for outer lastprivate conditional update.
3339 checkForLastprivateConditionalUpdate(*this, S);
Alexander Musmane4e893b2014-09-23 09:33:00 +00003340}
3341
cchen47d60942019-12-05 13:43:48 -05003342void CodeGenFunction::EmitOMPParallelMasterDirective(
3343 const OMPParallelMasterDirective &S) {
3344 // Emit directive as a combined directive that consists of two implicit
3345 // directives: 'parallel' with 'master' directive.
3346 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
3347 Action.Enter(CGF);
3348 OMPPrivateScope PrivateScope(CGF);
3349 bool Copyins = CGF.EmitOMPCopyinClause(S);
3350 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
3351 if (Copyins) {
3352 // Emit implicit barrier to synchronize threads and avoid data races on
3353 // propagation master's thread values of threadprivate variables to local
3354 // instances of that variables of all other implicit threads.
3355 CGF.CGM.getOpenMPRuntime().emitBarrierCall(
3356 CGF, S.getBeginLoc(), OMPD_unknown, /*EmitChecks=*/false,
3357 /*ForceSimpleCall=*/true);
3358 }
3359 CGF.EmitOMPPrivateClause(S, PrivateScope);
3360 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
3361 (void)PrivateScope.Privatize();
3362 emitMaster(CGF, S);
3363 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel);
3364 };
Alexey Bataev46978742020-01-30 10:46:11 -05003365 {
3366 auto LPCRegion =
3367 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
3368 emitCommonOMPParallelDirective(*this, S, OMPD_master, CodeGen,
3369 emitEmptyBoundParameters);
3370 emitPostUpdateForReductionClause(*this, S,
3371 [](CodeGenFunction &) { return nullptr; });
3372 }
3373 // Check for outer lastprivate conditional update.
3374 checkForLastprivateConditionalUpdate(*this, S);
cchen47d60942019-12-05 13:43:48 -05003375}
3376
Alexey Bataev84d0b3e2014-07-08 08:12:03 +00003377void CodeGenFunction::EmitOMPParallelSectionsDirective(
Alexey Bataev68adb7d2015-04-14 03:29:22 +00003378 const OMPParallelSectionsDirective &S) {
3379 // Emit directive as a combined directive that consists of two implicit
3380 // directives: 'parallel' with 'sections' directive.
Alexey Bataevc99042b2018-03-15 18:10:54 +00003381 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
3382 Action.Enter(CGF);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003383 CGF.EmitSections(S);
3384 };
Alexey Bataev46978742020-01-30 10:46:11 -05003385 {
3386 auto LPCRegion =
3387 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
3388 emitCommonOMPParallelDirective(*this, S, OMPD_sections, CodeGen,
3389 emitEmptyBoundParameters);
3390 }
3391 // Check for outer lastprivate conditional update.
3392 checkForLastprivateConditionalUpdate(*this, S);
Alexey Bataev84d0b3e2014-07-08 08:12:03 +00003393}
3394
Alexey Bataev475a7442018-01-12 19:39:11 +00003395void CodeGenFunction::EmitOMPTaskBasedDirective(
3396 const OMPExecutableDirective &S, const OpenMPDirectiveKind CapturedRegion,
3397 const RegionCodeGenTy &BodyGen, const TaskGenTy &TaskGen,
3398 OMPTaskDataTy &Data) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00003399 // Emit outlined function for task construct.
Alexey Bataev475a7442018-01-12 19:39:11 +00003400 const CapturedStmt *CS = S.getCapturedStmt(CapturedRegion);
Alexey Bataevddf3db92018-04-13 17:31:06 +00003401 auto I = CS->getCapturedDecl()->param_begin();
3402 auto PartId = std::next(I);
3403 auto TaskT = std::next(I, 4);
Alexey Bataev24b5bae2016-04-28 09:23:51 +00003404 // Check if the task is final
3405 if (const auto *Clause = S.getSingleClause<OMPFinalClause>()) {
3406 // If the condition constant folds and can be elided, try to avoid emitting
3407 // the condition and the dead arm of the if/else.
Alexey Bataevddf3db92018-04-13 17:31:06 +00003408 const Expr *Cond = Clause->getCondition();
Alexey Bataev24b5bae2016-04-28 09:23:51 +00003409 bool CondConstant;
3410 if (ConstantFoldsToSimpleInteger(Cond, CondConstant))
3411 Data.Final.setInt(CondConstant);
3412 else
3413 Data.Final.setPointer(EvaluateExprAsBool(Cond));
3414 } else {
3415 // By default the task is not final.
3416 Data.Final.setInt(/*IntVal=*/false);
3417 }
Alexey Bataev1e1e2862016-05-10 12:21:02 +00003418 // Check if the task has 'priority' clause.
3419 if (const auto *Clause = S.getSingleClause<OMPPriorityClause>()) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00003420 const Expr *Prio = Clause->getPriority();
Alexey Bataev5140e742016-07-19 04:21:09 +00003421 Data.Priority.setInt(/*IntVal=*/true);
Alexey Bataevad537bb2016-05-30 09:06:50 +00003422 Data.Priority.setPointer(EmitScalarConversion(
3423 EmitScalarExpr(Prio), Prio->getType(),
3424 getContext().getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1),
3425 Prio->getExprLoc()));
Alexey Bataev1e1e2862016-05-10 12:21:02 +00003426 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00003427 // The first function argument for tasks is a thread id, the second one is a
3428 // part id (0 for tied tasks, >=0 for untied task).
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003429 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
3430 // Get list of private variables.
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00003431 for (const auto *C : S.getClausesOfKind<OMPPrivateClause>()) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003432 auto IRef = C->varlist_begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00003433 for (const Expr *IInit : C->private_copies()) {
3434 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003435 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
Alexey Bataev7292c292016-04-25 12:22:29 +00003436 Data.PrivateVars.push_back(*IRef);
3437 Data.PrivateCopies.push_back(IInit);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003438 }
3439 ++IRef;
3440 }
3441 }
3442 EmittedAsPrivate.clear();
3443 // Get list of firstprivate variables.
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00003444 for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003445 auto IRef = C->varlist_begin();
3446 auto IElemInitRef = C->inits().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00003447 for (const Expr *IInit : C->private_copies()) {
3448 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003449 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
Alexey Bataev7292c292016-04-25 12:22:29 +00003450 Data.FirstprivateVars.push_back(*IRef);
3451 Data.FirstprivateCopies.push_back(IInit);
3452 Data.FirstprivateInits.push_back(*IElemInitRef);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003453 }
Richard Trieucc3949d2016-02-18 22:34:54 +00003454 ++IRef;
3455 ++IElemInitRef;
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003456 }
3457 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00003458 // Get list of lastprivate variables (for taskloops).
3459 llvm::DenseMap<const VarDecl *, const DeclRefExpr *> LastprivateDstsOrigs;
3460 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) {
3461 auto IRef = C->varlist_begin();
3462 auto ID = C->destination_exprs().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00003463 for (const Expr *IInit : C->private_copies()) {
3464 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
Alexey Bataevf93095a2016-05-05 08:46:22 +00003465 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
3466 Data.LastprivateVars.push_back(*IRef);
3467 Data.LastprivateCopies.push_back(IInit);
3468 }
3469 LastprivateDstsOrigs.insert(
3470 {cast<VarDecl>(cast<DeclRefExpr>(*ID)->getDecl()),
3471 cast<DeclRefExpr>(*IRef)});
3472 ++IRef;
3473 ++ID;
3474 }
3475 }
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003476 SmallVector<const Expr *, 4> LHSs;
3477 SmallVector<const Expr *, 4> RHSs;
3478 for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) {
3479 auto IPriv = C->privates().begin();
3480 auto IRed = C->reduction_ops().begin();
3481 auto ILHS = C->lhs_exprs().begin();
3482 auto IRHS = C->rhs_exprs().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00003483 for (const Expr *Ref : C->varlists()) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003484 Data.ReductionVars.emplace_back(Ref);
3485 Data.ReductionCopies.emplace_back(*IPriv);
3486 Data.ReductionOps.emplace_back(*IRed);
3487 LHSs.emplace_back(*ILHS);
3488 RHSs.emplace_back(*IRHS);
3489 std::advance(IPriv, 1);
3490 std::advance(IRed, 1);
3491 std::advance(ILHS, 1);
3492 std::advance(IRHS, 1);
3493 }
3494 }
3495 Data.Reductions = CGM.getOpenMPRuntime().emitTaskReductionInit(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003496 *this, S.getBeginLoc(), LHSs, RHSs, Data);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003497 // Build list of dependences.
Alexey Bataev7292c292016-04-25 12:22:29 +00003498 for (const auto *C : S.getClausesOfKind<OMPDependClause>())
Alexey Bataevddf3db92018-04-13 17:31:06 +00003499 for (const Expr *IRef : C->varlists())
Alexey Bataev43a919f2018-04-13 17:48:43 +00003500 Data.Dependences.emplace_back(C->getDependencyKind(), IRef);
Alexey Bataev475a7442018-01-12 19:39:11 +00003501 auto &&CodeGen = [&Data, &S, CS, &BodyGen, &LastprivateDstsOrigs,
3502 CapturedRegion](CodeGenFunction &CGF,
3503 PrePostActionTy &Action) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003504 // Set proper addresses for generated private copies.
Alexey Bataev7292c292016-04-25 12:22:29 +00003505 OMPPrivateScope Scope(CGF);
Alexey Bataevf93095a2016-05-05 08:46:22 +00003506 if (!Data.PrivateVars.empty() || !Data.FirstprivateVars.empty() ||
3507 !Data.LastprivateVars.empty()) {
James Y Knight9871db02019-02-05 16:42:33 +00003508 llvm::FunctionType *CopyFnTy = llvm::FunctionType::get(
3509 CGF.Builder.getVoidTy(), {CGF.Builder.getInt8PtrTy()}, true);
Alexey Bataev3c595a62017-08-14 15:01:03 +00003510 enum { PrivatesParam = 2, CopyFnParam = 3 };
Alexey Bataevddf3db92018-04-13 17:31:06 +00003511 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
3512 CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(CopyFnParam)));
3513 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
3514 CS->getCapturedDecl()->getParam(PrivatesParam)));
Alexey Bataev48591dd2016-04-20 04:01:36 +00003515 // Map privates.
3516 llvm::SmallVector<std::pair<const VarDecl *, Address>, 16> PrivatePtrs;
3517 llvm::SmallVector<llvm::Value *, 16> CallArgs;
3518 CallArgs.push_back(PrivatesPtr);
Alexey Bataevddf3db92018-04-13 17:31:06 +00003519 for (const Expr *E : Data.PrivateVars) {
3520 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev48591dd2016-04-20 04:01:36 +00003521 Address PrivatePtr = CGF.CreateMemTemp(
3522 CGF.getContext().getPointerType(E->getType()), ".priv.ptr.addr");
Alexey Bataevddf3db92018-04-13 17:31:06 +00003523 PrivatePtrs.emplace_back(VD, PrivatePtr);
Alexey Bataev48591dd2016-04-20 04:01:36 +00003524 CallArgs.push_back(PrivatePtr.getPointer());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003525 }
Alexey Bataevddf3db92018-04-13 17:31:06 +00003526 for (const Expr *E : Data.FirstprivateVars) {
3527 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev48591dd2016-04-20 04:01:36 +00003528 Address PrivatePtr =
3529 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()),
3530 ".firstpriv.ptr.addr");
Alexey Bataevddf3db92018-04-13 17:31:06 +00003531 PrivatePtrs.emplace_back(VD, PrivatePtr);
Alexey Bataev48591dd2016-04-20 04:01:36 +00003532 CallArgs.push_back(PrivatePtr.getPointer());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003533 }
Alexey Bataevddf3db92018-04-13 17:31:06 +00003534 for (const Expr *E : Data.LastprivateVars) {
3535 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataevf93095a2016-05-05 08:46:22 +00003536 Address PrivatePtr =
3537 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()),
3538 ".lastpriv.ptr.addr");
Alexey Bataevddf3db92018-04-13 17:31:06 +00003539 PrivatePtrs.emplace_back(VD, PrivatePtr);
Alexey Bataevf93095a2016-05-05 08:46:22 +00003540 CallArgs.push_back(PrivatePtr.getPointer());
3541 }
James Y Knight9871db02019-02-05 16:42:33 +00003542 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
3543 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
Alexey Bataevddf3db92018-04-13 17:31:06 +00003544 for (const auto &Pair : LastprivateDstsOrigs) {
3545 const auto *OrigVD = cast<VarDecl>(Pair.second->getDecl());
Bruno Ricci5fc4db72018-12-21 14:10:18 +00003546 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(OrigVD),
3547 /*RefersToEnclosingVariableOrCapture=*/
3548 CGF.CapturedStmtInfo->lookup(OrigVD) != nullptr,
3549 Pair.second->getType(), VK_LValue,
3550 Pair.second->getExprLoc());
Alexey Bataevf93095a2016-05-05 08:46:22 +00003551 Scope.addPrivate(Pair.first, [&CGF, &DRE]() {
Akira Hatanakaf139ae32019-12-03 15:17:01 -08003552 return CGF.EmitLValue(&DRE).getAddress(CGF);
Alexey Bataevf93095a2016-05-05 08:46:22 +00003553 });
3554 }
Alexey Bataevddf3db92018-04-13 17:31:06 +00003555 for (const auto &Pair : PrivatePtrs) {
Alexey Bataev48591dd2016-04-20 04:01:36 +00003556 Address Replacement(CGF.Builder.CreateLoad(Pair.second),
3557 CGF.getContext().getDeclAlign(Pair.first));
3558 Scope.addPrivate(Pair.first, [Replacement]() { return Replacement; });
3559 }
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003560 }
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003561 if (Data.Reductions) {
Alexey Bataev475a7442018-01-12 19:39:11 +00003562 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003563 ReductionCodeGen RedCG(Data.ReductionVars, Data.ReductionCopies,
3564 Data.ReductionOps);
3565 llvm::Value *ReductionsPtr = CGF.Builder.CreateLoad(
3566 CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(9)));
3567 for (unsigned Cnt = 0, E = Data.ReductionVars.size(); Cnt < E; ++Cnt) {
3568 RedCG.emitSharedLValue(CGF, Cnt);
3569 RedCG.emitAggregateType(CGF, Cnt);
Alexey Bataev2e0cbe502018-03-08 15:24:08 +00003570 // FIXME: This must removed once the runtime library is fixed.
3571 // Emit required threadprivate variables for
Raphael Isemannb23ccec2018-12-10 12:37:46 +00003572 // initializer/combiner/finalizer.
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003573 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
Alexey Bataev2e0cbe502018-03-08 15:24:08 +00003574 RedCG, Cnt);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003575 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003576 CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003577 Replacement =
3578 Address(CGF.EmitScalarConversion(
3579 Replacement.getPointer(), CGF.getContext().VoidPtrTy,
3580 CGF.getContext().getPointerType(
3581 Data.ReductionCopies[Cnt]->getType()),
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00003582 Data.ReductionCopies[Cnt]->getExprLoc()),
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003583 Replacement.getAlignment());
3584 Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement);
3585 Scope.addPrivate(RedCG.getBaseDecl(Cnt),
3586 [Replacement]() { return Replacement; });
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003587 }
3588 }
Alexey Bataev88202be2017-07-27 13:20:36 +00003589 // Privatize all private variables except for in_reduction items.
Alexey Bataev48591dd2016-04-20 04:01:36 +00003590 (void)Scope.Privatize();
Alexey Bataev88202be2017-07-27 13:20:36 +00003591 SmallVector<const Expr *, 4> InRedVars;
3592 SmallVector<const Expr *, 4> InRedPrivs;
3593 SmallVector<const Expr *, 4> InRedOps;
3594 SmallVector<const Expr *, 4> TaskgroupDescriptors;
3595 for (const auto *C : S.getClausesOfKind<OMPInReductionClause>()) {
3596 auto IPriv = C->privates().begin();
3597 auto IRed = C->reduction_ops().begin();
3598 auto ITD = C->taskgroup_descriptors().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00003599 for (const Expr *Ref : C->varlists()) {
Alexey Bataev88202be2017-07-27 13:20:36 +00003600 InRedVars.emplace_back(Ref);
3601 InRedPrivs.emplace_back(*IPriv);
3602 InRedOps.emplace_back(*IRed);
3603 TaskgroupDescriptors.emplace_back(*ITD);
3604 std::advance(IPriv, 1);
3605 std::advance(IRed, 1);
3606 std::advance(ITD, 1);
3607 }
3608 }
3609 // Privatize in_reduction items here, because taskgroup descriptors must be
3610 // privatized earlier.
3611 OMPPrivateScope InRedScope(CGF);
3612 if (!InRedVars.empty()) {
3613 ReductionCodeGen RedCG(InRedVars, InRedPrivs, InRedOps);
3614 for (unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) {
3615 RedCG.emitSharedLValue(CGF, Cnt);
3616 RedCG.emitAggregateType(CGF, Cnt);
3617 // The taskgroup descriptor variable is always implicit firstprivate and
Raphael Isemannb23ccec2018-12-10 12:37:46 +00003618 // privatized already during processing of the firstprivates.
Alexey Bataev2e0cbe502018-03-08 15:24:08 +00003619 // FIXME: This must removed once the runtime library is fixed.
3620 // Emit required threadprivate variables for
Raphael Isemannb23ccec2018-12-10 12:37:46 +00003621 // initializer/combiner/finalizer.
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003622 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
Alexey Bataev2e0cbe502018-03-08 15:24:08 +00003623 RedCG, Cnt);
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00003624 llvm::Value *ReductionsPtr =
3625 CGF.EmitLoadOfScalar(CGF.EmitLValue(TaskgroupDescriptors[Cnt]),
3626 TaskgroupDescriptors[Cnt]->getExprLoc());
Alexey Bataev88202be2017-07-27 13:20:36 +00003627 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003628 CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt));
Alexey Bataev88202be2017-07-27 13:20:36 +00003629 Replacement = Address(
3630 CGF.EmitScalarConversion(
3631 Replacement.getPointer(), CGF.getContext().VoidPtrTy,
3632 CGF.getContext().getPointerType(InRedPrivs[Cnt]->getType()),
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00003633 InRedPrivs[Cnt]->getExprLoc()),
Alexey Bataev88202be2017-07-27 13:20:36 +00003634 Replacement.getAlignment());
3635 Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement);
3636 InRedScope.addPrivate(RedCG.getBaseDecl(Cnt),
3637 [Replacement]() { return Replacement; });
Alexey Bataev88202be2017-07-27 13:20:36 +00003638 }
3639 }
3640 (void)InRedScope.Privatize();
Alexey Bataev48591dd2016-04-20 04:01:36 +00003641
3642 Action.Enter(CGF);
Alexey Bataev7292c292016-04-25 12:22:29 +00003643 BodyGen(CGF);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003644 };
James Y Knight9871db02019-02-05 16:42:33 +00003645 llvm::Function *OutlinedFn = CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
Alexey Bataev7292c292016-04-25 12:22:29 +00003646 S, *I, *PartId, *TaskT, S.getDirectiveKind(), CodeGen, Data.Tied,
3647 Data.NumberOfParts);
Alexey Bataev5bbcead2019-10-14 17:17:41 +00003648 OMPLexicalScope Scope(*this, S, llvm::None,
Alexey Bataev61205822019-12-04 09:50:21 -05003649 !isOpenMPParallelDirective(S.getDirectiveKind()) &&
3650 !isOpenMPSimdDirective(S.getDirectiveKind()));
Alexey Bataev7292c292016-04-25 12:22:29 +00003651 TaskGen(*this, OutlinedFn, Data);
3652}
3653
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003654static ImplicitParamDecl *
3655createImplicitFirstprivateForType(ASTContext &C, OMPTaskDataTy &Data,
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00003656 QualType Ty, CapturedDecl *CD,
3657 SourceLocation Loc) {
3658 auto *OrigVD = ImplicitParamDecl::Create(C, CD, Loc, /*Id=*/nullptr, Ty,
3659 ImplicitParamDecl::Other);
3660 auto *OrigRef = DeclRefExpr::Create(
3661 C, NestedNameSpecifierLoc(), SourceLocation(), OrigVD,
3662 /*RefersToEnclosingVariableOrCapture=*/false, Loc, Ty, VK_LValue);
3663 auto *PrivateVD = ImplicitParamDecl::Create(C, CD, Loc, /*Id=*/nullptr, Ty,
3664 ImplicitParamDecl::Other);
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003665 auto *PrivateRef = DeclRefExpr::Create(
3666 C, NestedNameSpecifierLoc(), SourceLocation(), PrivateVD,
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00003667 /*RefersToEnclosingVariableOrCapture=*/false, Loc, Ty, VK_LValue);
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003668 QualType ElemType = C.getBaseElementType(Ty);
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00003669 auto *InitVD = ImplicitParamDecl::Create(C, CD, Loc, /*Id=*/nullptr, ElemType,
3670 ImplicitParamDecl::Other);
3671 auto *InitRef = DeclRefExpr::Create(
3672 C, NestedNameSpecifierLoc(), SourceLocation(), InitVD,
3673 /*RefersToEnclosingVariableOrCapture=*/false, Loc, ElemType, VK_LValue);
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003674 PrivateVD->setInitStyle(VarDecl::CInit);
3675 PrivateVD->setInit(ImplicitCastExpr::Create(C, ElemType, CK_LValueToRValue,
3676 InitRef, /*BasePath=*/nullptr,
3677 VK_RValue));
3678 Data.FirstprivateVars.emplace_back(OrigRef);
3679 Data.FirstprivateCopies.emplace_back(PrivateRef);
3680 Data.FirstprivateInits.emplace_back(InitRef);
3681 return OrigVD;
3682}
3683
3684void CodeGenFunction::EmitOMPTargetTaskBasedDirective(
3685 const OMPExecutableDirective &S, const RegionCodeGenTy &BodyGen,
3686 OMPTargetDataInfo &InputInfo) {
3687 // Emit outlined function for task construct.
Alexey Bataevddf3db92018-04-13 17:31:06 +00003688 const CapturedStmt *CS = S.getCapturedStmt(OMPD_task);
3689 Address CapturedStruct = GenerateCapturedStmtArgument(*CS);
3690 QualType SharedsTy = getContext().getRecordType(CS->getCapturedRecordDecl());
3691 auto I = CS->getCapturedDecl()->param_begin();
3692 auto PartId = std::next(I);
3693 auto TaskT = std::next(I, 4);
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003694 OMPTaskDataTy Data;
3695 // The task is not final.
3696 Data.Final.setInt(/*IntVal=*/false);
3697 // Get list of firstprivate variables.
3698 for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) {
3699 auto IRef = C->varlist_begin();
3700 auto IElemInitRef = C->inits().begin();
3701 for (auto *IInit : C->private_copies()) {
3702 Data.FirstprivateVars.push_back(*IRef);
3703 Data.FirstprivateCopies.push_back(IInit);
3704 Data.FirstprivateInits.push_back(*IElemInitRef);
3705 ++IRef;
3706 ++IElemInitRef;
3707 }
3708 }
3709 OMPPrivateScope TargetScope(*this);
3710 VarDecl *BPVD = nullptr;
3711 VarDecl *PVD = nullptr;
3712 VarDecl *SVD = nullptr;
3713 if (InputInfo.NumberOfTargetItems > 0) {
3714 auto *CD = CapturedDecl::Create(
3715 getContext(), getContext().getTranslationUnitDecl(), /*NumParams=*/0);
3716 llvm::APInt ArrSize(/*numBits=*/32, InputInfo.NumberOfTargetItems);
3717 QualType BaseAndPointersType = getContext().getConstantArrayType(
Richard Smith772e2662019-10-04 01:25:59 +00003718 getContext().VoidPtrTy, ArrSize, nullptr, ArrayType::Normal,
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003719 /*IndexTypeQuals=*/0);
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00003720 BPVD = createImplicitFirstprivateForType(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003721 getContext(), Data, BaseAndPointersType, CD, S.getBeginLoc());
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00003722 PVD = createImplicitFirstprivateForType(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003723 getContext(), Data, BaseAndPointersType, CD, S.getBeginLoc());
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003724 QualType SizesType = getContext().getConstantArrayType(
Alexey Bataeva90fc662019-06-25 16:00:43 +00003725 getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1),
Richard Smith772e2662019-10-04 01:25:59 +00003726 ArrSize, nullptr, ArrayType::Normal,
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003727 /*IndexTypeQuals=*/0);
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00003728 SVD = createImplicitFirstprivateForType(getContext(), Data, SizesType, CD,
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003729 S.getBeginLoc());
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003730 TargetScope.addPrivate(
3731 BPVD, [&InputInfo]() { return InputInfo.BasePointersArray; });
3732 TargetScope.addPrivate(PVD,
3733 [&InputInfo]() { return InputInfo.PointersArray; });
3734 TargetScope.addPrivate(SVD,
3735 [&InputInfo]() { return InputInfo.SizesArray; });
3736 }
3737 (void)TargetScope.Privatize();
3738 // Build list of dependences.
3739 for (const auto *C : S.getClausesOfKind<OMPDependClause>())
Alexey Bataevddf3db92018-04-13 17:31:06 +00003740 for (const Expr *IRef : C->varlists())
Alexey Bataev43a919f2018-04-13 17:48:43 +00003741 Data.Dependences.emplace_back(C->getDependencyKind(), IRef);
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003742 auto &&CodeGen = [&Data, &S, CS, &BodyGen, BPVD, PVD, SVD,
3743 &InputInfo](CodeGenFunction &CGF, PrePostActionTy &Action) {
3744 // Set proper addresses for generated private copies.
3745 OMPPrivateScope Scope(CGF);
3746 if (!Data.FirstprivateVars.empty()) {
James Y Knight9871db02019-02-05 16:42:33 +00003747 llvm::FunctionType *CopyFnTy = llvm::FunctionType::get(
3748 CGF.Builder.getVoidTy(), {CGF.Builder.getInt8PtrTy()}, true);
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003749 enum { PrivatesParam = 2, CopyFnParam = 3 };
Alexey Bataevddf3db92018-04-13 17:31:06 +00003750 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
3751 CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(CopyFnParam)));
3752 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
3753 CS->getCapturedDecl()->getParam(PrivatesParam)));
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003754 // Map privates.
3755 llvm::SmallVector<std::pair<const VarDecl *, Address>, 16> PrivatePtrs;
3756 llvm::SmallVector<llvm::Value *, 16> CallArgs;
3757 CallArgs.push_back(PrivatesPtr);
Alexey Bataevddf3db92018-04-13 17:31:06 +00003758 for (const Expr *E : Data.FirstprivateVars) {
3759 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003760 Address PrivatePtr =
3761 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()),
3762 ".firstpriv.ptr.addr");
Alexey Bataevddf3db92018-04-13 17:31:06 +00003763 PrivatePtrs.emplace_back(VD, PrivatePtr);
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003764 CallArgs.push_back(PrivatePtr.getPointer());
3765 }
James Y Knight9871db02019-02-05 16:42:33 +00003766 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
3767 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
Alexey Bataevddf3db92018-04-13 17:31:06 +00003768 for (const auto &Pair : PrivatePtrs) {
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003769 Address Replacement(CGF.Builder.CreateLoad(Pair.second),
3770 CGF.getContext().getDeclAlign(Pair.first));
3771 Scope.addPrivate(Pair.first, [Replacement]() { return Replacement; });
3772 }
3773 }
3774 // Privatize all private variables except for in_reduction items.
3775 (void)Scope.Privatize();
Alexey Bataev8451efa2018-01-15 19:06:12 +00003776 if (InputInfo.NumberOfTargetItems > 0) {
3777 InputInfo.BasePointersArray = CGF.Builder.CreateConstArrayGEP(
James Y Knight751fe282019-02-09 22:22:28 +00003778 CGF.GetAddrOfLocalVar(BPVD), /*Index=*/0);
Alexey Bataev8451efa2018-01-15 19:06:12 +00003779 InputInfo.PointersArray = CGF.Builder.CreateConstArrayGEP(
James Y Knight751fe282019-02-09 22:22:28 +00003780 CGF.GetAddrOfLocalVar(PVD), /*Index=*/0);
Alexey Bataev8451efa2018-01-15 19:06:12 +00003781 InputInfo.SizesArray = CGF.Builder.CreateConstArrayGEP(
James Y Knight751fe282019-02-09 22:22:28 +00003782 CGF.GetAddrOfLocalVar(SVD), /*Index=*/0);
Alexey Bataev8451efa2018-01-15 19:06:12 +00003783 }
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003784
3785 Action.Enter(CGF);
Alexey Bataev475a7442018-01-12 19:39:11 +00003786 OMPLexicalScope LexScope(CGF, S, OMPD_task, /*EmitPreInitStmt=*/false);
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003787 BodyGen(CGF);
3788 };
James Y Knight9871db02019-02-05 16:42:33 +00003789 llvm::Function *OutlinedFn = CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003790 S, *I, *PartId, *TaskT, S.getDirectiveKind(), CodeGen, /*Tied=*/true,
3791 Data.NumberOfParts);
3792 llvm::APInt TrueOrFalse(32, S.hasClausesOfKind<OMPNowaitClause>() ? 1 : 0);
3793 IntegerLiteral IfCond(getContext(), TrueOrFalse,
3794 getContext().getIntTypeForBitwidth(32, /*Signed=*/0),
3795 SourceLocation());
3796
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003797 CGM.getOpenMPRuntime().emitTaskCall(*this, S.getBeginLoc(), S, OutlinedFn,
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003798 SharedsTy, CapturedStruct, &IfCond, Data);
3799}
3800
Alexey Bataev7292c292016-04-25 12:22:29 +00003801void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &S) {
3802 // Emit outlined function for task construct.
Alexey Bataev475a7442018-01-12 19:39:11 +00003803 const CapturedStmt *CS = S.getCapturedStmt(OMPD_task);
Alexey Bataevddf3db92018-04-13 17:31:06 +00003804 Address CapturedStruct = GenerateCapturedStmtArgument(*CS);
3805 QualType SharedsTy = getContext().getRecordType(CS->getCapturedRecordDecl());
Alexey Bataev1d677132015-04-22 13:57:31 +00003806 const Expr *IfCond = nullptr;
Alexey Bataev7371aa32015-09-03 08:45:56 +00003807 for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
3808 if (C->getNameModifier() == OMPD_unknown ||
3809 C->getNameModifier() == OMPD_task) {
3810 IfCond = C->getCondition();
3811 break;
3812 }
Alexey Bataev1d677132015-04-22 13:57:31 +00003813 }
Alexey Bataev7292c292016-04-25 12:22:29 +00003814
Alexey Bataev24b5bae2016-04-28 09:23:51 +00003815 OMPTaskDataTy Data;
3816 // Check if we should emit tied or untied task.
3817 Data.Tied = !S.getSingleClause<OMPUntiedClause>();
Alexey Bataev7292c292016-04-25 12:22:29 +00003818 auto &&BodyGen = [CS](CodeGenFunction &CGF, PrePostActionTy &) {
3819 CGF.EmitStmt(CS->getCapturedStmt());
3820 };
Alexey Bataev24b5bae2016-04-28 09:23:51 +00003821 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
James Y Knight9871db02019-02-05 16:42:33 +00003822 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00003823 const OMPTaskDataTy &Data) {
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003824 CGF.CGM.getOpenMPRuntime().emitTaskCall(CGF, S.getBeginLoc(), S, OutlinedFn,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00003825 SharedsTy, CapturedStruct, IfCond,
3826 Data);
Alexey Bataev7292c292016-04-25 12:22:29 +00003827 };
Alexey Bataev46978742020-01-30 10:46:11 -05003828 auto LPCRegion =
3829 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
Alexey Bataev475a7442018-01-12 19:39:11 +00003830 EmitOMPTaskBasedDirective(S, OMPD_task, BodyGen, TaskGen, Data);
Alexey Bataev9c2e8ee2014-07-11 11:25:16 +00003831}
3832
Alexey Bataev9f797f32015-02-05 05:57:51 +00003833void CodeGenFunction::EmitOMPTaskyieldDirective(
3834 const OMPTaskyieldDirective &S) {
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003835 CGM.getOpenMPRuntime().emitTaskyieldCall(*this, S.getBeginLoc());
Alexey Bataev68446b72014-07-18 07:47:19 +00003836}
3837
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00003838void CodeGenFunction::EmitOMPBarrierDirective(const OMPBarrierDirective &S) {
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003839 CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(), OMPD_barrier);
Alexey Bataev4d1dfea2014-07-18 09:11:51 +00003840}
3841
Alexey Bataev8b8e2022015-04-27 05:22:09 +00003842void CodeGenFunction::EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S) {
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003843 CGM.getOpenMPRuntime().emitTaskwaitCall(*this, S.getBeginLoc());
Alexey Bataev2df347a2014-07-18 10:17:07 +00003844}
3845
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00003846void CodeGenFunction::EmitOMPTaskgroupDirective(
3847 const OMPTaskgroupDirective &S) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003848 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
3849 Action.Enter(CGF);
Alexey Bataev3b1b8952017-07-25 15:53:26 +00003850 if (const Expr *E = S.getReductionRef()) {
3851 SmallVector<const Expr *, 4> LHSs;
3852 SmallVector<const Expr *, 4> RHSs;
3853 OMPTaskDataTy Data;
3854 for (const auto *C : S.getClausesOfKind<OMPTaskReductionClause>()) {
3855 auto IPriv = C->privates().begin();
3856 auto IRed = C->reduction_ops().begin();
3857 auto ILHS = C->lhs_exprs().begin();
3858 auto IRHS = C->rhs_exprs().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00003859 for (const Expr *Ref : C->varlists()) {
Alexey Bataev3b1b8952017-07-25 15:53:26 +00003860 Data.ReductionVars.emplace_back(Ref);
3861 Data.ReductionCopies.emplace_back(*IPriv);
3862 Data.ReductionOps.emplace_back(*IRed);
3863 LHSs.emplace_back(*ILHS);
3864 RHSs.emplace_back(*IRHS);
3865 std::advance(IPriv, 1);
3866 std::advance(IRed, 1);
3867 std::advance(ILHS, 1);
3868 std::advance(IRHS, 1);
3869 }
3870 }
3871 llvm::Value *ReductionDesc =
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003872 CGF.CGM.getOpenMPRuntime().emitTaskReductionInit(CGF, S.getBeginLoc(),
Alexey Bataev3b1b8952017-07-25 15:53:26 +00003873 LHSs, RHSs, Data);
3874 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3875 CGF.EmitVarDecl(*VD);
3876 CGF.EmitStoreOfScalar(ReductionDesc, CGF.GetAddrOfLocalVar(VD),
3877 /*Volatile=*/false, E->getType());
3878 }
Alexey Bataev475a7442018-01-12 19:39:11 +00003879 CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00003880 };
Alexey Bataev475a7442018-01-12 19:39:11 +00003881 OMPLexicalScope Scope(*this, S, OMPD_unknown);
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003882 CGM.getOpenMPRuntime().emitTaskgroupRegion(*this, CodeGen, S.getBeginLoc());
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00003883}
3884
Alexey Bataevcc37cc12014-11-20 04:34:54 +00003885void CodeGenFunction::EmitOMPFlushDirective(const OMPFlushDirective &S) {
Alexey Bataeve8e05de2020-02-07 12:22:23 -05003886 llvm::AtomicOrdering AO = S.getSingleClause<OMPFlushClause>()
3887 ? llvm::AtomicOrdering::NotAtomic
3888 : llvm::AtomicOrdering::AcquireRelease;
Alexey Bataevddf3db92018-04-13 17:31:06 +00003889 CGM.getOpenMPRuntime().emitFlush(
3890 *this,
3891 [&S]() -> ArrayRef<const Expr *> {
3892 if (const auto *FlushClause = S.getSingleClause<OMPFlushClause>())
3893 return llvm::makeArrayRef(FlushClause->varlist_begin(),
3894 FlushClause->varlist_end());
3895 return llvm::None;
3896 }(),
Alexey Bataeve8e05de2020-02-07 12:22:23 -05003897 S.getBeginLoc(), AO);
Alexey Bataev6125da92014-07-21 11:26:11 +00003898}
3899
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003900void CodeGenFunction::EmitOMPDistributeLoop(const OMPLoopDirective &S,
3901 const CodeGenLoopTy &CodeGenLoop,
3902 Expr *IncExpr) {
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003903 // Emit the loop iteration variable.
Alexey Bataevddf3db92018-04-13 17:31:06 +00003904 const auto *IVExpr = cast<DeclRefExpr>(S.getIterationVariable());
3905 const auto *IVDecl = cast<VarDecl>(IVExpr->getDecl());
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003906 EmitVarDecl(*IVDecl);
3907
3908 // Emit the iterations count variable.
3909 // If it is not a variable, Sema decided to calculate iterations count on each
3910 // iteration (e.g., it is foldable into a constant).
Alexey Bataevddf3db92018-04-13 17:31:06 +00003911 if (const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003912 EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
3913 // Emit calculation of the iterations count.
3914 EmitIgnoredExpr(S.getCalcLastIteration());
3915 }
3916
Alexey Bataevddf3db92018-04-13 17:31:06 +00003917 CGOpenMPRuntime &RT = CGM.getOpenMPRuntime();
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003918
Carlo Bertolli962bb802017-01-03 18:24:42 +00003919 bool HasLastprivateClause = false;
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003920 // Check pre-condition.
3921 {
Alexey Bataev5a3af132016-03-29 08:58:54 +00003922 OMPLoopScope PreInitScope(*this, S);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003923 // Skip the entire loop if we don't meet the precondition.
3924 // If the condition constant folds and can be elided, avoid emitting the
3925 // whole loop.
3926 bool CondConstant;
3927 llvm::BasicBlock *ContBlock = nullptr;
3928 if (ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
3929 if (!CondConstant)
3930 return;
3931 } else {
Alexey Bataevddf3db92018-04-13 17:31:06 +00003932 llvm::BasicBlock *ThenBlock = createBasicBlock("omp.precond.then");
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003933 ContBlock = createBasicBlock("omp.precond.end");
3934 emitPreCond(*this, S, S.getPreCond(), ThenBlock, ContBlock,
3935 getProfileCount(&S));
3936 EmitBlock(ThenBlock);
3937 incrementProfileCounter(&S);
3938 }
3939
Alexey Bataev617db5f2017-12-04 15:38:33 +00003940 emitAlignedClause(*this, S);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003941 // Emit 'then' code.
3942 {
3943 // Emit helper vars inits.
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003944
3945 LValue LB = EmitOMPHelperVar(
3946 *this, cast<DeclRefExpr>(
3947 (isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
3948 ? S.getCombinedLowerBoundVariable()
3949 : S.getLowerBoundVariable())));
3950 LValue UB = EmitOMPHelperVar(
3951 *this, cast<DeclRefExpr>(
3952 (isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
3953 ? S.getCombinedUpperBoundVariable()
3954 : S.getUpperBoundVariable())));
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003955 LValue ST =
3956 EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getStrideVariable()));
3957 LValue IL =
3958 EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getIsLastIterVariable()));
3959
3960 OMPPrivateScope LoopScope(*this);
Carlo Bertolli962bb802017-01-03 18:24:42 +00003961 if (EmitOMPFirstprivateClause(S, LoopScope)) {
Alexey Bataev617db5f2017-12-04 15:38:33 +00003962 // Emit implicit barrier to synchronize threads and avoid data races
3963 // on initialization of firstprivate variables and post-update of
Carlo Bertolli962bb802017-01-03 18:24:42 +00003964 // lastprivate variables.
3965 CGM.getOpenMPRuntime().emitBarrierCall(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003966 *this, S.getBeginLoc(), OMPD_unknown, /*EmitChecks=*/false,
Alexey Bataev617db5f2017-12-04 15:38:33 +00003967 /*ForceSimpleCall=*/true);
Carlo Bertolli962bb802017-01-03 18:24:42 +00003968 }
3969 EmitOMPPrivateClause(S, LoopScope);
Alexey Bataev617db5f2017-12-04 15:38:33 +00003970 if (isOpenMPSimdDirective(S.getDirectiveKind()) &&
Alexey Bataev999277a2017-12-06 14:31:09 +00003971 !isOpenMPParallelDirective(S.getDirectiveKind()) &&
3972 !isOpenMPTeamsDirective(S.getDirectiveKind()))
Alexey Bataev617db5f2017-12-04 15:38:33 +00003973 EmitOMPReductionClauseInit(S, LoopScope);
Carlo Bertolli962bb802017-01-03 18:24:42 +00003974 HasLastprivateClause = EmitOMPLastprivateClauseInit(S, LoopScope);
Alexey Bataev5dff95c2016-04-22 03:56:56 +00003975 EmitOMPPrivateLoopCounters(S, LoopScope);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003976 (void)LoopScope.Privatize();
Alexey Bataev60705422018-10-30 15:50:12 +00003977 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()))
3978 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*this, S);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003979
3980 // Detect the distribute schedule kind and chunk.
3981 llvm::Value *Chunk = nullptr;
3982 OpenMPDistScheduleClauseKind ScheduleKind = OMPC_DIST_SCHEDULE_unknown;
Alexey Bataevddf3db92018-04-13 17:31:06 +00003983 if (const auto *C = S.getSingleClause<OMPDistScheduleClause>()) {
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003984 ScheduleKind = C->getDistScheduleKind();
Alexey Bataevddf3db92018-04-13 17:31:06 +00003985 if (const Expr *Ch = C->getChunkSize()) {
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003986 Chunk = EmitScalarExpr(Ch);
3987 Chunk = EmitScalarConversion(Chunk, Ch->getType(),
Alexey Bataev617db5f2017-12-04 15:38:33 +00003988 S.getIterationVariable()->getType(),
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003989 S.getBeginLoc());
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003990 }
Gheorghe-Teodor Bercea02650d42018-09-27 19:22:56 +00003991 } else {
3992 // Default behaviour for dist_schedule clause.
3993 CGM.getOpenMPRuntime().getDefaultDistScheduleAndChunk(
3994 *this, S, ScheduleKind, Chunk);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003995 }
3996 const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
3997 const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
3998
3999 // OpenMP [2.10.8, distribute Construct, Description]
4000 // If dist_schedule is specified, kind must be static. If specified,
4001 // iterations are divided into chunks of size chunk_size, chunks are
4002 // assigned to the teams of the league in a round-robin fashion in the
4003 // order of the team number. When no chunk_size is specified, the
4004 // iteration space is divided into chunks that are approximately equal
4005 // in size, and at most one chunk is distributed to each team of the
4006 // league. The size of the chunks is unspecified in this case.
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00004007 bool StaticChunked = RT.isStaticChunked(
4008 ScheduleKind, /* Chunked */ Chunk != nullptr) &&
4009 isOpenMPLoopBoundSharingDirective(S.getDirectiveKind());
Carlo Bertollifc35ad22016-03-07 16:04:49 +00004010 if (RT.isStaticNonchunked(ScheduleKind,
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00004011 /* Chunked */ Chunk != nullptr) ||
4012 StaticChunked) {
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00004013 CGOpenMPRuntime::StaticRTInput StaticInit(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08004014 IVSize, IVSigned, /* Ordered = */ false, IL.getAddress(*this),
4015 LB.getAddress(*this), UB.getAddress(*this), ST.getAddress(*this),
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00004016 StaticChunked ? Chunk : nullptr);
Stephen Kellyf2ceec42018-08-09 21:08:08 +00004017 RT.emitDistributeStaticInit(*this, S.getBeginLoc(), ScheduleKind,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00004018 StaticInit);
Alexey Bataevddf3db92018-04-13 17:31:06 +00004019 JumpDest LoopExit =
Carlo Bertollifc35ad22016-03-07 16:04:49 +00004020 getJumpDestInCurrentScope(createBasicBlock("omp.loop.exit"));
4021 // UB = min(UB, GlobalUB);
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00004022 EmitIgnoredExpr(isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
4023 ? S.getCombinedEnsureUpperBound()
4024 : S.getEnsureUpperBound());
Carlo Bertollifc35ad22016-03-07 16:04:49 +00004025 // IV = LB;
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00004026 EmitIgnoredExpr(isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
4027 ? S.getCombinedInit()
4028 : S.getInit());
4029
Alexey Bataevddf3db92018-04-13 17:31:06 +00004030 const Expr *Cond =
4031 isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
4032 ? S.getCombinedCond()
4033 : S.getCond();
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00004034
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00004035 if (StaticChunked)
4036 Cond = S.getCombinedDistCond();
4037
4038 // For static unchunked schedules generate:
4039 //
4040 // 1. For distribute alone, codegen
4041 // while (idx <= UB) {
4042 // BODY;
4043 // ++idx;
4044 // }
4045 //
4046 // 2. When combined with 'for' (e.g. as in 'distribute parallel for')
4047 // while (idx <= UB) {
4048 // <CodeGen rest of pragma>(LB, UB);
4049 // idx += ST;
4050 // }
4051 //
4052 // For static chunk one schedule generate:
4053 //
4054 // while (IV <= GlobalUB) {
4055 // <CodeGen rest of pragma>(LB, UB);
4056 // LB += ST;
4057 // UB += ST;
4058 // UB = min(UB, GlobalUB);
4059 // IV = LB;
4060 // }
4061 //
Alexey Bataev779a1802019-12-06 12:21:31 -05004062 emitCommonSimdLoop(
4063 *this, S,
4064 [&S](CodeGenFunction &CGF, PrePostActionTy &) {
4065 if (isOpenMPSimdDirective(S.getDirectiveKind()))
4066 CGF.EmitOMPSimdInit(S, /*IsMonotonic=*/true);
4067 },
4068 [&S, &LoopScope, Cond, IncExpr, LoopExit, &CodeGenLoop,
4069 StaticChunked](CodeGenFunction &CGF, PrePostActionTy &) {
4070 CGF.EmitOMPInnerLoop(
4071 S, LoopScope.requiresCleanups(), Cond, IncExpr,
4072 [&S, LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
4073 CodeGenLoop(CGF, S, LoopExit);
4074 },
4075 [&S, StaticChunked](CodeGenFunction &CGF) {
4076 if (StaticChunked) {
4077 CGF.EmitIgnoredExpr(S.getCombinedNextLowerBound());
4078 CGF.EmitIgnoredExpr(S.getCombinedNextUpperBound());
4079 CGF.EmitIgnoredExpr(S.getCombinedEnsureUpperBound());
4080 CGF.EmitIgnoredExpr(S.getCombinedInit());
4081 }
4082 });
4083 });
Carlo Bertollifc35ad22016-03-07 16:04:49 +00004084 EmitBlock(LoopExit.getBlock());
4085 // Tell the runtime we are done.
Alexey Bataevc33ba8c2020-01-17 14:05:40 -05004086 RT.emitForStaticFinish(*this, S.getEndLoc(), S.getDirectiveKind());
Carlo Bertollifc35ad22016-03-07 16:04:49 +00004087 } else {
4088 // Emit the outer loop, which requests its work chunk [LB..UB] from
4089 // runtime and runs the inner loop to process it.
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00004090 const OMPLoopArguments LoopArguments = {
Akira Hatanakaf139ae32019-12-03 15:17:01 -08004091 LB.getAddress(*this), UB.getAddress(*this), ST.getAddress(*this),
4092 IL.getAddress(*this), Chunk};
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00004093 EmitOMPDistributeOuterLoop(ScheduleKind, S, LoopScope, LoopArguments,
4094 CodeGenLoop);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00004095 }
Alexey Bataev617db5f2017-12-04 15:38:33 +00004096 if (isOpenMPSimdDirective(S.getDirectiveKind())) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00004097 EmitOMPSimdFinal(S, [IL, &S](CodeGenFunction &CGF) {
Alexey Bataev617db5f2017-12-04 15:38:33 +00004098 return CGF.Builder.CreateIsNotNull(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00004099 CGF.EmitLoadOfScalar(IL, S.getBeginLoc()));
Alexey Bataev617db5f2017-12-04 15:38:33 +00004100 });
4101 }
Carlo Bertollibeda2142018-02-22 19:38:14 +00004102 if (isOpenMPSimdDirective(S.getDirectiveKind()) &&
4103 !isOpenMPParallelDirective(S.getDirectiveKind()) &&
4104 !isOpenMPTeamsDirective(S.getDirectiveKind())) {
Jonas Hahnfeld5aaaece2018-10-02 19:12:47 +00004105 EmitOMPReductionClauseFinal(S, OMPD_simd);
Carlo Bertollibeda2142018-02-22 19:38:14 +00004106 // Emit post-update of the reduction variables if IsLastIter != 0.
4107 emitPostUpdateForReductionClause(
Alexey Bataevddf3db92018-04-13 17:31:06 +00004108 *this, S, [IL, &S](CodeGenFunction &CGF) {
Carlo Bertollibeda2142018-02-22 19:38:14 +00004109 return CGF.Builder.CreateIsNotNull(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00004110 CGF.EmitLoadOfScalar(IL, S.getBeginLoc()));
Carlo Bertollibeda2142018-02-22 19:38:14 +00004111 });
Alexey Bataev617db5f2017-12-04 15:38:33 +00004112 }
Carlo Bertolli962bb802017-01-03 18:24:42 +00004113 // Emit final copy of the lastprivate variables if IsLastIter != 0.
Alexey Bataev617db5f2017-12-04 15:38:33 +00004114 if (HasLastprivateClause) {
Carlo Bertolli962bb802017-01-03 18:24:42 +00004115 EmitOMPLastprivateClauseFinal(
4116 S, /*NoFinals=*/false,
Stephen Kellyf2ceec42018-08-09 21:08:08 +00004117 Builder.CreateIsNotNull(EmitLoadOfScalar(IL, S.getBeginLoc())));
Alexey Bataev617db5f2017-12-04 15:38:33 +00004118 }
Carlo Bertollifc35ad22016-03-07 16:04:49 +00004119 }
4120
4121 // We're now done with the loop, so jump to the continuation block.
4122 if (ContBlock) {
4123 EmitBranch(ContBlock);
4124 EmitBlock(ContBlock, true);
4125 }
4126 }
4127}
4128
Carlo Bertolli6200a3d2015-12-14 14:51:25 +00004129void CodeGenFunction::EmitOMPDistributeDirective(
4130 const OMPDistributeDirective &S) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004131 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00004132 CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc());
Carlo Bertollifc35ad22016-03-07 16:04:49 +00004133 };
Alexey Bataev475a7442018-01-12 19:39:11 +00004134 OMPLexicalScope Scope(*this, S, OMPD_unknown);
Alexey Bataev10a54312017-11-27 16:54:08 +00004135 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_distribute, CodeGen);
Carlo Bertolli6200a3d2015-12-14 14:51:25 +00004136}
4137
Alexey Bataev5f600d62015-09-29 03:48:57 +00004138static llvm::Function *emitOutlinedOrderedFunction(CodeGenModule &CGM,
Alexey Bataevc33ba8c2020-01-17 14:05:40 -05004139 const CapturedStmt *S,
4140 SourceLocation Loc) {
Alexey Bataev5f600d62015-09-29 03:48:57 +00004141 CodeGenFunction CGF(CGM, /*suppressNewContext=*/true);
4142 CodeGenFunction::CGCapturedStmtInfo CapStmtInfo;
4143 CGF.CapturedStmtInfo = &CapStmtInfo;
Alexey Bataevc33ba8c2020-01-17 14:05:40 -05004144 llvm::Function *Fn = CGF.GenerateOpenMPCapturedStmtFunction(*S, Loc);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00004145 Fn->setDoesNotRecurse();
Alexey Bataev5f600d62015-09-29 03:48:57 +00004146 return Fn;
4147}
4148
Alexey Bataev98eb6e32015-04-22 11:15:40 +00004149void CodeGenFunction::EmitOMPOrderedDirective(const OMPOrderedDirective &S) {
Alexey Bataev475a7442018-01-12 19:39:11 +00004150 if (S.hasClausesOfKind<OMPDependClause>()) {
4151 assert(!S.getAssociatedStmt() &&
4152 "No associated statement must be in ordered depend construct.");
Alexey Bataev8b427062016-05-25 12:36:08 +00004153 for (const auto *DC : S.getClausesOfKind<OMPDependClause>())
4154 CGM.getOpenMPRuntime().emitDoacrossOrdered(*this, DC);
Alexey Bataev8ef31412015-12-18 07:58:25 +00004155 return;
Alexey Bataev8b427062016-05-25 12:36:08 +00004156 }
Alexey Bataevddf3db92018-04-13 17:31:06 +00004157 const auto *C = S.getSingleClause<OMPSIMDClause>();
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004158 auto &&CodeGen = [&S, C, this](CodeGenFunction &CGF,
4159 PrePostActionTy &Action) {
Alexey Bataev475a7442018-01-12 19:39:11 +00004160 const CapturedStmt *CS = S.getInnermostCapturedStmt();
Alexey Bataev5f600d62015-09-29 03:48:57 +00004161 if (C) {
Alexey Bataev5f600d62015-09-29 03:48:57 +00004162 llvm::SmallVector<llvm::Value *, 16> CapturedVars;
4163 CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
Alexey Bataevc33ba8c2020-01-17 14:05:40 -05004164 llvm::Function *OutlinedFn =
4165 emitOutlinedOrderedFunction(CGM, CS, S.getBeginLoc());
Stephen Kellyf2ceec42018-08-09 21:08:08 +00004166 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, S.getBeginLoc(),
Alexey Bataev3c595a62017-08-14 15:01:03 +00004167 OutlinedFn, CapturedVars);
Alexey Bataev5f600d62015-09-29 03:48:57 +00004168 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004169 Action.Enter(CGF);
Alexey Bataev475a7442018-01-12 19:39:11 +00004170 CGF.EmitStmt(CS->getCapturedStmt());
Alexey Bataev5f600d62015-09-29 03:48:57 +00004171 }
Alexey Bataev98eb6e32015-04-22 11:15:40 +00004172 };
Alexey Bataev475a7442018-01-12 19:39:11 +00004173 OMPLexicalScope Scope(*this, S, OMPD_unknown);
Stephen Kellyf2ceec42018-08-09 21:08:08 +00004174 CGM.getOpenMPRuntime().emitOrderedRegion(*this, CodeGen, S.getBeginLoc(), !C);
Alexey Bataev9fb6e642014-07-22 06:45:04 +00004175}
4176
Alexey Bataevb57056f2015-01-22 06:17:56 +00004177static llvm::Value *convertToScalarValue(CodeGenFunction &CGF, RValue Val,
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00004178 QualType SrcType, QualType DestType,
4179 SourceLocation Loc) {
Alexey Bataevb57056f2015-01-22 06:17:56 +00004180 assert(CGF.hasScalarEvaluationKind(DestType) &&
4181 "DestType must have scalar evaluation kind.");
4182 assert(!Val.isAggregate() && "Must be a scalar or complex.");
Alexey Bataevddf3db92018-04-13 17:31:06 +00004183 return Val.isScalar() ? CGF.EmitScalarConversion(Val.getScalarVal(), SrcType,
4184 DestType, Loc)
4185 : CGF.EmitComplexToScalarConversion(
4186 Val.getComplexVal(), SrcType, DestType, Loc);
Alexey Bataevb57056f2015-01-22 06:17:56 +00004187}
4188
4189static CodeGenFunction::ComplexPairTy
4190convertToComplexValue(CodeGenFunction &CGF, RValue Val, QualType SrcType,
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00004191 QualType DestType, SourceLocation Loc) {
Alexey Bataevb57056f2015-01-22 06:17:56 +00004192 assert(CGF.getEvaluationKind(DestType) == TEK_Complex &&
4193 "DestType must have complex evaluation kind.");
4194 CodeGenFunction::ComplexPairTy ComplexVal;
4195 if (Val.isScalar()) {
4196 // Convert the input element to the element type of the complex.
Alexey Bataevddf3db92018-04-13 17:31:06 +00004197 QualType DestElementType =
4198 DestType->castAs<ComplexType>()->getElementType();
4199 llvm::Value *ScalarVal = CGF.EmitScalarConversion(
4200 Val.getScalarVal(), SrcType, DestElementType, Loc);
Alexey Bataevb57056f2015-01-22 06:17:56 +00004201 ComplexVal = CodeGenFunction::ComplexPairTy(
4202 ScalarVal, llvm::Constant::getNullValue(ScalarVal->getType()));
4203 } else {
4204 assert(Val.isComplex() && "Must be a scalar or complex.");
Alexey Bataevddf3db92018-04-13 17:31:06 +00004205 QualType SrcElementType = SrcType->castAs<ComplexType>()->getElementType();
4206 QualType DestElementType =
4207 DestType->castAs<ComplexType>()->getElementType();
Alexey Bataevb57056f2015-01-22 06:17:56 +00004208 ComplexVal.first = CGF.EmitScalarConversion(
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00004209 Val.getComplexVal().first, SrcElementType, DestElementType, Loc);
Alexey Bataevb57056f2015-01-22 06:17:56 +00004210 ComplexVal.second = CGF.EmitScalarConversion(
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00004211 Val.getComplexVal().second, SrcElementType, DestElementType, Loc);
Alexey Bataevb57056f2015-01-22 06:17:56 +00004212 }
4213 return ComplexVal;
4214}
4215
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004216static void emitSimpleAtomicStore(CodeGenFunction &CGF, llvm::AtomicOrdering AO,
Alexey Bataev5e018f92015-04-23 06:35:10 +00004217 LValue LVal, RValue RVal) {
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004218 if (LVal.isGlobalReg())
Alexey Bataev5e018f92015-04-23 06:35:10 +00004219 CGF.EmitStoreThroughGlobalRegLValue(RVal, LVal);
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004220 else
4221 CGF.EmitAtomicStore(RVal, LVal, AO, LVal.isVolatile(), /*isInit=*/false);
4222}
4223
4224static RValue emitSimpleAtomicLoad(CodeGenFunction &CGF,
4225 llvm::AtomicOrdering AO, LValue LVal,
4226 SourceLocation Loc) {
4227 if (LVal.isGlobalReg())
4228 return CGF.EmitLoadOfLValue(LVal, Loc);
4229 return CGF.EmitAtomicLoad(
4230 LVal, Loc, llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO),
4231 LVal.isVolatile());
Alexey Bataev5e018f92015-04-23 06:35:10 +00004232}
4233
Alexey Bataev8524d152016-01-21 12:35:58 +00004234void CodeGenFunction::emitOMPSimpleStore(LValue LVal, RValue RVal,
4235 QualType RValTy, SourceLocation Loc) {
4236 switch (getEvaluationKind(LVal.getType())) {
Alexey Bataev5e018f92015-04-23 06:35:10 +00004237 case TEK_Scalar:
Alexey Bataev8524d152016-01-21 12:35:58 +00004238 EmitStoreThroughLValue(RValue::get(convertToScalarValue(
4239 *this, RVal, RValTy, LVal.getType(), Loc)),
4240 LVal);
Alexey Bataev5e018f92015-04-23 06:35:10 +00004241 break;
4242 case TEK_Complex:
Alexey Bataev8524d152016-01-21 12:35:58 +00004243 EmitStoreOfComplex(
4244 convertToComplexValue(*this, RVal, RValTy, LVal.getType(), Loc), LVal,
Alexey Bataev5e018f92015-04-23 06:35:10 +00004245 /*isInit=*/false);
4246 break;
4247 case TEK_Aggregate:
4248 llvm_unreachable("Must be a scalar or complex.");
4249 }
4250}
4251
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004252static void emitOMPAtomicReadExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO,
Alexey Bataevb57056f2015-01-22 06:17:56 +00004253 const Expr *X, const Expr *V,
4254 SourceLocation Loc) {
4255 // v = x;
4256 assert(V->isLValue() && "V of 'omp atomic read' is not lvalue");
4257 assert(X->isLValue() && "X of 'omp atomic read' is not lvalue");
4258 LValue XLValue = CGF.EmitLValue(X);
4259 LValue VLValue = CGF.EmitLValue(V);
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004260 RValue Res = emitSimpleAtomicLoad(CGF, AO, XLValue, Loc);
4261 // OpenMP, 2.17.7, atomic Construct
4262 // If the read or capture clause is specified and the acquire, acq_rel, or
4263 // seq_cst clause is specified then the strong flush on exit from the atomic
4264 // operation is also an acquire flush.
4265 switch (AO) {
4266 case llvm::AtomicOrdering::Acquire:
4267 case llvm::AtomicOrdering::AcquireRelease:
4268 case llvm::AtomicOrdering::SequentiallyConsistent:
4269 CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc,
4270 llvm::AtomicOrdering::Acquire);
4271 break;
4272 case llvm::AtomicOrdering::Monotonic:
4273 case llvm::AtomicOrdering::Release:
4274 break;
4275 case llvm::AtomicOrdering::NotAtomic:
4276 case llvm::AtomicOrdering::Unordered:
4277 llvm_unreachable("Unexpected ordering.");
4278 }
Alexey Bataev8524d152016-01-21 12:35:58 +00004279 CGF.emitOMPSimpleStore(VLValue, Res, X->getType().getNonReferenceType(), Loc);
Alexey Bataevf117f2c2020-01-28 11:19:45 -05004280 CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, V);
Alexey Bataevb57056f2015-01-22 06:17:56 +00004281}
4282
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004283static void emitOMPAtomicWriteExpr(CodeGenFunction &CGF,
4284 llvm::AtomicOrdering AO, const Expr *X,
4285 const Expr *E, SourceLocation Loc) {
Alexey Bataevb8329262015-02-27 06:33:30 +00004286 // x = expr;
4287 assert(X->isLValue() && "X of 'omp atomic write' is not lvalue");
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004288 emitSimpleAtomicStore(CGF, AO, CGF.EmitLValue(X), CGF.EmitAnyExpr(E));
Alexey Bataevf117f2c2020-01-28 11:19:45 -05004289 CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, X);
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004290 // OpenMP, 2.17.7, atomic Construct
4291 // If the write, update, or capture clause is specified and the release,
4292 // acq_rel, or seq_cst clause is specified then the strong flush on entry to
4293 // the atomic operation is also a release flush.
4294 switch (AO) {
4295 case llvm::AtomicOrdering::Release:
4296 case llvm::AtomicOrdering::AcquireRelease:
4297 case llvm::AtomicOrdering::SequentiallyConsistent:
4298 CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc,
4299 llvm::AtomicOrdering::Release);
4300 break;
4301 case llvm::AtomicOrdering::Acquire:
4302 case llvm::AtomicOrdering::Monotonic:
4303 break;
4304 case llvm::AtomicOrdering::NotAtomic:
4305 case llvm::AtomicOrdering::Unordered:
4306 llvm_unreachable("Unexpected ordering.");
4307 }
Alexey Bataevb8329262015-02-27 06:33:30 +00004308}
4309
Benjamin Kramer439ee9d2015-05-01 13:59:53 +00004310static std::pair<bool, RValue> emitOMPAtomicRMW(CodeGenFunction &CGF, LValue X,
4311 RValue Update,
4312 BinaryOperatorKind BO,
4313 llvm::AtomicOrdering AO,
4314 bool IsXLHSInRHSPart) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00004315 ASTContext &Context = CGF.getContext();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004316 // Allow atomicrmw only if 'x' and 'update' are integer values, lvalue for 'x'
Alexey Bataevb4505a72015-03-30 05:20:59 +00004317 // expression is simple and atomic is allowed for the given type for the
4318 // target platform.
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004319 if (BO == BO_Comma || !Update.isScalar() ||
Akira Hatanakaf139ae32019-12-03 15:17:01 -08004320 !Update.getScalarVal()->getType()->isIntegerTy() || !X.isSimple() ||
4321 (!isa<llvm::ConstantInt>(Update.getScalarVal()) &&
4322 (Update.getScalarVal()->getType() !=
4323 X.getAddress(CGF).getElementType())) ||
4324 !X.getAddress(CGF).getElementType()->isIntegerTy() ||
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004325 !Context.getTargetInfo().hasBuiltinAtomic(
4326 Context.getTypeSize(X.getType()), Context.toBits(X.getAlignment())))
Alexey Bataev5e018f92015-04-23 06:35:10 +00004327 return std::make_pair(false, RValue::get(nullptr));
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004328
4329 llvm::AtomicRMWInst::BinOp RMWOp;
4330 switch (BO) {
4331 case BO_Add:
4332 RMWOp = llvm::AtomicRMWInst::Add;
4333 break;
4334 case BO_Sub:
4335 if (!IsXLHSInRHSPart)
Alexey Bataev5e018f92015-04-23 06:35:10 +00004336 return std::make_pair(false, RValue::get(nullptr));
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004337 RMWOp = llvm::AtomicRMWInst::Sub;
4338 break;
4339 case BO_And:
4340 RMWOp = llvm::AtomicRMWInst::And;
4341 break;
4342 case BO_Or:
4343 RMWOp = llvm::AtomicRMWInst::Or;
4344 break;
4345 case BO_Xor:
4346 RMWOp = llvm::AtomicRMWInst::Xor;
4347 break;
4348 case BO_LT:
4349 RMWOp = X.getType()->hasSignedIntegerRepresentation()
4350 ? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Min
4351 : llvm::AtomicRMWInst::Max)
4352 : (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMin
4353 : llvm::AtomicRMWInst::UMax);
4354 break;
4355 case BO_GT:
4356 RMWOp = X.getType()->hasSignedIntegerRepresentation()
4357 ? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Max
4358 : llvm::AtomicRMWInst::Min)
4359 : (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMax
4360 : llvm::AtomicRMWInst::UMin);
4361 break;
Alexey Bataev5e018f92015-04-23 06:35:10 +00004362 case BO_Assign:
4363 RMWOp = llvm::AtomicRMWInst::Xchg;
4364 break;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004365 case BO_Mul:
4366 case BO_Div:
4367 case BO_Rem:
4368 case BO_Shl:
4369 case BO_Shr:
4370 case BO_LAnd:
4371 case BO_LOr:
Alexey Bataev5e018f92015-04-23 06:35:10 +00004372 return std::make_pair(false, RValue::get(nullptr));
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004373 case BO_PtrMemD:
4374 case BO_PtrMemI:
4375 case BO_LE:
4376 case BO_GE:
4377 case BO_EQ:
4378 case BO_NE:
Richard Smithc70f1d62017-12-14 15:16:18 +00004379 case BO_Cmp:
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004380 case BO_AddAssign:
4381 case BO_SubAssign:
4382 case BO_AndAssign:
4383 case BO_OrAssign:
4384 case BO_XorAssign:
4385 case BO_MulAssign:
4386 case BO_DivAssign:
4387 case BO_RemAssign:
4388 case BO_ShlAssign:
4389 case BO_ShrAssign:
4390 case BO_Comma:
4391 llvm_unreachable("Unsupported atomic update operation");
4392 }
Alexey Bataevddf3db92018-04-13 17:31:06 +00004393 llvm::Value *UpdateVal = Update.getScalarVal();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004394 if (auto *IC = dyn_cast<llvm::ConstantInt>(UpdateVal)) {
4395 UpdateVal = CGF.Builder.CreateIntCast(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08004396 IC, X.getAddress(CGF).getElementType(),
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004397 X.getType()->hasSignedIntegerRepresentation());
4398 }
Alexey Bataevddf3db92018-04-13 17:31:06 +00004399 llvm::Value *Res =
Akira Hatanakaf139ae32019-12-03 15:17:01 -08004400 CGF.Builder.CreateAtomicRMW(RMWOp, X.getPointer(CGF), UpdateVal, AO);
Alexey Bataev5e018f92015-04-23 06:35:10 +00004401 return std::make_pair(true, RValue::get(Res));
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004402}
4403
Alexey Bataev5e018f92015-04-23 06:35:10 +00004404std::pair<bool, RValue> CodeGenFunction::EmitOMPAtomicSimpleUpdateExpr(
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004405 LValue X, RValue E, BinaryOperatorKind BO, bool IsXLHSInRHSPart,
4406 llvm::AtomicOrdering AO, SourceLocation Loc,
Alexey Bataevddf3db92018-04-13 17:31:06 +00004407 const llvm::function_ref<RValue(RValue)> CommonGen) {
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004408 // Update expressions are allowed to have the following forms:
4409 // x binop= expr; -> xrval + expr;
4410 // x++, ++x -> xrval + 1;
4411 // x--, --x -> xrval - 1;
4412 // x = x binop expr; -> xrval binop expr
4413 // x = expr Op x; - > expr binop xrval;
Alexey Bataev5e018f92015-04-23 06:35:10 +00004414 auto Res = emitOMPAtomicRMW(*this, X, E, BO, AO, IsXLHSInRHSPart);
4415 if (!Res.first) {
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004416 if (X.isGlobalReg()) {
4417 // Emit an update expression: 'xrval' binop 'expr' or 'expr' binop
4418 // 'xrval'.
4419 EmitStoreThroughLValue(CommonGen(EmitLoadOfLValue(X, Loc)), X);
4420 } else {
4421 // Perform compare-and-swap procedure.
4422 EmitAtomicUpdate(X, AO, CommonGen, X.getType().isVolatileQualified());
Alexey Bataevb4505a72015-03-30 05:20:59 +00004423 }
4424 }
Alexey Bataev5e018f92015-04-23 06:35:10 +00004425 return Res;
Alexey Bataevb4505a72015-03-30 05:20:59 +00004426}
4427
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004428static void emitOMPAtomicUpdateExpr(CodeGenFunction &CGF,
4429 llvm::AtomicOrdering AO, const Expr *X,
4430 const Expr *E, const Expr *UE,
4431 bool IsXLHSInRHSPart, SourceLocation Loc) {
Alexey Bataevb4505a72015-03-30 05:20:59 +00004432 assert(isa<BinaryOperator>(UE->IgnoreImpCasts()) &&
4433 "Update expr in 'atomic update' must be a binary operator.");
Alexey Bataevddf3db92018-04-13 17:31:06 +00004434 const auto *BOUE = cast<BinaryOperator>(UE->IgnoreImpCasts());
Alexey Bataevb4505a72015-03-30 05:20:59 +00004435 // Update expressions are allowed to have the following forms:
4436 // x binop= expr; -> xrval + expr;
4437 // x++, ++x -> xrval + 1;
4438 // x--, --x -> xrval - 1;
4439 // x = x binop expr; -> xrval binop expr
4440 // x = expr Op x; - > expr binop xrval;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004441 assert(X->isLValue() && "X of 'omp atomic update' is not lvalue");
Alexey Bataevb4505a72015-03-30 05:20:59 +00004442 LValue XLValue = CGF.EmitLValue(X);
4443 RValue ExprRValue = CGF.EmitAnyExpr(E);
Alexey Bataevddf3db92018-04-13 17:31:06 +00004444 const auto *LHS = cast<OpaqueValueExpr>(BOUE->getLHS()->IgnoreImpCasts());
4445 const auto *RHS = cast<OpaqueValueExpr>(BOUE->getRHS()->IgnoreImpCasts());
4446 const OpaqueValueExpr *XRValExpr = IsXLHSInRHSPart ? LHS : RHS;
4447 const OpaqueValueExpr *ERValExpr = IsXLHSInRHSPart ? RHS : LHS;
4448 auto &&Gen = [&CGF, UE, ExprRValue, XRValExpr, ERValExpr](RValue XRValue) {
4449 CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue);
4450 CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, XRValue);
4451 return CGF.EmitAnyExpr(UE);
4452 };
Alexey Bataev5e018f92015-04-23 06:35:10 +00004453 (void)CGF.EmitOMPAtomicSimpleUpdateExpr(
4454 XLValue, ExprRValue, BOUE->getOpcode(), IsXLHSInRHSPart, AO, Loc, Gen);
Alexey Bataevf117f2c2020-01-28 11:19:45 -05004455 CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, X);
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004456 // OpenMP, 2.17.7, atomic Construct
4457 // If the write, update, or capture clause is specified and the release,
4458 // acq_rel, or seq_cst clause is specified then the strong flush on entry to
4459 // the atomic operation is also a release flush.
4460 switch (AO) {
4461 case llvm::AtomicOrdering::Release:
4462 case llvm::AtomicOrdering::AcquireRelease:
4463 case llvm::AtomicOrdering::SequentiallyConsistent:
4464 CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc,
4465 llvm::AtomicOrdering::Release);
4466 break;
4467 case llvm::AtomicOrdering::Acquire:
4468 case llvm::AtomicOrdering::Monotonic:
4469 break;
4470 case llvm::AtomicOrdering::NotAtomic:
4471 case llvm::AtomicOrdering::Unordered:
4472 llvm_unreachable("Unexpected ordering.");
4473 }
Alexey Bataev5e018f92015-04-23 06:35:10 +00004474}
4475
4476static RValue convertToType(CodeGenFunction &CGF, RValue Value,
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00004477 QualType SourceType, QualType ResType,
4478 SourceLocation Loc) {
Alexey Bataev5e018f92015-04-23 06:35:10 +00004479 switch (CGF.getEvaluationKind(ResType)) {
4480 case TEK_Scalar:
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00004481 return RValue::get(
4482 convertToScalarValue(CGF, Value, SourceType, ResType, Loc));
Alexey Bataev5e018f92015-04-23 06:35:10 +00004483 case TEK_Complex: {
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00004484 auto Res = convertToComplexValue(CGF, Value, SourceType, ResType, Loc);
Alexey Bataev5e018f92015-04-23 06:35:10 +00004485 return RValue::getComplex(Res.first, Res.second);
4486 }
4487 case TEK_Aggregate:
4488 break;
4489 }
4490 llvm_unreachable("Must be a scalar or complex.");
4491}
4492
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004493static void emitOMPAtomicCaptureExpr(CodeGenFunction &CGF,
4494 llvm::AtomicOrdering AO,
Alexey Bataev5e018f92015-04-23 06:35:10 +00004495 bool IsPostfixUpdate, const Expr *V,
4496 const Expr *X, const Expr *E,
4497 const Expr *UE, bool IsXLHSInRHSPart,
4498 SourceLocation Loc) {
4499 assert(X->isLValue() && "X of 'omp atomic capture' is not lvalue");
4500 assert(V->isLValue() && "V of 'omp atomic capture' is not lvalue");
4501 RValue NewVVal;
4502 LValue VLValue = CGF.EmitLValue(V);
4503 LValue XLValue = CGF.EmitLValue(X);
4504 RValue ExprRValue = CGF.EmitAnyExpr(E);
Alexey Bataev5e018f92015-04-23 06:35:10 +00004505 QualType NewVValType;
4506 if (UE) {
4507 // 'x' is updated with some additional value.
4508 assert(isa<BinaryOperator>(UE->IgnoreImpCasts()) &&
4509 "Update expr in 'atomic capture' must be a binary operator.");
Alexey Bataevddf3db92018-04-13 17:31:06 +00004510 const auto *BOUE = cast<BinaryOperator>(UE->IgnoreImpCasts());
Alexey Bataev5e018f92015-04-23 06:35:10 +00004511 // Update expressions are allowed to have the following forms:
4512 // x binop= expr; -> xrval + expr;
4513 // x++, ++x -> xrval + 1;
4514 // x--, --x -> xrval - 1;
4515 // x = x binop expr; -> xrval binop expr
4516 // x = expr Op x; - > expr binop xrval;
Alexey Bataevddf3db92018-04-13 17:31:06 +00004517 const auto *LHS = cast<OpaqueValueExpr>(BOUE->getLHS()->IgnoreImpCasts());
4518 const auto *RHS = cast<OpaqueValueExpr>(BOUE->getRHS()->IgnoreImpCasts());
4519 const OpaqueValueExpr *XRValExpr = IsXLHSInRHSPart ? LHS : RHS;
Alexey Bataev5e018f92015-04-23 06:35:10 +00004520 NewVValType = XRValExpr->getType();
Alexey Bataevddf3db92018-04-13 17:31:06 +00004521 const OpaqueValueExpr *ERValExpr = IsXLHSInRHSPart ? RHS : LHS;
Alexey Bataev5e018f92015-04-23 06:35:10 +00004522 auto &&Gen = [&CGF, &NewVVal, UE, ExprRValue, XRValExpr, ERValExpr,
Alexey Bataevddf3db92018-04-13 17:31:06 +00004523 IsPostfixUpdate](RValue XRValue) {
Alexey Bataev5e018f92015-04-23 06:35:10 +00004524 CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue);
4525 CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, XRValue);
4526 RValue Res = CGF.EmitAnyExpr(UE);
4527 NewVVal = IsPostfixUpdate ? XRValue : Res;
4528 return Res;
4529 };
4530 auto Res = CGF.EmitOMPAtomicSimpleUpdateExpr(
4531 XLValue, ExprRValue, BOUE->getOpcode(), IsXLHSInRHSPart, AO, Loc, Gen);
Alexey Bataevf117f2c2020-01-28 11:19:45 -05004532 CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, X);
Alexey Bataev5e018f92015-04-23 06:35:10 +00004533 if (Res.first) {
4534 // 'atomicrmw' instruction was generated.
4535 if (IsPostfixUpdate) {
4536 // Use old value from 'atomicrmw'.
4537 NewVVal = Res.second;
4538 } else {
4539 // 'atomicrmw' does not provide new value, so evaluate it using old
4540 // value of 'x'.
4541 CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue);
4542 CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, Res.second);
4543 NewVVal = CGF.EmitAnyExpr(UE);
4544 }
4545 }
4546 } else {
4547 // 'x' is simply rewritten with some 'expr'.
4548 NewVValType = X->getType().getNonReferenceType();
4549 ExprRValue = convertToType(CGF, ExprRValue, E->getType(),
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00004550 X->getType().getNonReferenceType(), Loc);
Alexey Bataevddf3db92018-04-13 17:31:06 +00004551 auto &&Gen = [&NewVVal, ExprRValue](RValue XRValue) {
Alexey Bataev5e018f92015-04-23 06:35:10 +00004552 NewVVal = XRValue;
4553 return ExprRValue;
4554 };
4555 // Try to perform atomicrmw xchg, otherwise simple exchange.
4556 auto Res = CGF.EmitOMPAtomicSimpleUpdateExpr(
4557 XLValue, ExprRValue, /*BO=*/BO_Assign, /*IsXLHSInRHSPart=*/false, AO,
4558 Loc, Gen);
Alexey Bataevf117f2c2020-01-28 11:19:45 -05004559 CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, X);
Alexey Bataev5e018f92015-04-23 06:35:10 +00004560 if (Res.first) {
4561 // 'atomicrmw' instruction was generated.
4562 NewVVal = IsPostfixUpdate ? Res.second : ExprRValue;
4563 }
4564 }
4565 // Emit post-update store to 'v' of old/new 'x' value.
Alexey Bataev8524d152016-01-21 12:35:58 +00004566 CGF.emitOMPSimpleStore(VLValue, NewVVal, NewVValType, Loc);
Alexey Bataevf117f2c2020-01-28 11:19:45 -05004567 CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, V);
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004568 // OpenMP, 2.17.7, atomic Construct
4569 // If the write, update, or capture clause is specified and the release,
4570 // acq_rel, or seq_cst clause is specified then the strong flush on entry to
4571 // the atomic operation is also a release flush.
4572 // If the read or capture clause is specified and the acquire, acq_rel, or
4573 // seq_cst clause is specified then the strong flush on exit from the atomic
4574 // operation is also an acquire flush.
4575 switch (AO) {
4576 case llvm::AtomicOrdering::Release:
4577 CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc,
4578 llvm::AtomicOrdering::Release);
4579 break;
4580 case llvm::AtomicOrdering::Acquire:
4581 CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc,
4582 llvm::AtomicOrdering::Acquire);
4583 break;
4584 case llvm::AtomicOrdering::AcquireRelease:
4585 case llvm::AtomicOrdering::SequentiallyConsistent:
4586 CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc,
4587 llvm::AtomicOrdering::AcquireRelease);
4588 break;
4589 case llvm::AtomicOrdering::Monotonic:
4590 break;
4591 case llvm::AtomicOrdering::NotAtomic:
4592 case llvm::AtomicOrdering::Unordered:
4593 llvm_unreachable("Unexpected ordering.");
4594 }
Alexey Bataevb4505a72015-03-30 05:20:59 +00004595}
4596
Alexey Bataevddf3db92018-04-13 17:31:06 +00004597static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004598 llvm::AtomicOrdering AO, bool IsPostfixUpdate,
Alexey Bataev5e018f92015-04-23 06:35:10 +00004599 const Expr *X, const Expr *V, const Expr *E,
4600 const Expr *UE, bool IsXLHSInRHSPart,
4601 SourceLocation Loc) {
Alexey Bataevb57056f2015-01-22 06:17:56 +00004602 switch (Kind) {
4603 case OMPC_read:
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004604 emitOMPAtomicReadExpr(CGF, AO, X, V, Loc);
Alexey Bataevb57056f2015-01-22 06:17:56 +00004605 break;
4606 case OMPC_write:
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004607 emitOMPAtomicWriteExpr(CGF, AO, X, E, Loc);
Alexey Bataevb8329262015-02-27 06:33:30 +00004608 break;
Alexey Bataevb4505a72015-03-30 05:20:59 +00004609 case OMPC_unknown:
Alexey Bataevb57056f2015-01-22 06:17:56 +00004610 case OMPC_update:
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004611 emitOMPAtomicUpdateExpr(CGF, AO, X, E, UE, IsXLHSInRHSPart, Loc);
Alexey Bataevb4505a72015-03-30 05:20:59 +00004612 break;
Alexey Bataevb57056f2015-01-22 06:17:56 +00004613 case OMPC_capture:
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004614 emitOMPAtomicCaptureExpr(CGF, AO, IsPostfixUpdate, V, X, E, UE,
Alexey Bataev5e018f92015-04-23 06:35:10 +00004615 IsXLHSInRHSPart, Loc);
4616 break;
Alexey Bataevb57056f2015-01-22 06:17:56 +00004617 case OMPC_if:
4618 case OMPC_final:
4619 case OMPC_num_threads:
4620 case OMPC_private:
4621 case OMPC_firstprivate:
4622 case OMPC_lastprivate:
4623 case OMPC_reduction:
Alexey Bataev169d96a2017-07-18 20:17:46 +00004624 case OMPC_task_reduction:
Alexey Bataevfa312f32017-07-21 18:48:21 +00004625 case OMPC_in_reduction:
Alexey Bataevb57056f2015-01-22 06:17:56 +00004626 case OMPC_safelen:
Alexey Bataev66b15b52015-08-21 11:14:16 +00004627 case OMPC_simdlen:
Alexey Bataev9cc10fc2019-03-12 18:52:33 +00004628 case OMPC_allocator:
Alexey Bataeve04483e2019-03-27 14:14:31 +00004629 case OMPC_allocate:
Alexey Bataevb57056f2015-01-22 06:17:56 +00004630 case OMPC_collapse:
4631 case OMPC_default:
4632 case OMPC_seq_cst:
Alexey Bataevea9166b2020-02-06 16:30:23 -05004633 case OMPC_acq_rel:
Alexey Bataev04a830f2020-02-10 14:30:39 -05004634 case OMPC_acquire:
Alexey Bataev95598342020-02-10 15:49:05 -05004635 case OMPC_release:
Alexey Bataev9a8defc2020-02-11 11:10:43 -05004636 case OMPC_relaxed:
Alexey Bataevb57056f2015-01-22 06:17:56 +00004637 case OMPC_shared:
4638 case OMPC_linear:
4639 case OMPC_aligned:
4640 case OMPC_copyin:
4641 case OMPC_copyprivate:
4642 case OMPC_flush:
4643 case OMPC_proc_bind:
4644 case OMPC_schedule:
4645 case OMPC_ordered:
4646 case OMPC_nowait:
4647 case OMPC_untied:
4648 case OMPC_threadprivate:
Alexey Bataev1c2cfbc2015-06-23 14:25:19 +00004649 case OMPC_depend:
Alexey Bataevb57056f2015-01-22 06:17:56 +00004650 case OMPC_mergeable:
Michael Wonge710d542015-08-07 16:16:36 +00004651 case OMPC_device:
Alexey Bataev346265e2015-09-25 10:37:12 +00004652 case OMPC_threads:
Alexey Bataevd14d1e62015-09-28 06:39:35 +00004653 case OMPC_simd:
Kelvin Li0bff7af2015-11-23 05:32:03 +00004654 case OMPC_map:
Kelvin Li099bb8c2015-11-24 20:50:12 +00004655 case OMPC_num_teams:
Kelvin Lia15fb1a2015-11-27 18:47:36 +00004656 case OMPC_thread_limit:
Alexey Bataeva0569352015-12-01 10:17:31 +00004657 case OMPC_priority:
Alexey Bataev1fd4aed2015-12-07 12:52:51 +00004658 case OMPC_grainsize:
Alexey Bataevb825de12015-12-07 10:51:44 +00004659 case OMPC_nogroup:
Alexey Bataev382967a2015-12-08 12:06:20 +00004660 case OMPC_num_tasks:
Alexey Bataev28c75412015-12-15 08:19:24 +00004661 case OMPC_hint:
Carlo Bertollib4adf552016-01-15 18:50:31 +00004662 case OMPC_dist_schedule:
Arpith Chacko Jacob3cf89042016-01-26 16:37:23 +00004663 case OMPC_defaultmap:
Alexey Bataeve48a5fc2016-04-12 05:28:34 +00004664 case OMPC_uniform:
Samuel Antao661c0902016-05-26 17:39:58 +00004665 case OMPC_to:
Samuel Antaoec172c62016-05-26 17:49:04 +00004666 case OMPC_from:
Carlo Bertolli2404b172016-07-13 15:37:16 +00004667 case OMPC_use_device_ptr:
Carlo Bertolli70594e92016-07-13 17:16:49 +00004668 case OMPC_is_device_ptr:
Kelvin Li1408f912018-09-26 04:28:39 +00004669 case OMPC_unified_address:
Alexey Bataev94c50642018-10-01 14:26:31 +00004670 case OMPC_unified_shared_memory:
Patrick Lyster6bdf63b2018-10-03 20:07:58 +00004671 case OMPC_reverse_offload:
Patrick Lyster3fe9e392018-10-11 14:41:10 +00004672 case OMPC_dynamic_allocators:
Patrick Lyster7a2a27c2018-11-02 12:18:11 +00004673 case OMPC_atomic_default_mem_order:
Alexey Bataev729e2422019-08-23 16:11:14 +00004674 case OMPC_device_type:
Alexey Bataevdba792c2019-09-23 18:13:31 +00004675 case OMPC_match:
Alexey Bataevb6e70842019-12-16 15:54:17 -05004676 case OMPC_nontemporal:
Alexey Bataevcb8e6912020-01-31 16:09:26 -05004677 case OMPC_order:
Alexey Bataevb57056f2015-01-22 06:17:56 +00004678 llvm_unreachable("Clause is not allowed in 'omp atomic'.");
4679 }
4680}
4681
4682void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &S) {
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004683 llvm::AtomicOrdering AO = llvm::AtomicOrdering::Monotonic;
Alexey Bataev2d4f80f2020-02-11 15:15:21 -05004684 bool MemOrderingSpecified = false;
4685 if (S.getSingleClause<OMPSeqCstClause>()) {
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004686 AO = llvm::AtomicOrdering::SequentiallyConsistent;
Alexey Bataev2d4f80f2020-02-11 15:15:21 -05004687 MemOrderingSpecified = true;
4688 } else if (S.getSingleClause<OMPAcqRelClause>()) {
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004689 AO = llvm::AtomicOrdering::AcquireRelease;
Alexey Bataev2d4f80f2020-02-11 15:15:21 -05004690 MemOrderingSpecified = true;
4691 } else if (S.getSingleClause<OMPAcquireClause>()) {
Alexey Bataev04a830f2020-02-10 14:30:39 -05004692 AO = llvm::AtomicOrdering::Acquire;
Alexey Bataev2d4f80f2020-02-11 15:15:21 -05004693 MemOrderingSpecified = true;
4694 } else if (S.getSingleClause<OMPReleaseClause>()) {
Alexey Bataev95598342020-02-10 15:49:05 -05004695 AO = llvm::AtomicOrdering::Release;
Alexey Bataev2d4f80f2020-02-11 15:15:21 -05004696 MemOrderingSpecified = true;
4697 } else if (S.getSingleClause<OMPRelaxedClause>()) {
Alexey Bataev9a8defc2020-02-11 11:10:43 -05004698 AO = llvm::AtomicOrdering::Monotonic;
Alexey Bataev2d4f80f2020-02-11 15:15:21 -05004699 MemOrderingSpecified = true;
4700 }
Alexey Bataevb57056f2015-01-22 06:17:56 +00004701 OpenMPClauseKind Kind = OMPC_unknown;
Alexey Bataevddf3db92018-04-13 17:31:06 +00004702 for (const OMPClause *C : S.clauses()) {
Alexey Bataev9a8defc2020-02-11 11:10:43 -05004703 // Find first clause (skip seq_cst|acq_rel|aqcuire|release|relaxed clause,
4704 // if it is first).
Alexey Bataevea9166b2020-02-06 16:30:23 -05004705 if (C->getClauseKind() != OMPC_seq_cst &&
Alexey Bataev04a830f2020-02-10 14:30:39 -05004706 C->getClauseKind() != OMPC_acq_rel &&
Alexey Bataev95598342020-02-10 15:49:05 -05004707 C->getClauseKind() != OMPC_acquire &&
Alexey Bataev9a8defc2020-02-11 11:10:43 -05004708 C->getClauseKind() != OMPC_release &&
4709 C->getClauseKind() != OMPC_relaxed) {
Alexey Bataevb57056f2015-01-22 06:17:56 +00004710 Kind = C->getClauseKind();
4711 break;
4712 }
4713 }
Alexey Bataev2d4f80f2020-02-11 15:15:21 -05004714 if (!MemOrderingSpecified) {
4715 llvm::AtomicOrdering DefaultOrder =
4716 CGM.getOpenMPRuntime().getDefaultMemoryOrdering();
4717 if (DefaultOrder == llvm::AtomicOrdering::Monotonic ||
4718 DefaultOrder == llvm::AtomicOrdering::SequentiallyConsistent ||
4719 (DefaultOrder == llvm::AtomicOrdering::AcquireRelease &&
4720 Kind == OMPC_capture)) {
4721 AO = DefaultOrder;
4722 } else if (DefaultOrder == llvm::AtomicOrdering::AcquireRelease) {
4723 if (Kind == OMPC_unknown || Kind == OMPC_update || Kind == OMPC_write) {
4724 AO = llvm::AtomicOrdering::Release;
4725 } else if (Kind == OMPC_read) {
4726 assert(Kind == OMPC_read && "Unexpected atomic kind.");
4727 AO = llvm::AtomicOrdering::Acquire;
4728 }
4729 }
4730 }
Alexey Bataev10fec572015-03-11 04:48:56 +00004731
Alexey Bataevddf3db92018-04-13 17:31:06 +00004732 const Stmt *CS = S.getInnermostCapturedStmt()->IgnoreContainers();
Bill Wendling7c44da22018-10-31 03:48:47 +00004733 if (const auto *FE = dyn_cast<FullExpr>(CS))
4734 enterFullExpression(FE);
Alexey Bataev5e018f92015-04-23 06:35:10 +00004735 // Processing for statements under 'atomic capture'.
4736 if (const auto *Compound = dyn_cast<CompoundStmt>(CS)) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00004737 for (const Stmt *C : Compound->body()) {
Bill Wendling7c44da22018-10-31 03:48:47 +00004738 if (const auto *FE = dyn_cast<FullExpr>(C))
4739 enterFullExpression(FE);
Alexey Bataev5e018f92015-04-23 06:35:10 +00004740 }
4741 }
Alexey Bataev10fec572015-03-11 04:48:56 +00004742
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004743 auto &&CodeGen = [&S, Kind, AO, CS](CodeGenFunction &CGF,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004744 PrePostActionTy &) {
Alexey Bataev33c56402015-12-14 09:26:19 +00004745 CGF.EmitStopPoint(CS);
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004746 emitOMPAtomicExpr(CGF, Kind, AO, S.isPostfixUpdate(), S.getX(), S.getV(),
4747 S.getExpr(), S.getUpdateExpr(), S.isXLHSInRHSPart(),
4748 S.getBeginLoc());
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00004749 };
Alexey Bataev475a7442018-01-12 19:39:11 +00004750 OMPLexicalScope Scope(*this, S, OMPD_unknown);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00004751 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_atomic, CodeGen);
Alexey Bataev0162e452014-07-22 10:10:35 +00004752}
4753
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00004754static void emitCommonOMPTargetDirective(CodeGenFunction &CGF,
4755 const OMPExecutableDirective &S,
4756 const RegionCodeGenTy &CodeGen) {
4757 assert(isOpenMPTargetExecutionDirective(S.getDirectiveKind()));
4758 CodeGenModule &CGM = CGF.CGM;
Samuel Antaobed3c462015-10-02 16:14:20 +00004759
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00004760 // On device emit this construct as inlined code.
4761 if (CGM.getLangOpts().OpenMPIsDevice) {
4762 OMPLexicalScope Scope(CGF, S, OMPD_target);
4763 CGM.getOpenMPRuntime().emitInlinedDirective(
4764 CGF, OMPD_target, [&S](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataev4ac68a22018-05-16 15:08:32 +00004765 CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00004766 });
4767 return;
4768 }
4769
Alexey Bataev46978742020-01-30 10:46:11 -05004770 auto LPCRegion =
4771 CGOpenMPRuntime::LastprivateConditionalRAII::disable(CGF, S);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004772 llvm::Function *Fn = nullptr;
4773 llvm::Constant *FnID = nullptr;
Samuel Antaobed3c462015-10-02 16:14:20 +00004774
Samuel Antaobed3c462015-10-02 16:14:20 +00004775 const Expr *IfCond = nullptr;
Arpith Chacko Jacobfe4890a2017-01-18 20:40:48 +00004776 // Check for the at most one if clause associated with the target region.
4777 for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
4778 if (C->getNameModifier() == OMPD_unknown ||
4779 C->getNameModifier() == OMPD_target) {
4780 IfCond = C->getCondition();
4781 break;
4782 }
Samuel Antaobed3c462015-10-02 16:14:20 +00004783 }
4784
4785 // Check if we have any device clause associated with the directive.
4786 const Expr *Device = nullptr;
Alexey Bataevddf3db92018-04-13 17:31:06 +00004787 if (auto *C = S.getSingleClause<OMPDeviceClause>())
Samuel Antaobed3c462015-10-02 16:14:20 +00004788 Device = C->getDevice();
Samuel Antaobed3c462015-10-02 16:14:20 +00004789
Samuel Antaoee8fb302016-01-06 13:42:12 +00004790 // Check if we have an if clause whose conditional always evaluates to false
4791 // or if we do not have any targets specified. If so the target region is not
4792 // an offload entry point.
4793 bool IsOffloadEntry = true;
4794 if (IfCond) {
4795 bool Val;
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00004796 if (CGF.ConstantFoldsToSimpleInteger(IfCond, Val) && !Val)
Samuel Antaoee8fb302016-01-06 13:42:12 +00004797 IsOffloadEntry = false;
4798 }
4799 if (CGM.getLangOpts().OMPTargetTriples.empty())
4800 IsOffloadEntry = false;
4801
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00004802 assert(CGF.CurFuncDecl && "No parent declaration for target region!");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004803 StringRef ParentName;
4804 // In case we have Ctors/Dtors we use the complete type variant to produce
4805 // the mangling of the device outlined kernel.
Alexey Bataevddf3db92018-04-13 17:31:06 +00004806 if (const auto *D = dyn_cast<CXXConstructorDecl>(CGF.CurFuncDecl))
Samuel Antaoee8fb302016-01-06 13:42:12 +00004807 ParentName = CGM.getMangledName(GlobalDecl(D, Ctor_Complete));
Alexey Bataevddf3db92018-04-13 17:31:06 +00004808 else if (const auto *D = dyn_cast<CXXDestructorDecl>(CGF.CurFuncDecl))
Samuel Antaoee8fb302016-01-06 13:42:12 +00004809 ParentName = CGM.getMangledName(GlobalDecl(D, Dtor_Complete));
4810 else
4811 ParentName =
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00004812 CGM.getMangledName(GlobalDecl(cast<FunctionDecl>(CGF.CurFuncDecl)));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004813
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00004814 // Emit target region as a standalone region.
4815 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(S, ParentName, Fn, FnID,
4816 IsOffloadEntry, CodeGen);
Alexey Bataev8451efa2018-01-15 19:06:12 +00004817 OMPLexicalScope Scope(CGF, S, OMPD_task);
Alexey Bataevec7946e2019-09-23 14:06:51 +00004818 auto &&SizeEmitter =
4819 [IsOffloadEntry](CodeGenFunction &CGF,
4820 const OMPLoopDirective &D) -> llvm::Value * {
4821 if (IsOffloadEntry) {
4822 OMPLoopScope(CGF, D);
4823 // Emit calculation of the iterations count.
4824 llvm::Value *NumIterations = CGF.EmitScalarExpr(D.getNumIterations());
4825 NumIterations = CGF.Builder.CreateIntCast(NumIterations, CGF.Int64Ty,
4826 /*isSigned=*/false);
4827 return NumIterations;
4828 }
4829 return nullptr;
Alexey Bataev7bb33532019-01-07 21:30:43 +00004830 };
Alexey Bataevec7946e2019-09-23 14:06:51 +00004831 CGM.getOpenMPRuntime().emitTargetCall(CGF, S, Fn, FnID, IfCond, Device,
4832 SizeEmitter);
Alexey Bataev0bd520b2014-09-19 08:19:49 +00004833}
4834
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00004835static void emitTargetRegion(CodeGenFunction &CGF, const OMPTargetDirective &S,
4836 PrePostActionTy &Action) {
Alexey Bataev63cc8e92018-03-20 14:45:59 +00004837 Action.Enter(CGF);
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00004838 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
4839 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
4840 CGF.EmitOMPPrivateClause(S, PrivateScope);
4841 (void)PrivateScope.Privatize();
Alexey Bataev60705422018-10-30 15:50:12 +00004842 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()))
4843 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00004844
Alexey Bataev475a7442018-01-12 19:39:11 +00004845 CGF.EmitStmt(S.getCapturedStmt(OMPD_target)->getCapturedStmt());
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00004846}
4847
4848void CodeGenFunction::EmitOMPTargetDeviceFunction(CodeGenModule &CGM,
4849 StringRef ParentName,
4850 const OMPTargetDirective &S) {
4851 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
4852 emitTargetRegion(CGF, S, Action);
4853 };
4854 llvm::Function *Fn;
4855 llvm::Constant *Addr;
4856 // Emit target region as a standalone region.
4857 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
4858 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
4859 assert(Fn && Addr && "Target device function emission failed.");
4860}
4861
4862void CodeGenFunction::EmitOMPTargetDirective(const OMPTargetDirective &S) {
4863 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
4864 emitTargetRegion(CGF, S, Action);
4865 };
4866 emitCommonOMPTargetDirective(*this, S, CodeGen);
4867}
4868
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00004869static void emitCommonOMPTeamsDirective(CodeGenFunction &CGF,
4870 const OMPExecutableDirective &S,
4871 OpenMPDirectiveKind InnermostKind,
4872 const RegionCodeGenTy &CodeGen) {
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00004873 const CapturedStmt *CS = S.getCapturedStmt(OMPD_teams);
James Y Knight9871db02019-02-05 16:42:33 +00004874 llvm::Function *OutlinedFn =
Alexey Bataevddf3db92018-04-13 17:31:06 +00004875 CGF.CGM.getOpenMPRuntime().emitTeamsOutlinedFunction(
4876 S, *CS->getCapturedDecl()->param_begin(), InnermostKind, CodeGen);
Samuel Antaob68e2db2016-03-03 16:20:23 +00004877
Alexey Bataevddf3db92018-04-13 17:31:06 +00004878 const auto *NT = S.getSingleClause<OMPNumTeamsClause>();
4879 const auto *TL = S.getSingleClause<OMPThreadLimitClause>();
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00004880 if (NT || TL) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00004881 const Expr *NumTeams = NT ? NT->getNumTeams() : nullptr;
4882 const Expr *ThreadLimit = TL ? TL->getThreadLimit() : nullptr;
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00004883
Carlo Bertollic6872252016-04-04 15:55:02 +00004884 CGF.CGM.getOpenMPRuntime().emitNumTeamsClause(CGF, NumTeams, ThreadLimit,
Stephen Kellyf2ceec42018-08-09 21:08:08 +00004885 S.getBeginLoc());
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00004886 }
4887
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00004888 OMPTeamsScope Scope(CGF, S);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004889 llvm::SmallVector<llvm::Value *, 16> CapturedVars;
4890 CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
Stephen Kellyf2ceec42018-08-09 21:08:08 +00004891 CGF.CGM.getOpenMPRuntime().emitTeamsCall(CGF, S, S.getBeginLoc(), OutlinedFn,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00004892 CapturedVars);
4893}
4894
4895void CodeGenFunction::EmitOMPTeamsDirective(const OMPTeamsDirective &S) {
Kelvin Li51336dd2016-12-15 17:55:32 +00004896 // Emit teams region as a standalone region.
Alexey Bataevc99042b2018-03-15 18:10:54 +00004897 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataev63cc8e92018-03-20 14:45:59 +00004898 Action.Enter(CGF);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00004899 OMPPrivateScope PrivateScope(CGF);
Carlo Bertolli6ad7b5a2016-03-03 22:09:40 +00004900 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
4901 CGF.EmitOMPPrivateClause(S, PrivateScope);
Arpith Chacko Jacobfc711b12017-02-16 16:48:49 +00004902 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00004903 (void)PrivateScope.Privatize();
Alexey Bataev475a7442018-01-12 19:39:11 +00004904 CGF.EmitStmt(S.getCapturedStmt(OMPD_teams)->getCapturedStmt());
Arpith Chacko Jacobfc711b12017-02-16 16:48:49 +00004905 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00004906 };
Alexey Bataev2139ed62017-11-16 18:20:21 +00004907 emitCommonOMPTeamsDirective(*this, S, OMPD_distribute, CodeGen);
Alexey Bataevddf3db92018-04-13 17:31:06 +00004908 emitPostUpdateForReductionClause(*this, S,
4909 [](CodeGenFunction &) { return nullptr; });
Alexey Bataev13314bf2014-10-09 04:18:56 +00004910}
Alexey Bataev6d4ed052015-07-01 06:57:41 +00004911
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00004912static void emitTargetTeamsRegion(CodeGenFunction &CGF, PrePostActionTy &Action,
4913 const OMPTargetTeamsDirective &S) {
4914 auto *CS = S.getCapturedStmt(OMPD_teams);
4915 Action.Enter(CGF);
Alexey Bataevf9fc42e2017-11-22 14:25:55 +00004916 // Emit teams region as a standalone region.
4917 auto &&CodeGen = [&S, CS](CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataev63cc8e92018-03-20 14:45:59 +00004918 Action.Enter(CGF);
Alexey Bataevf9fc42e2017-11-22 14:25:55 +00004919 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
4920 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
4921 CGF.EmitOMPPrivateClause(S, PrivateScope);
4922 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
4923 (void)PrivateScope.Privatize();
Alexey Bataev60705422018-10-30 15:50:12 +00004924 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()))
4925 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00004926 CGF.EmitStmt(CS->getCapturedStmt());
Alexey Bataevf9fc42e2017-11-22 14:25:55 +00004927 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00004928 };
4929 emitCommonOMPTeamsDirective(CGF, S, OMPD_teams, CodeGen);
Alexey Bataevddf3db92018-04-13 17:31:06 +00004930 emitPostUpdateForReductionClause(CGF, S,
4931 [](CodeGenFunction &) { return nullptr; });
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00004932}
4933
4934void CodeGenFunction::EmitOMPTargetTeamsDeviceFunction(
4935 CodeGenModule &CGM, StringRef ParentName,
4936 const OMPTargetTeamsDirective &S) {
4937 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
4938 emitTargetTeamsRegion(CGF, Action, S);
4939 };
4940 llvm::Function *Fn;
4941 llvm::Constant *Addr;
4942 // Emit target region as a standalone region.
4943 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
4944 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
4945 assert(Fn && Addr && "Target device function emission failed.");
4946}
4947
4948void CodeGenFunction::EmitOMPTargetTeamsDirective(
4949 const OMPTargetTeamsDirective &S) {
4950 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
4951 emitTargetTeamsRegion(CGF, Action, S);
4952 };
4953 emitCommonOMPTargetDirective(*this, S, CodeGen);
4954}
4955
Alexey Bataevdfa430f2017-12-08 15:03:50 +00004956static void
4957emitTargetTeamsDistributeRegion(CodeGenFunction &CGF, PrePostActionTy &Action,
4958 const OMPTargetTeamsDistributeDirective &S) {
4959 Action.Enter(CGF);
4960 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
4961 CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc());
4962 };
4963
4964 // Emit teams region as a standalone region.
4965 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
Alexey Bataevc99042b2018-03-15 18:10:54 +00004966 PrePostActionTy &Action) {
Alexey Bataev63cc8e92018-03-20 14:45:59 +00004967 Action.Enter(CGF);
Alexey Bataevdfa430f2017-12-08 15:03:50 +00004968 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
4969 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
4970 (void)PrivateScope.Privatize();
4971 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute,
4972 CodeGenDistribute);
4973 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
4974 };
4975 emitCommonOMPTeamsDirective(CGF, S, OMPD_distribute, CodeGen);
4976 emitPostUpdateForReductionClause(CGF, S,
4977 [](CodeGenFunction &) { return nullptr; });
4978}
4979
4980void CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction(
4981 CodeGenModule &CGM, StringRef ParentName,
4982 const OMPTargetTeamsDistributeDirective &S) {
4983 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
4984 emitTargetTeamsDistributeRegion(CGF, Action, S);
4985 };
4986 llvm::Function *Fn;
4987 llvm::Constant *Addr;
4988 // Emit target region as a standalone region.
4989 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
4990 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
4991 assert(Fn && Addr && "Target device function emission failed.");
4992}
4993
4994void CodeGenFunction::EmitOMPTargetTeamsDistributeDirective(
4995 const OMPTargetTeamsDistributeDirective &S) {
4996 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
4997 emitTargetTeamsDistributeRegion(CGF, Action, S);
4998 };
4999 emitCommonOMPTargetDirective(*this, S, CodeGen);
5000}
5001
Alexey Bataevfbe17fb2017-12-13 19:45:06 +00005002static void emitTargetTeamsDistributeSimdRegion(
5003 CodeGenFunction &CGF, PrePostActionTy &Action,
5004 const OMPTargetTeamsDistributeSimdDirective &S) {
5005 Action.Enter(CGF);
5006 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
5007 CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc());
5008 };
5009
5010 // Emit teams region as a standalone region.
5011 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
Alexey Bataevc99042b2018-03-15 18:10:54 +00005012 PrePostActionTy &Action) {
Alexey Bataev63cc8e92018-03-20 14:45:59 +00005013 Action.Enter(CGF);
Alexey Bataevfbe17fb2017-12-13 19:45:06 +00005014 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
5015 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
5016 (void)PrivateScope.Privatize();
5017 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute,
5018 CodeGenDistribute);
5019 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
5020 };
5021 emitCommonOMPTeamsDirective(CGF, S, OMPD_distribute_simd, CodeGen);
5022 emitPostUpdateForReductionClause(CGF, S,
5023 [](CodeGenFunction &) { return nullptr; });
5024}
5025
5026void CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction(
5027 CodeGenModule &CGM, StringRef ParentName,
5028 const OMPTargetTeamsDistributeSimdDirective &S) {
5029 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5030 emitTargetTeamsDistributeSimdRegion(CGF, Action, S);
5031 };
5032 llvm::Function *Fn;
5033 llvm::Constant *Addr;
5034 // Emit target region as a standalone region.
5035 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
5036 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
5037 assert(Fn && Addr && "Target device function emission failed.");
5038}
5039
5040void CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDirective(
5041 const OMPTargetTeamsDistributeSimdDirective &S) {
5042 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5043 emitTargetTeamsDistributeSimdRegion(CGF, Action, S);
5044 };
5045 emitCommonOMPTargetDirective(*this, S, CodeGen);
5046}
5047
Carlo Bertolliba1487b2017-10-04 14:12:09 +00005048void CodeGenFunction::EmitOMPTeamsDistributeDirective(
5049 const OMPTeamsDistributeDirective &S) {
5050
5051 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
5052 CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc());
5053 };
5054
5055 // Emit teams region as a standalone region.
5056 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
Alexey Bataevc99042b2018-03-15 18:10:54 +00005057 PrePostActionTy &Action) {
Alexey Bataev63cc8e92018-03-20 14:45:59 +00005058 Action.Enter(CGF);
Carlo Bertolliba1487b2017-10-04 14:12:09 +00005059 OMPPrivateScope PrivateScope(CGF);
5060 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
5061 (void)PrivateScope.Privatize();
5062 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute,
5063 CodeGenDistribute);
5064 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
5065 };
Alexey Bataev95c6dd42017-11-29 15:14:16 +00005066 emitCommonOMPTeamsDirective(*this, S, OMPD_distribute, CodeGen);
Carlo Bertolliba1487b2017-10-04 14:12:09 +00005067 emitPostUpdateForReductionClause(*this, S,
5068 [](CodeGenFunction &) { return nullptr; });
5069}
5070
Alexey Bataev999277a2017-12-06 14:31:09 +00005071void CodeGenFunction::EmitOMPTeamsDistributeSimdDirective(
5072 const OMPTeamsDistributeSimdDirective &S) {
5073 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
5074 CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc());
5075 };
5076
5077 // Emit teams region as a standalone region.
5078 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
Alexey Bataevc99042b2018-03-15 18:10:54 +00005079 PrePostActionTy &Action) {
Alexey Bataev63cc8e92018-03-20 14:45:59 +00005080 Action.Enter(CGF);
Alexey Bataev999277a2017-12-06 14:31:09 +00005081 OMPPrivateScope PrivateScope(CGF);
5082 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
5083 (void)PrivateScope.Privatize();
5084 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_simd,
5085 CodeGenDistribute);
5086 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
5087 };
5088 emitCommonOMPTeamsDirective(*this, S, OMPD_distribute_simd, CodeGen);
5089 emitPostUpdateForReductionClause(*this, S,
5090 [](CodeGenFunction &) { return nullptr; });
5091}
5092
Carlo Bertolli62fae152017-11-20 20:46:39 +00005093void CodeGenFunction::EmitOMPTeamsDistributeParallelForDirective(
5094 const OMPTeamsDistributeParallelForDirective &S) {
5095 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
5096 CGF.EmitOMPDistributeLoop(S, emitInnerParallelForWhenCombined,
5097 S.getDistInc());
5098 };
5099
5100 // Emit teams region as a standalone region.
5101 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
Alexey Bataevc99042b2018-03-15 18:10:54 +00005102 PrePostActionTy &Action) {
Alexey Bataev63cc8e92018-03-20 14:45:59 +00005103 Action.Enter(CGF);
Carlo Bertolli62fae152017-11-20 20:46:39 +00005104 OMPPrivateScope PrivateScope(CGF);
5105 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
5106 (void)PrivateScope.Privatize();
Alexey Bataev10a54312017-11-27 16:54:08 +00005107 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute,
5108 CodeGenDistribute);
Carlo Bertolli62fae152017-11-20 20:46:39 +00005109 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
5110 };
5111 emitCommonOMPTeamsDirective(*this, S, OMPD_distribute_parallel_for, CodeGen);
5112 emitPostUpdateForReductionClause(*this, S,
5113 [](CodeGenFunction &) { return nullptr; });
5114}
5115
Carlo Bertolli56a2aa42017-12-04 20:57:19 +00005116void CodeGenFunction::EmitOMPTeamsDistributeParallelForSimdDirective(
5117 const OMPTeamsDistributeParallelForSimdDirective &S) {
5118 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
5119 CGF.EmitOMPDistributeLoop(S, emitInnerParallelForWhenCombined,
5120 S.getDistInc());
5121 };
5122
5123 // Emit teams region as a standalone region.
5124 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
Alexey Bataevc99042b2018-03-15 18:10:54 +00005125 PrePostActionTy &Action) {
Alexey Bataev63cc8e92018-03-20 14:45:59 +00005126 Action.Enter(CGF);
Carlo Bertolli56a2aa42017-12-04 20:57:19 +00005127 OMPPrivateScope PrivateScope(CGF);
5128 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
5129 (void)PrivateScope.Privatize();
5130 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(
5131 CGF, OMPD_distribute, CodeGenDistribute, /*HasCancel=*/false);
5132 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
5133 };
Alexey Bataev0b978942019-12-11 15:26:38 -05005134 emitCommonOMPTeamsDirective(*this, S, OMPD_distribute_parallel_for_simd,
5135 CodeGen);
Carlo Bertolli56a2aa42017-12-04 20:57:19 +00005136 emitPostUpdateForReductionClause(*this, S,
5137 [](CodeGenFunction &) { return nullptr; });
5138}
5139
Carlo Bertolli52978c32018-01-03 21:12:44 +00005140static void emitTargetTeamsDistributeParallelForRegion(
5141 CodeGenFunction &CGF, const OMPTargetTeamsDistributeParallelForDirective &S,
5142 PrePostActionTy &Action) {
Carlo Bertolli79712092018-02-28 20:48:35 +00005143 Action.Enter(CGF);
Carlo Bertolli52978c32018-01-03 21:12:44 +00005144 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
5145 CGF.EmitOMPDistributeLoop(S, emitInnerParallelForWhenCombined,
5146 S.getDistInc());
5147 };
5148
5149 // Emit teams region as a standalone region.
5150 auto &&CodeGenTeams = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
Alexey Bataevc99042b2018-03-15 18:10:54 +00005151 PrePostActionTy &Action) {
Alexey Bataev63cc8e92018-03-20 14:45:59 +00005152 Action.Enter(CGF);
Carlo Bertolli52978c32018-01-03 21:12:44 +00005153 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
5154 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
5155 (void)PrivateScope.Privatize();
5156 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(
5157 CGF, OMPD_distribute, CodeGenDistribute, /*HasCancel=*/false);
5158 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
5159 };
5160
5161 emitCommonOMPTeamsDirective(CGF, S, OMPD_distribute_parallel_for,
5162 CodeGenTeams);
5163 emitPostUpdateForReductionClause(CGF, S,
5164 [](CodeGenFunction &) { return nullptr; });
5165}
5166
5167void CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction(
5168 CodeGenModule &CGM, StringRef ParentName,
5169 const OMPTargetTeamsDistributeParallelForDirective &S) {
5170 // Emit SPMD target teams distribute parallel for region as a standalone
5171 // region.
5172 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5173 emitTargetTeamsDistributeParallelForRegion(CGF, S, Action);
5174 };
5175 llvm::Function *Fn;
5176 llvm::Constant *Addr;
5177 // Emit target region as a standalone region.
5178 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
5179 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
5180 assert(Fn && Addr && "Target device function emission failed.");
5181}
5182
5183void CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDirective(
5184 const OMPTargetTeamsDistributeParallelForDirective &S) {
5185 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5186 emitTargetTeamsDistributeParallelForRegion(CGF, S, Action);
5187 };
5188 emitCommonOMPTargetDirective(*this, S, CodeGen);
5189}
5190
Alexey Bataev647dd842018-01-15 20:59:40 +00005191static void emitTargetTeamsDistributeParallelForSimdRegion(
5192 CodeGenFunction &CGF,
5193 const OMPTargetTeamsDistributeParallelForSimdDirective &S,
5194 PrePostActionTy &Action) {
Carlo Bertolli79712092018-02-28 20:48:35 +00005195 Action.Enter(CGF);
Alexey Bataev647dd842018-01-15 20:59:40 +00005196 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
5197 CGF.EmitOMPDistributeLoop(S, emitInnerParallelForWhenCombined,
5198 S.getDistInc());
5199 };
5200
5201 // Emit teams region as a standalone region.
5202 auto &&CodeGenTeams = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
Alexey Bataevc99042b2018-03-15 18:10:54 +00005203 PrePostActionTy &Action) {
Alexey Bataev63cc8e92018-03-20 14:45:59 +00005204 Action.Enter(CGF);
Alexey Bataev647dd842018-01-15 20:59:40 +00005205 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
5206 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
5207 (void)PrivateScope.Privatize();
5208 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(
5209 CGF, OMPD_distribute, CodeGenDistribute, /*HasCancel=*/false);
5210 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
5211 };
5212
5213 emitCommonOMPTeamsDirective(CGF, S, OMPD_distribute_parallel_for_simd,
5214 CodeGenTeams);
5215 emitPostUpdateForReductionClause(CGF, S,
5216 [](CodeGenFunction &) { return nullptr; });
5217}
5218
5219void CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(
5220 CodeGenModule &CGM, StringRef ParentName,
5221 const OMPTargetTeamsDistributeParallelForSimdDirective &S) {
5222 // Emit SPMD target teams distribute parallel for simd region as a standalone
5223 // region.
5224 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5225 emitTargetTeamsDistributeParallelForSimdRegion(CGF, S, Action);
5226 };
5227 llvm::Function *Fn;
5228 llvm::Constant *Addr;
5229 // Emit target region as a standalone region.
5230 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
5231 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
5232 assert(Fn && Addr && "Target device function emission failed.");
5233}
5234
5235void CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForSimdDirective(
5236 const OMPTargetTeamsDistributeParallelForSimdDirective &S) {
5237 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5238 emitTargetTeamsDistributeParallelForSimdRegion(CGF, S, Action);
5239 };
5240 emitCommonOMPTargetDirective(*this, S, CodeGen);
5241}
5242
Alexey Bataev6d4ed052015-07-01 06:57:41 +00005243void CodeGenFunction::EmitOMPCancellationPointDirective(
5244 const OMPCancellationPointDirective &S) {
Stephen Kellyf2ceec42018-08-09 21:08:08 +00005245 CGM.getOpenMPRuntime().emitCancellationPointCall(*this, S.getBeginLoc(),
Alexey Bataev0f34da12015-07-02 04:17:07 +00005246 S.getCancelRegion());
Alexey Bataev6d4ed052015-07-01 06:57:41 +00005247}
5248
Alexey Bataev80909872015-07-02 11:25:17 +00005249void CodeGenFunction::EmitOMPCancelDirective(const OMPCancelDirective &S) {
Alexey Bataev87933c72015-09-18 08:07:34 +00005250 const Expr *IfCond = nullptr;
5251 for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
5252 if (C->getNameModifier() == OMPD_unknown ||
5253 C->getNameModifier() == OMPD_cancel) {
5254 IfCond = C->getCondition();
5255 break;
5256 }
5257 }
Johannes Doerfert10fedd92019-12-26 11:23:38 -06005258 if (llvm::OpenMPIRBuilder *OMPBuilder = CGM.getOpenMPIRBuilder()) {
5259 // TODO: This check is necessary as we only generate `omp parallel` through
5260 // the OpenMPIRBuilder for now.
5261 if (S.getCancelRegion() == OMPD_parallel) {
5262 llvm::Value *IfCondition = nullptr;
5263 if (IfCond)
5264 IfCondition = EmitScalarExpr(IfCond,
5265 /*IgnoreResultAssign=*/true);
5266 return Builder.restoreIP(
5267 OMPBuilder->CreateCancel(Builder, IfCondition, S.getCancelRegion()));
5268 }
5269 }
5270
Stephen Kellyf2ceec42018-08-09 21:08:08 +00005271 CGM.getOpenMPRuntime().emitCancelCall(*this, S.getBeginLoc(), IfCond,
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00005272 S.getCancelRegion());
Alexey Bataev80909872015-07-02 11:25:17 +00005273}
5274
Alexey Bataev81c7ea02015-07-03 09:56:58 +00005275CodeGenFunction::JumpDest
5276CodeGenFunction::getOMPCancelDestination(OpenMPDirectiveKind Kind) {
Alexey Bataev957d8562016-11-17 15:12:05 +00005277 if (Kind == OMPD_parallel || Kind == OMPD_task ||
Alexey Bataeve0ca4792020-02-12 16:12:53 -05005278 Kind == OMPD_target_parallel || Kind == OMPD_taskloop ||
5279 Kind == OMPD_master_taskloop || Kind == OMPD_parallel_master_taskloop)
Alexey Bataev81c7ea02015-07-03 09:56:58 +00005280 return ReturnBlock;
Alexey Bataev25e5b442015-09-15 12:52:43 +00005281 assert(Kind == OMPD_for || Kind == OMPD_section || Kind == OMPD_sections ||
Alexey Bataev957d8562016-11-17 15:12:05 +00005282 Kind == OMPD_parallel_sections || Kind == OMPD_parallel_for ||
5283 Kind == OMPD_distribute_parallel_for ||
Alexey Bataevdcb4b8fb2017-11-22 20:19:50 +00005284 Kind == OMPD_target_parallel_for ||
Alexey Bataev16e79882017-11-22 21:12:03 +00005285 Kind == OMPD_teams_distribute_parallel_for ||
5286 Kind == OMPD_target_teams_distribute_parallel_for);
Alexey Bataev957d8562016-11-17 15:12:05 +00005287 return OMPCancelStack.getExitBlock();
Alexey Bataev81c7ea02015-07-03 09:56:58 +00005288}
Michael Wong65f367f2015-07-21 13:44:28 +00005289
Samuel Antaocc10b852016-07-28 14:23:26 +00005290void CodeGenFunction::EmitOMPUseDevicePtrClause(
5291 const OMPClause &NC, OMPPrivateScope &PrivateScope,
5292 const llvm::DenseMap<const ValueDecl *, Address> &CaptureDeviceAddrMap) {
5293 const auto &C = cast<OMPUseDevicePtrClause>(NC);
5294 auto OrigVarIt = C.varlist_begin();
5295 auto InitIt = C.inits().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00005296 for (const Expr *PvtVarIt : C.private_copies()) {
5297 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*OrigVarIt)->getDecl());
5298 const auto *InitVD = cast<VarDecl>(cast<DeclRefExpr>(*InitIt)->getDecl());
5299 const auto *PvtVD = cast<VarDecl>(cast<DeclRefExpr>(PvtVarIt)->getDecl());
Samuel Antaocc10b852016-07-28 14:23:26 +00005300
5301 // In order to identify the right initializer we need to match the
5302 // declaration used by the mapping logic. In some cases we may get
5303 // OMPCapturedExprDecl that refers to the original declaration.
5304 const ValueDecl *MatchingVD = OrigVD;
Alexey Bataevddf3db92018-04-13 17:31:06 +00005305 if (const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
Samuel Antaocc10b852016-07-28 14:23:26 +00005306 // OMPCapturedExprDecl are used to privative fields of the current
5307 // structure.
Alexey Bataevddf3db92018-04-13 17:31:06 +00005308 const auto *ME = cast<MemberExpr>(OED->getInit());
Samuel Antaocc10b852016-07-28 14:23:26 +00005309 assert(isa<CXXThisExpr>(ME->getBase()) &&
5310 "Base should be the current struct!");
5311 MatchingVD = ME->getMemberDecl();
5312 }
5313
5314 // If we don't have information about the current list item, move on to
5315 // the next one.
5316 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
5317 if (InitAddrIt == CaptureDeviceAddrMap.end())
5318 continue;
5319
Alexey Bataevddf3db92018-04-13 17:31:06 +00005320 bool IsRegistered = PrivateScope.addPrivate(OrigVD, [this, OrigVD,
5321 InitAddrIt, InitVD,
5322 PvtVD]() {
Samuel Antaocc10b852016-07-28 14:23:26 +00005323 // Initialize the temporary initialization variable with the address we
5324 // get from the runtime library. We have to cast the source address
5325 // because it is always a void *. References are materialized in the
5326 // privatization scope, so the initialization here disregards the fact
5327 // the original variable is a reference.
5328 QualType AddrQTy =
5329 getContext().getPointerType(OrigVD->getType().getNonReferenceType());
5330 llvm::Type *AddrTy = ConvertTypeForMem(AddrQTy);
5331 Address InitAddr = Builder.CreateBitCast(InitAddrIt->second, AddrTy);
5332 setAddrOfLocalVar(InitVD, InitAddr);
5333
5334 // Emit private declaration, it will be initialized by the value we
5335 // declaration we just added to the local declarations map.
5336 EmitDecl(*PvtVD);
5337
5338 // The initialization variables reached its purpose in the emission
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00005339 // of the previous declaration, so we don't need it anymore.
Samuel Antaocc10b852016-07-28 14:23:26 +00005340 LocalDeclMap.erase(InitVD);
5341
5342 // Return the address of the private variable.
5343 return GetAddrOfLocalVar(PvtVD);
5344 });
5345 assert(IsRegistered && "firstprivate var already registered as private");
5346 // Silence the warning about unused variable.
5347 (void)IsRegistered;
5348
5349 ++OrigVarIt;
5350 ++InitIt;
5351 }
5352}
5353
Michael Wong65f367f2015-07-21 13:44:28 +00005354// Generate the instructions for '#pragma omp target data' directive.
5355void CodeGenFunction::EmitOMPTargetDataDirective(
5356 const OMPTargetDataDirective &S) {
Samuel Antaocc10b852016-07-28 14:23:26 +00005357 CGOpenMPRuntime::TargetDataInfo Info(/*RequiresDevicePointerInfo=*/true);
5358
5359 // Create a pre/post action to signal the privatization of the device pointer.
5360 // This action can be replaced by the OpenMP runtime code generation to
5361 // deactivate privatization.
5362 bool PrivatizeDevicePointers = false;
5363 class DevicePointerPrivActionTy : public PrePostActionTy {
5364 bool &PrivatizeDevicePointers;
5365
5366 public:
5367 explicit DevicePointerPrivActionTy(bool &PrivatizeDevicePointers)
5368 : PrePostActionTy(), PrivatizeDevicePointers(PrivatizeDevicePointers) {}
5369 void Enter(CodeGenFunction &CGF) override {
5370 PrivatizeDevicePointers = true;
5371 }
Samuel Antaodf158d52016-04-27 22:58:19 +00005372 };
Samuel Antaocc10b852016-07-28 14:23:26 +00005373 DevicePointerPrivActionTy PrivAction(PrivatizeDevicePointers);
5374
5375 auto &&CodeGen = [&S, &Info, &PrivatizeDevicePointers](
Alexey Bataev475a7442018-01-12 19:39:11 +00005376 CodeGenFunction &CGF, PrePostActionTy &Action) {
Samuel Antaocc10b852016-07-28 14:23:26 +00005377 auto &&InnermostCodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataev475a7442018-01-12 19:39:11 +00005378 CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
Samuel Antaocc10b852016-07-28 14:23:26 +00005379 };
5380
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00005381 // Codegen that selects whether to generate the privatization code or not.
Samuel Antaocc10b852016-07-28 14:23:26 +00005382 auto &&PrivCodeGen = [&S, &Info, &PrivatizeDevicePointers,
5383 &InnermostCodeGen](CodeGenFunction &CGF,
5384 PrePostActionTy &Action) {
5385 RegionCodeGenTy RCG(InnermostCodeGen);
5386 PrivatizeDevicePointers = false;
5387
5388 // Call the pre-action to change the status of PrivatizeDevicePointers if
5389 // needed.
5390 Action.Enter(CGF);
5391
5392 if (PrivatizeDevicePointers) {
5393 OMPPrivateScope PrivateScope(CGF);
5394 // Emit all instances of the use_device_ptr clause.
5395 for (const auto *C : S.getClausesOfKind<OMPUseDevicePtrClause>())
5396 CGF.EmitOMPUseDevicePtrClause(*C, PrivateScope,
5397 Info.CaptureDeviceAddrMap);
5398 (void)PrivateScope.Privatize();
5399 RCG(CGF);
Alexey Bataevddf3db92018-04-13 17:31:06 +00005400 } else {
Samuel Antaocc10b852016-07-28 14:23:26 +00005401 RCG(CGF);
Alexey Bataevddf3db92018-04-13 17:31:06 +00005402 }
Samuel Antaocc10b852016-07-28 14:23:26 +00005403 };
5404
5405 // Forward the provided action to the privatization codegen.
5406 RegionCodeGenTy PrivRCG(PrivCodeGen);
5407 PrivRCG.setAction(Action);
5408
5409 // Notwithstanding the body of the region is emitted as inlined directive,
5410 // we don't use an inline scope as changes in the references inside the
5411 // region are expected to be visible outside, so we do not privative them.
5412 OMPLexicalScope Scope(CGF, S);
5413 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_target_data,
5414 PrivRCG);
5415 };
5416
5417 RegionCodeGenTy RCG(CodeGen);
Samuel Antaodf158d52016-04-27 22:58:19 +00005418
5419 // If we don't have target devices, don't bother emitting the data mapping
5420 // code.
5421 if (CGM.getLangOpts().OMPTargetTriples.empty()) {
Samuel Antaocc10b852016-07-28 14:23:26 +00005422 RCG(*this);
Samuel Antaodf158d52016-04-27 22:58:19 +00005423 return;
5424 }
5425
5426 // Check if we have any if clause associated with the directive.
5427 const Expr *IfCond = nullptr;
Alexey Bataevddf3db92018-04-13 17:31:06 +00005428 if (const auto *C = S.getSingleClause<OMPIfClause>())
Samuel Antaodf158d52016-04-27 22:58:19 +00005429 IfCond = C->getCondition();
5430
5431 // Check if we have any device clause associated with the directive.
5432 const Expr *Device = nullptr;
Alexey Bataevddf3db92018-04-13 17:31:06 +00005433 if (const auto *C = S.getSingleClause<OMPDeviceClause>())
Samuel Antaodf158d52016-04-27 22:58:19 +00005434 Device = C->getDevice();
5435
Samuel Antaocc10b852016-07-28 14:23:26 +00005436 // Set the action to signal privatization of device pointers.
5437 RCG.setAction(PrivAction);
5438
5439 // Emit region code.
5440 CGM.getOpenMPRuntime().emitTargetDataCalls(*this, S, IfCond, Device, RCG,
5441 Info);
Michael Wong65f367f2015-07-21 13:44:28 +00005442}
Alexey Bataev49f6e782015-12-01 04:18:41 +00005443
Samuel Antaodf67fc42016-01-19 19:15:56 +00005444void CodeGenFunction::EmitOMPTargetEnterDataDirective(
5445 const OMPTargetEnterDataDirective &S) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00005446 // If we don't have target devices, don't bother emitting the data mapping
5447 // code.
5448 if (CGM.getLangOpts().OMPTargetTriples.empty())
5449 return;
5450
5451 // Check if we have any if clause associated with the directive.
5452 const Expr *IfCond = nullptr;
Alexey Bataevddf3db92018-04-13 17:31:06 +00005453 if (const auto *C = S.getSingleClause<OMPIfClause>())
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00005454 IfCond = C->getCondition();
5455
5456 // Check if we have any device clause associated with the directive.
5457 const Expr *Device = nullptr;
Alexey Bataevddf3db92018-04-13 17:31:06 +00005458 if (const auto *C = S.getSingleClause<OMPDeviceClause>())
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00005459 Device = C->getDevice();
5460
Alexey Bataev475a7442018-01-12 19:39:11 +00005461 OMPLexicalScope Scope(*this, S, OMPD_task);
Alexey Bataevd2202ca2017-12-27 17:58:32 +00005462 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*this, S, IfCond, Device);
Samuel Antaodf67fc42016-01-19 19:15:56 +00005463}
5464
Samuel Antao72590762016-01-19 20:04:50 +00005465void CodeGenFunction::EmitOMPTargetExitDataDirective(
5466 const OMPTargetExitDataDirective &S) {
Samuel Antao8dd66282016-04-27 23:14:30 +00005467 // If we don't have target devices, don't bother emitting the data mapping
5468 // code.
5469 if (CGM.getLangOpts().OMPTargetTriples.empty())
5470 return;
5471
5472 // Check if we have any if clause associated with the directive.
5473 const Expr *IfCond = nullptr;
Alexey Bataevddf3db92018-04-13 17:31:06 +00005474 if (const auto *C = S.getSingleClause<OMPIfClause>())
Samuel Antao8dd66282016-04-27 23:14:30 +00005475 IfCond = C->getCondition();
5476
5477 // Check if we have any device clause associated with the directive.
5478 const Expr *Device = nullptr;
Alexey Bataevddf3db92018-04-13 17:31:06 +00005479 if (const auto *C = S.getSingleClause<OMPDeviceClause>())
Samuel Antao8dd66282016-04-27 23:14:30 +00005480 Device = C->getDevice();
5481
Alexey Bataev475a7442018-01-12 19:39:11 +00005482 OMPLexicalScope Scope(*this, S, OMPD_task);
Alexey Bataevd2202ca2017-12-27 17:58:32 +00005483 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*this, S, IfCond, Device);
Samuel Antao72590762016-01-19 20:04:50 +00005484}
5485
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00005486static void emitTargetParallelRegion(CodeGenFunction &CGF,
5487 const OMPTargetParallelDirective &S,
5488 PrePostActionTy &Action) {
5489 // Get the captured statement associated with the 'parallel' region.
Alexey Bataevddf3db92018-04-13 17:31:06 +00005490 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00005491 Action.Enter(CGF);
Alexey Bataevc99042b2018-03-15 18:10:54 +00005492 auto &&CodeGen = [&S, CS](CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataev63cc8e92018-03-20 14:45:59 +00005493 Action.Enter(CGF);
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005494 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
5495 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
5496 CGF.EmitOMPPrivateClause(S, PrivateScope);
5497 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
5498 (void)PrivateScope.Privatize();
Alexey Bataev60705422018-10-30 15:50:12 +00005499 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()))
5500 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00005501 // TODO: Add support for clauses.
5502 CGF.EmitStmt(CS->getCapturedStmt());
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005503 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel);
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00005504 };
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00005505 emitCommonOMPParallelDirective(CGF, S, OMPD_parallel, CodeGen,
5506 emitEmptyBoundParameters);
Alexey Bataevddf3db92018-04-13 17:31:06 +00005507 emitPostUpdateForReductionClause(CGF, S,
5508 [](CodeGenFunction &) { return nullptr; });
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00005509}
5510
5511void CodeGenFunction::EmitOMPTargetParallelDeviceFunction(
5512 CodeGenModule &CGM, StringRef ParentName,
5513 const OMPTargetParallelDirective &S) {
5514 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5515 emitTargetParallelRegion(CGF, S, Action);
5516 };
5517 llvm::Function *Fn;
5518 llvm::Constant *Addr;
5519 // Emit target region as a standalone region.
5520 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
5521 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
5522 assert(Fn && Addr && "Target device function emission failed.");
5523}
5524
Arpith Chacko Jacobe955b3d2016-01-26 18:48:41 +00005525void CodeGenFunction::EmitOMPTargetParallelDirective(
5526 const OMPTargetParallelDirective &S) {
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00005527 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5528 emitTargetParallelRegion(CGF, S, Action);
5529 };
5530 emitCommonOMPTargetDirective(*this, S, CodeGen);
Arpith Chacko Jacobe955b3d2016-01-26 18:48:41 +00005531}
5532
Alexey Bataevfb0ebec2017-11-08 20:16:14 +00005533static void emitTargetParallelForRegion(CodeGenFunction &CGF,
5534 const OMPTargetParallelForDirective &S,
5535 PrePostActionTy &Action) {
5536 Action.Enter(CGF);
5537 // Emit directive as a combined directive that consists of two implicit
5538 // directives: 'parallel' with 'for' directive.
Alexey Bataevc99042b2018-03-15 18:10:54 +00005539 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5540 Action.Enter(CGF);
Alexey Bataev2139ed62017-11-16 18:20:21 +00005541 CodeGenFunction::OMPCancelStackRAII CancelRegion(
5542 CGF, OMPD_target_parallel_for, S.hasCancel());
Alexey Bataevfb0ebec2017-11-08 20:16:14 +00005543 CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds,
5544 emitDispatchForLoopBounds);
5545 };
5546 emitCommonOMPParallelDirective(CGF, S, OMPD_for, CodeGen,
5547 emitEmptyBoundParameters);
5548}
5549
5550void CodeGenFunction::EmitOMPTargetParallelForDeviceFunction(
5551 CodeGenModule &CGM, StringRef ParentName,
5552 const OMPTargetParallelForDirective &S) {
5553 // Emit SPMD target parallel for region as a standalone region.
5554 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5555 emitTargetParallelForRegion(CGF, S, Action);
5556 };
5557 llvm::Function *Fn;
5558 llvm::Constant *Addr;
5559 // Emit target region as a standalone region.
5560 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
5561 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
5562 assert(Fn && Addr && "Target device function emission failed.");
5563}
5564
Arpith Chacko Jacob05bebb52016-02-03 15:46:42 +00005565void CodeGenFunction::EmitOMPTargetParallelForDirective(
5566 const OMPTargetParallelForDirective &S) {
Alexey Bataevfb0ebec2017-11-08 20:16:14 +00005567 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5568 emitTargetParallelForRegion(CGF, S, Action);
5569 };
5570 emitCommonOMPTargetDirective(*this, S, CodeGen);
Arpith Chacko Jacob05bebb52016-02-03 15:46:42 +00005571}
5572
Alexey Bataev5d7edca2017-11-09 17:32:15 +00005573static void
5574emitTargetParallelForSimdRegion(CodeGenFunction &CGF,
5575 const OMPTargetParallelForSimdDirective &S,
5576 PrePostActionTy &Action) {
5577 Action.Enter(CGF);
5578 // Emit directive as a combined directive that consists of two implicit
5579 // directives: 'parallel' with 'for' directive.
Alexey Bataevc99042b2018-03-15 18:10:54 +00005580 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5581 Action.Enter(CGF);
Alexey Bataev5d7edca2017-11-09 17:32:15 +00005582 CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds,
5583 emitDispatchForLoopBounds);
5584 };
5585 emitCommonOMPParallelDirective(CGF, S, OMPD_simd, CodeGen,
5586 emitEmptyBoundParameters);
5587}
5588
5589void CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction(
5590 CodeGenModule &CGM, StringRef ParentName,
5591 const OMPTargetParallelForSimdDirective &S) {
5592 // Emit SPMD target parallel for region as a standalone region.
5593 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5594 emitTargetParallelForSimdRegion(CGF, S, Action);
5595 };
5596 llvm::Function *Fn;
5597 llvm::Constant *Addr;
5598 // Emit target region as a standalone region.
5599 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
5600 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
5601 assert(Fn && Addr && "Target device function emission failed.");
5602}
5603
5604void CodeGenFunction::EmitOMPTargetParallelForSimdDirective(
5605 const OMPTargetParallelForSimdDirective &S) {
5606 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5607 emitTargetParallelForSimdRegion(CGF, S, Action);
5608 };
5609 emitCommonOMPTargetDirective(*this, S, CodeGen);
5610}
5611
Alexey Bataev7292c292016-04-25 12:22:29 +00005612/// Emit a helper variable and return corresponding lvalue.
5613static void mapParam(CodeGenFunction &CGF, const DeclRefExpr *Helper,
5614 const ImplicitParamDecl *PVD,
5615 CodeGenFunction::OMPPrivateScope &Privates) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00005616 const auto *VDecl = cast<VarDecl>(Helper->getDecl());
5617 Privates.addPrivate(VDecl,
5618 [&CGF, PVD]() { return CGF.GetAddrOfLocalVar(PVD); });
Alexey Bataev7292c292016-04-25 12:22:29 +00005619}
5620
5621void CodeGenFunction::EmitOMPTaskLoopBasedDirective(const OMPLoopDirective &S) {
5622 assert(isOpenMPTaskLoopDirective(S.getDirectiveKind()));
5623 // Emit outlined function for task construct.
Alexey Bataev475a7442018-01-12 19:39:11 +00005624 const CapturedStmt *CS = S.getCapturedStmt(OMPD_taskloop);
Alexey Bataevddf3db92018-04-13 17:31:06 +00005625 Address CapturedStruct = GenerateCapturedStmtArgument(*CS);
5626 QualType SharedsTy = getContext().getRecordType(CS->getCapturedRecordDecl());
Alexey Bataev7292c292016-04-25 12:22:29 +00005627 const Expr *IfCond = nullptr;
5628 for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
5629 if (C->getNameModifier() == OMPD_unknown ||
5630 C->getNameModifier() == OMPD_taskloop) {
5631 IfCond = C->getCondition();
5632 break;
5633 }
5634 }
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005635
5636 OMPTaskDataTy Data;
5637 // Check if taskloop must be emitted without taskgroup.
5638 Data.Nogroup = S.getSingleClause<OMPNogroupClause>();
Alexey Bataev7292c292016-04-25 12:22:29 +00005639 // TODO: Check if we should emit tied or untied task.
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005640 Data.Tied = true;
5641 // Set scheduling for taskloop
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005642 if (const auto* Clause = S.getSingleClause<OMPGrainsizeClause>()) {
5643 // grainsize clause
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005644 Data.Schedule.setInt(/*IntVal=*/false);
5645 Data.Schedule.setPointer(EmitScalarExpr(Clause->getGrainsize()));
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005646 } else if (const auto* Clause = S.getSingleClause<OMPNumTasksClause>()) {
5647 // num_tasks clause
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005648 Data.Schedule.setInt(/*IntVal=*/true);
5649 Data.Schedule.setPointer(EmitScalarExpr(Clause->getNumTasks()));
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005650 }
Alexey Bataev7292c292016-04-25 12:22:29 +00005651
5652 auto &&BodyGen = [CS, &S](CodeGenFunction &CGF, PrePostActionTy &) {
5653 // if (PreCond) {
5654 // for (IV in 0..LastIteration) BODY;
5655 // <Final counter/linear vars updates>;
5656 // }
5657 //
5658
5659 // Emit: if (PreCond) - begin.
5660 // If the condition constant folds and can be elided, avoid emitting the
5661 // whole loop.
5662 bool CondConstant;
5663 llvm::BasicBlock *ContBlock = nullptr;
5664 OMPLoopScope PreInitScope(CGF, S);
5665 if (CGF.ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
5666 if (!CondConstant)
5667 return;
5668 } else {
Alexey Bataevddf3db92018-04-13 17:31:06 +00005669 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("taskloop.if.then");
Alexey Bataev7292c292016-04-25 12:22:29 +00005670 ContBlock = CGF.createBasicBlock("taskloop.if.end");
5671 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
5672 CGF.getProfileCount(&S));
5673 CGF.EmitBlock(ThenBlock);
5674 CGF.incrementProfileCounter(&S);
5675 }
5676
Alexey Bataev61205822019-12-04 09:50:21 -05005677 (void)CGF.EmitOMPLinearClauseInit(S);
Alexey Bataev1e73ef32016-04-28 12:14:51 +00005678
Alexey Bataev7292c292016-04-25 12:22:29 +00005679 OMPPrivateScope LoopScope(CGF);
5680 // Emit helper vars inits.
5681 enum { LowerBound = 5, UpperBound, Stride, LastIter };
5682 auto *I = CS->getCapturedDecl()->param_begin();
5683 auto *LBP = std::next(I, LowerBound);
5684 auto *UBP = std::next(I, UpperBound);
5685 auto *STP = std::next(I, Stride);
5686 auto *LIP = std::next(I, LastIter);
5687 mapParam(CGF, cast<DeclRefExpr>(S.getLowerBoundVariable()), *LBP,
5688 LoopScope);
5689 mapParam(CGF, cast<DeclRefExpr>(S.getUpperBoundVariable()), *UBP,
5690 LoopScope);
5691 mapParam(CGF, cast<DeclRefExpr>(S.getStrideVariable()), *STP, LoopScope);
5692 mapParam(CGF, cast<DeclRefExpr>(S.getIsLastIterVariable()), *LIP,
5693 LoopScope);
5694 CGF.EmitOMPPrivateLoopCounters(S, LoopScope);
Alexey Bataev14a388f2019-10-25 10:27:13 -04005695 CGF.EmitOMPLinearClause(S, LoopScope);
Alexey Bataevf93095a2016-05-05 08:46:22 +00005696 bool HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
Alexey Bataev7292c292016-04-25 12:22:29 +00005697 (void)LoopScope.Privatize();
5698 // Emit the loop iteration variable.
5699 const Expr *IVExpr = S.getIterationVariable();
Alexey Bataevddf3db92018-04-13 17:31:06 +00005700 const auto *IVDecl = cast<VarDecl>(cast<DeclRefExpr>(IVExpr)->getDecl());
Alexey Bataev7292c292016-04-25 12:22:29 +00005701 CGF.EmitVarDecl(*IVDecl);
5702 CGF.EmitIgnoredExpr(S.getInit());
5703
5704 // Emit the iterations count variable.
5705 // If it is not a variable, Sema decided to calculate iterations count on
5706 // each iteration (e.g., it is foldable into a constant).
Alexey Bataevddf3db92018-04-13 17:31:06 +00005707 if (const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
Alexey Bataev7292c292016-04-25 12:22:29 +00005708 CGF.EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
5709 // Emit calculation of the iterations count.
5710 CGF.EmitIgnoredExpr(S.getCalcLastIteration());
5711 }
5712
Alexey Bataev61205822019-12-04 09:50:21 -05005713 {
5714 OMPLexicalScope Scope(CGF, S, OMPD_taskloop, /*EmitPreInitStmt=*/false);
5715 emitCommonSimdLoop(
5716 CGF, S,
5717 [&S](CodeGenFunction &CGF, PrePostActionTy &) {
5718 if (isOpenMPSimdDirective(S.getDirectiveKind()))
5719 CGF.EmitOMPSimdInit(S);
5720 },
5721 [&S, &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) {
5722 CGF.EmitOMPInnerLoop(
5723 S, LoopScope.requiresCleanups(), S.getCond(), S.getInc(),
5724 [&S](CodeGenFunction &CGF) {
5725 CGF.EmitOMPLoopBody(S, CodeGenFunction::JumpDest());
5726 CGF.EmitStopPoint(&S);
5727 },
5728 [](CodeGenFunction &) {});
5729 });
5730 }
Alexey Bataev7292c292016-04-25 12:22:29 +00005731 // Emit: if (PreCond) - end.
5732 if (ContBlock) {
5733 CGF.EmitBranch(ContBlock);
5734 CGF.EmitBlock(ContBlock, true);
5735 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00005736 // Emit final copy of the lastprivate variables if IsLastIter != 0.
5737 if (HasLastprivateClause) {
5738 CGF.EmitOMPLastprivateClauseFinal(
5739 S, isOpenMPSimdDirective(S.getDirectiveKind()),
5740 CGF.Builder.CreateIsNotNull(CGF.EmitLoadOfScalar(
5741 CGF.GetAddrOfLocalVar(*LIP), /*Volatile=*/false,
Stephen Kellyf2ceec42018-08-09 21:08:08 +00005742 (*LIP)->getType(), S.getBeginLoc())));
Alexey Bataevf93095a2016-05-05 08:46:22 +00005743 }
Alexey Bataev14a388f2019-10-25 10:27:13 -04005744 CGF.EmitOMPLinearClauseFinal(S, [LIP, &S](CodeGenFunction &CGF) {
5745 return CGF.Builder.CreateIsNotNull(
5746 CGF.EmitLoadOfScalar(CGF.GetAddrOfLocalVar(*LIP), /*Volatile=*/false,
5747 (*LIP)->getType(), S.getBeginLoc()));
5748 });
Alexey Bataev7292c292016-04-25 12:22:29 +00005749 };
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005750 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
James Y Knight9871db02019-02-05 16:42:33 +00005751 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005752 const OMPTaskDataTy &Data) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00005753 auto &&CodeGen = [&S, OutlinedFn, SharedsTy, CapturedStruct, IfCond,
5754 &Data](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataev7292c292016-04-25 12:22:29 +00005755 OMPLoopScope PreInitScope(CGF, S);
Stephen Kellyf2ceec42018-08-09 21:08:08 +00005756 CGF.CGM.getOpenMPRuntime().emitTaskLoopCall(CGF, S.getBeginLoc(), S,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005757 OutlinedFn, SharedsTy,
5758 CapturedStruct, IfCond, Data);
Alexey Bataev7292c292016-04-25 12:22:29 +00005759 };
5760 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_taskloop,
5761 CodeGen);
5762 };
Alexey Bataev475a7442018-01-12 19:39:11 +00005763 if (Data.Nogroup) {
5764 EmitOMPTaskBasedDirective(S, OMPD_taskloop, BodyGen, TaskGen, Data);
5765 } else {
Alexey Bataev33446032017-07-12 18:09:32 +00005766 CGM.getOpenMPRuntime().emitTaskgroupRegion(
5767 *this,
5768 [&S, &BodyGen, &TaskGen, &Data](CodeGenFunction &CGF,
5769 PrePostActionTy &Action) {
5770 Action.Enter(CGF);
Alexey Bataev475a7442018-01-12 19:39:11 +00005771 CGF.EmitOMPTaskBasedDirective(S, OMPD_taskloop, BodyGen, TaskGen,
5772 Data);
Alexey Bataev33446032017-07-12 18:09:32 +00005773 },
Stephen Kellyf2ceec42018-08-09 21:08:08 +00005774 S.getBeginLoc());
Alexey Bataev33446032017-07-12 18:09:32 +00005775 }
Alexey Bataev7292c292016-04-25 12:22:29 +00005776}
5777
Alexey Bataev49f6e782015-12-01 04:18:41 +00005778void CodeGenFunction::EmitOMPTaskLoopDirective(const OMPTaskLoopDirective &S) {
Alexey Bataev46978742020-01-30 10:46:11 -05005779 auto LPCRegion =
5780 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
Alexey Bataev7292c292016-04-25 12:22:29 +00005781 EmitOMPTaskLoopBasedDirective(S);
Alexey Bataev49f6e782015-12-01 04:18:41 +00005782}
5783
Alexey Bataev0a6ed842015-12-03 09:40:15 +00005784void CodeGenFunction::EmitOMPTaskLoopSimdDirective(
5785 const OMPTaskLoopSimdDirective &S) {
Alexey Bataev46978742020-01-30 10:46:11 -05005786 auto LPCRegion =
5787 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
Alexey Bataev61205822019-12-04 09:50:21 -05005788 OMPLexicalScope Scope(*this, S);
Alexey Bataev1e73ef32016-04-28 12:14:51 +00005789 EmitOMPTaskLoopBasedDirective(S);
Alexey Bataev0a6ed842015-12-03 09:40:15 +00005790}
Samuel Antao686c70c2016-05-26 17:30:50 +00005791
Alexey Bataev60e51c42019-10-10 20:13:02 +00005792void CodeGenFunction::EmitOMPMasterTaskLoopDirective(
5793 const OMPMasterTaskLoopDirective &S) {
5794 auto &&CodeGen = [this, &S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5795 Action.Enter(CGF);
5796 EmitOMPTaskLoopBasedDirective(S);
5797 };
Alexey Bataev46978742020-01-30 10:46:11 -05005798 auto LPCRegion =
5799 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
Alexey Bataev60e51c42019-10-10 20:13:02 +00005800 OMPLexicalScope Scope(*this, S, llvm::None, /*EmitPreInitStmt=*/false);
5801 CGM.getOpenMPRuntime().emitMasterRegion(*this, CodeGen, S.getBeginLoc());
5802}
5803
Alexey Bataevb8552ab2019-10-18 16:47:35 +00005804void CodeGenFunction::EmitOMPMasterTaskLoopSimdDirective(
5805 const OMPMasterTaskLoopSimdDirective &S) {
5806 auto &&CodeGen = [this, &S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5807 Action.Enter(CGF);
5808 EmitOMPTaskLoopBasedDirective(S);
5809 };
Alexey Bataev46978742020-01-30 10:46:11 -05005810 auto LPCRegion =
5811 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
Alexey Bataev61205822019-12-04 09:50:21 -05005812 OMPLexicalScope Scope(*this, S);
Alexey Bataevb8552ab2019-10-18 16:47:35 +00005813 CGM.getOpenMPRuntime().emitMasterRegion(*this, CodeGen, S.getBeginLoc());
5814}
5815
Alexey Bataev5bbcead2019-10-14 17:17:41 +00005816void CodeGenFunction::EmitOMPParallelMasterTaskLoopDirective(
5817 const OMPParallelMasterTaskLoopDirective &S) {
5818 auto &&CodeGen = [this, &S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5819 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
5820 PrePostActionTy &Action) {
5821 Action.Enter(CGF);
5822 CGF.EmitOMPTaskLoopBasedDirective(S);
5823 };
Alexey Bataev18789bf2020-02-13 09:21:15 -05005824 OMPLexicalScope Scope(CGF, S, OMPD_parallel, /*EmitPreInitStmt=*/false);
Alexey Bataev5bbcead2019-10-14 17:17:41 +00005825 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
5826 S.getBeginLoc());
5827 };
Alexey Bataev46978742020-01-30 10:46:11 -05005828 auto LPCRegion =
5829 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
Alexey Bataev5bbcead2019-10-14 17:17:41 +00005830 emitCommonOMPParallelDirective(*this, S, OMPD_master_taskloop, CodeGen,
5831 emitEmptyBoundParameters);
5832}
5833
Alexey Bataev14a388f2019-10-25 10:27:13 -04005834void CodeGenFunction::EmitOMPParallelMasterTaskLoopSimdDirective(
5835 const OMPParallelMasterTaskLoopSimdDirective &S) {
5836 auto &&CodeGen = [this, &S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5837 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
5838 PrePostActionTy &Action) {
5839 Action.Enter(CGF);
5840 CGF.EmitOMPTaskLoopBasedDirective(S);
5841 };
5842 OMPLexicalScope Scope(CGF, S, OMPD_parallel, /*EmitPreInitStmt=*/false);
5843 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
5844 S.getBeginLoc());
5845 };
Alexey Bataev46978742020-01-30 10:46:11 -05005846 auto LPCRegion =
5847 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
Alexey Bataev14a388f2019-10-25 10:27:13 -04005848 emitCommonOMPParallelDirective(*this, S, OMPD_master_taskloop_simd, CodeGen,
5849 emitEmptyBoundParameters);
5850}
5851
Samuel Antao686c70c2016-05-26 17:30:50 +00005852// Generate the instructions for '#pragma omp target update' directive.
5853void CodeGenFunction::EmitOMPTargetUpdateDirective(
5854 const OMPTargetUpdateDirective &S) {
Samuel Antao8d2d7302016-05-26 18:30:22 +00005855 // If we don't have target devices, don't bother emitting the data mapping
5856 // code.
5857 if (CGM.getLangOpts().OMPTargetTriples.empty())
5858 return;
5859
5860 // Check if we have any if clause associated with the directive.
5861 const Expr *IfCond = nullptr;
Alexey Bataevddf3db92018-04-13 17:31:06 +00005862 if (const auto *C = S.getSingleClause<OMPIfClause>())
Samuel Antao8d2d7302016-05-26 18:30:22 +00005863 IfCond = C->getCondition();
5864
5865 // Check if we have any device clause associated with the directive.
5866 const Expr *Device = nullptr;
Alexey Bataevddf3db92018-04-13 17:31:06 +00005867 if (const auto *C = S.getSingleClause<OMPDeviceClause>())
Samuel Antao8d2d7302016-05-26 18:30:22 +00005868 Device = C->getDevice();
5869
Alexey Bataev475a7442018-01-12 19:39:11 +00005870 OMPLexicalScope Scope(*this, S, OMPD_task);
Alexey Bataevd2202ca2017-12-27 17:58:32 +00005871 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*this, S, IfCond, Device);
Samuel Antao686c70c2016-05-26 17:30:50 +00005872}
Alexey Bataeva8a9153a2017-12-29 18:07:07 +00005873
5874void CodeGenFunction::EmitSimpleOMPExecutableDirective(
5875 const OMPExecutableDirective &D) {
5876 if (!D.hasAssociatedStmt() || !D.getAssociatedStmt())
5877 return;
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08005878 auto &&CodeGen = [&D](CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataeva8a9153a2017-12-29 18:07:07 +00005879 if (isOpenMPSimdDirective(D.getDirectiveKind())) {
5880 emitOMPSimdRegion(CGF, cast<OMPLoopDirective>(D), Action);
5881 } else {
Alexey Bataev6ab5bb12018-10-29 15:01:58 +00005882 OMPPrivateScope LoopGlobals(CGF);
Alexey Bataeva8a9153a2017-12-29 18:07:07 +00005883 if (const auto *LD = dyn_cast<OMPLoopDirective>(&D)) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00005884 for (const Expr *E : LD->counters()) {
Simon Pilgrim93431f92020-01-11 16:00:17 +00005885 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev6ab5bb12018-10-29 15:01:58 +00005886 if (!VD->hasLocalStorage() && !CGF.LocalDeclMap.count(VD)) {
5887 LValue GlobLVal = CGF.EmitLValue(E);
5888 LoopGlobals.addPrivate(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08005889 VD, [&GlobLVal, &CGF]() { return GlobLVal.getAddress(CGF); });
Alexey Bataev6ab5bb12018-10-29 15:01:58 +00005890 }
Bjorn Pettersson6c2d83b2018-10-30 08:49:26 +00005891 if (isa<OMPCapturedExprDecl>(VD)) {
Alexey Bataeva8a9153a2017-12-29 18:07:07 +00005892 // Emit only those that were not explicitly referenced in clauses.
5893 if (!CGF.LocalDeclMap.count(VD))
5894 CGF.EmitVarDecl(*VD);
5895 }
5896 }
Alexey Bataevf138fda2018-08-13 19:04:24 +00005897 for (const auto *C : D.getClausesOfKind<OMPOrderedClause>()) {
5898 if (!C->getNumForLoops())
5899 continue;
5900 for (unsigned I = LD->getCollapsedNumber(),
5901 E = C->getLoopNumIterations().size();
5902 I < E; ++I) {
5903 if (const auto *VD = dyn_cast<OMPCapturedExprDecl>(
Mike Rice0ed46662018-09-20 17:19:41 +00005904 cast<DeclRefExpr>(C->getLoopCounter(I))->getDecl())) {
Alexey Bataevf138fda2018-08-13 19:04:24 +00005905 // Emit only those that were not explicitly referenced in clauses.
5906 if (!CGF.LocalDeclMap.count(VD))
5907 CGF.EmitVarDecl(*VD);
5908 }
5909 }
5910 }
Alexey Bataeva8a9153a2017-12-29 18:07:07 +00005911 }
Alexey Bataev6ab5bb12018-10-29 15:01:58 +00005912 LoopGlobals.Privatize();
Alexey Bataev475a7442018-01-12 19:39:11 +00005913 CGF.EmitStmt(D.getInnermostCapturedStmt()->getCapturedStmt());
Alexey Bataeva8a9153a2017-12-29 18:07:07 +00005914 }
5915 };
Alexey Bataev46978742020-01-30 10:46:11 -05005916 {
5917 auto LPCRegion =
5918 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, D);
5919 OMPSimdLexicalScope Scope(*this, D);
5920 CGM.getOpenMPRuntime().emitInlinedDirective(
5921 *this,
5922 isOpenMPSimdDirective(D.getDirectiveKind()) ? OMPD_simd
5923 : D.getDirectiveKind(),
5924 CodeGen);
5925 }
5926 // Check for outer lastprivate conditional update.
5927 checkForLastprivateConditionalUpdate(*this, D);
Alexey Bataeva8a9153a2017-12-29 18:07:07 +00005928}