1*67e74705SXin Li //===--- CGStmtOpenMP.cpp - Emit LLVM Code from Statements ----------------===//
2*67e74705SXin Li //
3*67e74705SXin Li // The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li //
10*67e74705SXin Li // This contains code to emit OpenMP nodes as LLVM code.
11*67e74705SXin Li //
12*67e74705SXin Li //===----------------------------------------------------------------------===//
13*67e74705SXin Li
14*67e74705SXin Li #include "CGCleanup.h"
15*67e74705SXin Li #include "CGOpenMPRuntime.h"
16*67e74705SXin Li #include "CodeGenFunction.h"
17*67e74705SXin Li #include "CodeGenModule.h"
18*67e74705SXin Li #include "TargetInfo.h"
19*67e74705SXin Li #include "clang/AST/Stmt.h"
20*67e74705SXin Li #include "clang/AST/StmtOpenMP.h"
21*67e74705SXin Li #include "clang/AST/DeclOpenMP.h"
22*67e74705SXin Li #include "llvm/IR/CallSite.h"
23*67e74705SXin Li using namespace clang;
24*67e74705SXin Li using namespace CodeGen;
25*67e74705SXin Li
26*67e74705SXin Li namespace {
27*67e74705SXin Li /// Lexical scope for OpenMP executable constructs, that handles correct codegen
28*67e74705SXin Li /// for captured expressions.
29*67e74705SXin Li class OMPLexicalScope final : public CodeGenFunction::LexicalScope {
emitPreInitStmt(CodeGenFunction & CGF,const OMPExecutableDirective & S)30*67e74705SXin Li void emitPreInitStmt(CodeGenFunction &CGF, const OMPExecutableDirective &S) {
31*67e74705SXin Li for (const auto *C : S.clauses()) {
32*67e74705SXin Li if (auto *CPI = OMPClauseWithPreInit::get(C)) {
33*67e74705SXin Li if (auto *PreInit = cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
34*67e74705SXin Li for (const auto *I : PreInit->decls()) {
35*67e74705SXin Li if (!I->hasAttr<OMPCaptureNoInitAttr>())
36*67e74705SXin Li CGF.EmitVarDecl(cast<VarDecl>(*I));
37*67e74705SXin Li else {
38*67e74705SXin Li CodeGenFunction::AutoVarEmission Emission =
39*67e74705SXin Li CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
40*67e74705SXin Li CGF.EmitAutoVarCleanups(Emission);
41*67e74705SXin Li }
42*67e74705SXin Li }
43*67e74705SXin Li }
44*67e74705SXin Li }
45*67e74705SXin Li }
46*67e74705SXin Li }
47*67e74705SXin Li CodeGenFunction::OMPPrivateScope InlinedShareds;
48*67e74705SXin Li
isCapturedVar(CodeGenFunction & CGF,const VarDecl * VD)49*67e74705SXin Li static bool isCapturedVar(CodeGenFunction &CGF, const VarDecl *VD) {
50*67e74705SXin Li return CGF.LambdaCaptureFields.lookup(VD) ||
51*67e74705SXin Li (CGF.CapturedStmtInfo && CGF.CapturedStmtInfo->lookup(VD)) ||
52*67e74705SXin Li (CGF.CurCodeDecl && isa<BlockDecl>(CGF.CurCodeDecl));
53*67e74705SXin Li }
54*67e74705SXin Li
55*67e74705SXin Li public:
OMPLexicalScope(CodeGenFunction & CGF,const OMPExecutableDirective & S,bool AsInlined=false)56*67e74705SXin Li OMPLexicalScope(CodeGenFunction &CGF, const OMPExecutableDirective &S,
57*67e74705SXin Li bool AsInlined = false)
58*67e74705SXin Li : CodeGenFunction::LexicalScope(CGF, S.getSourceRange()),
59*67e74705SXin Li InlinedShareds(CGF) {
60*67e74705SXin Li emitPreInitStmt(CGF, S);
61*67e74705SXin Li if (AsInlined) {
62*67e74705SXin Li if (S.hasAssociatedStmt()) {
63*67e74705SXin Li auto *CS = cast<CapturedStmt>(S.getAssociatedStmt());
64*67e74705SXin Li for (auto &C : CS->captures()) {
65*67e74705SXin Li if (C.capturesVariable() || C.capturesVariableByCopy()) {
66*67e74705SXin Li auto *VD = C.getCapturedVar();
67*67e74705SXin Li DeclRefExpr DRE(const_cast<VarDecl *>(VD),
68*67e74705SXin Li isCapturedVar(CGF, VD) ||
69*67e74705SXin Li (CGF.CapturedStmtInfo &&
70*67e74705SXin Li InlinedShareds.isGlobalVarCaptured(VD)),
71*67e74705SXin Li VD->getType().getNonReferenceType(), VK_LValue,
72*67e74705SXin Li SourceLocation());
73*67e74705SXin Li InlinedShareds.addPrivate(VD, [&CGF, &DRE]() -> Address {
74*67e74705SXin Li return CGF.EmitLValue(&DRE).getAddress();
75*67e74705SXin Li });
76*67e74705SXin Li }
77*67e74705SXin Li }
78*67e74705SXin Li (void)InlinedShareds.Privatize();
79*67e74705SXin Li }
80*67e74705SXin Li }
81*67e74705SXin Li }
82*67e74705SXin Li };
83*67e74705SXin Li
84*67e74705SXin Li /// Private scope for OpenMP loop-based directives, that supports capturing
85*67e74705SXin Li /// of used expression from loop statement.
86*67e74705SXin Li class OMPLoopScope : public CodeGenFunction::RunCleanupsScope {
emitPreInitStmt(CodeGenFunction & CGF,const OMPLoopDirective & S)87*67e74705SXin Li void emitPreInitStmt(CodeGenFunction &CGF, const OMPLoopDirective &S) {
88*67e74705SXin Li if (auto *LD = dyn_cast<OMPLoopDirective>(&S)) {
89*67e74705SXin Li if (auto *PreInits = cast_or_null<DeclStmt>(LD->getPreInits())) {
90*67e74705SXin Li for (const auto *I : PreInits->decls())
91*67e74705SXin Li CGF.EmitVarDecl(cast<VarDecl>(*I));
92*67e74705SXin Li }
93*67e74705SXin Li }
94*67e74705SXin Li }
95*67e74705SXin Li
96*67e74705SXin Li public:
OMPLoopScope(CodeGenFunction & CGF,const OMPLoopDirective & S)97*67e74705SXin Li OMPLoopScope(CodeGenFunction &CGF, const OMPLoopDirective &S)
98*67e74705SXin Li : CodeGenFunction::RunCleanupsScope(CGF) {
99*67e74705SXin Li emitPreInitStmt(CGF, S);
100*67e74705SXin Li }
101*67e74705SXin Li };
102*67e74705SXin Li
103*67e74705SXin Li } // namespace
104*67e74705SXin Li
getTypeSize(QualType Ty)105*67e74705SXin Li llvm::Value *CodeGenFunction::getTypeSize(QualType Ty) {
106*67e74705SXin Li auto &C = getContext();
107*67e74705SXin Li llvm::Value *Size = nullptr;
108*67e74705SXin Li auto SizeInChars = C.getTypeSizeInChars(Ty);
109*67e74705SXin Li if (SizeInChars.isZero()) {
110*67e74705SXin Li // getTypeSizeInChars() returns 0 for a VLA.
111*67e74705SXin Li while (auto *VAT = C.getAsVariableArrayType(Ty)) {
112*67e74705SXin Li llvm::Value *ArraySize;
113*67e74705SXin Li std::tie(ArraySize, Ty) = getVLASize(VAT);
114*67e74705SXin Li Size = Size ? Builder.CreateNUWMul(Size, ArraySize) : ArraySize;
115*67e74705SXin Li }
116*67e74705SXin Li SizeInChars = C.getTypeSizeInChars(Ty);
117*67e74705SXin Li if (SizeInChars.isZero())
118*67e74705SXin Li return llvm::ConstantInt::get(SizeTy, /*V=*/0);
119*67e74705SXin Li Size = Builder.CreateNUWMul(Size, CGM.getSize(SizeInChars));
120*67e74705SXin Li } else
121*67e74705SXin Li Size = CGM.getSize(SizeInChars);
122*67e74705SXin Li return Size;
123*67e74705SXin Li }
124*67e74705SXin Li
GenerateOpenMPCapturedVars(const CapturedStmt & S,SmallVectorImpl<llvm::Value * > & CapturedVars)125*67e74705SXin Li void CodeGenFunction::GenerateOpenMPCapturedVars(
126*67e74705SXin Li const CapturedStmt &S, SmallVectorImpl<llvm::Value *> &CapturedVars) {
127*67e74705SXin Li const RecordDecl *RD = S.getCapturedRecordDecl();
128*67e74705SXin Li auto CurField = RD->field_begin();
129*67e74705SXin Li auto CurCap = S.captures().begin();
130*67e74705SXin Li for (CapturedStmt::const_capture_init_iterator I = S.capture_init_begin(),
131*67e74705SXin Li E = S.capture_init_end();
132*67e74705SXin Li I != E; ++I, ++CurField, ++CurCap) {
133*67e74705SXin Li if (CurField->hasCapturedVLAType()) {
134*67e74705SXin Li auto VAT = CurField->getCapturedVLAType();
135*67e74705SXin Li auto *Val = VLASizeMap[VAT->getSizeExpr()];
136*67e74705SXin Li CapturedVars.push_back(Val);
137*67e74705SXin Li } else if (CurCap->capturesThis())
138*67e74705SXin Li CapturedVars.push_back(CXXThisValue);
139*67e74705SXin Li else if (CurCap->capturesVariableByCopy()) {
140*67e74705SXin Li llvm::Value *CV =
141*67e74705SXin Li EmitLoadOfLValue(EmitLValue(*I), SourceLocation()).getScalarVal();
142*67e74705SXin Li
143*67e74705SXin Li // If the field is not a pointer, we need to save the actual value
144*67e74705SXin Li // and load it as a void pointer.
145*67e74705SXin Li if (!CurField->getType()->isAnyPointerType()) {
146*67e74705SXin Li auto &Ctx = getContext();
147*67e74705SXin Li auto DstAddr = CreateMemTemp(
148*67e74705SXin Li Ctx.getUIntPtrType(),
149*67e74705SXin Li Twine(CurCap->getCapturedVar()->getName()) + ".casted");
150*67e74705SXin Li LValue DstLV = MakeAddrLValue(DstAddr, Ctx.getUIntPtrType());
151*67e74705SXin Li
152*67e74705SXin Li auto *SrcAddrVal = EmitScalarConversion(
153*67e74705SXin Li DstAddr.getPointer(), Ctx.getPointerType(Ctx.getUIntPtrType()),
154*67e74705SXin Li Ctx.getPointerType(CurField->getType()), SourceLocation());
155*67e74705SXin Li LValue SrcLV =
156*67e74705SXin Li MakeNaturalAlignAddrLValue(SrcAddrVal, CurField->getType());
157*67e74705SXin Li
158*67e74705SXin Li // Store the value using the source type pointer.
159*67e74705SXin Li EmitStoreThroughLValue(RValue::get(CV), SrcLV);
160*67e74705SXin Li
161*67e74705SXin Li // Load the value using the destination type pointer.
162*67e74705SXin Li CV = EmitLoadOfLValue(DstLV, SourceLocation()).getScalarVal();
163*67e74705SXin Li }
164*67e74705SXin Li CapturedVars.push_back(CV);
165*67e74705SXin Li } else {
166*67e74705SXin Li assert(CurCap->capturesVariable() && "Expected capture by reference.");
167*67e74705SXin Li CapturedVars.push_back(EmitLValue(*I).getAddress().getPointer());
168*67e74705SXin Li }
169*67e74705SXin Li }
170*67e74705SXin Li }
171*67e74705SXin Li
castValueFromUintptr(CodeGenFunction & CGF,QualType DstType,StringRef Name,LValue AddrLV,bool isReferenceType=false)172*67e74705SXin Li static Address castValueFromUintptr(CodeGenFunction &CGF, QualType DstType,
173*67e74705SXin Li StringRef Name, LValue AddrLV,
174*67e74705SXin Li bool isReferenceType = false) {
175*67e74705SXin Li ASTContext &Ctx = CGF.getContext();
176*67e74705SXin Li
177*67e74705SXin Li auto *CastedPtr = CGF.EmitScalarConversion(
178*67e74705SXin Li AddrLV.getAddress().getPointer(), Ctx.getUIntPtrType(),
179*67e74705SXin Li Ctx.getPointerType(DstType), SourceLocation());
180*67e74705SXin Li auto TmpAddr =
181*67e74705SXin Li CGF.MakeNaturalAlignAddrLValue(CastedPtr, Ctx.getPointerType(DstType))
182*67e74705SXin Li .getAddress();
183*67e74705SXin Li
184*67e74705SXin Li // If we are dealing with references we need to return the address of the
185*67e74705SXin Li // reference instead of the reference of the value.
186*67e74705SXin Li if (isReferenceType) {
187*67e74705SXin Li QualType RefType = Ctx.getLValueReferenceType(DstType);
188*67e74705SXin Li auto *RefVal = TmpAddr.getPointer();
189*67e74705SXin Li TmpAddr = CGF.CreateMemTemp(RefType, Twine(Name) + ".ref");
190*67e74705SXin Li auto TmpLVal = CGF.MakeAddrLValue(TmpAddr, RefType);
191*67e74705SXin Li CGF.EmitScalarInit(RefVal, TmpLVal);
192*67e74705SXin Li }
193*67e74705SXin Li
194*67e74705SXin Li return TmpAddr;
195*67e74705SXin Li }
196*67e74705SXin Li
197*67e74705SXin Li llvm::Function *
GenerateOpenMPCapturedStmtFunction(const CapturedStmt & S)198*67e74705SXin Li CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S) {
199*67e74705SXin Li assert(
200*67e74705SXin Li CapturedStmtInfo &&
201*67e74705SXin Li "CapturedStmtInfo should be set when generating the captured function");
202*67e74705SXin Li const CapturedDecl *CD = S.getCapturedDecl();
203*67e74705SXin Li const RecordDecl *RD = S.getCapturedRecordDecl();
204*67e74705SXin Li assert(CD->hasBody() && "missing CapturedDecl body");
205*67e74705SXin Li
206*67e74705SXin Li // Build the argument list.
207*67e74705SXin Li ASTContext &Ctx = CGM.getContext();
208*67e74705SXin Li FunctionArgList Args;
209*67e74705SXin Li Args.append(CD->param_begin(),
210*67e74705SXin Li std::next(CD->param_begin(), CD->getContextParamPosition()));
211*67e74705SXin Li auto I = S.captures().begin();
212*67e74705SXin Li for (auto *FD : RD->fields()) {
213*67e74705SXin Li QualType ArgType = FD->getType();
214*67e74705SXin Li IdentifierInfo *II = nullptr;
215*67e74705SXin Li VarDecl *CapVar = nullptr;
216*67e74705SXin Li
217*67e74705SXin Li // If this is a capture by copy and the type is not a pointer, the outlined
218*67e74705SXin Li // function argument type should be uintptr and the value properly casted to
219*67e74705SXin Li // uintptr. This is necessary given that the runtime library is only able to
220*67e74705SXin Li // deal with pointers. We can pass in the same way the VLA type sizes to the
221*67e74705SXin Li // outlined function.
222*67e74705SXin Li if ((I->capturesVariableByCopy() && !ArgType->isAnyPointerType()) ||
223*67e74705SXin Li I->capturesVariableArrayType())
224*67e74705SXin Li ArgType = Ctx.getUIntPtrType();
225*67e74705SXin Li
226*67e74705SXin Li if (I->capturesVariable() || I->capturesVariableByCopy()) {
227*67e74705SXin Li CapVar = I->getCapturedVar();
228*67e74705SXin Li II = CapVar->getIdentifier();
229*67e74705SXin Li } else if (I->capturesThis())
230*67e74705SXin Li II = &getContext().Idents.get("this");
231*67e74705SXin Li else {
232*67e74705SXin Li assert(I->capturesVariableArrayType());
233*67e74705SXin Li II = &getContext().Idents.get("vla");
234*67e74705SXin Li }
235*67e74705SXin Li if (ArgType->isVariablyModifiedType())
236*67e74705SXin Li ArgType = getContext().getVariableArrayDecayedType(ArgType);
237*67e74705SXin Li Args.push_back(ImplicitParamDecl::Create(getContext(), nullptr,
238*67e74705SXin Li FD->getLocation(), II, ArgType));
239*67e74705SXin Li ++I;
240*67e74705SXin Li }
241*67e74705SXin Li Args.append(
242*67e74705SXin Li std::next(CD->param_begin(), CD->getContextParamPosition() + 1),
243*67e74705SXin Li CD->param_end());
244*67e74705SXin Li
245*67e74705SXin Li // Create the function declaration.
246*67e74705SXin Li FunctionType::ExtInfo ExtInfo;
247*67e74705SXin Li const CGFunctionInfo &FuncInfo =
248*67e74705SXin Li CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Args);
249*67e74705SXin Li llvm::FunctionType *FuncLLVMTy = CGM.getTypes().GetFunctionType(FuncInfo);
250*67e74705SXin Li
251*67e74705SXin Li llvm::Function *F = llvm::Function::Create(
252*67e74705SXin Li FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
253*67e74705SXin Li CapturedStmtInfo->getHelperName(), &CGM.getModule());
254*67e74705SXin Li CGM.SetInternalFunctionAttributes(CD, F, FuncInfo);
255*67e74705SXin Li if (CD->isNothrow())
256*67e74705SXin Li F->addFnAttr(llvm::Attribute::NoUnwind);
257*67e74705SXin Li
258*67e74705SXin Li // Generate the function.
259*67e74705SXin Li StartFunction(CD, Ctx.VoidTy, F, FuncInfo, Args, CD->getLocation(),
260*67e74705SXin Li CD->getBody()->getLocStart());
261*67e74705SXin Li unsigned Cnt = CD->getContextParamPosition();
262*67e74705SXin Li I = S.captures().begin();
263*67e74705SXin Li for (auto *FD : RD->fields()) {
264*67e74705SXin Li // If we are capturing a pointer by copy we don't need to do anything, just
265*67e74705SXin Li // use the value that we get from the arguments.
266*67e74705SXin Li if (I->capturesVariableByCopy() && FD->getType()->isAnyPointerType()) {
267*67e74705SXin Li setAddrOfLocalVar(I->getCapturedVar(), GetAddrOfLocalVar(Args[Cnt]));
268*67e74705SXin Li ++Cnt;
269*67e74705SXin Li ++I;
270*67e74705SXin Li continue;
271*67e74705SXin Li }
272*67e74705SXin Li
273*67e74705SXin Li LValue ArgLVal =
274*67e74705SXin Li MakeAddrLValue(GetAddrOfLocalVar(Args[Cnt]), Args[Cnt]->getType(),
275*67e74705SXin Li AlignmentSource::Decl);
276*67e74705SXin Li if (FD->hasCapturedVLAType()) {
277*67e74705SXin Li LValue CastedArgLVal =
278*67e74705SXin Li MakeAddrLValue(castValueFromUintptr(*this, FD->getType(),
279*67e74705SXin Li Args[Cnt]->getName(), ArgLVal),
280*67e74705SXin Li FD->getType(), AlignmentSource::Decl);
281*67e74705SXin Li auto *ExprArg =
282*67e74705SXin Li EmitLoadOfLValue(CastedArgLVal, SourceLocation()).getScalarVal();
283*67e74705SXin Li auto VAT = FD->getCapturedVLAType();
284*67e74705SXin Li VLASizeMap[VAT->getSizeExpr()] = ExprArg;
285*67e74705SXin Li } else if (I->capturesVariable()) {
286*67e74705SXin Li auto *Var = I->getCapturedVar();
287*67e74705SXin Li QualType VarTy = Var->getType();
288*67e74705SXin Li Address ArgAddr = ArgLVal.getAddress();
289*67e74705SXin Li if (!VarTy->isReferenceType()) {
290*67e74705SXin Li ArgAddr = EmitLoadOfReference(
291*67e74705SXin Li ArgAddr, ArgLVal.getType()->castAs<ReferenceType>());
292*67e74705SXin Li }
293*67e74705SXin Li setAddrOfLocalVar(
294*67e74705SXin Li Var, Address(ArgAddr.getPointer(), getContext().getDeclAlign(Var)));
295*67e74705SXin Li } else if (I->capturesVariableByCopy()) {
296*67e74705SXin Li assert(!FD->getType()->isAnyPointerType() &&
297*67e74705SXin Li "Not expecting a captured pointer.");
298*67e74705SXin Li auto *Var = I->getCapturedVar();
299*67e74705SXin Li QualType VarTy = Var->getType();
300*67e74705SXin Li setAddrOfLocalVar(Var, castValueFromUintptr(*this, FD->getType(),
301*67e74705SXin Li Args[Cnt]->getName(), ArgLVal,
302*67e74705SXin Li VarTy->isReferenceType()));
303*67e74705SXin Li } else {
304*67e74705SXin Li // If 'this' is captured, load it into CXXThisValue.
305*67e74705SXin Li assert(I->capturesThis());
306*67e74705SXin Li CXXThisValue =
307*67e74705SXin Li EmitLoadOfLValue(ArgLVal, Args[Cnt]->getLocation()).getScalarVal();
308*67e74705SXin Li }
309*67e74705SXin Li ++Cnt;
310*67e74705SXin Li ++I;
311*67e74705SXin Li }
312*67e74705SXin Li
313*67e74705SXin Li PGO.assignRegionCounters(GlobalDecl(CD), F);
314*67e74705SXin Li CapturedStmtInfo->EmitBody(*this, CD->getBody());
315*67e74705SXin Li FinishFunction(CD->getBodyRBrace());
316*67e74705SXin Li
317*67e74705SXin Li return F;
318*67e74705SXin Li }
319*67e74705SXin Li
320*67e74705SXin Li //===----------------------------------------------------------------------===//
321*67e74705SXin Li // OpenMP Directive Emission
322*67e74705SXin Li //===----------------------------------------------------------------------===//
EmitOMPAggregateAssign(Address DestAddr,Address SrcAddr,QualType OriginalType,const llvm::function_ref<void (Address,Address)> & CopyGen)323*67e74705SXin Li void CodeGenFunction::EmitOMPAggregateAssign(
324*67e74705SXin Li Address DestAddr, Address SrcAddr, QualType OriginalType,
325*67e74705SXin Li const llvm::function_ref<void(Address, Address)> &CopyGen) {
326*67e74705SXin Li // Perform element-by-element initialization.
327*67e74705SXin Li QualType ElementTy;
328*67e74705SXin Li
329*67e74705SXin Li // Drill down to the base element type on both arrays.
330*67e74705SXin Li auto ArrayTy = OriginalType->getAsArrayTypeUnsafe();
331*67e74705SXin Li auto NumElements = emitArrayLength(ArrayTy, ElementTy, DestAddr);
332*67e74705SXin Li SrcAddr = Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType());
333*67e74705SXin Li
334*67e74705SXin Li auto SrcBegin = SrcAddr.getPointer();
335*67e74705SXin Li auto DestBegin = DestAddr.getPointer();
336*67e74705SXin Li // Cast from pointer to array type to pointer to single element.
337*67e74705SXin Li auto DestEnd = Builder.CreateGEP(DestBegin, NumElements);
338*67e74705SXin Li // The basic structure here is a while-do loop.
339*67e74705SXin Li auto BodyBB = createBasicBlock("omp.arraycpy.body");
340*67e74705SXin Li auto DoneBB = createBasicBlock("omp.arraycpy.done");
341*67e74705SXin Li auto IsEmpty =
342*67e74705SXin Li Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arraycpy.isempty");
343*67e74705SXin Li Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
344*67e74705SXin Li
345*67e74705SXin Li // Enter the loop body, making that address the current address.
346*67e74705SXin Li auto EntryBB = Builder.GetInsertBlock();
347*67e74705SXin Li EmitBlock(BodyBB);
348*67e74705SXin Li
349*67e74705SXin Li CharUnits ElementSize = getContext().getTypeSizeInChars(ElementTy);
350*67e74705SXin Li
351*67e74705SXin Li llvm::PHINode *SrcElementPHI =
352*67e74705SXin Li Builder.CreatePHI(SrcBegin->getType(), 2, "omp.arraycpy.srcElementPast");
353*67e74705SXin Li SrcElementPHI->addIncoming(SrcBegin, EntryBB);
354*67e74705SXin Li Address SrcElementCurrent =
355*67e74705SXin Li Address(SrcElementPHI,
356*67e74705SXin Li SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize));
357*67e74705SXin Li
358*67e74705SXin Li llvm::PHINode *DestElementPHI =
359*67e74705SXin Li Builder.CreatePHI(DestBegin->getType(), 2, "omp.arraycpy.destElementPast");
360*67e74705SXin Li DestElementPHI->addIncoming(DestBegin, EntryBB);
361*67e74705SXin Li Address DestElementCurrent =
362*67e74705SXin Li Address(DestElementPHI,
363*67e74705SXin Li DestAddr.getAlignment().alignmentOfArrayElement(ElementSize));
364*67e74705SXin Li
365*67e74705SXin Li // Emit copy.
366*67e74705SXin Li CopyGen(DestElementCurrent, SrcElementCurrent);
367*67e74705SXin Li
368*67e74705SXin Li // Shift the address forward by one element.
369*67e74705SXin Li auto DestElementNext = Builder.CreateConstGEP1_32(
370*67e74705SXin Li DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
371*67e74705SXin Li auto SrcElementNext = Builder.CreateConstGEP1_32(
372*67e74705SXin Li SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element");
373*67e74705SXin Li // Check whether we've reached the end.
374*67e74705SXin Li auto Done =
375*67e74705SXin Li Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done");
376*67e74705SXin Li Builder.CreateCondBr(Done, DoneBB, BodyBB);
377*67e74705SXin Li DestElementPHI->addIncoming(DestElementNext, Builder.GetInsertBlock());
378*67e74705SXin Li SrcElementPHI->addIncoming(SrcElementNext, Builder.GetInsertBlock());
379*67e74705SXin Li
380*67e74705SXin Li // Done.
381*67e74705SXin Li EmitBlock(DoneBB, /*IsFinished=*/true);
382*67e74705SXin Li }
383*67e74705SXin Li
384*67e74705SXin Li /// Check if the combiner is a call to UDR combiner and if it is so return the
385*67e74705SXin Li /// UDR decl used for reduction.
386*67e74705SXin Li static const OMPDeclareReductionDecl *
getReductionInit(const Expr * ReductionOp)387*67e74705SXin Li getReductionInit(const Expr *ReductionOp) {
388*67e74705SXin Li if (auto *CE = dyn_cast<CallExpr>(ReductionOp))
389*67e74705SXin Li if (auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
390*67e74705SXin Li if (auto *DRE =
391*67e74705SXin Li dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
392*67e74705SXin Li if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl()))
393*67e74705SXin Li return DRD;
394*67e74705SXin Li return nullptr;
395*67e74705SXin Li }
396*67e74705SXin Li
emitInitWithReductionInitializer(CodeGenFunction & CGF,const OMPDeclareReductionDecl * DRD,const Expr * InitOp,Address Private,Address Original,QualType Ty)397*67e74705SXin Li static void emitInitWithReductionInitializer(CodeGenFunction &CGF,
398*67e74705SXin Li const OMPDeclareReductionDecl *DRD,
399*67e74705SXin Li const Expr *InitOp,
400*67e74705SXin Li Address Private, Address Original,
401*67e74705SXin Li QualType Ty) {
402*67e74705SXin Li if (DRD->getInitializer()) {
403*67e74705SXin Li std::pair<llvm::Function *, llvm::Function *> Reduction =
404*67e74705SXin Li CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD);
405*67e74705SXin Li auto *CE = cast<CallExpr>(InitOp);
406*67e74705SXin Li auto *OVE = cast<OpaqueValueExpr>(CE->getCallee());
407*67e74705SXin Li const Expr *LHS = CE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
408*67e74705SXin Li const Expr *RHS = CE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
409*67e74705SXin Li auto *LHSDRE = cast<DeclRefExpr>(cast<UnaryOperator>(LHS)->getSubExpr());
410*67e74705SXin Li auto *RHSDRE = cast<DeclRefExpr>(cast<UnaryOperator>(RHS)->getSubExpr());
411*67e74705SXin Li CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
412*67e74705SXin Li PrivateScope.addPrivate(cast<VarDecl>(LHSDRE->getDecl()),
413*67e74705SXin Li [=]() -> Address { return Private; });
414*67e74705SXin Li PrivateScope.addPrivate(cast<VarDecl>(RHSDRE->getDecl()),
415*67e74705SXin Li [=]() -> Address { return Original; });
416*67e74705SXin Li (void)PrivateScope.Privatize();
417*67e74705SXin Li RValue Func = RValue::get(Reduction.second);
418*67e74705SXin Li CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func);
419*67e74705SXin Li CGF.EmitIgnoredExpr(InitOp);
420*67e74705SXin Li } else {
421*67e74705SXin Li llvm::Constant *Init = CGF.CGM.EmitNullConstant(Ty);
422*67e74705SXin Li auto *GV = new llvm::GlobalVariable(
423*67e74705SXin Li CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true,
424*67e74705SXin Li llvm::GlobalValue::PrivateLinkage, Init, ".init");
425*67e74705SXin Li LValue LV = CGF.MakeNaturalAlignAddrLValue(GV, Ty);
426*67e74705SXin Li RValue InitRVal;
427*67e74705SXin Li switch (CGF.getEvaluationKind(Ty)) {
428*67e74705SXin Li case TEK_Scalar:
429*67e74705SXin Li InitRVal = CGF.EmitLoadOfLValue(LV, SourceLocation());
430*67e74705SXin Li break;
431*67e74705SXin Li case TEK_Complex:
432*67e74705SXin Li InitRVal =
433*67e74705SXin Li RValue::getComplex(CGF.EmitLoadOfComplex(LV, SourceLocation()));
434*67e74705SXin Li break;
435*67e74705SXin Li case TEK_Aggregate:
436*67e74705SXin Li InitRVal = RValue::getAggregate(LV.getAddress());
437*67e74705SXin Li break;
438*67e74705SXin Li }
439*67e74705SXin Li OpaqueValueExpr OVE(SourceLocation(), Ty, VK_RValue);
440*67e74705SXin Li CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, InitRVal);
441*67e74705SXin Li CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(),
442*67e74705SXin Li /*IsInitializer=*/false);
443*67e74705SXin Li }
444*67e74705SXin Li }
445*67e74705SXin Li
446*67e74705SXin Li /// \brief Emit initialization of arrays of complex types.
447*67e74705SXin Li /// \param DestAddr Address of the array.
448*67e74705SXin Li /// \param Type Type of array.
449*67e74705SXin Li /// \param Init Initial expression of array.
450*67e74705SXin Li /// \param SrcAddr Address of the original array.
EmitOMPAggregateInit(CodeGenFunction & CGF,Address DestAddr,QualType Type,const Expr * Init,Address SrcAddr=Address::invalid ())451*67e74705SXin Li static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr,
452*67e74705SXin Li QualType Type, const Expr *Init,
453*67e74705SXin Li Address SrcAddr = Address::invalid()) {
454*67e74705SXin Li auto *DRD = getReductionInit(Init);
455*67e74705SXin Li // Perform element-by-element initialization.
456*67e74705SXin Li QualType ElementTy;
457*67e74705SXin Li
458*67e74705SXin Li // Drill down to the base element type on both arrays.
459*67e74705SXin Li auto ArrayTy = Type->getAsArrayTypeUnsafe();
460*67e74705SXin Li auto NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, DestAddr);
461*67e74705SXin Li DestAddr =
462*67e74705SXin Li CGF.Builder.CreateElementBitCast(DestAddr, DestAddr.getElementType());
463*67e74705SXin Li if (DRD)
464*67e74705SXin Li SrcAddr =
465*67e74705SXin Li CGF.Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType());
466*67e74705SXin Li
467*67e74705SXin Li llvm::Value *SrcBegin = nullptr;
468*67e74705SXin Li if (DRD)
469*67e74705SXin Li SrcBegin = SrcAddr.getPointer();
470*67e74705SXin Li auto DestBegin = DestAddr.getPointer();
471*67e74705SXin Li // Cast from pointer to array type to pointer to single element.
472*67e74705SXin Li auto DestEnd = CGF.Builder.CreateGEP(DestBegin, NumElements);
473*67e74705SXin Li // The basic structure here is a while-do loop.
474*67e74705SXin Li auto BodyBB = CGF.createBasicBlock("omp.arrayinit.body");
475*67e74705SXin Li auto DoneBB = CGF.createBasicBlock("omp.arrayinit.done");
476*67e74705SXin Li auto IsEmpty =
477*67e74705SXin Li CGF.Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arrayinit.isempty");
478*67e74705SXin Li CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
479*67e74705SXin Li
480*67e74705SXin Li // Enter the loop body, making that address the current address.
481*67e74705SXin Li auto EntryBB = CGF.Builder.GetInsertBlock();
482*67e74705SXin Li CGF.EmitBlock(BodyBB);
483*67e74705SXin Li
484*67e74705SXin Li CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
485*67e74705SXin Li
486*67e74705SXin Li llvm::PHINode *SrcElementPHI = nullptr;
487*67e74705SXin Li Address SrcElementCurrent = Address::invalid();
488*67e74705SXin Li if (DRD) {
489*67e74705SXin Li SrcElementPHI = CGF.Builder.CreatePHI(SrcBegin->getType(), 2,
490*67e74705SXin Li "omp.arraycpy.srcElementPast");
491*67e74705SXin Li SrcElementPHI->addIncoming(SrcBegin, EntryBB);
492*67e74705SXin Li SrcElementCurrent =
493*67e74705SXin Li Address(SrcElementPHI,
494*67e74705SXin Li SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize));
495*67e74705SXin Li }
496*67e74705SXin Li llvm::PHINode *DestElementPHI = CGF.Builder.CreatePHI(
497*67e74705SXin Li DestBegin->getType(), 2, "omp.arraycpy.destElementPast");
498*67e74705SXin Li DestElementPHI->addIncoming(DestBegin, EntryBB);
499*67e74705SXin Li Address DestElementCurrent =
500*67e74705SXin Li Address(DestElementPHI,
501*67e74705SXin Li DestAddr.getAlignment().alignmentOfArrayElement(ElementSize));
502*67e74705SXin Li
503*67e74705SXin Li // Emit copy.
504*67e74705SXin Li {
505*67e74705SXin Li CodeGenFunction::RunCleanupsScope InitScope(CGF);
506*67e74705SXin Li if (DRD && (DRD->getInitializer() || !Init)) {
507*67e74705SXin Li emitInitWithReductionInitializer(CGF, DRD, Init, DestElementCurrent,
508*67e74705SXin Li SrcElementCurrent, ElementTy);
509*67e74705SXin Li } else
510*67e74705SXin Li CGF.EmitAnyExprToMem(Init, DestElementCurrent, ElementTy.getQualifiers(),
511*67e74705SXin Li /*IsInitializer=*/false);
512*67e74705SXin Li }
513*67e74705SXin Li
514*67e74705SXin Li if (DRD) {
515*67e74705SXin Li // Shift the address forward by one element.
516*67e74705SXin Li auto SrcElementNext = CGF.Builder.CreateConstGEP1_32(
517*67e74705SXin Li SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
518*67e74705SXin Li SrcElementPHI->addIncoming(SrcElementNext, CGF.Builder.GetInsertBlock());
519*67e74705SXin Li }
520*67e74705SXin Li
521*67e74705SXin Li // Shift the address forward by one element.
522*67e74705SXin Li auto DestElementNext = CGF.Builder.CreateConstGEP1_32(
523*67e74705SXin Li DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
524*67e74705SXin Li // Check whether we've reached the end.
525*67e74705SXin Li auto Done =
526*67e74705SXin Li CGF.Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done");
527*67e74705SXin Li CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
528*67e74705SXin Li DestElementPHI->addIncoming(DestElementNext, CGF.Builder.GetInsertBlock());
529*67e74705SXin Li
530*67e74705SXin Li // Done.
531*67e74705SXin Li CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
532*67e74705SXin Li }
533*67e74705SXin Li
EmitOMPCopy(QualType OriginalType,Address DestAddr,Address SrcAddr,const VarDecl * DestVD,const VarDecl * SrcVD,const Expr * Copy)534*67e74705SXin Li void CodeGenFunction::EmitOMPCopy(QualType OriginalType, Address DestAddr,
535*67e74705SXin Li Address SrcAddr, const VarDecl *DestVD,
536*67e74705SXin Li const VarDecl *SrcVD, const Expr *Copy) {
537*67e74705SXin Li if (OriginalType->isArrayType()) {
538*67e74705SXin Li auto *BO = dyn_cast<BinaryOperator>(Copy);
539*67e74705SXin Li if (BO && BO->getOpcode() == BO_Assign) {
540*67e74705SXin Li // Perform simple memcpy for simple copying.
541*67e74705SXin Li EmitAggregateAssign(DestAddr, SrcAddr, OriginalType);
542*67e74705SXin Li } else {
543*67e74705SXin Li // For arrays with complex element types perform element by element
544*67e74705SXin Li // copying.
545*67e74705SXin Li EmitOMPAggregateAssign(
546*67e74705SXin Li DestAddr, SrcAddr, OriginalType,
547*67e74705SXin Li [this, Copy, SrcVD, DestVD](Address DestElement, Address SrcElement) {
548*67e74705SXin Li // Working with the single array element, so have to remap
549*67e74705SXin Li // destination and source variables to corresponding array
550*67e74705SXin Li // elements.
551*67e74705SXin Li CodeGenFunction::OMPPrivateScope Remap(*this);
552*67e74705SXin Li Remap.addPrivate(DestVD, [DestElement]() -> Address {
553*67e74705SXin Li return DestElement;
554*67e74705SXin Li });
555*67e74705SXin Li Remap.addPrivate(
556*67e74705SXin Li SrcVD, [SrcElement]() -> Address { return SrcElement; });
557*67e74705SXin Li (void)Remap.Privatize();
558*67e74705SXin Li EmitIgnoredExpr(Copy);
559*67e74705SXin Li });
560*67e74705SXin Li }
561*67e74705SXin Li } else {
562*67e74705SXin Li // Remap pseudo source variable to private copy.
563*67e74705SXin Li CodeGenFunction::OMPPrivateScope Remap(*this);
564*67e74705SXin Li Remap.addPrivate(SrcVD, [SrcAddr]() -> Address { return SrcAddr; });
565*67e74705SXin Li Remap.addPrivate(DestVD, [DestAddr]() -> Address { return DestAddr; });
566*67e74705SXin Li (void)Remap.Privatize();
567*67e74705SXin Li // Emit copying of the whole variable.
568*67e74705SXin Li EmitIgnoredExpr(Copy);
569*67e74705SXin Li }
570*67e74705SXin Li }
571*67e74705SXin Li
EmitOMPFirstprivateClause(const OMPExecutableDirective & D,OMPPrivateScope & PrivateScope)572*67e74705SXin Li bool CodeGenFunction::EmitOMPFirstprivateClause(const OMPExecutableDirective &D,
573*67e74705SXin Li OMPPrivateScope &PrivateScope) {
574*67e74705SXin Li if (!HaveInsertPoint())
575*67e74705SXin Li return false;
576*67e74705SXin Li bool FirstprivateIsLastprivate = false;
577*67e74705SXin Li llvm::DenseSet<const VarDecl *> Lastprivates;
578*67e74705SXin Li for (const auto *C : D.getClausesOfKind<OMPLastprivateClause>()) {
579*67e74705SXin Li for (const auto *D : C->varlists())
580*67e74705SXin Li Lastprivates.insert(
581*67e74705SXin Li cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl())->getCanonicalDecl());
582*67e74705SXin Li }
583*67e74705SXin Li llvm::DenseSet<const VarDecl *> EmittedAsFirstprivate;
584*67e74705SXin Li CGCapturedStmtInfo CapturesInfo(cast<CapturedStmt>(*D.getAssociatedStmt()));
585*67e74705SXin Li for (const auto *C : D.getClausesOfKind<OMPFirstprivateClause>()) {
586*67e74705SXin Li auto IRef = C->varlist_begin();
587*67e74705SXin Li auto InitsRef = C->inits().begin();
588*67e74705SXin Li for (auto IInit : C->private_copies()) {
589*67e74705SXin Li auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
590*67e74705SXin Li bool ThisFirstprivateIsLastprivate =
591*67e74705SXin Li Lastprivates.count(OrigVD->getCanonicalDecl()) > 0;
592*67e74705SXin Li auto *CapFD = CapturesInfo.lookup(OrigVD);
593*67e74705SXin Li auto *FD = CapturedStmtInfo->lookup(OrigVD);
594*67e74705SXin Li if (!ThisFirstprivateIsLastprivate && FD && (FD == CapFD) &&
595*67e74705SXin Li !FD->getType()->isReferenceType()) {
596*67e74705SXin Li EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl());
597*67e74705SXin Li ++IRef;
598*67e74705SXin Li ++InitsRef;
599*67e74705SXin Li continue;
600*67e74705SXin Li }
601*67e74705SXin Li FirstprivateIsLastprivate =
602*67e74705SXin Li FirstprivateIsLastprivate || ThisFirstprivateIsLastprivate;
603*67e74705SXin Li if (EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl()).second) {
604*67e74705SXin Li auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
605*67e74705SXin Li auto *VDInit = cast<VarDecl>(cast<DeclRefExpr>(*InitsRef)->getDecl());
606*67e74705SXin Li bool IsRegistered;
607*67e74705SXin Li DeclRefExpr DRE(const_cast<VarDecl *>(OrigVD),
608*67e74705SXin Li /*RefersToEnclosingVariableOrCapture=*/FD != nullptr,
609*67e74705SXin Li (*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc());
610*67e74705SXin Li Address OriginalAddr = EmitLValue(&DRE).getAddress();
611*67e74705SXin Li QualType Type = VD->getType();
612*67e74705SXin Li if (Type->isArrayType()) {
613*67e74705SXin Li // Emit VarDecl with copy init for arrays.
614*67e74705SXin Li // Get the address of the original variable captured in current
615*67e74705SXin Li // captured region.
616*67e74705SXin Li IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> Address {
617*67e74705SXin Li auto Emission = EmitAutoVarAlloca(*VD);
618*67e74705SXin Li auto *Init = VD->getInit();
619*67e74705SXin Li if (!isa<CXXConstructExpr>(Init) || isTrivialInitializer(Init)) {
620*67e74705SXin Li // Perform simple memcpy.
621*67e74705SXin Li EmitAggregateAssign(Emission.getAllocatedAddress(), OriginalAddr,
622*67e74705SXin Li Type);
623*67e74705SXin Li } else {
624*67e74705SXin Li EmitOMPAggregateAssign(
625*67e74705SXin Li Emission.getAllocatedAddress(), OriginalAddr, Type,
626*67e74705SXin Li [this, VDInit, Init](Address DestElement,
627*67e74705SXin Li Address SrcElement) {
628*67e74705SXin Li // Clean up any temporaries needed by the initialization.
629*67e74705SXin Li RunCleanupsScope InitScope(*this);
630*67e74705SXin Li // Emit initialization for single element.
631*67e74705SXin Li setAddrOfLocalVar(VDInit, SrcElement);
632*67e74705SXin Li EmitAnyExprToMem(Init, DestElement,
633*67e74705SXin Li Init->getType().getQualifiers(),
634*67e74705SXin Li /*IsInitializer*/ false);
635*67e74705SXin Li LocalDeclMap.erase(VDInit);
636*67e74705SXin Li });
637*67e74705SXin Li }
638*67e74705SXin Li EmitAutoVarCleanups(Emission);
639*67e74705SXin Li return Emission.getAllocatedAddress();
640*67e74705SXin Li });
641*67e74705SXin Li } else {
642*67e74705SXin Li IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> Address {
643*67e74705SXin Li // Emit private VarDecl with copy init.
644*67e74705SXin Li // Remap temp VDInit variable to the address of the original
645*67e74705SXin Li // variable
646*67e74705SXin Li // (for proper handling of captured global variables).
647*67e74705SXin Li setAddrOfLocalVar(VDInit, OriginalAddr);
648*67e74705SXin Li EmitDecl(*VD);
649*67e74705SXin Li LocalDeclMap.erase(VDInit);
650*67e74705SXin Li return GetAddrOfLocalVar(VD);
651*67e74705SXin Li });
652*67e74705SXin Li }
653*67e74705SXin Li assert(IsRegistered &&
654*67e74705SXin Li "firstprivate var already registered as private");
655*67e74705SXin Li // Silence the warning about unused variable.
656*67e74705SXin Li (void)IsRegistered;
657*67e74705SXin Li }
658*67e74705SXin Li ++IRef;
659*67e74705SXin Li ++InitsRef;
660*67e74705SXin Li }
661*67e74705SXin Li }
662*67e74705SXin Li return FirstprivateIsLastprivate && !EmittedAsFirstprivate.empty();
663*67e74705SXin Li }
664*67e74705SXin Li
EmitOMPPrivateClause(const OMPExecutableDirective & D,CodeGenFunction::OMPPrivateScope & PrivateScope)665*67e74705SXin Li void CodeGenFunction::EmitOMPPrivateClause(
666*67e74705SXin Li const OMPExecutableDirective &D,
667*67e74705SXin Li CodeGenFunction::OMPPrivateScope &PrivateScope) {
668*67e74705SXin Li if (!HaveInsertPoint())
669*67e74705SXin Li return;
670*67e74705SXin Li llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
671*67e74705SXin Li for (const auto *C : D.getClausesOfKind<OMPPrivateClause>()) {
672*67e74705SXin Li auto IRef = C->varlist_begin();
673*67e74705SXin Li for (auto IInit : C->private_copies()) {
674*67e74705SXin Li auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
675*67e74705SXin Li if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
676*67e74705SXin Li auto VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
677*67e74705SXin Li bool IsRegistered =
678*67e74705SXin Li PrivateScope.addPrivate(OrigVD, [&]() -> Address {
679*67e74705SXin Li // Emit private VarDecl with copy init.
680*67e74705SXin Li EmitDecl(*VD);
681*67e74705SXin Li return GetAddrOfLocalVar(VD);
682*67e74705SXin Li });
683*67e74705SXin Li assert(IsRegistered && "private var already registered as private");
684*67e74705SXin Li // Silence the warning about unused variable.
685*67e74705SXin Li (void)IsRegistered;
686*67e74705SXin Li }
687*67e74705SXin Li ++IRef;
688*67e74705SXin Li }
689*67e74705SXin Li }
690*67e74705SXin Li }
691*67e74705SXin Li
EmitOMPCopyinClause(const OMPExecutableDirective & D)692*67e74705SXin Li bool CodeGenFunction::EmitOMPCopyinClause(const OMPExecutableDirective &D) {
693*67e74705SXin Li if (!HaveInsertPoint())
694*67e74705SXin Li return false;
695*67e74705SXin Li // threadprivate_var1 = master_threadprivate_var1;
696*67e74705SXin Li // operator=(threadprivate_var2, master_threadprivate_var2);
697*67e74705SXin Li // ...
698*67e74705SXin Li // __kmpc_barrier(&loc, global_tid);
699*67e74705SXin Li llvm::DenseSet<const VarDecl *> CopiedVars;
700*67e74705SXin Li llvm::BasicBlock *CopyBegin = nullptr, *CopyEnd = nullptr;
701*67e74705SXin Li for (const auto *C : D.getClausesOfKind<OMPCopyinClause>()) {
702*67e74705SXin Li auto IRef = C->varlist_begin();
703*67e74705SXin Li auto ISrcRef = C->source_exprs().begin();
704*67e74705SXin Li auto IDestRef = C->destination_exprs().begin();
705*67e74705SXin Li for (auto *AssignOp : C->assignment_ops()) {
706*67e74705SXin Li auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
707*67e74705SXin Li QualType Type = VD->getType();
708*67e74705SXin Li if (CopiedVars.insert(VD->getCanonicalDecl()).second) {
709*67e74705SXin Li // Get the address of the master variable. If we are emitting code with
710*67e74705SXin Li // TLS support, the address is passed from the master as field in the
711*67e74705SXin Li // captured declaration.
712*67e74705SXin Li Address MasterAddr = Address::invalid();
713*67e74705SXin Li if (getLangOpts().OpenMPUseTLS &&
714*67e74705SXin Li getContext().getTargetInfo().isTLSSupported()) {
715*67e74705SXin Li assert(CapturedStmtInfo->lookup(VD) &&
716*67e74705SXin Li "Copyin threadprivates should have been captured!");
717*67e74705SXin Li DeclRefExpr DRE(const_cast<VarDecl *>(VD), true, (*IRef)->getType(),
718*67e74705SXin Li VK_LValue, (*IRef)->getExprLoc());
719*67e74705SXin Li MasterAddr = EmitLValue(&DRE).getAddress();
720*67e74705SXin Li LocalDeclMap.erase(VD);
721*67e74705SXin Li } else {
722*67e74705SXin Li MasterAddr =
723*67e74705SXin Li Address(VD->isStaticLocal() ? CGM.getStaticLocalDeclAddress(VD)
724*67e74705SXin Li : CGM.GetAddrOfGlobal(VD),
725*67e74705SXin Li getContext().getDeclAlign(VD));
726*67e74705SXin Li }
727*67e74705SXin Li // Get the address of the threadprivate variable.
728*67e74705SXin Li Address PrivateAddr = EmitLValue(*IRef).getAddress();
729*67e74705SXin Li if (CopiedVars.size() == 1) {
730*67e74705SXin Li // At first check if current thread is a master thread. If it is, no
731*67e74705SXin Li // need to copy data.
732*67e74705SXin Li CopyBegin = createBasicBlock("copyin.not.master");
733*67e74705SXin Li CopyEnd = createBasicBlock("copyin.not.master.end");
734*67e74705SXin Li Builder.CreateCondBr(
735*67e74705SXin Li Builder.CreateICmpNE(
736*67e74705SXin Li Builder.CreatePtrToInt(MasterAddr.getPointer(), CGM.IntPtrTy),
737*67e74705SXin Li Builder.CreatePtrToInt(PrivateAddr.getPointer(), CGM.IntPtrTy)),
738*67e74705SXin Li CopyBegin, CopyEnd);
739*67e74705SXin Li EmitBlock(CopyBegin);
740*67e74705SXin Li }
741*67e74705SXin Li auto *SrcVD = cast<VarDecl>(cast<DeclRefExpr>(*ISrcRef)->getDecl());
742*67e74705SXin Li auto *DestVD = cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
743*67e74705SXin Li EmitOMPCopy(Type, PrivateAddr, MasterAddr, DestVD, SrcVD, AssignOp);
744*67e74705SXin Li }
745*67e74705SXin Li ++IRef;
746*67e74705SXin Li ++ISrcRef;
747*67e74705SXin Li ++IDestRef;
748*67e74705SXin Li }
749*67e74705SXin Li }
750*67e74705SXin Li if (CopyEnd) {
751*67e74705SXin Li // Exit out of copying procedure for non-master thread.
752*67e74705SXin Li EmitBlock(CopyEnd, /*IsFinished=*/true);
753*67e74705SXin Li return true;
754*67e74705SXin Li }
755*67e74705SXin Li return false;
756*67e74705SXin Li }
757*67e74705SXin Li
EmitOMPLastprivateClauseInit(const OMPExecutableDirective & D,OMPPrivateScope & PrivateScope)758*67e74705SXin Li bool CodeGenFunction::EmitOMPLastprivateClauseInit(
759*67e74705SXin Li const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope) {
760*67e74705SXin Li if (!HaveInsertPoint())
761*67e74705SXin Li return false;
762*67e74705SXin Li bool HasAtLeastOneLastprivate = false;
763*67e74705SXin Li llvm::DenseSet<const VarDecl *> SIMDLCVs;
764*67e74705SXin Li if (isOpenMPSimdDirective(D.getDirectiveKind())) {
765*67e74705SXin Li auto *LoopDirective = cast<OMPLoopDirective>(&D);
766*67e74705SXin Li for (auto *C : LoopDirective->counters()) {
767*67e74705SXin Li SIMDLCVs.insert(
768*67e74705SXin Li cast<VarDecl>(cast<DeclRefExpr>(C)->getDecl())->getCanonicalDecl());
769*67e74705SXin Li }
770*67e74705SXin Li }
771*67e74705SXin Li llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
772*67e74705SXin Li for (const auto *C : D.getClausesOfKind<OMPLastprivateClause>()) {
773*67e74705SXin Li HasAtLeastOneLastprivate = true;
774*67e74705SXin Li if (isOpenMPTaskLoopDirective(D.getDirectiveKind()))
775*67e74705SXin Li break;
776*67e74705SXin Li auto IRef = C->varlist_begin();
777*67e74705SXin Li auto IDestRef = C->destination_exprs().begin();
778*67e74705SXin Li for (auto *IInit : C->private_copies()) {
779*67e74705SXin Li // Keep the address of the original variable for future update at the end
780*67e74705SXin Li // of the loop.
781*67e74705SXin Li auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
782*67e74705SXin Li // Taskloops do not require additional initialization, it is done in
783*67e74705SXin Li // runtime support library.
784*67e74705SXin Li if (AlreadyEmittedVars.insert(OrigVD->getCanonicalDecl()).second) {
785*67e74705SXin Li auto *DestVD = cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
786*67e74705SXin Li PrivateScope.addPrivate(DestVD, [this, OrigVD, IRef]() -> Address {
787*67e74705SXin Li DeclRefExpr DRE(
788*67e74705SXin Li const_cast<VarDecl *>(OrigVD),
789*67e74705SXin Li /*RefersToEnclosingVariableOrCapture=*/CapturedStmtInfo->lookup(
790*67e74705SXin Li OrigVD) != nullptr,
791*67e74705SXin Li (*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc());
792*67e74705SXin Li return EmitLValue(&DRE).getAddress();
793*67e74705SXin Li });
794*67e74705SXin Li // Check if the variable is also a firstprivate: in this case IInit is
795*67e74705SXin Li // not generated. Initialization of this variable will happen in codegen
796*67e74705SXin Li // for 'firstprivate' clause.
797*67e74705SXin Li if (IInit && !SIMDLCVs.count(OrigVD->getCanonicalDecl())) {
798*67e74705SXin Li auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
799*67e74705SXin Li bool IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> Address {
800*67e74705SXin Li // Emit private VarDecl with copy init.
801*67e74705SXin Li EmitDecl(*VD);
802*67e74705SXin Li return GetAddrOfLocalVar(VD);
803*67e74705SXin Li });
804*67e74705SXin Li assert(IsRegistered &&
805*67e74705SXin Li "lastprivate var already registered as private");
806*67e74705SXin Li (void)IsRegistered;
807*67e74705SXin Li }
808*67e74705SXin Li }
809*67e74705SXin Li ++IRef;
810*67e74705SXin Li ++IDestRef;
811*67e74705SXin Li }
812*67e74705SXin Li }
813*67e74705SXin Li return HasAtLeastOneLastprivate;
814*67e74705SXin Li }
815*67e74705SXin Li
EmitOMPLastprivateClauseFinal(const OMPExecutableDirective & D,bool NoFinals,llvm::Value * IsLastIterCond)816*67e74705SXin Li void CodeGenFunction::EmitOMPLastprivateClauseFinal(
817*67e74705SXin Li const OMPExecutableDirective &D, bool NoFinals,
818*67e74705SXin Li llvm::Value *IsLastIterCond) {
819*67e74705SXin Li if (!HaveInsertPoint())
820*67e74705SXin Li return;
821*67e74705SXin Li // Emit following code:
822*67e74705SXin Li // if (<IsLastIterCond>) {
823*67e74705SXin Li // orig_var1 = private_orig_var1;
824*67e74705SXin Li // ...
825*67e74705SXin Li // orig_varn = private_orig_varn;
826*67e74705SXin Li // }
827*67e74705SXin Li llvm::BasicBlock *ThenBB = nullptr;
828*67e74705SXin Li llvm::BasicBlock *DoneBB = nullptr;
829*67e74705SXin Li if (IsLastIterCond) {
830*67e74705SXin Li ThenBB = createBasicBlock(".omp.lastprivate.then");
831*67e74705SXin Li DoneBB = createBasicBlock(".omp.lastprivate.done");
832*67e74705SXin Li Builder.CreateCondBr(IsLastIterCond, ThenBB, DoneBB);
833*67e74705SXin Li EmitBlock(ThenBB);
834*67e74705SXin Li }
835*67e74705SXin Li llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
836*67e74705SXin Li llvm::DenseMap<const VarDecl *, const Expr *> LoopCountersAndUpdates;
837*67e74705SXin Li if (auto *LoopDirective = dyn_cast<OMPLoopDirective>(&D)) {
838*67e74705SXin Li auto IC = LoopDirective->counters().begin();
839*67e74705SXin Li for (auto F : LoopDirective->finals()) {
840*67e74705SXin Li auto *D =
841*67e74705SXin Li cast<VarDecl>(cast<DeclRefExpr>(*IC)->getDecl())->getCanonicalDecl();
842*67e74705SXin Li if (NoFinals)
843*67e74705SXin Li AlreadyEmittedVars.insert(D);
844*67e74705SXin Li else
845*67e74705SXin Li LoopCountersAndUpdates[D] = F;
846*67e74705SXin Li ++IC;
847*67e74705SXin Li }
848*67e74705SXin Li }
849*67e74705SXin Li for (const auto *C : D.getClausesOfKind<OMPLastprivateClause>()) {
850*67e74705SXin Li auto IRef = C->varlist_begin();
851*67e74705SXin Li auto ISrcRef = C->source_exprs().begin();
852*67e74705SXin Li auto IDestRef = C->destination_exprs().begin();
853*67e74705SXin Li for (auto *AssignOp : C->assignment_ops()) {
854*67e74705SXin Li auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
855*67e74705SXin Li QualType Type = PrivateVD->getType();
856*67e74705SXin Li auto *CanonicalVD = PrivateVD->getCanonicalDecl();
857*67e74705SXin Li if (AlreadyEmittedVars.insert(CanonicalVD).second) {
858*67e74705SXin Li // If lastprivate variable is a loop control variable for loop-based
859*67e74705SXin Li // directive, update its value before copyin back to original
860*67e74705SXin Li // variable.
861*67e74705SXin Li if (auto *FinalExpr = LoopCountersAndUpdates.lookup(CanonicalVD))
862*67e74705SXin Li EmitIgnoredExpr(FinalExpr);
863*67e74705SXin Li auto *SrcVD = cast<VarDecl>(cast<DeclRefExpr>(*ISrcRef)->getDecl());
864*67e74705SXin Li auto *DestVD = cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
865*67e74705SXin Li // Get the address of the original variable.
866*67e74705SXin Li Address OriginalAddr = GetAddrOfLocalVar(DestVD);
867*67e74705SXin Li // Get the address of the private variable.
868*67e74705SXin Li Address PrivateAddr = GetAddrOfLocalVar(PrivateVD);
869*67e74705SXin Li if (auto RefTy = PrivateVD->getType()->getAs<ReferenceType>())
870*67e74705SXin Li PrivateAddr =
871*67e74705SXin Li Address(Builder.CreateLoad(PrivateAddr),
872*67e74705SXin Li getNaturalTypeAlignment(RefTy->getPointeeType()));
873*67e74705SXin Li EmitOMPCopy(Type, OriginalAddr, PrivateAddr, DestVD, SrcVD, AssignOp);
874*67e74705SXin Li }
875*67e74705SXin Li ++IRef;
876*67e74705SXin Li ++ISrcRef;
877*67e74705SXin Li ++IDestRef;
878*67e74705SXin Li }
879*67e74705SXin Li if (auto *PostUpdate = C->getPostUpdateExpr())
880*67e74705SXin Li EmitIgnoredExpr(PostUpdate);
881*67e74705SXin Li }
882*67e74705SXin Li if (IsLastIterCond)
883*67e74705SXin Li EmitBlock(DoneBB, /*IsFinished=*/true);
884*67e74705SXin Li }
885*67e74705SXin Li
castToBase(CodeGenFunction & CGF,QualType BaseTy,QualType ElTy,LValue BaseLV,llvm::Value * Addr)886*67e74705SXin Li static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy,
887*67e74705SXin Li LValue BaseLV, llvm::Value *Addr) {
888*67e74705SXin Li Address Tmp = Address::invalid();
889*67e74705SXin Li Address TopTmp = Address::invalid();
890*67e74705SXin Li Address MostTopTmp = Address::invalid();
891*67e74705SXin Li BaseTy = BaseTy.getNonReferenceType();
892*67e74705SXin Li while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) &&
893*67e74705SXin Li !CGF.getContext().hasSameType(BaseTy, ElTy)) {
894*67e74705SXin Li Tmp = CGF.CreateMemTemp(BaseTy);
895*67e74705SXin Li if (TopTmp.isValid())
896*67e74705SXin Li CGF.Builder.CreateStore(Tmp.getPointer(), TopTmp);
897*67e74705SXin Li else
898*67e74705SXin Li MostTopTmp = Tmp;
899*67e74705SXin Li TopTmp = Tmp;
900*67e74705SXin Li BaseTy = BaseTy->getPointeeType();
901*67e74705SXin Li }
902*67e74705SXin Li llvm::Type *Ty = BaseLV.getPointer()->getType();
903*67e74705SXin Li if (Tmp.isValid())
904*67e74705SXin Li Ty = Tmp.getElementType();
905*67e74705SXin Li Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Addr, Ty);
906*67e74705SXin Li if (Tmp.isValid()) {
907*67e74705SXin Li CGF.Builder.CreateStore(Addr, Tmp);
908*67e74705SXin Li return MostTopTmp;
909*67e74705SXin Li }
910*67e74705SXin Li return Address(Addr, BaseLV.getAlignment());
911*67e74705SXin Li }
912*67e74705SXin Li
loadToBegin(CodeGenFunction & CGF,QualType BaseTy,QualType ElTy,LValue BaseLV)913*67e74705SXin Li static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy,
914*67e74705SXin Li LValue BaseLV) {
915*67e74705SXin Li BaseTy = BaseTy.getNonReferenceType();
916*67e74705SXin Li while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) &&
917*67e74705SXin Li !CGF.getContext().hasSameType(BaseTy, ElTy)) {
918*67e74705SXin Li if (auto *PtrTy = BaseTy->getAs<PointerType>())
919*67e74705SXin Li BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(), PtrTy);
920*67e74705SXin Li else {
921*67e74705SXin Li BaseLV = CGF.EmitLoadOfReferenceLValue(BaseLV.getAddress(),
922*67e74705SXin Li BaseTy->castAs<ReferenceType>());
923*67e74705SXin Li }
924*67e74705SXin Li BaseTy = BaseTy->getPointeeType();
925*67e74705SXin Li }
926*67e74705SXin Li return CGF.MakeAddrLValue(
927*67e74705SXin Li Address(
928*67e74705SXin Li CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
929*67e74705SXin Li BaseLV.getPointer(), CGF.ConvertTypeForMem(ElTy)->getPointerTo()),
930*67e74705SXin Li BaseLV.getAlignment()),
931*67e74705SXin Li BaseLV.getType(), BaseLV.getAlignmentSource());
932*67e74705SXin Li }
933*67e74705SXin Li
EmitOMPReductionClauseInit(const OMPExecutableDirective & D,CodeGenFunction::OMPPrivateScope & PrivateScope)934*67e74705SXin Li void CodeGenFunction::EmitOMPReductionClauseInit(
935*67e74705SXin Li const OMPExecutableDirective &D,
936*67e74705SXin Li CodeGenFunction::OMPPrivateScope &PrivateScope) {
937*67e74705SXin Li if (!HaveInsertPoint())
938*67e74705SXin Li return;
939*67e74705SXin Li for (const auto *C : D.getClausesOfKind<OMPReductionClause>()) {
940*67e74705SXin Li auto ILHS = C->lhs_exprs().begin();
941*67e74705SXin Li auto IRHS = C->rhs_exprs().begin();
942*67e74705SXin Li auto IPriv = C->privates().begin();
943*67e74705SXin Li auto IRed = C->reduction_ops().begin();
944*67e74705SXin Li for (auto IRef : C->varlists()) {
945*67e74705SXin Li auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
946*67e74705SXin Li auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
947*67e74705SXin Li auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*IPriv)->getDecl());
948*67e74705SXin Li auto *DRD = getReductionInit(*IRed);
949*67e74705SXin Li if (auto *OASE = dyn_cast<OMPArraySectionExpr>(IRef)) {
950*67e74705SXin Li auto *Base = OASE->getBase()->IgnoreParenImpCasts();
951*67e74705SXin Li while (auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base))
952*67e74705SXin Li Base = TempOASE->getBase()->IgnoreParenImpCasts();
953*67e74705SXin Li while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
954*67e74705SXin Li Base = TempASE->getBase()->IgnoreParenImpCasts();
955*67e74705SXin Li auto *DE = cast<DeclRefExpr>(Base);
956*67e74705SXin Li auto *OrigVD = cast<VarDecl>(DE->getDecl());
957*67e74705SXin Li auto OASELValueLB = EmitOMPArraySectionExpr(OASE);
958*67e74705SXin Li auto OASELValueUB =
959*67e74705SXin Li EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false);
960*67e74705SXin Li auto OriginalBaseLValue = EmitLValue(DE);
961*67e74705SXin Li LValue BaseLValue =
962*67e74705SXin Li loadToBegin(*this, OrigVD->getType(), OASELValueLB.getType(),
963*67e74705SXin Li OriginalBaseLValue);
964*67e74705SXin Li // Store the address of the original variable associated with the LHS
965*67e74705SXin Li // implicit variable.
966*67e74705SXin Li PrivateScope.addPrivate(LHSVD, [this, OASELValueLB]() -> Address {
967*67e74705SXin Li return OASELValueLB.getAddress();
968*67e74705SXin Li });
969*67e74705SXin Li // Emit reduction copy.
970*67e74705SXin Li bool IsRegistered = PrivateScope.addPrivate(
971*67e74705SXin Li OrigVD, [this, OrigVD, PrivateVD, BaseLValue, OASELValueLB,
972*67e74705SXin Li OASELValueUB, OriginalBaseLValue, DRD, IRed]() -> Address {
973*67e74705SXin Li // Emit VarDecl with copy init for arrays.
974*67e74705SXin Li // Get the address of the original variable captured in current
975*67e74705SXin Li // captured region.
976*67e74705SXin Li auto *Size = Builder.CreatePtrDiff(OASELValueUB.getPointer(),
977*67e74705SXin Li OASELValueLB.getPointer());
978*67e74705SXin Li Size = Builder.CreateNUWAdd(
979*67e74705SXin Li Size, llvm::ConstantInt::get(Size->getType(), /*V=*/1));
980*67e74705SXin Li CodeGenFunction::OpaqueValueMapping OpaqueMap(
981*67e74705SXin Li *this, cast<OpaqueValueExpr>(
982*67e74705SXin Li getContext()
983*67e74705SXin Li .getAsVariableArrayType(PrivateVD->getType())
984*67e74705SXin Li ->getSizeExpr()),
985*67e74705SXin Li RValue::get(Size));
986*67e74705SXin Li EmitVariablyModifiedType(PrivateVD->getType());
987*67e74705SXin Li auto Emission = EmitAutoVarAlloca(*PrivateVD);
988*67e74705SXin Li auto Addr = Emission.getAllocatedAddress();
989*67e74705SXin Li auto *Init = PrivateVD->getInit();
990*67e74705SXin Li EmitOMPAggregateInit(*this, Addr, PrivateVD->getType(),
991*67e74705SXin Li DRD ? *IRed : Init,
992*67e74705SXin Li OASELValueLB.getAddress());
993*67e74705SXin Li EmitAutoVarCleanups(Emission);
994*67e74705SXin Li // Emit private VarDecl with reduction init.
995*67e74705SXin Li auto *Offset = Builder.CreatePtrDiff(BaseLValue.getPointer(),
996*67e74705SXin Li OASELValueLB.getPointer());
997*67e74705SXin Li auto *Ptr = Builder.CreateGEP(Addr.getPointer(), Offset);
998*67e74705SXin Li return castToBase(*this, OrigVD->getType(),
999*67e74705SXin Li OASELValueLB.getType(), OriginalBaseLValue,
1000*67e74705SXin Li Ptr);
1001*67e74705SXin Li });
1002*67e74705SXin Li assert(IsRegistered && "private var already registered as private");
1003*67e74705SXin Li // Silence the warning about unused variable.
1004*67e74705SXin Li (void)IsRegistered;
1005*67e74705SXin Li PrivateScope.addPrivate(RHSVD, [this, PrivateVD]() -> Address {
1006*67e74705SXin Li return GetAddrOfLocalVar(PrivateVD);
1007*67e74705SXin Li });
1008*67e74705SXin Li } else if (auto *ASE = dyn_cast<ArraySubscriptExpr>(IRef)) {
1009*67e74705SXin Li auto *Base = ASE->getBase()->IgnoreParenImpCasts();
1010*67e74705SXin Li while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
1011*67e74705SXin Li Base = TempASE->getBase()->IgnoreParenImpCasts();
1012*67e74705SXin Li auto *DE = cast<DeclRefExpr>(Base);
1013*67e74705SXin Li auto *OrigVD = cast<VarDecl>(DE->getDecl());
1014*67e74705SXin Li auto ASELValue = EmitLValue(ASE);
1015*67e74705SXin Li auto OriginalBaseLValue = EmitLValue(DE);
1016*67e74705SXin Li LValue BaseLValue = loadToBegin(
1017*67e74705SXin Li *this, OrigVD->getType(), ASELValue.getType(), OriginalBaseLValue);
1018*67e74705SXin Li // Store the address of the original variable associated with the LHS
1019*67e74705SXin Li // implicit variable.
1020*67e74705SXin Li PrivateScope.addPrivate(LHSVD, [this, ASELValue]() -> Address {
1021*67e74705SXin Li return ASELValue.getAddress();
1022*67e74705SXin Li });
1023*67e74705SXin Li // Emit reduction copy.
1024*67e74705SXin Li bool IsRegistered = PrivateScope.addPrivate(
1025*67e74705SXin Li OrigVD, [this, OrigVD, PrivateVD, BaseLValue, ASELValue,
1026*67e74705SXin Li OriginalBaseLValue, DRD, IRed]() -> Address {
1027*67e74705SXin Li // Emit private VarDecl with reduction init.
1028*67e74705SXin Li AutoVarEmission Emission = EmitAutoVarAlloca(*PrivateVD);
1029*67e74705SXin Li auto Addr = Emission.getAllocatedAddress();
1030*67e74705SXin Li if (DRD && (DRD->getInitializer() || !PrivateVD->hasInit())) {
1031*67e74705SXin Li emitInitWithReductionInitializer(*this, DRD, *IRed, Addr,
1032*67e74705SXin Li ASELValue.getAddress(),
1033*67e74705SXin Li ASELValue.getType());
1034*67e74705SXin Li } else
1035*67e74705SXin Li EmitAutoVarInit(Emission);
1036*67e74705SXin Li EmitAutoVarCleanups(Emission);
1037*67e74705SXin Li auto *Offset = Builder.CreatePtrDiff(BaseLValue.getPointer(),
1038*67e74705SXin Li ASELValue.getPointer());
1039*67e74705SXin Li auto *Ptr = Builder.CreateGEP(Addr.getPointer(), Offset);
1040*67e74705SXin Li return castToBase(*this, OrigVD->getType(), ASELValue.getType(),
1041*67e74705SXin Li OriginalBaseLValue, Ptr);
1042*67e74705SXin Li });
1043*67e74705SXin Li assert(IsRegistered && "private var already registered as private");
1044*67e74705SXin Li // Silence the warning about unused variable.
1045*67e74705SXin Li (void)IsRegistered;
1046*67e74705SXin Li PrivateScope.addPrivate(RHSVD, [this, PrivateVD, RHSVD]() -> Address {
1047*67e74705SXin Li return Builder.CreateElementBitCast(
1048*67e74705SXin Li GetAddrOfLocalVar(PrivateVD), ConvertTypeForMem(RHSVD->getType()),
1049*67e74705SXin Li "rhs.begin");
1050*67e74705SXin Li });
1051*67e74705SXin Li } else {
1052*67e74705SXin Li auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(IRef)->getDecl());
1053*67e74705SXin Li QualType Type = PrivateVD->getType();
1054*67e74705SXin Li if (getContext().getAsArrayType(Type)) {
1055*67e74705SXin Li // Store the address of the original variable associated with the LHS
1056*67e74705SXin Li // implicit variable.
1057*67e74705SXin Li DeclRefExpr DRE(const_cast<VarDecl *>(OrigVD),
1058*67e74705SXin Li CapturedStmtInfo->lookup(OrigVD) != nullptr,
1059*67e74705SXin Li IRef->getType(), VK_LValue, IRef->getExprLoc());
1060*67e74705SXin Li Address OriginalAddr = EmitLValue(&DRE).getAddress();
1061*67e74705SXin Li PrivateScope.addPrivate(LHSVD, [this, &OriginalAddr,
1062*67e74705SXin Li LHSVD]() -> Address {
1063*67e74705SXin Li OriginalAddr = Builder.CreateElementBitCast(
1064*67e74705SXin Li OriginalAddr, ConvertTypeForMem(LHSVD->getType()), "lhs.begin");
1065*67e74705SXin Li return OriginalAddr;
1066*67e74705SXin Li });
1067*67e74705SXin Li bool IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> Address {
1068*67e74705SXin Li if (Type->isVariablyModifiedType()) {
1069*67e74705SXin Li CodeGenFunction::OpaqueValueMapping OpaqueMap(
1070*67e74705SXin Li *this, cast<OpaqueValueExpr>(
1071*67e74705SXin Li getContext()
1072*67e74705SXin Li .getAsVariableArrayType(PrivateVD->getType())
1073*67e74705SXin Li ->getSizeExpr()),
1074*67e74705SXin Li RValue::get(
1075*67e74705SXin Li getTypeSize(OrigVD->getType().getNonReferenceType())));
1076*67e74705SXin Li EmitVariablyModifiedType(Type);
1077*67e74705SXin Li }
1078*67e74705SXin Li auto Emission = EmitAutoVarAlloca(*PrivateVD);
1079*67e74705SXin Li auto Addr = Emission.getAllocatedAddress();
1080*67e74705SXin Li auto *Init = PrivateVD->getInit();
1081*67e74705SXin Li EmitOMPAggregateInit(*this, Addr, PrivateVD->getType(),
1082*67e74705SXin Li DRD ? *IRed : Init, OriginalAddr);
1083*67e74705SXin Li EmitAutoVarCleanups(Emission);
1084*67e74705SXin Li return Emission.getAllocatedAddress();
1085*67e74705SXin Li });
1086*67e74705SXin Li assert(IsRegistered && "private var already registered as private");
1087*67e74705SXin Li // Silence the warning about unused variable.
1088*67e74705SXin Li (void)IsRegistered;
1089*67e74705SXin Li PrivateScope.addPrivate(RHSVD, [this, PrivateVD, RHSVD]() -> Address {
1090*67e74705SXin Li return Builder.CreateElementBitCast(
1091*67e74705SXin Li GetAddrOfLocalVar(PrivateVD),
1092*67e74705SXin Li ConvertTypeForMem(RHSVD->getType()), "rhs.begin");
1093*67e74705SXin Li });
1094*67e74705SXin Li } else {
1095*67e74705SXin Li // Store the address of the original variable associated with the LHS
1096*67e74705SXin Li // implicit variable.
1097*67e74705SXin Li Address OriginalAddr = Address::invalid();
1098*67e74705SXin Li PrivateScope.addPrivate(LHSVD, [this, OrigVD, IRef,
1099*67e74705SXin Li &OriginalAddr]() -> Address {
1100*67e74705SXin Li DeclRefExpr DRE(const_cast<VarDecl *>(OrigVD),
1101*67e74705SXin Li CapturedStmtInfo->lookup(OrigVD) != nullptr,
1102*67e74705SXin Li IRef->getType(), VK_LValue, IRef->getExprLoc());
1103*67e74705SXin Li OriginalAddr = EmitLValue(&DRE).getAddress();
1104*67e74705SXin Li return OriginalAddr;
1105*67e74705SXin Li });
1106*67e74705SXin Li // Emit reduction copy.
1107*67e74705SXin Li bool IsRegistered = PrivateScope.addPrivate(
1108*67e74705SXin Li OrigVD, [this, PrivateVD, OriginalAddr, DRD, IRed]() -> Address {
1109*67e74705SXin Li // Emit private VarDecl with reduction init.
1110*67e74705SXin Li AutoVarEmission Emission = EmitAutoVarAlloca(*PrivateVD);
1111*67e74705SXin Li auto Addr = Emission.getAllocatedAddress();
1112*67e74705SXin Li if (DRD && (DRD->getInitializer() || !PrivateVD->hasInit())) {
1113*67e74705SXin Li emitInitWithReductionInitializer(*this, DRD, *IRed, Addr,
1114*67e74705SXin Li OriginalAddr,
1115*67e74705SXin Li PrivateVD->getType());
1116*67e74705SXin Li } else
1117*67e74705SXin Li EmitAutoVarInit(Emission);
1118*67e74705SXin Li EmitAutoVarCleanups(Emission);
1119*67e74705SXin Li return Addr;
1120*67e74705SXin Li });
1121*67e74705SXin Li assert(IsRegistered && "private var already registered as private");
1122*67e74705SXin Li // Silence the warning about unused variable.
1123*67e74705SXin Li (void)IsRegistered;
1124*67e74705SXin Li PrivateScope.addPrivate(RHSVD, [this, PrivateVD]() -> Address {
1125*67e74705SXin Li return GetAddrOfLocalVar(PrivateVD);
1126*67e74705SXin Li });
1127*67e74705SXin Li }
1128*67e74705SXin Li }
1129*67e74705SXin Li ++ILHS;
1130*67e74705SXin Li ++IRHS;
1131*67e74705SXin Li ++IPriv;
1132*67e74705SXin Li ++IRed;
1133*67e74705SXin Li }
1134*67e74705SXin Li }
1135*67e74705SXin Li }
1136*67e74705SXin Li
EmitOMPReductionClauseFinal(const OMPExecutableDirective & D)1137*67e74705SXin Li void CodeGenFunction::EmitOMPReductionClauseFinal(
1138*67e74705SXin Li const OMPExecutableDirective &D) {
1139*67e74705SXin Li if (!HaveInsertPoint())
1140*67e74705SXin Li return;
1141*67e74705SXin Li llvm::SmallVector<const Expr *, 8> Privates;
1142*67e74705SXin Li llvm::SmallVector<const Expr *, 8> LHSExprs;
1143*67e74705SXin Li llvm::SmallVector<const Expr *, 8> RHSExprs;
1144*67e74705SXin Li llvm::SmallVector<const Expr *, 8> ReductionOps;
1145*67e74705SXin Li bool HasAtLeastOneReduction = false;
1146*67e74705SXin Li for (const auto *C : D.getClausesOfKind<OMPReductionClause>()) {
1147*67e74705SXin Li HasAtLeastOneReduction = true;
1148*67e74705SXin Li Privates.append(C->privates().begin(), C->privates().end());
1149*67e74705SXin Li LHSExprs.append(C->lhs_exprs().begin(), C->lhs_exprs().end());
1150*67e74705SXin Li RHSExprs.append(C->rhs_exprs().begin(), C->rhs_exprs().end());
1151*67e74705SXin Li ReductionOps.append(C->reduction_ops().begin(), C->reduction_ops().end());
1152*67e74705SXin Li }
1153*67e74705SXin Li if (HasAtLeastOneReduction) {
1154*67e74705SXin Li // Emit nowait reduction if nowait clause is present or directive is a
1155*67e74705SXin Li // parallel directive (it always has implicit barrier).
1156*67e74705SXin Li CGM.getOpenMPRuntime().emitReduction(
1157*67e74705SXin Li *this, D.getLocEnd(), Privates, LHSExprs, RHSExprs, ReductionOps,
1158*67e74705SXin Li D.getSingleClause<OMPNowaitClause>() ||
1159*67e74705SXin Li isOpenMPParallelDirective(D.getDirectiveKind()) ||
1160*67e74705SXin Li D.getDirectiveKind() == OMPD_simd,
1161*67e74705SXin Li D.getDirectiveKind() == OMPD_simd);
1162*67e74705SXin Li }
1163*67e74705SXin Li }
1164*67e74705SXin Li
emitPostUpdateForReductionClause(CodeGenFunction & CGF,const OMPExecutableDirective & D,const llvm::function_ref<llvm::Value * (CodeGenFunction &)> & CondGen)1165*67e74705SXin Li static void emitPostUpdateForReductionClause(
1166*67e74705SXin Li CodeGenFunction &CGF, const OMPExecutableDirective &D,
1167*67e74705SXin Li const llvm::function_ref<llvm::Value *(CodeGenFunction &)> &CondGen) {
1168*67e74705SXin Li if (!CGF.HaveInsertPoint())
1169*67e74705SXin Li return;
1170*67e74705SXin Li llvm::BasicBlock *DoneBB = nullptr;
1171*67e74705SXin Li for (const auto *C : D.getClausesOfKind<OMPReductionClause>()) {
1172*67e74705SXin Li if (auto *PostUpdate = C->getPostUpdateExpr()) {
1173*67e74705SXin Li if (!DoneBB) {
1174*67e74705SXin Li if (auto *Cond = CondGen(CGF)) {
1175*67e74705SXin Li // If the first post-update expression is found, emit conditional
1176*67e74705SXin Li // block if it was requested.
1177*67e74705SXin Li auto *ThenBB = CGF.createBasicBlock(".omp.reduction.pu");
1178*67e74705SXin Li DoneBB = CGF.createBasicBlock(".omp.reduction.pu.done");
1179*67e74705SXin Li CGF.Builder.CreateCondBr(Cond, ThenBB, DoneBB);
1180*67e74705SXin Li CGF.EmitBlock(ThenBB);
1181*67e74705SXin Li }
1182*67e74705SXin Li }
1183*67e74705SXin Li CGF.EmitIgnoredExpr(PostUpdate);
1184*67e74705SXin Li }
1185*67e74705SXin Li }
1186*67e74705SXin Li if (DoneBB)
1187*67e74705SXin Li CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
1188*67e74705SXin Li }
1189*67e74705SXin Li
emitCommonOMPParallelDirective(CodeGenFunction & CGF,const OMPExecutableDirective & S,OpenMPDirectiveKind InnermostKind,const RegionCodeGenTy & CodeGen)1190*67e74705SXin Li static void emitCommonOMPParallelDirective(CodeGenFunction &CGF,
1191*67e74705SXin Li const OMPExecutableDirective &S,
1192*67e74705SXin Li OpenMPDirectiveKind InnermostKind,
1193*67e74705SXin Li const RegionCodeGenTy &CodeGen) {
1194*67e74705SXin Li auto CS = cast<CapturedStmt>(S.getAssociatedStmt());
1195*67e74705SXin Li auto OutlinedFn = CGF.CGM.getOpenMPRuntime().
1196*67e74705SXin Li emitParallelOrTeamsOutlinedFunction(S,
1197*67e74705SXin Li *CS->getCapturedDecl()->param_begin(), InnermostKind, CodeGen);
1198*67e74705SXin Li if (const auto *NumThreadsClause = S.getSingleClause<OMPNumThreadsClause>()) {
1199*67e74705SXin Li CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF);
1200*67e74705SXin Li auto NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads(),
1201*67e74705SXin Li /*IgnoreResultAssign*/ true);
1202*67e74705SXin Li CGF.CGM.getOpenMPRuntime().emitNumThreadsClause(
1203*67e74705SXin Li CGF, NumThreads, NumThreadsClause->getLocStart());
1204*67e74705SXin Li }
1205*67e74705SXin Li if (const auto *ProcBindClause = S.getSingleClause<OMPProcBindClause>()) {
1206*67e74705SXin Li CodeGenFunction::RunCleanupsScope ProcBindScope(CGF);
1207*67e74705SXin Li CGF.CGM.getOpenMPRuntime().emitProcBindClause(
1208*67e74705SXin Li CGF, ProcBindClause->getProcBindKind(), ProcBindClause->getLocStart());
1209*67e74705SXin Li }
1210*67e74705SXin Li const Expr *IfCond = nullptr;
1211*67e74705SXin Li for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
1212*67e74705SXin Li if (C->getNameModifier() == OMPD_unknown ||
1213*67e74705SXin Li C->getNameModifier() == OMPD_parallel) {
1214*67e74705SXin Li IfCond = C->getCondition();
1215*67e74705SXin Li break;
1216*67e74705SXin Li }
1217*67e74705SXin Li }
1218*67e74705SXin Li
1219*67e74705SXin Li OMPLexicalScope Scope(CGF, S);
1220*67e74705SXin Li llvm::SmallVector<llvm::Value *, 16> CapturedVars;
1221*67e74705SXin Li CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
1222*67e74705SXin Li CGF.CGM.getOpenMPRuntime().emitParallelCall(CGF, S.getLocStart(), OutlinedFn,
1223*67e74705SXin Li CapturedVars, IfCond);
1224*67e74705SXin Li }
1225*67e74705SXin Li
EmitOMPParallelDirective(const OMPParallelDirective & S)1226*67e74705SXin Li void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) {
1227*67e74705SXin Li // Emit parallel region as a standalone region.
1228*67e74705SXin Li auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
1229*67e74705SXin Li OMPPrivateScope PrivateScope(CGF);
1230*67e74705SXin Li bool Copyins = CGF.EmitOMPCopyinClause(S);
1231*67e74705SXin Li (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
1232*67e74705SXin Li if (Copyins) {
1233*67e74705SXin Li // Emit implicit barrier to synchronize threads and avoid data races on
1234*67e74705SXin Li // propagation master's thread values of threadprivate variables to local
1235*67e74705SXin Li // instances of that variables of all other implicit threads.
1236*67e74705SXin Li CGF.CGM.getOpenMPRuntime().emitBarrierCall(
1237*67e74705SXin Li CGF, S.getLocStart(), OMPD_unknown, /*EmitChecks=*/false,
1238*67e74705SXin Li /*ForceSimpleCall=*/true);
1239*67e74705SXin Li }
1240*67e74705SXin Li CGF.EmitOMPPrivateClause(S, PrivateScope);
1241*67e74705SXin Li CGF.EmitOMPReductionClauseInit(S, PrivateScope);
1242*67e74705SXin Li (void)PrivateScope.Privatize();
1243*67e74705SXin Li CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
1244*67e74705SXin Li CGF.EmitOMPReductionClauseFinal(S);
1245*67e74705SXin Li };
1246*67e74705SXin Li emitCommonOMPParallelDirective(*this, S, OMPD_parallel, CodeGen);
1247*67e74705SXin Li emitPostUpdateForReductionClause(
1248*67e74705SXin Li *this, S, [](CodeGenFunction &) -> llvm::Value * { return nullptr; });
1249*67e74705SXin Li }
1250*67e74705SXin Li
EmitOMPLoopBody(const OMPLoopDirective & D,JumpDest LoopExit)1251*67e74705SXin Li void CodeGenFunction::EmitOMPLoopBody(const OMPLoopDirective &D,
1252*67e74705SXin Li JumpDest LoopExit) {
1253*67e74705SXin Li RunCleanupsScope BodyScope(*this);
1254*67e74705SXin Li // Update counters values on current iteration.
1255*67e74705SXin Li for (auto I : D.updates()) {
1256*67e74705SXin Li EmitIgnoredExpr(I);
1257*67e74705SXin Li }
1258*67e74705SXin Li // Update the linear variables.
1259*67e74705SXin Li for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) {
1260*67e74705SXin Li for (auto *U : C->updates())
1261*67e74705SXin Li EmitIgnoredExpr(U);
1262*67e74705SXin Li }
1263*67e74705SXin Li
1264*67e74705SXin Li // On a continue in the body, jump to the end.
1265*67e74705SXin Li auto Continue = getJumpDestInCurrentScope("omp.body.continue");
1266*67e74705SXin Li BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
1267*67e74705SXin Li // Emit loop body.
1268*67e74705SXin Li EmitStmt(D.getBody());
1269*67e74705SXin Li // The end (updates/cleanups).
1270*67e74705SXin Li EmitBlock(Continue.getBlock());
1271*67e74705SXin Li BreakContinueStack.pop_back();
1272*67e74705SXin Li }
1273*67e74705SXin Li
EmitOMPInnerLoop(const Stmt & S,bool RequiresCleanup,const Expr * LoopCond,const Expr * IncExpr,const llvm::function_ref<void (CodeGenFunction &)> & BodyGen,const llvm::function_ref<void (CodeGenFunction &)> & PostIncGen)1274*67e74705SXin Li void CodeGenFunction::EmitOMPInnerLoop(
1275*67e74705SXin Li const Stmt &S, bool RequiresCleanup, const Expr *LoopCond,
1276*67e74705SXin Li const Expr *IncExpr,
1277*67e74705SXin Li const llvm::function_ref<void(CodeGenFunction &)> &BodyGen,
1278*67e74705SXin Li const llvm::function_ref<void(CodeGenFunction &)> &PostIncGen) {
1279*67e74705SXin Li auto LoopExit = getJumpDestInCurrentScope("omp.inner.for.end");
1280*67e74705SXin Li
1281*67e74705SXin Li // Start the loop with a block that tests the condition.
1282*67e74705SXin Li auto CondBlock = createBasicBlock("omp.inner.for.cond");
1283*67e74705SXin Li EmitBlock(CondBlock);
1284*67e74705SXin Li LoopStack.push(CondBlock, Builder.getCurrentDebugLocation());
1285*67e74705SXin Li
1286*67e74705SXin Li // If there are any cleanups between here and the loop-exit scope,
1287*67e74705SXin Li // create a block to stage a loop exit along.
1288*67e74705SXin Li auto ExitBlock = LoopExit.getBlock();
1289*67e74705SXin Li if (RequiresCleanup)
1290*67e74705SXin Li ExitBlock = createBasicBlock("omp.inner.for.cond.cleanup");
1291*67e74705SXin Li
1292*67e74705SXin Li auto LoopBody = createBasicBlock("omp.inner.for.body");
1293*67e74705SXin Li
1294*67e74705SXin Li // Emit condition.
1295*67e74705SXin Li EmitBranchOnBoolExpr(LoopCond, LoopBody, ExitBlock, getProfileCount(&S));
1296*67e74705SXin Li if (ExitBlock != LoopExit.getBlock()) {
1297*67e74705SXin Li EmitBlock(ExitBlock);
1298*67e74705SXin Li EmitBranchThroughCleanup(LoopExit);
1299*67e74705SXin Li }
1300*67e74705SXin Li
1301*67e74705SXin Li EmitBlock(LoopBody);
1302*67e74705SXin Li incrementProfileCounter(&S);
1303*67e74705SXin Li
1304*67e74705SXin Li // Create a block for the increment.
1305*67e74705SXin Li auto Continue = getJumpDestInCurrentScope("omp.inner.for.inc");
1306*67e74705SXin Li BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
1307*67e74705SXin Li
1308*67e74705SXin Li BodyGen(*this);
1309*67e74705SXin Li
1310*67e74705SXin Li // Emit "IV = IV + 1" and a back-edge to the condition block.
1311*67e74705SXin Li EmitBlock(Continue.getBlock());
1312*67e74705SXin Li EmitIgnoredExpr(IncExpr);
1313*67e74705SXin Li PostIncGen(*this);
1314*67e74705SXin Li BreakContinueStack.pop_back();
1315*67e74705SXin Li EmitBranch(CondBlock);
1316*67e74705SXin Li LoopStack.pop();
1317*67e74705SXin Li // Emit the fall-through block.
1318*67e74705SXin Li EmitBlock(LoopExit.getBlock());
1319*67e74705SXin Li }
1320*67e74705SXin Li
EmitOMPLinearClauseInit(const OMPLoopDirective & D)1321*67e74705SXin Li void CodeGenFunction::EmitOMPLinearClauseInit(const OMPLoopDirective &D) {
1322*67e74705SXin Li if (!HaveInsertPoint())
1323*67e74705SXin Li return;
1324*67e74705SXin Li // Emit inits for the linear variables.
1325*67e74705SXin Li for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) {
1326*67e74705SXin Li for (auto *Init : C->inits()) {
1327*67e74705SXin Li auto *VD = cast<VarDecl>(cast<DeclRefExpr>(Init)->getDecl());
1328*67e74705SXin Li if (auto *Ref = dyn_cast<DeclRefExpr>(VD->getInit()->IgnoreImpCasts())) {
1329*67e74705SXin Li AutoVarEmission Emission = EmitAutoVarAlloca(*VD);
1330*67e74705SXin Li auto *OrigVD = cast<VarDecl>(Ref->getDecl());
1331*67e74705SXin Li DeclRefExpr DRE(const_cast<VarDecl *>(OrigVD),
1332*67e74705SXin Li CapturedStmtInfo->lookup(OrigVD) != nullptr,
1333*67e74705SXin Li VD->getInit()->getType(), VK_LValue,
1334*67e74705SXin Li VD->getInit()->getExprLoc());
1335*67e74705SXin Li EmitExprAsInit(&DRE, VD, MakeAddrLValue(Emission.getAllocatedAddress(),
1336*67e74705SXin Li VD->getType()),
1337*67e74705SXin Li /*capturedByInit=*/false);
1338*67e74705SXin Li EmitAutoVarCleanups(Emission);
1339*67e74705SXin Li } else
1340*67e74705SXin Li EmitVarDecl(*VD);
1341*67e74705SXin Li }
1342*67e74705SXin Li // Emit the linear steps for the linear clauses.
1343*67e74705SXin Li // If a step is not constant, it is pre-calculated before the loop.
1344*67e74705SXin Li if (auto CS = cast_or_null<BinaryOperator>(C->getCalcStep()))
1345*67e74705SXin Li if (auto SaveRef = cast<DeclRefExpr>(CS->getLHS())) {
1346*67e74705SXin Li EmitVarDecl(*cast<VarDecl>(SaveRef->getDecl()));
1347*67e74705SXin Li // Emit calculation of the linear step.
1348*67e74705SXin Li EmitIgnoredExpr(CS);
1349*67e74705SXin Li }
1350*67e74705SXin Li }
1351*67e74705SXin Li }
1352*67e74705SXin Li
EmitOMPLinearClauseFinal(const OMPLoopDirective & D,const llvm::function_ref<llvm::Value * (CodeGenFunction &)> & CondGen)1353*67e74705SXin Li void CodeGenFunction::EmitOMPLinearClauseFinal(
1354*67e74705SXin Li const OMPLoopDirective &D,
1355*67e74705SXin Li const llvm::function_ref<llvm::Value *(CodeGenFunction &)> &CondGen) {
1356*67e74705SXin Li if (!HaveInsertPoint())
1357*67e74705SXin Li return;
1358*67e74705SXin Li llvm::BasicBlock *DoneBB = nullptr;
1359*67e74705SXin Li // Emit the final values of the linear variables.
1360*67e74705SXin Li for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) {
1361*67e74705SXin Li auto IC = C->varlist_begin();
1362*67e74705SXin Li for (auto *F : C->finals()) {
1363*67e74705SXin Li if (!DoneBB) {
1364*67e74705SXin Li if (auto *Cond = CondGen(*this)) {
1365*67e74705SXin Li // If the first post-update expression is found, emit conditional
1366*67e74705SXin Li // block if it was requested.
1367*67e74705SXin Li auto *ThenBB = createBasicBlock(".omp.linear.pu");
1368*67e74705SXin Li DoneBB = createBasicBlock(".omp.linear.pu.done");
1369*67e74705SXin Li Builder.CreateCondBr(Cond, ThenBB, DoneBB);
1370*67e74705SXin Li EmitBlock(ThenBB);
1371*67e74705SXin Li }
1372*67e74705SXin Li }
1373*67e74705SXin Li auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IC)->getDecl());
1374*67e74705SXin Li DeclRefExpr DRE(const_cast<VarDecl *>(OrigVD),
1375*67e74705SXin Li CapturedStmtInfo->lookup(OrigVD) != nullptr,
1376*67e74705SXin Li (*IC)->getType(), VK_LValue, (*IC)->getExprLoc());
1377*67e74705SXin Li Address OrigAddr = EmitLValue(&DRE).getAddress();
1378*67e74705SXin Li CodeGenFunction::OMPPrivateScope VarScope(*this);
1379*67e74705SXin Li VarScope.addPrivate(OrigVD, [OrigAddr]() -> Address { return OrigAddr; });
1380*67e74705SXin Li (void)VarScope.Privatize();
1381*67e74705SXin Li EmitIgnoredExpr(F);
1382*67e74705SXin Li ++IC;
1383*67e74705SXin Li }
1384*67e74705SXin Li if (auto *PostUpdate = C->getPostUpdateExpr())
1385*67e74705SXin Li EmitIgnoredExpr(PostUpdate);
1386*67e74705SXin Li }
1387*67e74705SXin Li if (DoneBB)
1388*67e74705SXin Li EmitBlock(DoneBB, /*IsFinished=*/true);
1389*67e74705SXin Li }
1390*67e74705SXin Li
emitAlignedClause(CodeGenFunction & CGF,const OMPExecutableDirective & D)1391*67e74705SXin Li static void emitAlignedClause(CodeGenFunction &CGF,
1392*67e74705SXin Li const OMPExecutableDirective &D) {
1393*67e74705SXin Li if (!CGF.HaveInsertPoint())
1394*67e74705SXin Li return;
1395*67e74705SXin Li for (const auto *Clause : D.getClausesOfKind<OMPAlignedClause>()) {
1396*67e74705SXin Li unsigned ClauseAlignment = 0;
1397*67e74705SXin Li if (auto AlignmentExpr = Clause->getAlignment()) {
1398*67e74705SXin Li auto AlignmentCI =
1399*67e74705SXin Li cast<llvm::ConstantInt>(CGF.EmitScalarExpr(AlignmentExpr));
1400*67e74705SXin Li ClauseAlignment = static_cast<unsigned>(AlignmentCI->getZExtValue());
1401*67e74705SXin Li }
1402*67e74705SXin Li for (auto E : Clause->varlists()) {
1403*67e74705SXin Li unsigned Alignment = ClauseAlignment;
1404*67e74705SXin Li if (Alignment == 0) {
1405*67e74705SXin Li // OpenMP [2.8.1, Description]
1406*67e74705SXin Li // If no optional parameter is specified, implementation-defined default
1407*67e74705SXin Li // alignments for SIMD instructions on the target platforms are assumed.
1408*67e74705SXin Li Alignment =
1409*67e74705SXin Li CGF.getContext()
1410*67e74705SXin Li .toCharUnitsFromBits(CGF.getContext().getOpenMPDefaultSimdAlign(
1411*67e74705SXin Li E->getType()->getPointeeType()))
1412*67e74705SXin Li .getQuantity();
1413*67e74705SXin Li }
1414*67e74705SXin Li assert((Alignment == 0 || llvm::isPowerOf2_32(Alignment)) &&
1415*67e74705SXin Li "alignment is not power of 2");
1416*67e74705SXin Li if (Alignment != 0) {
1417*67e74705SXin Li llvm::Value *PtrValue = CGF.EmitScalarExpr(E);
1418*67e74705SXin Li CGF.EmitAlignmentAssumption(PtrValue, Alignment);
1419*67e74705SXin Li }
1420*67e74705SXin Li }
1421*67e74705SXin Li }
1422*67e74705SXin Li }
1423*67e74705SXin Li
EmitOMPPrivateLoopCounters(const OMPLoopDirective & S,CodeGenFunction::OMPPrivateScope & LoopScope)1424*67e74705SXin Li void CodeGenFunction::EmitOMPPrivateLoopCounters(
1425*67e74705SXin Li const OMPLoopDirective &S, CodeGenFunction::OMPPrivateScope &LoopScope) {
1426*67e74705SXin Li if (!HaveInsertPoint())
1427*67e74705SXin Li return;
1428*67e74705SXin Li auto I = S.private_counters().begin();
1429*67e74705SXin Li for (auto *E : S.counters()) {
1430*67e74705SXin Li auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
1431*67e74705SXin Li auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl());
1432*67e74705SXin Li (void)LoopScope.addPrivate(VD, [&]() -> Address {
1433*67e74705SXin Li // Emit var without initialization.
1434*67e74705SXin Li if (!LocalDeclMap.count(PrivateVD)) {
1435*67e74705SXin Li auto VarEmission = EmitAutoVarAlloca(*PrivateVD);
1436*67e74705SXin Li EmitAutoVarCleanups(VarEmission);
1437*67e74705SXin Li }
1438*67e74705SXin Li DeclRefExpr DRE(const_cast<VarDecl *>(PrivateVD),
1439*67e74705SXin Li /*RefersToEnclosingVariableOrCapture=*/false,
1440*67e74705SXin Li (*I)->getType(), VK_LValue, (*I)->getExprLoc());
1441*67e74705SXin Li return EmitLValue(&DRE).getAddress();
1442*67e74705SXin Li });
1443*67e74705SXin Li if (LocalDeclMap.count(VD) || CapturedStmtInfo->lookup(VD) ||
1444*67e74705SXin Li VD->hasGlobalStorage()) {
1445*67e74705SXin Li (void)LoopScope.addPrivate(PrivateVD, [&]() -> Address {
1446*67e74705SXin Li DeclRefExpr DRE(const_cast<VarDecl *>(VD),
1447*67e74705SXin Li LocalDeclMap.count(VD) || CapturedStmtInfo->lookup(VD),
1448*67e74705SXin Li E->getType(), VK_LValue, E->getExprLoc());
1449*67e74705SXin Li return EmitLValue(&DRE).getAddress();
1450*67e74705SXin Li });
1451*67e74705SXin Li }
1452*67e74705SXin Li ++I;
1453*67e74705SXin Li }
1454*67e74705SXin Li }
1455*67e74705SXin Li
emitPreCond(CodeGenFunction & CGF,const OMPLoopDirective & S,const Expr * Cond,llvm::BasicBlock * TrueBlock,llvm::BasicBlock * FalseBlock,uint64_t TrueCount)1456*67e74705SXin Li static void emitPreCond(CodeGenFunction &CGF, const OMPLoopDirective &S,
1457*67e74705SXin Li const Expr *Cond, llvm::BasicBlock *TrueBlock,
1458*67e74705SXin Li llvm::BasicBlock *FalseBlock, uint64_t TrueCount) {
1459*67e74705SXin Li if (!CGF.HaveInsertPoint())
1460*67e74705SXin Li return;
1461*67e74705SXin Li {
1462*67e74705SXin Li CodeGenFunction::OMPPrivateScope PreCondScope(CGF);
1463*67e74705SXin Li CGF.EmitOMPPrivateLoopCounters(S, PreCondScope);
1464*67e74705SXin Li (void)PreCondScope.Privatize();
1465*67e74705SXin Li // Get initial values of real counters.
1466*67e74705SXin Li for (auto I : S.inits()) {
1467*67e74705SXin Li CGF.EmitIgnoredExpr(I);
1468*67e74705SXin Li }
1469*67e74705SXin Li }
1470*67e74705SXin Li // Check that loop is executed at least one time.
1471*67e74705SXin Li CGF.EmitBranchOnBoolExpr(Cond, TrueBlock, FalseBlock, TrueCount);
1472*67e74705SXin Li }
1473*67e74705SXin Li
EmitOMPLinearClause(const OMPLoopDirective & D,CodeGenFunction::OMPPrivateScope & PrivateScope)1474*67e74705SXin Li void CodeGenFunction::EmitOMPLinearClause(
1475*67e74705SXin Li const OMPLoopDirective &D, CodeGenFunction::OMPPrivateScope &PrivateScope) {
1476*67e74705SXin Li if (!HaveInsertPoint())
1477*67e74705SXin Li return;
1478*67e74705SXin Li llvm::DenseSet<const VarDecl *> SIMDLCVs;
1479*67e74705SXin Li if (isOpenMPSimdDirective(D.getDirectiveKind())) {
1480*67e74705SXin Li auto *LoopDirective = cast<OMPLoopDirective>(&D);
1481*67e74705SXin Li for (auto *C : LoopDirective->counters()) {
1482*67e74705SXin Li SIMDLCVs.insert(
1483*67e74705SXin Li cast<VarDecl>(cast<DeclRefExpr>(C)->getDecl())->getCanonicalDecl());
1484*67e74705SXin Li }
1485*67e74705SXin Li }
1486*67e74705SXin Li for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) {
1487*67e74705SXin Li auto CurPrivate = C->privates().begin();
1488*67e74705SXin Li for (auto *E : C->varlists()) {
1489*67e74705SXin Li auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
1490*67e74705SXin Li auto *PrivateVD =
1491*67e74705SXin Li cast<VarDecl>(cast<DeclRefExpr>(*CurPrivate)->getDecl());
1492*67e74705SXin Li if (!SIMDLCVs.count(VD->getCanonicalDecl())) {
1493*67e74705SXin Li bool IsRegistered = PrivateScope.addPrivate(VD, [&]() -> Address {
1494*67e74705SXin Li // Emit private VarDecl with copy init.
1495*67e74705SXin Li EmitVarDecl(*PrivateVD);
1496*67e74705SXin Li return GetAddrOfLocalVar(PrivateVD);
1497*67e74705SXin Li });
1498*67e74705SXin Li assert(IsRegistered && "linear var already registered as private");
1499*67e74705SXin Li // Silence the warning about unused variable.
1500*67e74705SXin Li (void)IsRegistered;
1501*67e74705SXin Li } else
1502*67e74705SXin Li EmitVarDecl(*PrivateVD);
1503*67e74705SXin Li ++CurPrivate;
1504*67e74705SXin Li }
1505*67e74705SXin Li }
1506*67e74705SXin Li }
1507*67e74705SXin Li
emitSimdlenSafelenClause(CodeGenFunction & CGF,const OMPExecutableDirective & D,bool IsMonotonic)1508*67e74705SXin Li static void emitSimdlenSafelenClause(CodeGenFunction &CGF,
1509*67e74705SXin Li const OMPExecutableDirective &D,
1510*67e74705SXin Li bool IsMonotonic) {
1511*67e74705SXin Li if (!CGF.HaveInsertPoint())
1512*67e74705SXin Li return;
1513*67e74705SXin Li if (const auto *C = D.getSingleClause<OMPSimdlenClause>()) {
1514*67e74705SXin Li RValue Len = CGF.EmitAnyExpr(C->getSimdlen(), AggValueSlot::ignored(),
1515*67e74705SXin Li /*ignoreResult=*/true);
1516*67e74705SXin Li llvm::ConstantInt *Val = cast<llvm::ConstantInt>(Len.getScalarVal());
1517*67e74705SXin Li CGF.LoopStack.setVectorizeWidth(Val->getZExtValue());
1518*67e74705SXin Li // In presence of finite 'safelen', it may be unsafe to mark all
1519*67e74705SXin Li // the memory instructions parallel, because loop-carried
1520*67e74705SXin Li // dependences of 'safelen' iterations are possible.
1521*67e74705SXin Li if (!IsMonotonic)
1522*67e74705SXin Li CGF.LoopStack.setParallel(!D.getSingleClause<OMPSafelenClause>());
1523*67e74705SXin Li } else if (const auto *C = D.getSingleClause<OMPSafelenClause>()) {
1524*67e74705SXin Li RValue Len = CGF.EmitAnyExpr(C->getSafelen(), AggValueSlot::ignored(),
1525*67e74705SXin Li /*ignoreResult=*/true);
1526*67e74705SXin Li llvm::ConstantInt *Val = cast<llvm::ConstantInt>(Len.getScalarVal());
1527*67e74705SXin Li CGF.LoopStack.setVectorizeWidth(Val->getZExtValue());
1528*67e74705SXin Li // In presence of finite 'safelen', it may be unsafe to mark all
1529*67e74705SXin Li // the memory instructions parallel, because loop-carried
1530*67e74705SXin Li // dependences of 'safelen' iterations are possible.
1531*67e74705SXin Li CGF.LoopStack.setParallel(false);
1532*67e74705SXin Li }
1533*67e74705SXin Li }
1534*67e74705SXin Li
EmitOMPSimdInit(const OMPLoopDirective & D,bool IsMonotonic)1535*67e74705SXin Li void CodeGenFunction::EmitOMPSimdInit(const OMPLoopDirective &D,
1536*67e74705SXin Li bool IsMonotonic) {
1537*67e74705SXin Li // Walk clauses and process safelen/lastprivate.
1538*67e74705SXin Li LoopStack.setParallel(!IsMonotonic);
1539*67e74705SXin Li LoopStack.setVectorizeEnable(true);
1540*67e74705SXin Li emitSimdlenSafelenClause(*this, D, IsMonotonic);
1541*67e74705SXin Li }
1542*67e74705SXin Li
EmitOMPSimdFinal(const OMPLoopDirective & D,const llvm::function_ref<llvm::Value * (CodeGenFunction &)> & CondGen)1543*67e74705SXin Li void CodeGenFunction::EmitOMPSimdFinal(
1544*67e74705SXin Li const OMPLoopDirective &D,
1545*67e74705SXin Li const llvm::function_ref<llvm::Value *(CodeGenFunction &)> &CondGen) {
1546*67e74705SXin Li if (!HaveInsertPoint())
1547*67e74705SXin Li return;
1548*67e74705SXin Li llvm::BasicBlock *DoneBB = nullptr;
1549*67e74705SXin Li auto IC = D.counters().begin();
1550*67e74705SXin Li auto IPC = D.private_counters().begin();
1551*67e74705SXin Li for (auto F : D.finals()) {
1552*67e74705SXin Li auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>((*IC))->getDecl());
1553*67e74705SXin Li auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>((*IPC))->getDecl());
1554*67e74705SXin Li auto *CED = dyn_cast<OMPCapturedExprDecl>(OrigVD);
1555*67e74705SXin Li if (LocalDeclMap.count(OrigVD) || CapturedStmtInfo->lookup(OrigVD) ||
1556*67e74705SXin Li OrigVD->hasGlobalStorage() || CED) {
1557*67e74705SXin Li if (!DoneBB) {
1558*67e74705SXin Li if (auto *Cond = CondGen(*this)) {
1559*67e74705SXin Li // If the first post-update expression is found, emit conditional
1560*67e74705SXin Li // block if it was requested.
1561*67e74705SXin Li auto *ThenBB = createBasicBlock(".omp.final.then");
1562*67e74705SXin Li DoneBB = createBasicBlock(".omp.final.done");
1563*67e74705SXin Li Builder.CreateCondBr(Cond, ThenBB, DoneBB);
1564*67e74705SXin Li EmitBlock(ThenBB);
1565*67e74705SXin Li }
1566*67e74705SXin Li }
1567*67e74705SXin Li Address OrigAddr = Address::invalid();
1568*67e74705SXin Li if (CED)
1569*67e74705SXin Li OrigAddr = EmitLValue(CED->getInit()->IgnoreImpCasts()).getAddress();
1570*67e74705SXin Li else {
1571*67e74705SXin Li DeclRefExpr DRE(const_cast<VarDecl *>(PrivateVD),
1572*67e74705SXin Li /*RefersToEnclosingVariableOrCapture=*/false,
1573*67e74705SXin Li (*IPC)->getType(), VK_LValue, (*IPC)->getExprLoc());
1574*67e74705SXin Li OrigAddr = EmitLValue(&DRE).getAddress();
1575*67e74705SXin Li }
1576*67e74705SXin Li OMPPrivateScope VarScope(*this);
1577*67e74705SXin Li VarScope.addPrivate(OrigVD,
1578*67e74705SXin Li [OrigAddr]() -> Address { return OrigAddr; });
1579*67e74705SXin Li (void)VarScope.Privatize();
1580*67e74705SXin Li EmitIgnoredExpr(F);
1581*67e74705SXin Li }
1582*67e74705SXin Li ++IC;
1583*67e74705SXin Li ++IPC;
1584*67e74705SXin Li }
1585*67e74705SXin Li if (DoneBB)
1586*67e74705SXin Li EmitBlock(DoneBB, /*IsFinished=*/true);
1587*67e74705SXin Li }
1588*67e74705SXin Li
EmitOMPSimdDirective(const OMPSimdDirective & S)1589*67e74705SXin Li void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) {
1590*67e74705SXin Li auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
1591*67e74705SXin Li OMPLoopScope PreInitScope(CGF, S);
1592*67e74705SXin Li // if (PreCond) {
1593*67e74705SXin Li // for (IV in 0..LastIteration) BODY;
1594*67e74705SXin Li // <Final counter/linear vars updates>;
1595*67e74705SXin Li // }
1596*67e74705SXin Li //
1597*67e74705SXin Li
1598*67e74705SXin Li // Emit: if (PreCond) - begin.
1599*67e74705SXin Li // If the condition constant folds and can be elided, avoid emitting the
1600*67e74705SXin Li // whole loop.
1601*67e74705SXin Li bool CondConstant;
1602*67e74705SXin Li llvm::BasicBlock *ContBlock = nullptr;
1603*67e74705SXin Li if (CGF.ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
1604*67e74705SXin Li if (!CondConstant)
1605*67e74705SXin Li return;
1606*67e74705SXin Li } else {
1607*67e74705SXin Li auto *ThenBlock = CGF.createBasicBlock("simd.if.then");
1608*67e74705SXin Li ContBlock = CGF.createBasicBlock("simd.if.end");
1609*67e74705SXin Li emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
1610*67e74705SXin Li CGF.getProfileCount(&S));
1611*67e74705SXin Li CGF.EmitBlock(ThenBlock);
1612*67e74705SXin Li CGF.incrementProfileCounter(&S);
1613*67e74705SXin Li }
1614*67e74705SXin Li
1615*67e74705SXin Li // Emit the loop iteration variable.
1616*67e74705SXin Li const Expr *IVExpr = S.getIterationVariable();
1617*67e74705SXin Li const VarDecl *IVDecl = cast<VarDecl>(cast<DeclRefExpr>(IVExpr)->getDecl());
1618*67e74705SXin Li CGF.EmitVarDecl(*IVDecl);
1619*67e74705SXin Li CGF.EmitIgnoredExpr(S.getInit());
1620*67e74705SXin Li
1621*67e74705SXin Li // Emit the iterations count variable.
1622*67e74705SXin Li // If it is not a variable, Sema decided to calculate iterations count on
1623*67e74705SXin Li // each iteration (e.g., it is foldable into a constant).
1624*67e74705SXin Li if (auto LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
1625*67e74705SXin Li CGF.EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
1626*67e74705SXin Li // Emit calculation of the iterations count.
1627*67e74705SXin Li CGF.EmitIgnoredExpr(S.getCalcLastIteration());
1628*67e74705SXin Li }
1629*67e74705SXin Li
1630*67e74705SXin Li CGF.EmitOMPSimdInit(S);
1631*67e74705SXin Li
1632*67e74705SXin Li emitAlignedClause(CGF, S);
1633*67e74705SXin Li CGF.EmitOMPLinearClauseInit(S);
1634*67e74705SXin Li {
1635*67e74705SXin Li OMPPrivateScope LoopScope(CGF);
1636*67e74705SXin Li CGF.EmitOMPPrivateLoopCounters(S, LoopScope);
1637*67e74705SXin Li CGF.EmitOMPLinearClause(S, LoopScope);
1638*67e74705SXin Li CGF.EmitOMPPrivateClause(S, LoopScope);
1639*67e74705SXin Li CGF.EmitOMPReductionClauseInit(S, LoopScope);
1640*67e74705SXin Li bool HasLastprivateClause =
1641*67e74705SXin Li CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
1642*67e74705SXin Li (void)LoopScope.Privatize();
1643*67e74705SXin Li CGF.EmitOMPInnerLoop(S, LoopScope.requiresCleanups(), S.getCond(),
1644*67e74705SXin Li S.getInc(),
1645*67e74705SXin Li [&S](CodeGenFunction &CGF) {
1646*67e74705SXin Li CGF.EmitOMPLoopBody(S, JumpDest());
1647*67e74705SXin Li CGF.EmitStopPoint(&S);
1648*67e74705SXin Li },
1649*67e74705SXin Li [](CodeGenFunction &) {});
1650*67e74705SXin Li CGF.EmitOMPSimdFinal(
1651*67e74705SXin Li S, [](CodeGenFunction &) -> llvm::Value * { return nullptr; });
1652*67e74705SXin Li // Emit final copy of the lastprivate variables at the end of loops.
1653*67e74705SXin Li if (HasLastprivateClause)
1654*67e74705SXin Li CGF.EmitOMPLastprivateClauseFinal(S, /*NoFinals=*/true);
1655*67e74705SXin Li CGF.EmitOMPReductionClauseFinal(S);
1656*67e74705SXin Li emitPostUpdateForReductionClause(
1657*67e74705SXin Li CGF, S, [](CodeGenFunction &) -> llvm::Value * { return nullptr; });
1658*67e74705SXin Li }
1659*67e74705SXin Li CGF.EmitOMPLinearClauseFinal(
1660*67e74705SXin Li S, [](CodeGenFunction &) -> llvm::Value * { return nullptr; });
1661*67e74705SXin Li // Emit: if (PreCond) - end.
1662*67e74705SXin Li if (ContBlock) {
1663*67e74705SXin Li CGF.EmitBranch(ContBlock);
1664*67e74705SXin Li CGF.EmitBlock(ContBlock, true);
1665*67e74705SXin Li }
1666*67e74705SXin Li };
1667*67e74705SXin Li OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
1668*67e74705SXin Li CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen);
1669*67e74705SXin Li }
1670*67e74705SXin Li
EmitOMPOuterLoop(bool DynamicOrOrdered,bool IsMonotonic,const OMPLoopDirective & S,OMPPrivateScope & LoopScope,bool Ordered,Address LB,Address UB,Address ST,Address IL,llvm::Value * Chunk)1671*67e74705SXin Li void CodeGenFunction::EmitOMPOuterLoop(bool DynamicOrOrdered, bool IsMonotonic,
1672*67e74705SXin Li const OMPLoopDirective &S, OMPPrivateScope &LoopScope, bool Ordered,
1673*67e74705SXin Li Address LB, Address UB, Address ST, Address IL, llvm::Value *Chunk) {
1674*67e74705SXin Li auto &RT = CGM.getOpenMPRuntime();
1675*67e74705SXin Li
1676*67e74705SXin Li const Expr *IVExpr = S.getIterationVariable();
1677*67e74705SXin Li const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
1678*67e74705SXin Li const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
1679*67e74705SXin Li
1680*67e74705SXin Li auto LoopExit = getJumpDestInCurrentScope("omp.dispatch.end");
1681*67e74705SXin Li
1682*67e74705SXin Li // Start the loop with a block that tests the condition.
1683*67e74705SXin Li auto CondBlock = createBasicBlock("omp.dispatch.cond");
1684*67e74705SXin Li EmitBlock(CondBlock);
1685*67e74705SXin Li LoopStack.push(CondBlock, Builder.getCurrentDebugLocation());
1686*67e74705SXin Li
1687*67e74705SXin Li llvm::Value *BoolCondVal = nullptr;
1688*67e74705SXin Li if (!DynamicOrOrdered) {
1689*67e74705SXin Li // UB = min(UB, GlobalUB)
1690*67e74705SXin Li EmitIgnoredExpr(S.getEnsureUpperBound());
1691*67e74705SXin Li // IV = LB
1692*67e74705SXin Li EmitIgnoredExpr(S.getInit());
1693*67e74705SXin Li // IV < UB
1694*67e74705SXin Li BoolCondVal = EvaluateExprAsBool(S.getCond());
1695*67e74705SXin Li } else {
1696*67e74705SXin Li BoolCondVal = RT.emitForNext(*this, S.getLocStart(), IVSize, IVSigned, IL,
1697*67e74705SXin Li LB, UB, ST);
1698*67e74705SXin Li }
1699*67e74705SXin Li
1700*67e74705SXin Li // If there are any cleanups between here and the loop-exit scope,
1701*67e74705SXin Li // create a block to stage a loop exit along.
1702*67e74705SXin Li auto ExitBlock = LoopExit.getBlock();
1703*67e74705SXin Li if (LoopScope.requiresCleanups())
1704*67e74705SXin Li ExitBlock = createBasicBlock("omp.dispatch.cleanup");
1705*67e74705SXin Li
1706*67e74705SXin Li auto LoopBody = createBasicBlock("omp.dispatch.body");
1707*67e74705SXin Li Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock);
1708*67e74705SXin Li if (ExitBlock != LoopExit.getBlock()) {
1709*67e74705SXin Li EmitBlock(ExitBlock);
1710*67e74705SXin Li EmitBranchThroughCleanup(LoopExit);
1711*67e74705SXin Li }
1712*67e74705SXin Li EmitBlock(LoopBody);
1713*67e74705SXin Li
1714*67e74705SXin Li // Emit "IV = LB" (in case of static schedule, we have already calculated new
1715*67e74705SXin Li // LB for loop condition and emitted it above).
1716*67e74705SXin Li if (DynamicOrOrdered)
1717*67e74705SXin Li EmitIgnoredExpr(S.getInit());
1718*67e74705SXin Li
1719*67e74705SXin Li // Create a block for the increment.
1720*67e74705SXin Li auto Continue = getJumpDestInCurrentScope("omp.dispatch.inc");
1721*67e74705SXin Li BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
1722*67e74705SXin Li
1723*67e74705SXin Li // Generate !llvm.loop.parallel metadata for loads and stores for loops
1724*67e74705SXin Li // with dynamic/guided scheduling and without ordered clause.
1725*67e74705SXin Li if (!isOpenMPSimdDirective(S.getDirectiveKind()))
1726*67e74705SXin Li LoopStack.setParallel(!IsMonotonic);
1727*67e74705SXin Li else
1728*67e74705SXin Li EmitOMPSimdInit(S, IsMonotonic);
1729*67e74705SXin Li
1730*67e74705SXin Li SourceLocation Loc = S.getLocStart();
1731*67e74705SXin Li EmitOMPInnerLoop(S, LoopScope.requiresCleanups(), S.getCond(), S.getInc(),
1732*67e74705SXin Li [&S, LoopExit](CodeGenFunction &CGF) {
1733*67e74705SXin Li CGF.EmitOMPLoopBody(S, LoopExit);
1734*67e74705SXin Li CGF.EmitStopPoint(&S);
1735*67e74705SXin Li },
1736*67e74705SXin Li [Ordered, IVSize, IVSigned, Loc](CodeGenFunction &CGF) {
1737*67e74705SXin Li if (Ordered) {
1738*67e74705SXin Li CGF.CGM.getOpenMPRuntime().emitForOrderedIterationEnd(
1739*67e74705SXin Li CGF, Loc, IVSize, IVSigned);
1740*67e74705SXin Li }
1741*67e74705SXin Li });
1742*67e74705SXin Li
1743*67e74705SXin Li EmitBlock(Continue.getBlock());
1744*67e74705SXin Li BreakContinueStack.pop_back();
1745*67e74705SXin Li if (!DynamicOrOrdered) {
1746*67e74705SXin Li // Emit "LB = LB + Stride", "UB = UB + Stride".
1747*67e74705SXin Li EmitIgnoredExpr(S.getNextLowerBound());
1748*67e74705SXin Li EmitIgnoredExpr(S.getNextUpperBound());
1749*67e74705SXin Li }
1750*67e74705SXin Li
1751*67e74705SXin Li EmitBranch(CondBlock);
1752*67e74705SXin Li LoopStack.pop();
1753*67e74705SXin Li // Emit the fall-through block.
1754*67e74705SXin Li EmitBlock(LoopExit.getBlock());
1755*67e74705SXin Li
1756*67e74705SXin Li // Tell the runtime we are done.
1757*67e74705SXin Li if (!DynamicOrOrdered)
1758*67e74705SXin Li RT.emitForStaticFinish(*this, S.getLocEnd());
1759*67e74705SXin Li
1760*67e74705SXin Li }
1761*67e74705SXin Li
EmitOMPForOuterLoop(const OpenMPScheduleTy & ScheduleKind,bool IsMonotonic,const OMPLoopDirective & S,OMPPrivateScope & LoopScope,bool Ordered,Address LB,Address UB,Address ST,Address IL,llvm::Value * Chunk)1762*67e74705SXin Li void CodeGenFunction::EmitOMPForOuterLoop(
1763*67e74705SXin Li const OpenMPScheduleTy &ScheduleKind, bool IsMonotonic,
1764*67e74705SXin Li const OMPLoopDirective &S, OMPPrivateScope &LoopScope, bool Ordered,
1765*67e74705SXin Li Address LB, Address UB, Address ST, Address IL, llvm::Value *Chunk) {
1766*67e74705SXin Li auto &RT = CGM.getOpenMPRuntime();
1767*67e74705SXin Li
1768*67e74705SXin Li // Dynamic scheduling of the outer loop (dynamic, guided, auto, runtime).
1769*67e74705SXin Li const bool DynamicOrOrdered =
1770*67e74705SXin Li Ordered || RT.isDynamic(ScheduleKind.Schedule);
1771*67e74705SXin Li
1772*67e74705SXin Li assert((Ordered ||
1773*67e74705SXin Li !RT.isStaticNonchunked(ScheduleKind.Schedule,
1774*67e74705SXin Li /*Chunked=*/Chunk != nullptr)) &&
1775*67e74705SXin Li "static non-chunked schedule does not need outer loop");
1776*67e74705SXin Li
1777*67e74705SXin Li // Emit outer loop.
1778*67e74705SXin Li //
1779*67e74705SXin Li // OpenMP [2.7.1, Loop Construct, Description, table 2-1]
1780*67e74705SXin Li // When schedule(dynamic,chunk_size) is specified, the iterations are
1781*67e74705SXin Li // distributed to threads in the team in chunks as the threads request them.
1782*67e74705SXin Li // Each thread executes a chunk of iterations, then requests another chunk,
1783*67e74705SXin Li // until no chunks remain to be distributed. Each chunk contains chunk_size
1784*67e74705SXin Li // iterations, except for the last chunk to be distributed, which may have
1785*67e74705SXin Li // fewer iterations. When no chunk_size is specified, it defaults to 1.
1786*67e74705SXin Li //
1787*67e74705SXin Li // When schedule(guided,chunk_size) is specified, the iterations are assigned
1788*67e74705SXin Li // to threads in the team in chunks as the executing threads request them.
1789*67e74705SXin Li // Each thread executes a chunk of iterations, then requests another chunk,
1790*67e74705SXin Li // until no chunks remain to be assigned. For a chunk_size of 1, the size of
1791*67e74705SXin Li // each chunk is proportional to the number of unassigned iterations divided
1792*67e74705SXin Li // by the number of threads in the team, decreasing to 1. For a chunk_size
1793*67e74705SXin Li // with value k (greater than 1), the size of each chunk is determined in the
1794*67e74705SXin Li // same way, with the restriction that the chunks do not contain fewer than k
1795*67e74705SXin Li // iterations (except for the last chunk to be assigned, which may have fewer
1796*67e74705SXin Li // than k iterations).
1797*67e74705SXin Li //
1798*67e74705SXin Li // When schedule(auto) is specified, the decision regarding scheduling is
1799*67e74705SXin Li // delegated to the compiler and/or runtime system. The programmer gives the
1800*67e74705SXin Li // implementation the freedom to choose any possible mapping of iterations to
1801*67e74705SXin Li // threads in the team.
1802*67e74705SXin Li //
1803*67e74705SXin Li // When schedule(runtime) is specified, the decision regarding scheduling is
1804*67e74705SXin Li // deferred until run time, and the schedule and chunk size are taken from the
1805*67e74705SXin Li // run-sched-var ICV. If the ICV is set to auto, the schedule is
1806*67e74705SXin Li // implementation defined
1807*67e74705SXin Li //
1808*67e74705SXin Li // while(__kmpc_dispatch_next(&LB, &UB)) {
1809*67e74705SXin Li // idx = LB;
1810*67e74705SXin Li // while (idx <= UB) { BODY; ++idx;
1811*67e74705SXin Li // __kmpc_dispatch_fini_(4|8)[u](); // For ordered loops only.
1812*67e74705SXin Li // } // inner loop
1813*67e74705SXin Li // }
1814*67e74705SXin Li //
1815*67e74705SXin Li // OpenMP [2.7.1, Loop Construct, Description, table 2-1]
1816*67e74705SXin Li // When schedule(static, chunk_size) is specified, iterations are divided into
1817*67e74705SXin Li // chunks of size chunk_size, and the chunks are assigned to the threads in
1818*67e74705SXin Li // the team in a round-robin fashion in the order of the thread number.
1819*67e74705SXin Li //
1820*67e74705SXin Li // while(UB = min(UB, GlobalUB), idx = LB, idx < UB) {
1821*67e74705SXin Li // while (idx <= UB) { BODY; ++idx; } // inner loop
1822*67e74705SXin Li // LB = LB + ST;
1823*67e74705SXin Li // UB = UB + ST;
1824*67e74705SXin Li // }
1825*67e74705SXin Li //
1826*67e74705SXin Li
1827*67e74705SXin Li const Expr *IVExpr = S.getIterationVariable();
1828*67e74705SXin Li const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
1829*67e74705SXin Li const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
1830*67e74705SXin Li
1831*67e74705SXin Li if (DynamicOrOrdered) {
1832*67e74705SXin Li llvm::Value *UBVal = EmitScalarExpr(S.getLastIteration());
1833*67e74705SXin Li RT.emitForDispatchInit(*this, S.getLocStart(), ScheduleKind, IVSize,
1834*67e74705SXin Li IVSigned, Ordered, UBVal, Chunk);
1835*67e74705SXin Li } else {
1836*67e74705SXin Li RT.emitForStaticInit(*this, S.getLocStart(), ScheduleKind, IVSize, IVSigned,
1837*67e74705SXin Li Ordered, IL, LB, UB, ST, Chunk);
1838*67e74705SXin Li }
1839*67e74705SXin Li
1840*67e74705SXin Li EmitOMPOuterLoop(DynamicOrOrdered, IsMonotonic, S, LoopScope, Ordered, LB, UB,
1841*67e74705SXin Li ST, IL, Chunk);
1842*67e74705SXin Li }
1843*67e74705SXin Li
EmitOMPDistributeOuterLoop(OpenMPDistScheduleClauseKind ScheduleKind,const OMPDistributeDirective & S,OMPPrivateScope & LoopScope,Address LB,Address UB,Address ST,Address IL,llvm::Value * Chunk)1844*67e74705SXin Li void CodeGenFunction::EmitOMPDistributeOuterLoop(
1845*67e74705SXin Li OpenMPDistScheduleClauseKind ScheduleKind,
1846*67e74705SXin Li const OMPDistributeDirective &S, OMPPrivateScope &LoopScope,
1847*67e74705SXin Li Address LB, Address UB, Address ST, Address IL, llvm::Value *Chunk) {
1848*67e74705SXin Li
1849*67e74705SXin Li auto &RT = CGM.getOpenMPRuntime();
1850*67e74705SXin Li
1851*67e74705SXin Li // Emit outer loop.
1852*67e74705SXin Li // Same behavior as a OMPForOuterLoop, except that schedule cannot be
1853*67e74705SXin Li // dynamic
1854*67e74705SXin Li //
1855*67e74705SXin Li
1856*67e74705SXin Li const Expr *IVExpr = S.getIterationVariable();
1857*67e74705SXin Li const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
1858*67e74705SXin Li const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
1859*67e74705SXin Li
1860*67e74705SXin Li RT.emitDistributeStaticInit(*this, S.getLocStart(), ScheduleKind,
1861*67e74705SXin Li IVSize, IVSigned, /* Ordered = */ false,
1862*67e74705SXin Li IL, LB, UB, ST, Chunk);
1863*67e74705SXin Li
1864*67e74705SXin Li EmitOMPOuterLoop(/* DynamicOrOrdered = */ false, /* IsMonotonic = */ false,
1865*67e74705SXin Li S, LoopScope, /* Ordered = */ false, LB, UB, ST, IL, Chunk);
1866*67e74705SXin Li }
1867*67e74705SXin Li
EmitOMPDistributeParallelForDirective(const OMPDistributeParallelForDirective & S)1868*67e74705SXin Li void CodeGenFunction::EmitOMPDistributeParallelForDirective(
1869*67e74705SXin Li const OMPDistributeParallelForDirective &S) {
1870*67e74705SXin Li OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
1871*67e74705SXin Li CGM.getOpenMPRuntime().emitInlinedDirective(
1872*67e74705SXin Li *this, OMPD_distribute_parallel_for,
1873*67e74705SXin Li [&S](CodeGenFunction &CGF, PrePostActionTy &) {
1874*67e74705SXin Li OMPLoopScope PreInitScope(CGF, S);
1875*67e74705SXin Li CGF.EmitStmt(
1876*67e74705SXin Li cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
1877*67e74705SXin Li });
1878*67e74705SXin Li }
1879*67e74705SXin Li
EmitOMPDistributeParallelForSimdDirective(const OMPDistributeParallelForSimdDirective & S)1880*67e74705SXin Li void CodeGenFunction::EmitOMPDistributeParallelForSimdDirective(
1881*67e74705SXin Li const OMPDistributeParallelForSimdDirective &S) {
1882*67e74705SXin Li OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
1883*67e74705SXin Li CGM.getOpenMPRuntime().emitInlinedDirective(
1884*67e74705SXin Li *this, OMPD_distribute_parallel_for_simd,
1885*67e74705SXin Li [&S](CodeGenFunction &CGF, PrePostActionTy &) {
1886*67e74705SXin Li OMPLoopScope PreInitScope(CGF, S);
1887*67e74705SXin Li CGF.EmitStmt(
1888*67e74705SXin Li cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
1889*67e74705SXin Li });
1890*67e74705SXin Li }
1891*67e74705SXin Li
EmitOMPDistributeSimdDirective(const OMPDistributeSimdDirective & S)1892*67e74705SXin Li void CodeGenFunction::EmitOMPDistributeSimdDirective(
1893*67e74705SXin Li const OMPDistributeSimdDirective &S) {
1894*67e74705SXin Li OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
1895*67e74705SXin Li CGM.getOpenMPRuntime().emitInlinedDirective(
1896*67e74705SXin Li *this, OMPD_distribute_simd,
1897*67e74705SXin Li [&S](CodeGenFunction &CGF, PrePostActionTy &) {
1898*67e74705SXin Li OMPLoopScope PreInitScope(CGF, S);
1899*67e74705SXin Li CGF.EmitStmt(
1900*67e74705SXin Li cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
1901*67e74705SXin Li });
1902*67e74705SXin Li }
1903*67e74705SXin Li
EmitOMPTargetParallelForSimdDirective(const OMPTargetParallelForSimdDirective & S)1904*67e74705SXin Li void CodeGenFunction::EmitOMPTargetParallelForSimdDirective(
1905*67e74705SXin Li const OMPTargetParallelForSimdDirective &S) {
1906*67e74705SXin Li OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
1907*67e74705SXin Li CGM.getOpenMPRuntime().emitInlinedDirective(
1908*67e74705SXin Li *this, OMPD_target_parallel_for_simd,
1909*67e74705SXin Li [&S](CodeGenFunction &CGF, PrePostActionTy &) {
1910*67e74705SXin Li OMPLoopScope PreInitScope(CGF, S);
1911*67e74705SXin Li CGF.EmitStmt(
1912*67e74705SXin Li cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
1913*67e74705SXin Li });
1914*67e74705SXin Li }
1915*67e74705SXin Li
1916*67e74705SXin Li /// \brief Emit a helper variable and return corresponding lvalue.
EmitOMPHelperVar(CodeGenFunction & CGF,const DeclRefExpr * Helper)1917*67e74705SXin Li static LValue EmitOMPHelperVar(CodeGenFunction &CGF,
1918*67e74705SXin Li const DeclRefExpr *Helper) {
1919*67e74705SXin Li auto VDecl = cast<VarDecl>(Helper->getDecl());
1920*67e74705SXin Li CGF.EmitVarDecl(*VDecl);
1921*67e74705SXin Li return CGF.EmitLValue(Helper);
1922*67e74705SXin Li }
1923*67e74705SXin Li
1924*67e74705SXin Li namespace {
1925*67e74705SXin Li struct ScheduleKindModifiersTy {
1926*67e74705SXin Li OpenMPScheduleClauseKind Kind;
1927*67e74705SXin Li OpenMPScheduleClauseModifier M1;
1928*67e74705SXin Li OpenMPScheduleClauseModifier M2;
ScheduleKindModifiersTy__anon14ec2c572f11::ScheduleKindModifiersTy1929*67e74705SXin Li ScheduleKindModifiersTy(OpenMPScheduleClauseKind Kind,
1930*67e74705SXin Li OpenMPScheduleClauseModifier M1,
1931*67e74705SXin Li OpenMPScheduleClauseModifier M2)
1932*67e74705SXin Li : Kind(Kind), M1(M1), M2(M2) {}
1933*67e74705SXin Li };
1934*67e74705SXin Li } // namespace
1935*67e74705SXin Li
EmitOMPWorksharingLoop(const OMPLoopDirective & S)1936*67e74705SXin Li bool CodeGenFunction::EmitOMPWorksharingLoop(const OMPLoopDirective &S) {
1937*67e74705SXin Li // Emit the loop iteration variable.
1938*67e74705SXin Li auto IVExpr = cast<DeclRefExpr>(S.getIterationVariable());
1939*67e74705SXin Li auto IVDecl = cast<VarDecl>(IVExpr->getDecl());
1940*67e74705SXin Li EmitVarDecl(*IVDecl);
1941*67e74705SXin Li
1942*67e74705SXin Li // Emit the iterations count variable.
1943*67e74705SXin Li // If it is not a variable, Sema decided to calculate iterations count on each
1944*67e74705SXin Li // iteration (e.g., it is foldable into a constant).
1945*67e74705SXin Li if (auto LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
1946*67e74705SXin Li EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
1947*67e74705SXin Li // Emit calculation of the iterations count.
1948*67e74705SXin Li EmitIgnoredExpr(S.getCalcLastIteration());
1949*67e74705SXin Li }
1950*67e74705SXin Li
1951*67e74705SXin Li auto &RT = CGM.getOpenMPRuntime();
1952*67e74705SXin Li
1953*67e74705SXin Li bool HasLastprivateClause;
1954*67e74705SXin Li // Check pre-condition.
1955*67e74705SXin Li {
1956*67e74705SXin Li OMPLoopScope PreInitScope(*this, S);
1957*67e74705SXin Li // Skip the entire loop if we don't meet the precondition.
1958*67e74705SXin Li // If the condition constant folds and can be elided, avoid emitting the
1959*67e74705SXin Li // whole loop.
1960*67e74705SXin Li bool CondConstant;
1961*67e74705SXin Li llvm::BasicBlock *ContBlock = nullptr;
1962*67e74705SXin Li if (ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
1963*67e74705SXin Li if (!CondConstant)
1964*67e74705SXin Li return false;
1965*67e74705SXin Li } else {
1966*67e74705SXin Li auto *ThenBlock = createBasicBlock("omp.precond.then");
1967*67e74705SXin Li ContBlock = createBasicBlock("omp.precond.end");
1968*67e74705SXin Li emitPreCond(*this, S, S.getPreCond(), ThenBlock, ContBlock,
1969*67e74705SXin Li getProfileCount(&S));
1970*67e74705SXin Li EmitBlock(ThenBlock);
1971*67e74705SXin Li incrementProfileCounter(&S);
1972*67e74705SXin Li }
1973*67e74705SXin Li
1974*67e74705SXin Li bool Ordered = false;
1975*67e74705SXin Li if (auto *OrderedClause = S.getSingleClause<OMPOrderedClause>()) {
1976*67e74705SXin Li if (OrderedClause->getNumForLoops())
1977*67e74705SXin Li RT.emitDoacrossInit(*this, S);
1978*67e74705SXin Li else
1979*67e74705SXin Li Ordered = true;
1980*67e74705SXin Li }
1981*67e74705SXin Li
1982*67e74705SXin Li llvm::DenseSet<const Expr *> EmittedFinals;
1983*67e74705SXin Li emitAlignedClause(*this, S);
1984*67e74705SXin Li EmitOMPLinearClauseInit(S);
1985*67e74705SXin Li // Emit helper vars inits.
1986*67e74705SXin Li LValue LB =
1987*67e74705SXin Li EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getLowerBoundVariable()));
1988*67e74705SXin Li LValue UB =
1989*67e74705SXin Li EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getUpperBoundVariable()));
1990*67e74705SXin Li LValue ST =
1991*67e74705SXin Li EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getStrideVariable()));
1992*67e74705SXin Li LValue IL =
1993*67e74705SXin Li EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getIsLastIterVariable()));
1994*67e74705SXin Li
1995*67e74705SXin Li // Emit 'then' code.
1996*67e74705SXin Li {
1997*67e74705SXin Li OMPPrivateScope LoopScope(*this);
1998*67e74705SXin Li if (EmitOMPFirstprivateClause(S, LoopScope)) {
1999*67e74705SXin Li // Emit implicit barrier to synchronize threads and avoid data races on
2000*67e74705SXin Li // initialization of firstprivate variables and post-update of
2001*67e74705SXin Li // lastprivate variables.
2002*67e74705SXin Li CGM.getOpenMPRuntime().emitBarrierCall(
2003*67e74705SXin Li *this, S.getLocStart(), OMPD_unknown, /*EmitChecks=*/false,
2004*67e74705SXin Li /*ForceSimpleCall=*/true);
2005*67e74705SXin Li }
2006*67e74705SXin Li EmitOMPPrivateClause(S, LoopScope);
2007*67e74705SXin Li HasLastprivateClause = EmitOMPLastprivateClauseInit(S, LoopScope);
2008*67e74705SXin Li EmitOMPReductionClauseInit(S, LoopScope);
2009*67e74705SXin Li EmitOMPPrivateLoopCounters(S, LoopScope);
2010*67e74705SXin Li EmitOMPLinearClause(S, LoopScope);
2011*67e74705SXin Li (void)LoopScope.Privatize();
2012*67e74705SXin Li
2013*67e74705SXin Li // Detect the loop schedule kind and chunk.
2014*67e74705SXin Li llvm::Value *Chunk = nullptr;
2015*67e74705SXin Li OpenMPScheduleTy ScheduleKind;
2016*67e74705SXin Li if (auto *C = S.getSingleClause<OMPScheduleClause>()) {
2017*67e74705SXin Li ScheduleKind.Schedule = C->getScheduleKind();
2018*67e74705SXin Li ScheduleKind.M1 = C->getFirstScheduleModifier();
2019*67e74705SXin Li ScheduleKind.M2 = C->getSecondScheduleModifier();
2020*67e74705SXin Li if (const auto *Ch = C->getChunkSize()) {
2021*67e74705SXin Li Chunk = EmitScalarExpr(Ch);
2022*67e74705SXin Li Chunk = EmitScalarConversion(Chunk, Ch->getType(),
2023*67e74705SXin Li S.getIterationVariable()->getType(),
2024*67e74705SXin Li S.getLocStart());
2025*67e74705SXin Li }
2026*67e74705SXin Li }
2027*67e74705SXin Li const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
2028*67e74705SXin Li const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
2029*67e74705SXin Li // OpenMP 4.5, 2.7.1 Loop Construct, Description.
2030*67e74705SXin Li // If the static schedule kind is specified or if the ordered clause is
2031*67e74705SXin Li // specified, and if no monotonic modifier is specified, the effect will
2032*67e74705SXin Li // be as if the monotonic modifier was specified.
2033*67e74705SXin Li if (RT.isStaticNonchunked(ScheduleKind.Schedule,
2034*67e74705SXin Li /* Chunked */ Chunk != nullptr) &&
2035*67e74705SXin Li !Ordered) {
2036*67e74705SXin Li if (isOpenMPSimdDirective(S.getDirectiveKind()))
2037*67e74705SXin Li EmitOMPSimdInit(S, /*IsMonotonic=*/true);
2038*67e74705SXin Li // OpenMP [2.7.1, Loop Construct, Description, table 2-1]
2039*67e74705SXin Li // When no chunk_size is specified, the iteration space is divided into
2040*67e74705SXin Li // chunks that are approximately equal in size, and at most one chunk is
2041*67e74705SXin Li // distributed to each thread. Note that the size of the chunks is
2042*67e74705SXin Li // unspecified in this case.
2043*67e74705SXin Li RT.emitForStaticInit(*this, S.getLocStart(), ScheduleKind,
2044*67e74705SXin Li IVSize, IVSigned, Ordered,
2045*67e74705SXin Li IL.getAddress(), LB.getAddress(),
2046*67e74705SXin Li UB.getAddress(), ST.getAddress());
2047*67e74705SXin Li auto LoopExit =
2048*67e74705SXin Li getJumpDestInCurrentScope(createBasicBlock("omp.loop.exit"));
2049*67e74705SXin Li // UB = min(UB, GlobalUB);
2050*67e74705SXin Li EmitIgnoredExpr(S.getEnsureUpperBound());
2051*67e74705SXin Li // IV = LB;
2052*67e74705SXin Li EmitIgnoredExpr(S.getInit());
2053*67e74705SXin Li // while (idx <= UB) { BODY; ++idx; }
2054*67e74705SXin Li EmitOMPInnerLoop(S, LoopScope.requiresCleanups(), S.getCond(),
2055*67e74705SXin Li S.getInc(),
2056*67e74705SXin Li [&S, LoopExit](CodeGenFunction &CGF) {
2057*67e74705SXin Li CGF.EmitOMPLoopBody(S, LoopExit);
2058*67e74705SXin Li CGF.EmitStopPoint(&S);
2059*67e74705SXin Li },
2060*67e74705SXin Li [](CodeGenFunction &) {});
2061*67e74705SXin Li EmitBlock(LoopExit.getBlock());
2062*67e74705SXin Li // Tell the runtime we are done.
2063*67e74705SXin Li RT.emitForStaticFinish(*this, S.getLocStart());
2064*67e74705SXin Li } else {
2065*67e74705SXin Li const bool IsMonotonic =
2066*67e74705SXin Li Ordered || ScheduleKind.Schedule == OMPC_SCHEDULE_static ||
2067*67e74705SXin Li ScheduleKind.Schedule == OMPC_SCHEDULE_unknown ||
2068*67e74705SXin Li ScheduleKind.M1 == OMPC_SCHEDULE_MODIFIER_monotonic ||
2069*67e74705SXin Li ScheduleKind.M2 == OMPC_SCHEDULE_MODIFIER_monotonic;
2070*67e74705SXin Li // Emit the outer loop, which requests its work chunk [LB..UB] from
2071*67e74705SXin Li // runtime and runs the inner loop to process it.
2072*67e74705SXin Li EmitOMPForOuterLoop(ScheduleKind, IsMonotonic, S, LoopScope, Ordered,
2073*67e74705SXin Li LB.getAddress(), UB.getAddress(), ST.getAddress(),
2074*67e74705SXin Li IL.getAddress(), Chunk);
2075*67e74705SXin Li }
2076*67e74705SXin Li if (isOpenMPSimdDirective(S.getDirectiveKind())) {
2077*67e74705SXin Li EmitOMPSimdFinal(S,
2078*67e74705SXin Li [&](CodeGenFunction &CGF) -> llvm::Value * {
2079*67e74705SXin Li return CGF.Builder.CreateIsNotNull(
2080*67e74705SXin Li CGF.EmitLoadOfScalar(IL, S.getLocStart()));
2081*67e74705SXin Li });
2082*67e74705SXin Li }
2083*67e74705SXin Li EmitOMPReductionClauseFinal(S);
2084*67e74705SXin Li // Emit post-update of the reduction variables if IsLastIter != 0.
2085*67e74705SXin Li emitPostUpdateForReductionClause(
2086*67e74705SXin Li *this, S, [&](CodeGenFunction &CGF) -> llvm::Value * {
2087*67e74705SXin Li return CGF.Builder.CreateIsNotNull(
2088*67e74705SXin Li CGF.EmitLoadOfScalar(IL, S.getLocStart()));
2089*67e74705SXin Li });
2090*67e74705SXin Li // Emit final copy of the lastprivate variables if IsLastIter != 0.
2091*67e74705SXin Li if (HasLastprivateClause)
2092*67e74705SXin Li EmitOMPLastprivateClauseFinal(
2093*67e74705SXin Li S, isOpenMPSimdDirective(S.getDirectiveKind()),
2094*67e74705SXin Li Builder.CreateIsNotNull(EmitLoadOfScalar(IL, S.getLocStart())));
2095*67e74705SXin Li }
2096*67e74705SXin Li EmitOMPLinearClauseFinal(S, [&](CodeGenFunction &CGF) -> llvm::Value * {
2097*67e74705SXin Li return CGF.Builder.CreateIsNotNull(
2098*67e74705SXin Li CGF.EmitLoadOfScalar(IL, S.getLocStart()));
2099*67e74705SXin Li });
2100*67e74705SXin Li // We're now done with the loop, so jump to the continuation block.
2101*67e74705SXin Li if (ContBlock) {
2102*67e74705SXin Li EmitBranch(ContBlock);
2103*67e74705SXin Li EmitBlock(ContBlock, true);
2104*67e74705SXin Li }
2105*67e74705SXin Li }
2106*67e74705SXin Li return HasLastprivateClause;
2107*67e74705SXin Li }
2108*67e74705SXin Li
EmitOMPForDirective(const OMPForDirective & S)2109*67e74705SXin Li void CodeGenFunction::EmitOMPForDirective(const OMPForDirective &S) {
2110*67e74705SXin Li bool HasLastprivates = false;
2111*67e74705SXin Li auto &&CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF,
2112*67e74705SXin Li PrePostActionTy &) {
2113*67e74705SXin Li HasLastprivates = CGF.EmitOMPWorksharingLoop(S);
2114*67e74705SXin Li };
2115*67e74705SXin Li {
2116*67e74705SXin Li OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
2117*67e74705SXin Li CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_for, CodeGen,
2118*67e74705SXin Li S.hasCancel());
2119*67e74705SXin Li }
2120*67e74705SXin Li
2121*67e74705SXin Li // Emit an implicit barrier at the end.
2122*67e74705SXin Li if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates) {
2123*67e74705SXin Li CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), OMPD_for);
2124*67e74705SXin Li }
2125*67e74705SXin Li }
2126*67e74705SXin Li
EmitOMPForSimdDirective(const OMPForSimdDirective & S)2127*67e74705SXin Li void CodeGenFunction::EmitOMPForSimdDirective(const OMPForSimdDirective &S) {
2128*67e74705SXin Li bool HasLastprivates = false;
2129*67e74705SXin Li auto &&CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF,
2130*67e74705SXin Li PrePostActionTy &) {
2131*67e74705SXin Li HasLastprivates = CGF.EmitOMPWorksharingLoop(S);
2132*67e74705SXin Li };
2133*67e74705SXin Li {
2134*67e74705SXin Li OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
2135*67e74705SXin Li CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen);
2136*67e74705SXin Li }
2137*67e74705SXin Li
2138*67e74705SXin Li // Emit an implicit barrier at the end.
2139*67e74705SXin Li if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates) {
2140*67e74705SXin Li CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), OMPD_for);
2141*67e74705SXin Li }
2142*67e74705SXin Li }
2143*67e74705SXin Li
createSectionLVal(CodeGenFunction & CGF,QualType Ty,const Twine & Name,llvm::Value * Init=nullptr)2144*67e74705SXin Li static LValue createSectionLVal(CodeGenFunction &CGF, QualType Ty,
2145*67e74705SXin Li const Twine &Name,
2146*67e74705SXin Li llvm::Value *Init = nullptr) {
2147*67e74705SXin Li auto LVal = CGF.MakeAddrLValue(CGF.CreateMemTemp(Ty, Name), Ty);
2148*67e74705SXin Li if (Init)
2149*67e74705SXin Li CGF.EmitScalarInit(Init, LVal);
2150*67e74705SXin Li return LVal;
2151*67e74705SXin Li }
2152*67e74705SXin Li
EmitSections(const OMPExecutableDirective & S)2153*67e74705SXin Li void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
2154*67e74705SXin Li auto *Stmt = cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt();
2155*67e74705SXin Li auto *CS = dyn_cast<CompoundStmt>(Stmt);
2156*67e74705SXin Li bool HasLastprivates = false;
2157*67e74705SXin Li auto &&CodeGen = [&S, Stmt, CS, &HasLastprivates](CodeGenFunction &CGF,
2158*67e74705SXin Li PrePostActionTy &) {
2159*67e74705SXin Li auto &C = CGF.CGM.getContext();
2160*67e74705SXin Li auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
2161*67e74705SXin Li // Emit helper vars inits.
2162*67e74705SXin Li LValue LB = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.lb.",
2163*67e74705SXin Li CGF.Builder.getInt32(0));
2164*67e74705SXin Li auto *GlobalUBVal = CS != nullptr ? CGF.Builder.getInt32(CS->size() - 1)
2165*67e74705SXin Li : CGF.Builder.getInt32(0);
2166*67e74705SXin Li LValue UB =
2167*67e74705SXin Li createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.ub.", GlobalUBVal);
2168*67e74705SXin Li LValue ST = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.st.",
2169*67e74705SXin Li CGF.Builder.getInt32(1));
2170*67e74705SXin Li LValue IL = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.il.",
2171*67e74705SXin Li CGF.Builder.getInt32(0));
2172*67e74705SXin Li // Loop counter.
2173*67e74705SXin Li LValue IV = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.iv.");
2174*67e74705SXin Li OpaqueValueExpr IVRefExpr(S.getLocStart(), KmpInt32Ty, VK_LValue);
2175*67e74705SXin Li CodeGenFunction::OpaqueValueMapping OpaqueIV(CGF, &IVRefExpr, IV);
2176*67e74705SXin Li OpaqueValueExpr UBRefExpr(S.getLocStart(), KmpInt32Ty, VK_LValue);
2177*67e74705SXin Li CodeGenFunction::OpaqueValueMapping OpaqueUB(CGF, &UBRefExpr, UB);
2178*67e74705SXin Li // Generate condition for loop.
2179*67e74705SXin Li BinaryOperator Cond(&IVRefExpr, &UBRefExpr, BO_LE, C.BoolTy, VK_RValue,
2180*67e74705SXin Li OK_Ordinary, S.getLocStart(),
2181*67e74705SXin Li /*fpContractable=*/false);
2182*67e74705SXin Li // Increment for loop counter.
2183*67e74705SXin Li UnaryOperator Inc(&IVRefExpr, UO_PreInc, KmpInt32Ty, VK_RValue, OK_Ordinary,
2184*67e74705SXin Li S.getLocStart());
2185*67e74705SXin Li auto BodyGen = [Stmt, CS, &S, &IV](CodeGenFunction &CGF) {
2186*67e74705SXin Li // Iterate through all sections and emit a switch construct:
2187*67e74705SXin Li // switch (IV) {
2188*67e74705SXin Li // case 0:
2189*67e74705SXin Li // <SectionStmt[0]>;
2190*67e74705SXin Li // break;
2191*67e74705SXin Li // ...
2192*67e74705SXin Li // case <NumSection> - 1:
2193*67e74705SXin Li // <SectionStmt[<NumSection> - 1]>;
2194*67e74705SXin Li // break;
2195*67e74705SXin Li // }
2196*67e74705SXin Li // .omp.sections.exit:
2197*67e74705SXin Li auto *ExitBB = CGF.createBasicBlock(".omp.sections.exit");
2198*67e74705SXin Li auto *SwitchStmt = CGF.Builder.CreateSwitch(
2199*67e74705SXin Li CGF.EmitLoadOfLValue(IV, S.getLocStart()).getScalarVal(), ExitBB,
2200*67e74705SXin Li CS == nullptr ? 1 : CS->size());
2201*67e74705SXin Li if (CS) {
2202*67e74705SXin Li unsigned CaseNumber = 0;
2203*67e74705SXin Li for (auto *SubStmt : CS->children()) {
2204*67e74705SXin Li auto CaseBB = CGF.createBasicBlock(".omp.sections.case");
2205*67e74705SXin Li CGF.EmitBlock(CaseBB);
2206*67e74705SXin Li SwitchStmt->addCase(CGF.Builder.getInt32(CaseNumber), CaseBB);
2207*67e74705SXin Li CGF.EmitStmt(SubStmt);
2208*67e74705SXin Li CGF.EmitBranch(ExitBB);
2209*67e74705SXin Li ++CaseNumber;
2210*67e74705SXin Li }
2211*67e74705SXin Li } else {
2212*67e74705SXin Li auto CaseBB = CGF.createBasicBlock(".omp.sections.case");
2213*67e74705SXin Li CGF.EmitBlock(CaseBB);
2214*67e74705SXin Li SwitchStmt->addCase(CGF.Builder.getInt32(0), CaseBB);
2215*67e74705SXin Li CGF.EmitStmt(Stmt);
2216*67e74705SXin Li CGF.EmitBranch(ExitBB);
2217*67e74705SXin Li }
2218*67e74705SXin Li CGF.EmitBlock(ExitBB, /*IsFinished=*/true);
2219*67e74705SXin Li };
2220*67e74705SXin Li
2221*67e74705SXin Li CodeGenFunction::OMPPrivateScope LoopScope(CGF);
2222*67e74705SXin Li if (CGF.EmitOMPFirstprivateClause(S, LoopScope)) {
2223*67e74705SXin Li // Emit implicit barrier to synchronize threads and avoid data races on
2224*67e74705SXin Li // initialization of firstprivate variables and post-update of lastprivate
2225*67e74705SXin Li // variables.
2226*67e74705SXin Li CGF.CGM.getOpenMPRuntime().emitBarrierCall(
2227*67e74705SXin Li CGF, S.getLocStart(), OMPD_unknown, /*EmitChecks=*/false,
2228*67e74705SXin Li /*ForceSimpleCall=*/true);
2229*67e74705SXin Li }
2230*67e74705SXin Li CGF.EmitOMPPrivateClause(S, LoopScope);
2231*67e74705SXin Li HasLastprivates = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
2232*67e74705SXin Li CGF.EmitOMPReductionClauseInit(S, LoopScope);
2233*67e74705SXin Li (void)LoopScope.Privatize();
2234*67e74705SXin Li
2235*67e74705SXin Li // Emit static non-chunked loop.
2236*67e74705SXin Li OpenMPScheduleTy ScheduleKind;
2237*67e74705SXin Li ScheduleKind.Schedule = OMPC_SCHEDULE_static;
2238*67e74705SXin Li CGF.CGM.getOpenMPRuntime().emitForStaticInit(
2239*67e74705SXin Li CGF, S.getLocStart(), ScheduleKind, /*IVSize=*/32,
2240*67e74705SXin Li /*IVSigned=*/true, /*Ordered=*/false, IL.getAddress(), LB.getAddress(),
2241*67e74705SXin Li UB.getAddress(), ST.getAddress());
2242*67e74705SXin Li // UB = min(UB, GlobalUB);
2243*67e74705SXin Li auto *UBVal = CGF.EmitLoadOfScalar(UB, S.getLocStart());
2244*67e74705SXin Li auto *MinUBGlobalUB = CGF.Builder.CreateSelect(
2245*67e74705SXin Li CGF.Builder.CreateICmpSLT(UBVal, GlobalUBVal), UBVal, GlobalUBVal);
2246*67e74705SXin Li CGF.EmitStoreOfScalar(MinUBGlobalUB, UB);
2247*67e74705SXin Li // IV = LB;
2248*67e74705SXin Li CGF.EmitStoreOfScalar(CGF.EmitLoadOfScalar(LB, S.getLocStart()), IV);
2249*67e74705SXin Li // while (idx <= UB) { BODY; ++idx; }
2250*67e74705SXin Li CGF.EmitOMPInnerLoop(S, /*RequiresCleanup=*/false, &Cond, &Inc, BodyGen,
2251*67e74705SXin Li [](CodeGenFunction &) {});
2252*67e74705SXin Li // Tell the runtime we are done.
2253*67e74705SXin Li CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getLocStart());
2254*67e74705SXin Li CGF.EmitOMPReductionClauseFinal(S);
2255*67e74705SXin Li // Emit post-update of the reduction variables if IsLastIter != 0.
2256*67e74705SXin Li emitPostUpdateForReductionClause(
2257*67e74705SXin Li CGF, S, [&](CodeGenFunction &CGF) -> llvm::Value * {
2258*67e74705SXin Li return CGF.Builder.CreateIsNotNull(
2259*67e74705SXin Li CGF.EmitLoadOfScalar(IL, S.getLocStart()));
2260*67e74705SXin Li });
2261*67e74705SXin Li
2262*67e74705SXin Li // Emit final copy of the lastprivate variables if IsLastIter != 0.
2263*67e74705SXin Li if (HasLastprivates)
2264*67e74705SXin Li CGF.EmitOMPLastprivateClauseFinal(
2265*67e74705SXin Li S, /*NoFinals=*/false,
2266*67e74705SXin Li CGF.Builder.CreateIsNotNull(
2267*67e74705SXin Li CGF.EmitLoadOfScalar(IL, S.getLocStart())));
2268*67e74705SXin Li };
2269*67e74705SXin Li
2270*67e74705SXin Li bool HasCancel = false;
2271*67e74705SXin Li if (auto *OSD = dyn_cast<OMPSectionsDirective>(&S))
2272*67e74705SXin Li HasCancel = OSD->hasCancel();
2273*67e74705SXin Li else if (auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&S))
2274*67e74705SXin Li HasCancel = OPSD->hasCancel();
2275*67e74705SXin Li CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_sections, CodeGen,
2276*67e74705SXin Li HasCancel);
2277*67e74705SXin Li // Emit barrier for lastprivates only if 'sections' directive has 'nowait'
2278*67e74705SXin Li // clause. Otherwise the barrier will be generated by the codegen for the
2279*67e74705SXin Li // directive.
2280*67e74705SXin Li if (HasLastprivates && S.getSingleClause<OMPNowaitClause>()) {
2281*67e74705SXin Li // Emit implicit barrier to synchronize threads and avoid data races on
2282*67e74705SXin Li // initialization of firstprivate variables.
2283*67e74705SXin Li CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(),
2284*67e74705SXin Li OMPD_unknown);
2285*67e74705SXin Li }
2286*67e74705SXin Li }
2287*67e74705SXin Li
EmitOMPSectionsDirective(const OMPSectionsDirective & S)2288*67e74705SXin Li void CodeGenFunction::EmitOMPSectionsDirective(const OMPSectionsDirective &S) {
2289*67e74705SXin Li {
2290*67e74705SXin Li OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
2291*67e74705SXin Li EmitSections(S);
2292*67e74705SXin Li }
2293*67e74705SXin Li // Emit an implicit barrier at the end.
2294*67e74705SXin Li if (!S.getSingleClause<OMPNowaitClause>()) {
2295*67e74705SXin Li CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(),
2296*67e74705SXin Li OMPD_sections);
2297*67e74705SXin Li }
2298*67e74705SXin Li }
2299*67e74705SXin Li
EmitOMPSectionDirective(const OMPSectionDirective & S)2300*67e74705SXin Li void CodeGenFunction::EmitOMPSectionDirective(const OMPSectionDirective &S) {
2301*67e74705SXin Li auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
2302*67e74705SXin Li CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
2303*67e74705SXin Li };
2304*67e74705SXin Li OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
2305*67e74705SXin Li CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_section, CodeGen,
2306*67e74705SXin Li S.hasCancel());
2307*67e74705SXin Li }
2308*67e74705SXin Li
EmitOMPSingleDirective(const OMPSingleDirective & S)2309*67e74705SXin Li void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &S) {
2310*67e74705SXin Li llvm::SmallVector<const Expr *, 8> CopyprivateVars;
2311*67e74705SXin Li llvm::SmallVector<const Expr *, 8> DestExprs;
2312*67e74705SXin Li llvm::SmallVector<const Expr *, 8> SrcExprs;
2313*67e74705SXin Li llvm::SmallVector<const Expr *, 8> AssignmentOps;
2314*67e74705SXin Li // Check if there are any 'copyprivate' clauses associated with this
2315*67e74705SXin Li // 'single' construct.
2316*67e74705SXin Li // Build a list of copyprivate variables along with helper expressions
2317*67e74705SXin Li // (<source>, <destination>, <destination>=<source> expressions)
2318*67e74705SXin Li for (const auto *C : S.getClausesOfKind<OMPCopyprivateClause>()) {
2319*67e74705SXin Li CopyprivateVars.append(C->varlists().begin(), C->varlists().end());
2320*67e74705SXin Li DestExprs.append(C->destination_exprs().begin(),
2321*67e74705SXin Li C->destination_exprs().end());
2322*67e74705SXin Li SrcExprs.append(C->source_exprs().begin(), C->source_exprs().end());
2323*67e74705SXin Li AssignmentOps.append(C->assignment_ops().begin(),
2324*67e74705SXin Li C->assignment_ops().end());
2325*67e74705SXin Li }
2326*67e74705SXin Li // Emit code for 'single' region along with 'copyprivate' clauses
2327*67e74705SXin Li auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
2328*67e74705SXin Li Action.Enter(CGF);
2329*67e74705SXin Li OMPPrivateScope SingleScope(CGF);
2330*67e74705SXin Li (void)CGF.EmitOMPFirstprivateClause(S, SingleScope);
2331*67e74705SXin Li CGF.EmitOMPPrivateClause(S, SingleScope);
2332*67e74705SXin Li (void)SingleScope.Privatize();
2333*67e74705SXin Li CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
2334*67e74705SXin Li };
2335*67e74705SXin Li {
2336*67e74705SXin Li OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
2337*67e74705SXin Li CGM.getOpenMPRuntime().emitSingleRegion(*this, CodeGen, S.getLocStart(),
2338*67e74705SXin Li CopyprivateVars, DestExprs,
2339*67e74705SXin Li SrcExprs, AssignmentOps);
2340*67e74705SXin Li }
2341*67e74705SXin Li // Emit an implicit barrier at the end (to avoid data race on firstprivate
2342*67e74705SXin Li // init or if no 'nowait' clause was specified and no 'copyprivate' clause).
2343*67e74705SXin Li if (!S.getSingleClause<OMPNowaitClause>() && CopyprivateVars.empty()) {
2344*67e74705SXin Li CGM.getOpenMPRuntime().emitBarrierCall(
2345*67e74705SXin Li *this, S.getLocStart(),
2346*67e74705SXin Li S.getSingleClause<OMPNowaitClause>() ? OMPD_unknown : OMPD_single);
2347*67e74705SXin Li }
2348*67e74705SXin Li }
2349*67e74705SXin Li
EmitOMPMasterDirective(const OMPMasterDirective & S)2350*67e74705SXin Li void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &S) {
2351*67e74705SXin Li auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
2352*67e74705SXin Li Action.Enter(CGF);
2353*67e74705SXin Li CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
2354*67e74705SXin Li };
2355*67e74705SXin Li OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
2356*67e74705SXin Li CGM.getOpenMPRuntime().emitMasterRegion(*this, CodeGen, S.getLocStart());
2357*67e74705SXin Li }
2358*67e74705SXin Li
EmitOMPCriticalDirective(const OMPCriticalDirective & S)2359*67e74705SXin Li void CodeGenFunction::EmitOMPCriticalDirective(const OMPCriticalDirective &S) {
2360*67e74705SXin Li auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
2361*67e74705SXin Li Action.Enter(CGF);
2362*67e74705SXin Li CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
2363*67e74705SXin Li };
2364*67e74705SXin Li Expr *Hint = nullptr;
2365*67e74705SXin Li if (auto *HintClause = S.getSingleClause<OMPHintClause>())
2366*67e74705SXin Li Hint = HintClause->getHint();
2367*67e74705SXin Li OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
2368*67e74705SXin Li CGM.getOpenMPRuntime().emitCriticalRegion(*this,
2369*67e74705SXin Li S.getDirectiveName().getAsString(),
2370*67e74705SXin Li CodeGen, S.getLocStart(), Hint);
2371*67e74705SXin Li }
2372*67e74705SXin Li
EmitOMPParallelForDirective(const OMPParallelForDirective & S)2373*67e74705SXin Li void CodeGenFunction::EmitOMPParallelForDirective(
2374*67e74705SXin Li const OMPParallelForDirective &S) {
2375*67e74705SXin Li // Emit directive as a combined directive that consists of two implicit
2376*67e74705SXin Li // directives: 'parallel' with 'for' directive.
2377*67e74705SXin Li auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
2378*67e74705SXin Li CGF.EmitOMPWorksharingLoop(S);
2379*67e74705SXin Li };
2380*67e74705SXin Li emitCommonOMPParallelDirective(*this, S, OMPD_for, CodeGen);
2381*67e74705SXin Li }
2382*67e74705SXin Li
EmitOMPParallelForSimdDirective(const OMPParallelForSimdDirective & S)2383*67e74705SXin Li void CodeGenFunction::EmitOMPParallelForSimdDirective(
2384*67e74705SXin Li const OMPParallelForSimdDirective &S) {
2385*67e74705SXin Li // Emit directive as a combined directive that consists of two implicit
2386*67e74705SXin Li // directives: 'parallel' with 'for' directive.
2387*67e74705SXin Li auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
2388*67e74705SXin Li CGF.EmitOMPWorksharingLoop(S);
2389*67e74705SXin Li };
2390*67e74705SXin Li emitCommonOMPParallelDirective(*this, S, OMPD_simd, CodeGen);
2391*67e74705SXin Li }
2392*67e74705SXin Li
EmitOMPParallelSectionsDirective(const OMPParallelSectionsDirective & S)2393*67e74705SXin Li void CodeGenFunction::EmitOMPParallelSectionsDirective(
2394*67e74705SXin Li const OMPParallelSectionsDirective &S) {
2395*67e74705SXin Li // Emit directive as a combined directive that consists of two implicit
2396*67e74705SXin Li // directives: 'parallel' with 'sections' directive.
2397*67e74705SXin Li auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
2398*67e74705SXin Li CGF.EmitSections(S);
2399*67e74705SXin Li };
2400*67e74705SXin Li emitCommonOMPParallelDirective(*this, S, OMPD_sections, CodeGen);
2401*67e74705SXin Li }
2402*67e74705SXin Li
EmitOMPTaskBasedDirective(const OMPExecutableDirective & S,const RegionCodeGenTy & BodyGen,const TaskGenTy & TaskGen,OMPTaskDataTy & Data)2403*67e74705SXin Li void CodeGenFunction::EmitOMPTaskBasedDirective(const OMPExecutableDirective &S,
2404*67e74705SXin Li const RegionCodeGenTy &BodyGen,
2405*67e74705SXin Li const TaskGenTy &TaskGen,
2406*67e74705SXin Li OMPTaskDataTy &Data) {
2407*67e74705SXin Li // Emit outlined function for task construct.
2408*67e74705SXin Li auto CS = cast<CapturedStmt>(S.getAssociatedStmt());
2409*67e74705SXin Li auto *I = CS->getCapturedDecl()->param_begin();
2410*67e74705SXin Li auto *PartId = std::next(I);
2411*67e74705SXin Li auto *TaskT = std::next(I, 4);
2412*67e74705SXin Li // Check if the task is final
2413*67e74705SXin Li if (const auto *Clause = S.getSingleClause<OMPFinalClause>()) {
2414*67e74705SXin Li // If the condition constant folds and can be elided, try to avoid emitting
2415*67e74705SXin Li // the condition and the dead arm of the if/else.
2416*67e74705SXin Li auto *Cond = Clause->getCondition();
2417*67e74705SXin Li bool CondConstant;
2418*67e74705SXin Li if (ConstantFoldsToSimpleInteger(Cond, CondConstant))
2419*67e74705SXin Li Data.Final.setInt(CondConstant);
2420*67e74705SXin Li else
2421*67e74705SXin Li Data.Final.setPointer(EvaluateExprAsBool(Cond));
2422*67e74705SXin Li } else {
2423*67e74705SXin Li // By default the task is not final.
2424*67e74705SXin Li Data.Final.setInt(/*IntVal=*/false);
2425*67e74705SXin Li }
2426*67e74705SXin Li // Check if the task has 'priority' clause.
2427*67e74705SXin Li if (const auto *Clause = S.getSingleClause<OMPPriorityClause>()) {
2428*67e74705SXin Li // Runtime currently does not support codegen for priority clause argument.
2429*67e74705SXin Li // TODO: Add codegen for priority clause arg when runtime lib support it.
2430*67e74705SXin Li auto *Prio = Clause->getPriority();
2431*67e74705SXin Li Data.Priority.setInt(Prio);
2432*67e74705SXin Li Data.Priority.setPointer(EmitScalarConversion(
2433*67e74705SXin Li EmitScalarExpr(Prio), Prio->getType(),
2434*67e74705SXin Li getContext().getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1),
2435*67e74705SXin Li Prio->getExprLoc()));
2436*67e74705SXin Li }
2437*67e74705SXin Li // The first function argument for tasks is a thread id, the second one is a
2438*67e74705SXin Li // part id (0 for tied tasks, >=0 for untied task).
2439*67e74705SXin Li llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
2440*67e74705SXin Li // Get list of private variables.
2441*67e74705SXin Li for (const auto *C : S.getClausesOfKind<OMPPrivateClause>()) {
2442*67e74705SXin Li auto IRef = C->varlist_begin();
2443*67e74705SXin Li for (auto *IInit : C->private_copies()) {
2444*67e74705SXin Li auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
2445*67e74705SXin Li if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
2446*67e74705SXin Li Data.PrivateVars.push_back(*IRef);
2447*67e74705SXin Li Data.PrivateCopies.push_back(IInit);
2448*67e74705SXin Li }
2449*67e74705SXin Li ++IRef;
2450*67e74705SXin Li }
2451*67e74705SXin Li }
2452*67e74705SXin Li EmittedAsPrivate.clear();
2453*67e74705SXin Li // Get list of firstprivate variables.
2454*67e74705SXin Li for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) {
2455*67e74705SXin Li auto IRef = C->varlist_begin();
2456*67e74705SXin Li auto IElemInitRef = C->inits().begin();
2457*67e74705SXin Li for (auto *IInit : C->private_copies()) {
2458*67e74705SXin Li auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
2459*67e74705SXin Li if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
2460*67e74705SXin Li Data.FirstprivateVars.push_back(*IRef);
2461*67e74705SXin Li Data.FirstprivateCopies.push_back(IInit);
2462*67e74705SXin Li Data.FirstprivateInits.push_back(*IElemInitRef);
2463*67e74705SXin Li }
2464*67e74705SXin Li ++IRef;
2465*67e74705SXin Li ++IElemInitRef;
2466*67e74705SXin Li }
2467*67e74705SXin Li }
2468*67e74705SXin Li // Get list of lastprivate variables (for taskloops).
2469*67e74705SXin Li llvm::DenseMap<const VarDecl *, const DeclRefExpr *> LastprivateDstsOrigs;
2470*67e74705SXin Li for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) {
2471*67e74705SXin Li auto IRef = C->varlist_begin();
2472*67e74705SXin Li auto ID = C->destination_exprs().begin();
2473*67e74705SXin Li for (auto *IInit : C->private_copies()) {
2474*67e74705SXin Li auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
2475*67e74705SXin Li if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
2476*67e74705SXin Li Data.LastprivateVars.push_back(*IRef);
2477*67e74705SXin Li Data.LastprivateCopies.push_back(IInit);
2478*67e74705SXin Li }
2479*67e74705SXin Li LastprivateDstsOrigs.insert(
2480*67e74705SXin Li {cast<VarDecl>(cast<DeclRefExpr>(*ID)->getDecl()),
2481*67e74705SXin Li cast<DeclRefExpr>(*IRef)});
2482*67e74705SXin Li ++IRef;
2483*67e74705SXin Li ++ID;
2484*67e74705SXin Li }
2485*67e74705SXin Li }
2486*67e74705SXin Li // Build list of dependences.
2487*67e74705SXin Li for (const auto *C : S.getClausesOfKind<OMPDependClause>())
2488*67e74705SXin Li for (auto *IRef : C->varlists())
2489*67e74705SXin Li Data.Dependences.push_back(std::make_pair(C->getDependencyKind(), IRef));
2490*67e74705SXin Li auto &&CodeGen = [PartId, &S, &Data, CS, &BodyGen, &LastprivateDstsOrigs](
2491*67e74705SXin Li CodeGenFunction &CGF, PrePostActionTy &Action) {
2492*67e74705SXin Li // Set proper addresses for generated private copies.
2493*67e74705SXin Li OMPPrivateScope Scope(CGF);
2494*67e74705SXin Li if (!Data.PrivateVars.empty() || !Data.FirstprivateVars.empty() ||
2495*67e74705SXin Li !Data.LastprivateVars.empty()) {
2496*67e74705SXin Li auto *CopyFn = CGF.Builder.CreateLoad(
2497*67e74705SXin Li CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(3)));
2498*67e74705SXin Li auto *PrivatesPtr = CGF.Builder.CreateLoad(
2499*67e74705SXin Li CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(2)));
2500*67e74705SXin Li // Map privates.
2501*67e74705SXin Li llvm::SmallVector<std::pair<const VarDecl *, Address>, 16> PrivatePtrs;
2502*67e74705SXin Li llvm::SmallVector<llvm::Value *, 16> CallArgs;
2503*67e74705SXin Li CallArgs.push_back(PrivatesPtr);
2504*67e74705SXin Li for (auto *E : Data.PrivateVars) {
2505*67e74705SXin Li auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
2506*67e74705SXin Li Address PrivatePtr = CGF.CreateMemTemp(
2507*67e74705SXin Li CGF.getContext().getPointerType(E->getType()), ".priv.ptr.addr");
2508*67e74705SXin Li PrivatePtrs.push_back(std::make_pair(VD, PrivatePtr));
2509*67e74705SXin Li CallArgs.push_back(PrivatePtr.getPointer());
2510*67e74705SXin Li }
2511*67e74705SXin Li for (auto *E : Data.FirstprivateVars) {
2512*67e74705SXin Li auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
2513*67e74705SXin Li Address PrivatePtr =
2514*67e74705SXin Li CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()),
2515*67e74705SXin Li ".firstpriv.ptr.addr");
2516*67e74705SXin Li PrivatePtrs.push_back(std::make_pair(VD, PrivatePtr));
2517*67e74705SXin Li CallArgs.push_back(PrivatePtr.getPointer());
2518*67e74705SXin Li }
2519*67e74705SXin Li for (auto *E : Data.LastprivateVars) {
2520*67e74705SXin Li auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
2521*67e74705SXin Li Address PrivatePtr =
2522*67e74705SXin Li CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()),
2523*67e74705SXin Li ".lastpriv.ptr.addr");
2524*67e74705SXin Li PrivatePtrs.push_back(std::make_pair(VD, PrivatePtr));
2525*67e74705SXin Li CallArgs.push_back(PrivatePtr.getPointer());
2526*67e74705SXin Li }
2527*67e74705SXin Li CGF.EmitRuntimeCall(CopyFn, CallArgs);
2528*67e74705SXin Li for (auto &&Pair : LastprivateDstsOrigs) {
2529*67e74705SXin Li auto *OrigVD = cast<VarDecl>(Pair.second->getDecl());
2530*67e74705SXin Li DeclRefExpr DRE(
2531*67e74705SXin Li const_cast<VarDecl *>(OrigVD),
2532*67e74705SXin Li /*RefersToEnclosingVariableOrCapture=*/CGF.CapturedStmtInfo->lookup(
2533*67e74705SXin Li OrigVD) != nullptr,
2534*67e74705SXin Li Pair.second->getType(), VK_LValue, Pair.second->getExprLoc());
2535*67e74705SXin Li Scope.addPrivate(Pair.first, [&CGF, &DRE]() {
2536*67e74705SXin Li return CGF.EmitLValue(&DRE).getAddress();
2537*67e74705SXin Li });
2538*67e74705SXin Li }
2539*67e74705SXin Li for (auto &&Pair : PrivatePtrs) {
2540*67e74705SXin Li Address Replacement(CGF.Builder.CreateLoad(Pair.second),
2541*67e74705SXin Li CGF.getContext().getDeclAlign(Pair.first));
2542*67e74705SXin Li Scope.addPrivate(Pair.first, [Replacement]() { return Replacement; });
2543*67e74705SXin Li }
2544*67e74705SXin Li }
2545*67e74705SXin Li (void)Scope.Privatize();
2546*67e74705SXin Li
2547*67e74705SXin Li Action.Enter(CGF);
2548*67e74705SXin Li BodyGen(CGF);
2549*67e74705SXin Li };
2550*67e74705SXin Li auto *OutlinedFn = CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
2551*67e74705SXin Li S, *I, *PartId, *TaskT, S.getDirectiveKind(), CodeGen, Data.Tied,
2552*67e74705SXin Li Data.NumberOfParts);
2553*67e74705SXin Li OMPLexicalScope Scope(*this, S);
2554*67e74705SXin Li TaskGen(*this, OutlinedFn, Data);
2555*67e74705SXin Li }
2556*67e74705SXin Li
EmitOMPTaskDirective(const OMPTaskDirective & S)2557*67e74705SXin Li void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &S) {
2558*67e74705SXin Li // Emit outlined function for task construct.
2559*67e74705SXin Li auto CS = cast<CapturedStmt>(S.getAssociatedStmt());
2560*67e74705SXin Li auto CapturedStruct = GenerateCapturedStmtArgument(*CS);
2561*67e74705SXin Li auto SharedsTy = getContext().getRecordType(CS->getCapturedRecordDecl());
2562*67e74705SXin Li const Expr *IfCond = nullptr;
2563*67e74705SXin Li for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
2564*67e74705SXin Li if (C->getNameModifier() == OMPD_unknown ||
2565*67e74705SXin Li C->getNameModifier() == OMPD_task) {
2566*67e74705SXin Li IfCond = C->getCondition();
2567*67e74705SXin Li break;
2568*67e74705SXin Li }
2569*67e74705SXin Li }
2570*67e74705SXin Li
2571*67e74705SXin Li OMPTaskDataTy Data;
2572*67e74705SXin Li // Check if we should emit tied or untied task.
2573*67e74705SXin Li Data.Tied = !S.getSingleClause<OMPUntiedClause>();
2574*67e74705SXin Li auto &&BodyGen = [CS](CodeGenFunction &CGF, PrePostActionTy &) {
2575*67e74705SXin Li CGF.EmitStmt(CS->getCapturedStmt());
2576*67e74705SXin Li };
2577*67e74705SXin Li auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
2578*67e74705SXin Li IfCond](CodeGenFunction &CGF, llvm::Value *OutlinedFn,
2579*67e74705SXin Li const OMPTaskDataTy &Data) {
2580*67e74705SXin Li CGF.CGM.getOpenMPRuntime().emitTaskCall(CGF, S.getLocStart(), S, OutlinedFn,
2581*67e74705SXin Li SharedsTy, CapturedStruct, IfCond,
2582*67e74705SXin Li Data);
2583*67e74705SXin Li };
2584*67e74705SXin Li EmitOMPTaskBasedDirective(S, BodyGen, TaskGen, Data);
2585*67e74705SXin Li }
2586*67e74705SXin Li
EmitOMPTaskyieldDirective(const OMPTaskyieldDirective & S)2587*67e74705SXin Li void CodeGenFunction::EmitOMPTaskyieldDirective(
2588*67e74705SXin Li const OMPTaskyieldDirective &S) {
2589*67e74705SXin Li CGM.getOpenMPRuntime().emitTaskyieldCall(*this, S.getLocStart());
2590*67e74705SXin Li }
2591*67e74705SXin Li
EmitOMPBarrierDirective(const OMPBarrierDirective & S)2592*67e74705SXin Li void CodeGenFunction::EmitOMPBarrierDirective(const OMPBarrierDirective &S) {
2593*67e74705SXin Li CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), OMPD_barrier);
2594*67e74705SXin Li }
2595*67e74705SXin Li
EmitOMPTaskwaitDirective(const OMPTaskwaitDirective & S)2596*67e74705SXin Li void CodeGenFunction::EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S) {
2597*67e74705SXin Li CGM.getOpenMPRuntime().emitTaskwaitCall(*this, S.getLocStart());
2598*67e74705SXin Li }
2599*67e74705SXin Li
EmitOMPTaskgroupDirective(const OMPTaskgroupDirective & S)2600*67e74705SXin Li void CodeGenFunction::EmitOMPTaskgroupDirective(
2601*67e74705SXin Li const OMPTaskgroupDirective &S) {
2602*67e74705SXin Li auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
2603*67e74705SXin Li Action.Enter(CGF);
2604*67e74705SXin Li CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
2605*67e74705SXin Li };
2606*67e74705SXin Li OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
2607*67e74705SXin Li CGM.getOpenMPRuntime().emitTaskgroupRegion(*this, CodeGen, S.getLocStart());
2608*67e74705SXin Li }
2609*67e74705SXin Li
EmitOMPFlushDirective(const OMPFlushDirective & S)2610*67e74705SXin Li void CodeGenFunction::EmitOMPFlushDirective(const OMPFlushDirective &S) {
2611*67e74705SXin Li CGM.getOpenMPRuntime().emitFlush(*this, [&]() -> ArrayRef<const Expr *> {
2612*67e74705SXin Li if (const auto *FlushClause = S.getSingleClause<OMPFlushClause>()) {
2613*67e74705SXin Li return llvm::makeArrayRef(FlushClause->varlist_begin(),
2614*67e74705SXin Li FlushClause->varlist_end());
2615*67e74705SXin Li }
2616*67e74705SXin Li return llvm::None;
2617*67e74705SXin Li }(), S.getLocStart());
2618*67e74705SXin Li }
2619*67e74705SXin Li
EmitOMPDistributeLoop(const OMPDistributeDirective & S)2620*67e74705SXin Li void CodeGenFunction::EmitOMPDistributeLoop(const OMPDistributeDirective &S) {
2621*67e74705SXin Li // Emit the loop iteration variable.
2622*67e74705SXin Li auto IVExpr = cast<DeclRefExpr>(S.getIterationVariable());
2623*67e74705SXin Li auto IVDecl = cast<VarDecl>(IVExpr->getDecl());
2624*67e74705SXin Li EmitVarDecl(*IVDecl);
2625*67e74705SXin Li
2626*67e74705SXin Li // Emit the iterations count variable.
2627*67e74705SXin Li // If it is not a variable, Sema decided to calculate iterations count on each
2628*67e74705SXin Li // iteration (e.g., it is foldable into a constant).
2629*67e74705SXin Li if (auto LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
2630*67e74705SXin Li EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
2631*67e74705SXin Li // Emit calculation of the iterations count.
2632*67e74705SXin Li EmitIgnoredExpr(S.getCalcLastIteration());
2633*67e74705SXin Li }
2634*67e74705SXin Li
2635*67e74705SXin Li auto &RT = CGM.getOpenMPRuntime();
2636*67e74705SXin Li
2637*67e74705SXin Li // Check pre-condition.
2638*67e74705SXin Li {
2639*67e74705SXin Li OMPLoopScope PreInitScope(*this, S);
2640*67e74705SXin Li // Skip the entire loop if we don't meet the precondition.
2641*67e74705SXin Li // If the condition constant folds and can be elided, avoid emitting the
2642*67e74705SXin Li // whole loop.
2643*67e74705SXin Li bool CondConstant;
2644*67e74705SXin Li llvm::BasicBlock *ContBlock = nullptr;
2645*67e74705SXin Li if (ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
2646*67e74705SXin Li if (!CondConstant)
2647*67e74705SXin Li return;
2648*67e74705SXin Li } else {
2649*67e74705SXin Li auto *ThenBlock = createBasicBlock("omp.precond.then");
2650*67e74705SXin Li ContBlock = createBasicBlock("omp.precond.end");
2651*67e74705SXin Li emitPreCond(*this, S, S.getPreCond(), ThenBlock, ContBlock,
2652*67e74705SXin Li getProfileCount(&S));
2653*67e74705SXin Li EmitBlock(ThenBlock);
2654*67e74705SXin Li incrementProfileCounter(&S);
2655*67e74705SXin Li }
2656*67e74705SXin Li
2657*67e74705SXin Li // Emit 'then' code.
2658*67e74705SXin Li {
2659*67e74705SXin Li // Emit helper vars inits.
2660*67e74705SXin Li LValue LB =
2661*67e74705SXin Li EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getLowerBoundVariable()));
2662*67e74705SXin Li LValue UB =
2663*67e74705SXin Li EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getUpperBoundVariable()));
2664*67e74705SXin Li LValue ST =
2665*67e74705SXin Li EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getStrideVariable()));
2666*67e74705SXin Li LValue IL =
2667*67e74705SXin Li EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getIsLastIterVariable()));
2668*67e74705SXin Li
2669*67e74705SXin Li OMPPrivateScope LoopScope(*this);
2670*67e74705SXin Li EmitOMPPrivateLoopCounters(S, LoopScope);
2671*67e74705SXin Li (void)LoopScope.Privatize();
2672*67e74705SXin Li
2673*67e74705SXin Li // Detect the distribute schedule kind and chunk.
2674*67e74705SXin Li llvm::Value *Chunk = nullptr;
2675*67e74705SXin Li OpenMPDistScheduleClauseKind ScheduleKind = OMPC_DIST_SCHEDULE_unknown;
2676*67e74705SXin Li if (auto *C = S.getSingleClause<OMPDistScheduleClause>()) {
2677*67e74705SXin Li ScheduleKind = C->getDistScheduleKind();
2678*67e74705SXin Li if (const auto *Ch = C->getChunkSize()) {
2679*67e74705SXin Li Chunk = EmitScalarExpr(Ch);
2680*67e74705SXin Li Chunk = EmitScalarConversion(Chunk, Ch->getType(),
2681*67e74705SXin Li S.getIterationVariable()->getType(),
2682*67e74705SXin Li S.getLocStart());
2683*67e74705SXin Li }
2684*67e74705SXin Li }
2685*67e74705SXin Li const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
2686*67e74705SXin Li const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
2687*67e74705SXin Li
2688*67e74705SXin Li // OpenMP [2.10.8, distribute Construct, Description]
2689*67e74705SXin Li // If dist_schedule is specified, kind must be static. If specified,
2690*67e74705SXin Li // iterations are divided into chunks of size chunk_size, chunks are
2691*67e74705SXin Li // assigned to the teams of the league in a round-robin fashion in the
2692*67e74705SXin Li // order of the team number. When no chunk_size is specified, the
2693*67e74705SXin Li // iteration space is divided into chunks that are approximately equal
2694*67e74705SXin Li // in size, and at most one chunk is distributed to each team of the
2695*67e74705SXin Li // league. The size of the chunks is unspecified in this case.
2696*67e74705SXin Li if (RT.isStaticNonchunked(ScheduleKind,
2697*67e74705SXin Li /* Chunked */ Chunk != nullptr)) {
2698*67e74705SXin Li RT.emitDistributeStaticInit(*this, S.getLocStart(), ScheduleKind,
2699*67e74705SXin Li IVSize, IVSigned, /* Ordered = */ false,
2700*67e74705SXin Li IL.getAddress(), LB.getAddress(),
2701*67e74705SXin Li UB.getAddress(), ST.getAddress());
2702*67e74705SXin Li auto LoopExit =
2703*67e74705SXin Li getJumpDestInCurrentScope(createBasicBlock("omp.loop.exit"));
2704*67e74705SXin Li // UB = min(UB, GlobalUB);
2705*67e74705SXin Li EmitIgnoredExpr(S.getEnsureUpperBound());
2706*67e74705SXin Li // IV = LB;
2707*67e74705SXin Li EmitIgnoredExpr(S.getInit());
2708*67e74705SXin Li // while (idx <= UB) { BODY; ++idx; }
2709*67e74705SXin Li EmitOMPInnerLoop(S, LoopScope.requiresCleanups(), S.getCond(),
2710*67e74705SXin Li S.getInc(),
2711*67e74705SXin Li [&S, LoopExit](CodeGenFunction &CGF) {
2712*67e74705SXin Li CGF.EmitOMPLoopBody(S, LoopExit);
2713*67e74705SXin Li CGF.EmitStopPoint(&S);
2714*67e74705SXin Li },
2715*67e74705SXin Li [](CodeGenFunction &) {});
2716*67e74705SXin Li EmitBlock(LoopExit.getBlock());
2717*67e74705SXin Li // Tell the runtime we are done.
2718*67e74705SXin Li RT.emitForStaticFinish(*this, S.getLocStart());
2719*67e74705SXin Li } else {
2720*67e74705SXin Li // Emit the outer loop, which requests its work chunk [LB..UB] from
2721*67e74705SXin Li // runtime and runs the inner loop to process it.
2722*67e74705SXin Li EmitOMPDistributeOuterLoop(ScheduleKind, S, LoopScope,
2723*67e74705SXin Li LB.getAddress(), UB.getAddress(), ST.getAddress(),
2724*67e74705SXin Li IL.getAddress(), Chunk);
2725*67e74705SXin Li }
2726*67e74705SXin Li }
2727*67e74705SXin Li
2728*67e74705SXin Li // We're now done with the loop, so jump to the continuation block.
2729*67e74705SXin Li if (ContBlock) {
2730*67e74705SXin Li EmitBranch(ContBlock);
2731*67e74705SXin Li EmitBlock(ContBlock, true);
2732*67e74705SXin Li }
2733*67e74705SXin Li }
2734*67e74705SXin Li }
2735*67e74705SXin Li
EmitOMPDistributeDirective(const OMPDistributeDirective & S)2736*67e74705SXin Li void CodeGenFunction::EmitOMPDistributeDirective(
2737*67e74705SXin Li const OMPDistributeDirective &S) {
2738*67e74705SXin Li auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
2739*67e74705SXin Li CGF.EmitOMPDistributeLoop(S);
2740*67e74705SXin Li };
2741*67e74705SXin Li OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
2742*67e74705SXin Li CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_distribute, CodeGen,
2743*67e74705SXin Li false);
2744*67e74705SXin Li }
2745*67e74705SXin Li
emitOutlinedOrderedFunction(CodeGenModule & CGM,const CapturedStmt * S)2746*67e74705SXin Li static llvm::Function *emitOutlinedOrderedFunction(CodeGenModule &CGM,
2747*67e74705SXin Li const CapturedStmt *S) {
2748*67e74705SXin Li CodeGenFunction CGF(CGM, /*suppressNewContext=*/true);
2749*67e74705SXin Li CodeGenFunction::CGCapturedStmtInfo CapStmtInfo;
2750*67e74705SXin Li CGF.CapturedStmtInfo = &CapStmtInfo;
2751*67e74705SXin Li auto *Fn = CGF.GenerateOpenMPCapturedStmtFunction(*S);
2752*67e74705SXin Li Fn->addFnAttr(llvm::Attribute::NoInline);
2753*67e74705SXin Li return Fn;
2754*67e74705SXin Li }
2755*67e74705SXin Li
EmitOMPOrderedDirective(const OMPOrderedDirective & S)2756*67e74705SXin Li void CodeGenFunction::EmitOMPOrderedDirective(const OMPOrderedDirective &S) {
2757*67e74705SXin Li if (!S.getAssociatedStmt()) {
2758*67e74705SXin Li for (const auto *DC : S.getClausesOfKind<OMPDependClause>())
2759*67e74705SXin Li CGM.getOpenMPRuntime().emitDoacrossOrdered(*this, DC);
2760*67e74705SXin Li return;
2761*67e74705SXin Li }
2762*67e74705SXin Li auto *C = S.getSingleClause<OMPSIMDClause>();
2763*67e74705SXin Li auto &&CodeGen = [&S, C, this](CodeGenFunction &CGF,
2764*67e74705SXin Li PrePostActionTy &Action) {
2765*67e74705SXin Li if (C) {
2766*67e74705SXin Li auto CS = cast<CapturedStmt>(S.getAssociatedStmt());
2767*67e74705SXin Li llvm::SmallVector<llvm::Value *, 16> CapturedVars;
2768*67e74705SXin Li CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
2769*67e74705SXin Li auto *OutlinedFn = emitOutlinedOrderedFunction(CGM, CS);
2770*67e74705SXin Li CGF.EmitNounwindRuntimeCall(OutlinedFn, CapturedVars);
2771*67e74705SXin Li } else {
2772*67e74705SXin Li Action.Enter(CGF);
2773*67e74705SXin Li CGF.EmitStmt(
2774*67e74705SXin Li cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
2775*67e74705SXin Li }
2776*67e74705SXin Li };
2777*67e74705SXin Li OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
2778*67e74705SXin Li CGM.getOpenMPRuntime().emitOrderedRegion(*this, CodeGen, S.getLocStart(), !C);
2779*67e74705SXin Li }
2780*67e74705SXin Li
convertToScalarValue(CodeGenFunction & CGF,RValue Val,QualType SrcType,QualType DestType,SourceLocation Loc)2781*67e74705SXin Li static llvm::Value *convertToScalarValue(CodeGenFunction &CGF, RValue Val,
2782*67e74705SXin Li QualType SrcType, QualType DestType,
2783*67e74705SXin Li SourceLocation Loc) {
2784*67e74705SXin Li assert(CGF.hasScalarEvaluationKind(DestType) &&
2785*67e74705SXin Li "DestType must have scalar evaluation kind.");
2786*67e74705SXin Li assert(!Val.isAggregate() && "Must be a scalar or complex.");
2787*67e74705SXin Li return Val.isScalar()
2788*67e74705SXin Li ? CGF.EmitScalarConversion(Val.getScalarVal(), SrcType, DestType,
2789*67e74705SXin Li Loc)
2790*67e74705SXin Li : CGF.EmitComplexToScalarConversion(Val.getComplexVal(), SrcType,
2791*67e74705SXin Li DestType, Loc);
2792*67e74705SXin Li }
2793*67e74705SXin Li
2794*67e74705SXin Li static CodeGenFunction::ComplexPairTy
convertToComplexValue(CodeGenFunction & CGF,RValue Val,QualType SrcType,QualType DestType,SourceLocation Loc)2795*67e74705SXin Li convertToComplexValue(CodeGenFunction &CGF, RValue Val, QualType SrcType,
2796*67e74705SXin Li QualType DestType, SourceLocation Loc) {
2797*67e74705SXin Li assert(CGF.getEvaluationKind(DestType) == TEK_Complex &&
2798*67e74705SXin Li "DestType must have complex evaluation kind.");
2799*67e74705SXin Li CodeGenFunction::ComplexPairTy ComplexVal;
2800*67e74705SXin Li if (Val.isScalar()) {
2801*67e74705SXin Li // Convert the input element to the element type of the complex.
2802*67e74705SXin Li auto DestElementType = DestType->castAs<ComplexType>()->getElementType();
2803*67e74705SXin Li auto ScalarVal = CGF.EmitScalarConversion(Val.getScalarVal(), SrcType,
2804*67e74705SXin Li DestElementType, Loc);
2805*67e74705SXin Li ComplexVal = CodeGenFunction::ComplexPairTy(
2806*67e74705SXin Li ScalarVal, llvm::Constant::getNullValue(ScalarVal->getType()));
2807*67e74705SXin Li } else {
2808*67e74705SXin Li assert(Val.isComplex() && "Must be a scalar or complex.");
2809*67e74705SXin Li auto SrcElementType = SrcType->castAs<ComplexType>()->getElementType();
2810*67e74705SXin Li auto DestElementType = DestType->castAs<ComplexType>()->getElementType();
2811*67e74705SXin Li ComplexVal.first = CGF.EmitScalarConversion(
2812*67e74705SXin Li Val.getComplexVal().first, SrcElementType, DestElementType, Loc);
2813*67e74705SXin Li ComplexVal.second = CGF.EmitScalarConversion(
2814*67e74705SXin Li Val.getComplexVal().second, SrcElementType, DestElementType, Loc);
2815*67e74705SXin Li }
2816*67e74705SXin Li return ComplexVal;
2817*67e74705SXin Li }
2818*67e74705SXin Li
emitSimpleAtomicStore(CodeGenFunction & CGF,bool IsSeqCst,LValue LVal,RValue RVal)2819*67e74705SXin Li static void emitSimpleAtomicStore(CodeGenFunction &CGF, bool IsSeqCst,
2820*67e74705SXin Li LValue LVal, RValue RVal) {
2821*67e74705SXin Li if (LVal.isGlobalReg()) {
2822*67e74705SXin Li CGF.EmitStoreThroughGlobalRegLValue(RVal, LVal);
2823*67e74705SXin Li } else {
2824*67e74705SXin Li CGF.EmitAtomicStore(RVal, LVal,
2825*67e74705SXin Li IsSeqCst ? llvm::AtomicOrdering::SequentiallyConsistent
2826*67e74705SXin Li : llvm::AtomicOrdering::Monotonic,
2827*67e74705SXin Li LVal.isVolatile(), /*IsInit=*/false);
2828*67e74705SXin Li }
2829*67e74705SXin Li }
2830*67e74705SXin Li
emitOMPSimpleStore(LValue LVal,RValue RVal,QualType RValTy,SourceLocation Loc)2831*67e74705SXin Li void CodeGenFunction::emitOMPSimpleStore(LValue LVal, RValue RVal,
2832*67e74705SXin Li QualType RValTy, SourceLocation Loc) {
2833*67e74705SXin Li switch (getEvaluationKind(LVal.getType())) {
2834*67e74705SXin Li case TEK_Scalar:
2835*67e74705SXin Li EmitStoreThroughLValue(RValue::get(convertToScalarValue(
2836*67e74705SXin Li *this, RVal, RValTy, LVal.getType(), Loc)),
2837*67e74705SXin Li LVal);
2838*67e74705SXin Li break;
2839*67e74705SXin Li case TEK_Complex:
2840*67e74705SXin Li EmitStoreOfComplex(
2841*67e74705SXin Li convertToComplexValue(*this, RVal, RValTy, LVal.getType(), Loc), LVal,
2842*67e74705SXin Li /*isInit=*/false);
2843*67e74705SXin Li break;
2844*67e74705SXin Li case TEK_Aggregate:
2845*67e74705SXin Li llvm_unreachable("Must be a scalar or complex.");
2846*67e74705SXin Li }
2847*67e74705SXin Li }
2848*67e74705SXin Li
EmitOMPAtomicReadExpr(CodeGenFunction & CGF,bool IsSeqCst,const Expr * X,const Expr * V,SourceLocation Loc)2849*67e74705SXin Li static void EmitOMPAtomicReadExpr(CodeGenFunction &CGF, bool IsSeqCst,
2850*67e74705SXin Li const Expr *X, const Expr *V,
2851*67e74705SXin Li SourceLocation Loc) {
2852*67e74705SXin Li // v = x;
2853*67e74705SXin Li assert(V->isLValue() && "V of 'omp atomic read' is not lvalue");
2854*67e74705SXin Li assert(X->isLValue() && "X of 'omp atomic read' is not lvalue");
2855*67e74705SXin Li LValue XLValue = CGF.EmitLValue(X);
2856*67e74705SXin Li LValue VLValue = CGF.EmitLValue(V);
2857*67e74705SXin Li RValue Res = XLValue.isGlobalReg()
2858*67e74705SXin Li ? CGF.EmitLoadOfLValue(XLValue, Loc)
2859*67e74705SXin Li : CGF.EmitAtomicLoad(
2860*67e74705SXin Li XLValue, Loc,
2861*67e74705SXin Li IsSeqCst ? llvm::AtomicOrdering::SequentiallyConsistent
2862*67e74705SXin Li : llvm::AtomicOrdering::Monotonic,
2863*67e74705SXin Li XLValue.isVolatile());
2864*67e74705SXin Li // OpenMP, 2.12.6, atomic Construct
2865*67e74705SXin Li // Any atomic construct with a seq_cst clause forces the atomically
2866*67e74705SXin Li // performed operation to include an implicit flush operation without a
2867*67e74705SXin Li // list.
2868*67e74705SXin Li if (IsSeqCst)
2869*67e74705SXin Li CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc);
2870*67e74705SXin Li CGF.emitOMPSimpleStore(VLValue, Res, X->getType().getNonReferenceType(), Loc);
2871*67e74705SXin Li }
2872*67e74705SXin Li
EmitOMPAtomicWriteExpr(CodeGenFunction & CGF,bool IsSeqCst,const Expr * X,const Expr * E,SourceLocation Loc)2873*67e74705SXin Li static void EmitOMPAtomicWriteExpr(CodeGenFunction &CGF, bool IsSeqCst,
2874*67e74705SXin Li const Expr *X, const Expr *E,
2875*67e74705SXin Li SourceLocation Loc) {
2876*67e74705SXin Li // x = expr;
2877*67e74705SXin Li assert(X->isLValue() && "X of 'omp atomic write' is not lvalue");
2878*67e74705SXin Li emitSimpleAtomicStore(CGF, IsSeqCst, CGF.EmitLValue(X), CGF.EmitAnyExpr(E));
2879*67e74705SXin Li // OpenMP, 2.12.6, atomic Construct
2880*67e74705SXin Li // Any atomic construct with a seq_cst clause forces the atomically
2881*67e74705SXin Li // performed operation to include an implicit flush operation without a
2882*67e74705SXin Li // list.
2883*67e74705SXin Li if (IsSeqCst)
2884*67e74705SXin Li CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc);
2885*67e74705SXin Li }
2886*67e74705SXin Li
emitOMPAtomicRMW(CodeGenFunction & CGF,LValue X,RValue Update,BinaryOperatorKind BO,llvm::AtomicOrdering AO,bool IsXLHSInRHSPart)2887*67e74705SXin Li static std::pair<bool, RValue> emitOMPAtomicRMW(CodeGenFunction &CGF, LValue X,
2888*67e74705SXin Li RValue Update,
2889*67e74705SXin Li BinaryOperatorKind BO,
2890*67e74705SXin Li llvm::AtomicOrdering AO,
2891*67e74705SXin Li bool IsXLHSInRHSPart) {
2892*67e74705SXin Li auto &Context = CGF.CGM.getContext();
2893*67e74705SXin Li // Allow atomicrmw only if 'x' and 'update' are integer values, lvalue for 'x'
2894*67e74705SXin Li // expression is simple and atomic is allowed for the given type for the
2895*67e74705SXin Li // target platform.
2896*67e74705SXin Li if (BO == BO_Comma || !Update.isScalar() ||
2897*67e74705SXin Li !Update.getScalarVal()->getType()->isIntegerTy() ||
2898*67e74705SXin Li !X.isSimple() || (!isa<llvm::ConstantInt>(Update.getScalarVal()) &&
2899*67e74705SXin Li (Update.getScalarVal()->getType() !=
2900*67e74705SXin Li X.getAddress().getElementType())) ||
2901*67e74705SXin Li !X.getAddress().getElementType()->isIntegerTy() ||
2902*67e74705SXin Li !Context.getTargetInfo().hasBuiltinAtomic(
2903*67e74705SXin Li Context.getTypeSize(X.getType()), Context.toBits(X.getAlignment())))
2904*67e74705SXin Li return std::make_pair(false, RValue::get(nullptr));
2905*67e74705SXin Li
2906*67e74705SXin Li llvm::AtomicRMWInst::BinOp RMWOp;
2907*67e74705SXin Li switch (BO) {
2908*67e74705SXin Li case BO_Add:
2909*67e74705SXin Li RMWOp = llvm::AtomicRMWInst::Add;
2910*67e74705SXin Li break;
2911*67e74705SXin Li case BO_Sub:
2912*67e74705SXin Li if (!IsXLHSInRHSPart)
2913*67e74705SXin Li return std::make_pair(false, RValue::get(nullptr));
2914*67e74705SXin Li RMWOp = llvm::AtomicRMWInst::Sub;
2915*67e74705SXin Li break;
2916*67e74705SXin Li case BO_And:
2917*67e74705SXin Li RMWOp = llvm::AtomicRMWInst::And;
2918*67e74705SXin Li break;
2919*67e74705SXin Li case BO_Or:
2920*67e74705SXin Li RMWOp = llvm::AtomicRMWInst::Or;
2921*67e74705SXin Li break;
2922*67e74705SXin Li case BO_Xor:
2923*67e74705SXin Li RMWOp = llvm::AtomicRMWInst::Xor;
2924*67e74705SXin Li break;
2925*67e74705SXin Li case BO_LT:
2926*67e74705SXin Li RMWOp = X.getType()->hasSignedIntegerRepresentation()
2927*67e74705SXin Li ? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Min
2928*67e74705SXin Li : llvm::AtomicRMWInst::Max)
2929*67e74705SXin Li : (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMin
2930*67e74705SXin Li : llvm::AtomicRMWInst::UMax);
2931*67e74705SXin Li break;
2932*67e74705SXin Li case BO_GT:
2933*67e74705SXin Li RMWOp = X.getType()->hasSignedIntegerRepresentation()
2934*67e74705SXin Li ? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Max
2935*67e74705SXin Li : llvm::AtomicRMWInst::Min)
2936*67e74705SXin Li : (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMax
2937*67e74705SXin Li : llvm::AtomicRMWInst::UMin);
2938*67e74705SXin Li break;
2939*67e74705SXin Li case BO_Assign:
2940*67e74705SXin Li RMWOp = llvm::AtomicRMWInst::Xchg;
2941*67e74705SXin Li break;
2942*67e74705SXin Li case BO_Mul:
2943*67e74705SXin Li case BO_Div:
2944*67e74705SXin Li case BO_Rem:
2945*67e74705SXin Li case BO_Shl:
2946*67e74705SXin Li case BO_Shr:
2947*67e74705SXin Li case BO_LAnd:
2948*67e74705SXin Li case BO_LOr:
2949*67e74705SXin Li return std::make_pair(false, RValue::get(nullptr));
2950*67e74705SXin Li case BO_PtrMemD:
2951*67e74705SXin Li case BO_PtrMemI:
2952*67e74705SXin Li case BO_LE:
2953*67e74705SXin Li case BO_GE:
2954*67e74705SXin Li case BO_EQ:
2955*67e74705SXin Li case BO_NE:
2956*67e74705SXin Li case BO_AddAssign:
2957*67e74705SXin Li case BO_SubAssign:
2958*67e74705SXin Li case BO_AndAssign:
2959*67e74705SXin Li case BO_OrAssign:
2960*67e74705SXin Li case BO_XorAssign:
2961*67e74705SXin Li case BO_MulAssign:
2962*67e74705SXin Li case BO_DivAssign:
2963*67e74705SXin Li case BO_RemAssign:
2964*67e74705SXin Li case BO_ShlAssign:
2965*67e74705SXin Li case BO_ShrAssign:
2966*67e74705SXin Li case BO_Comma:
2967*67e74705SXin Li llvm_unreachable("Unsupported atomic update operation");
2968*67e74705SXin Li }
2969*67e74705SXin Li auto *UpdateVal = Update.getScalarVal();
2970*67e74705SXin Li if (auto *IC = dyn_cast<llvm::ConstantInt>(UpdateVal)) {
2971*67e74705SXin Li UpdateVal = CGF.Builder.CreateIntCast(
2972*67e74705SXin Li IC, X.getAddress().getElementType(),
2973*67e74705SXin Li X.getType()->hasSignedIntegerRepresentation());
2974*67e74705SXin Li }
2975*67e74705SXin Li auto *Res = CGF.Builder.CreateAtomicRMW(RMWOp, X.getPointer(), UpdateVal, AO);
2976*67e74705SXin Li return std::make_pair(true, RValue::get(Res));
2977*67e74705SXin Li }
2978*67e74705SXin Li
EmitOMPAtomicSimpleUpdateExpr(LValue X,RValue E,BinaryOperatorKind BO,bool IsXLHSInRHSPart,llvm::AtomicOrdering AO,SourceLocation Loc,const llvm::function_ref<RValue (RValue)> & CommonGen)2979*67e74705SXin Li std::pair<bool, RValue> CodeGenFunction::EmitOMPAtomicSimpleUpdateExpr(
2980*67e74705SXin Li LValue X, RValue E, BinaryOperatorKind BO, bool IsXLHSInRHSPart,
2981*67e74705SXin Li llvm::AtomicOrdering AO, SourceLocation Loc,
2982*67e74705SXin Li const llvm::function_ref<RValue(RValue)> &CommonGen) {
2983*67e74705SXin Li // Update expressions are allowed to have the following forms:
2984*67e74705SXin Li // x binop= expr; -> xrval + expr;
2985*67e74705SXin Li // x++, ++x -> xrval + 1;
2986*67e74705SXin Li // x--, --x -> xrval - 1;
2987*67e74705SXin Li // x = x binop expr; -> xrval binop expr
2988*67e74705SXin Li // x = expr Op x; - > expr binop xrval;
2989*67e74705SXin Li auto Res = emitOMPAtomicRMW(*this, X, E, BO, AO, IsXLHSInRHSPart);
2990*67e74705SXin Li if (!Res.first) {
2991*67e74705SXin Li if (X.isGlobalReg()) {
2992*67e74705SXin Li // Emit an update expression: 'xrval' binop 'expr' or 'expr' binop
2993*67e74705SXin Li // 'xrval'.
2994*67e74705SXin Li EmitStoreThroughLValue(CommonGen(EmitLoadOfLValue(X, Loc)), X);
2995*67e74705SXin Li } else {
2996*67e74705SXin Li // Perform compare-and-swap procedure.
2997*67e74705SXin Li EmitAtomicUpdate(X, AO, CommonGen, X.getType().isVolatileQualified());
2998*67e74705SXin Li }
2999*67e74705SXin Li }
3000*67e74705SXin Li return Res;
3001*67e74705SXin Li }
3002*67e74705SXin Li
EmitOMPAtomicUpdateExpr(CodeGenFunction & CGF,bool IsSeqCst,const Expr * X,const Expr * E,const Expr * UE,bool IsXLHSInRHSPart,SourceLocation Loc)3003*67e74705SXin Li static void EmitOMPAtomicUpdateExpr(CodeGenFunction &CGF, bool IsSeqCst,
3004*67e74705SXin Li const Expr *X, const Expr *E,
3005*67e74705SXin Li const Expr *UE, bool IsXLHSInRHSPart,
3006*67e74705SXin Li SourceLocation Loc) {
3007*67e74705SXin Li assert(isa<BinaryOperator>(UE->IgnoreImpCasts()) &&
3008*67e74705SXin Li "Update expr in 'atomic update' must be a binary operator.");
3009*67e74705SXin Li auto *BOUE = cast<BinaryOperator>(UE->IgnoreImpCasts());
3010*67e74705SXin Li // Update expressions are allowed to have the following forms:
3011*67e74705SXin Li // x binop= expr; -> xrval + expr;
3012*67e74705SXin Li // x++, ++x -> xrval + 1;
3013*67e74705SXin Li // x--, --x -> xrval - 1;
3014*67e74705SXin Li // x = x binop expr; -> xrval binop expr
3015*67e74705SXin Li // x = expr Op x; - > expr binop xrval;
3016*67e74705SXin Li assert(X->isLValue() && "X of 'omp atomic update' is not lvalue");
3017*67e74705SXin Li LValue XLValue = CGF.EmitLValue(X);
3018*67e74705SXin Li RValue ExprRValue = CGF.EmitAnyExpr(E);
3019*67e74705SXin Li auto AO = IsSeqCst ? llvm::AtomicOrdering::SequentiallyConsistent
3020*67e74705SXin Li : llvm::AtomicOrdering::Monotonic;
3021*67e74705SXin Li auto *LHS = cast<OpaqueValueExpr>(BOUE->getLHS()->IgnoreImpCasts());
3022*67e74705SXin Li auto *RHS = cast<OpaqueValueExpr>(BOUE->getRHS()->IgnoreImpCasts());
3023*67e74705SXin Li auto *XRValExpr = IsXLHSInRHSPart ? LHS : RHS;
3024*67e74705SXin Li auto *ERValExpr = IsXLHSInRHSPart ? RHS : LHS;
3025*67e74705SXin Li auto Gen =
3026*67e74705SXin Li [&CGF, UE, ExprRValue, XRValExpr, ERValExpr](RValue XRValue) -> RValue {
3027*67e74705SXin Li CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue);
3028*67e74705SXin Li CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, XRValue);
3029*67e74705SXin Li return CGF.EmitAnyExpr(UE);
3030*67e74705SXin Li };
3031*67e74705SXin Li (void)CGF.EmitOMPAtomicSimpleUpdateExpr(
3032*67e74705SXin Li XLValue, ExprRValue, BOUE->getOpcode(), IsXLHSInRHSPart, AO, Loc, Gen);
3033*67e74705SXin Li // OpenMP, 2.12.6, atomic Construct
3034*67e74705SXin Li // Any atomic construct with a seq_cst clause forces the atomically
3035*67e74705SXin Li // performed operation to include an implicit flush operation without a
3036*67e74705SXin Li // list.
3037*67e74705SXin Li if (IsSeqCst)
3038*67e74705SXin Li CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc);
3039*67e74705SXin Li }
3040*67e74705SXin Li
convertToType(CodeGenFunction & CGF,RValue Value,QualType SourceType,QualType ResType,SourceLocation Loc)3041*67e74705SXin Li static RValue convertToType(CodeGenFunction &CGF, RValue Value,
3042*67e74705SXin Li QualType SourceType, QualType ResType,
3043*67e74705SXin Li SourceLocation Loc) {
3044*67e74705SXin Li switch (CGF.getEvaluationKind(ResType)) {
3045*67e74705SXin Li case TEK_Scalar:
3046*67e74705SXin Li return RValue::get(
3047*67e74705SXin Li convertToScalarValue(CGF, Value, SourceType, ResType, Loc));
3048*67e74705SXin Li case TEK_Complex: {
3049*67e74705SXin Li auto Res = convertToComplexValue(CGF, Value, SourceType, ResType, Loc);
3050*67e74705SXin Li return RValue::getComplex(Res.first, Res.second);
3051*67e74705SXin Li }
3052*67e74705SXin Li case TEK_Aggregate:
3053*67e74705SXin Li break;
3054*67e74705SXin Li }
3055*67e74705SXin Li llvm_unreachable("Must be a scalar or complex.");
3056*67e74705SXin Li }
3057*67e74705SXin Li
EmitOMPAtomicCaptureExpr(CodeGenFunction & CGF,bool IsSeqCst,bool IsPostfixUpdate,const Expr * V,const Expr * X,const Expr * E,const Expr * UE,bool IsXLHSInRHSPart,SourceLocation Loc)3058*67e74705SXin Li static void EmitOMPAtomicCaptureExpr(CodeGenFunction &CGF, bool IsSeqCst,
3059*67e74705SXin Li bool IsPostfixUpdate, const Expr *V,
3060*67e74705SXin Li const Expr *X, const Expr *E,
3061*67e74705SXin Li const Expr *UE, bool IsXLHSInRHSPart,
3062*67e74705SXin Li SourceLocation Loc) {
3063*67e74705SXin Li assert(X->isLValue() && "X of 'omp atomic capture' is not lvalue");
3064*67e74705SXin Li assert(V->isLValue() && "V of 'omp atomic capture' is not lvalue");
3065*67e74705SXin Li RValue NewVVal;
3066*67e74705SXin Li LValue VLValue = CGF.EmitLValue(V);
3067*67e74705SXin Li LValue XLValue = CGF.EmitLValue(X);
3068*67e74705SXin Li RValue ExprRValue = CGF.EmitAnyExpr(E);
3069*67e74705SXin Li auto AO = IsSeqCst ? llvm::AtomicOrdering::SequentiallyConsistent
3070*67e74705SXin Li : llvm::AtomicOrdering::Monotonic;
3071*67e74705SXin Li QualType NewVValType;
3072*67e74705SXin Li if (UE) {
3073*67e74705SXin Li // 'x' is updated with some additional value.
3074*67e74705SXin Li assert(isa<BinaryOperator>(UE->IgnoreImpCasts()) &&
3075*67e74705SXin Li "Update expr in 'atomic capture' must be a binary operator.");
3076*67e74705SXin Li auto *BOUE = cast<BinaryOperator>(UE->IgnoreImpCasts());
3077*67e74705SXin Li // Update expressions are allowed to have the following forms:
3078*67e74705SXin Li // x binop= expr; -> xrval + expr;
3079*67e74705SXin Li // x++, ++x -> xrval + 1;
3080*67e74705SXin Li // x--, --x -> xrval - 1;
3081*67e74705SXin Li // x = x binop expr; -> xrval binop expr
3082*67e74705SXin Li // x = expr Op x; - > expr binop xrval;
3083*67e74705SXin Li auto *LHS = cast<OpaqueValueExpr>(BOUE->getLHS()->IgnoreImpCasts());
3084*67e74705SXin Li auto *RHS = cast<OpaqueValueExpr>(BOUE->getRHS()->IgnoreImpCasts());
3085*67e74705SXin Li auto *XRValExpr = IsXLHSInRHSPart ? LHS : RHS;
3086*67e74705SXin Li NewVValType = XRValExpr->getType();
3087*67e74705SXin Li auto *ERValExpr = IsXLHSInRHSPart ? RHS : LHS;
3088*67e74705SXin Li auto &&Gen = [&CGF, &NewVVal, UE, ExprRValue, XRValExpr, ERValExpr,
3089*67e74705SXin Li IsSeqCst, IsPostfixUpdate](RValue XRValue) -> RValue {
3090*67e74705SXin Li CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue);
3091*67e74705SXin Li CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, XRValue);
3092*67e74705SXin Li RValue Res = CGF.EmitAnyExpr(UE);
3093*67e74705SXin Li NewVVal = IsPostfixUpdate ? XRValue : Res;
3094*67e74705SXin Li return Res;
3095*67e74705SXin Li };
3096*67e74705SXin Li auto Res = CGF.EmitOMPAtomicSimpleUpdateExpr(
3097*67e74705SXin Li XLValue, ExprRValue, BOUE->getOpcode(), IsXLHSInRHSPart, AO, Loc, Gen);
3098*67e74705SXin Li if (Res.first) {
3099*67e74705SXin Li // 'atomicrmw' instruction was generated.
3100*67e74705SXin Li if (IsPostfixUpdate) {
3101*67e74705SXin Li // Use old value from 'atomicrmw'.
3102*67e74705SXin Li NewVVal = Res.second;
3103*67e74705SXin Li } else {
3104*67e74705SXin Li // 'atomicrmw' does not provide new value, so evaluate it using old
3105*67e74705SXin Li // value of 'x'.
3106*67e74705SXin Li CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue);
3107*67e74705SXin Li CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, Res.second);
3108*67e74705SXin Li NewVVal = CGF.EmitAnyExpr(UE);
3109*67e74705SXin Li }
3110*67e74705SXin Li }
3111*67e74705SXin Li } else {
3112*67e74705SXin Li // 'x' is simply rewritten with some 'expr'.
3113*67e74705SXin Li NewVValType = X->getType().getNonReferenceType();
3114*67e74705SXin Li ExprRValue = convertToType(CGF, ExprRValue, E->getType(),
3115*67e74705SXin Li X->getType().getNonReferenceType(), Loc);
3116*67e74705SXin Li auto &&Gen = [&CGF, &NewVVal, ExprRValue](RValue XRValue) -> RValue {
3117*67e74705SXin Li NewVVal = XRValue;
3118*67e74705SXin Li return ExprRValue;
3119*67e74705SXin Li };
3120*67e74705SXin Li // Try to perform atomicrmw xchg, otherwise simple exchange.
3121*67e74705SXin Li auto Res = CGF.EmitOMPAtomicSimpleUpdateExpr(
3122*67e74705SXin Li XLValue, ExprRValue, /*BO=*/BO_Assign, /*IsXLHSInRHSPart=*/false, AO,
3123*67e74705SXin Li Loc, Gen);
3124*67e74705SXin Li if (Res.first) {
3125*67e74705SXin Li // 'atomicrmw' instruction was generated.
3126*67e74705SXin Li NewVVal = IsPostfixUpdate ? Res.second : ExprRValue;
3127*67e74705SXin Li }
3128*67e74705SXin Li }
3129*67e74705SXin Li // Emit post-update store to 'v' of old/new 'x' value.
3130*67e74705SXin Li CGF.emitOMPSimpleStore(VLValue, NewVVal, NewVValType, Loc);
3131*67e74705SXin Li // OpenMP, 2.12.6, atomic Construct
3132*67e74705SXin Li // Any atomic construct with a seq_cst clause forces the atomically
3133*67e74705SXin Li // performed operation to include an implicit flush operation without a
3134*67e74705SXin Li // list.
3135*67e74705SXin Li if (IsSeqCst)
3136*67e74705SXin Li CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc);
3137*67e74705SXin Li }
3138*67e74705SXin Li
EmitOMPAtomicExpr(CodeGenFunction & CGF,OpenMPClauseKind Kind,bool IsSeqCst,bool IsPostfixUpdate,const Expr * X,const Expr * V,const Expr * E,const Expr * UE,bool IsXLHSInRHSPart,SourceLocation Loc)3139*67e74705SXin Li static void EmitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
3140*67e74705SXin Li bool IsSeqCst, bool IsPostfixUpdate,
3141*67e74705SXin Li const Expr *X, const Expr *V, const Expr *E,
3142*67e74705SXin Li const Expr *UE, bool IsXLHSInRHSPart,
3143*67e74705SXin Li SourceLocation Loc) {
3144*67e74705SXin Li switch (Kind) {
3145*67e74705SXin Li case OMPC_read:
3146*67e74705SXin Li EmitOMPAtomicReadExpr(CGF, IsSeqCst, X, V, Loc);
3147*67e74705SXin Li break;
3148*67e74705SXin Li case OMPC_write:
3149*67e74705SXin Li EmitOMPAtomicWriteExpr(CGF, IsSeqCst, X, E, Loc);
3150*67e74705SXin Li break;
3151*67e74705SXin Li case OMPC_unknown:
3152*67e74705SXin Li case OMPC_update:
3153*67e74705SXin Li EmitOMPAtomicUpdateExpr(CGF, IsSeqCst, X, E, UE, IsXLHSInRHSPart, Loc);
3154*67e74705SXin Li break;
3155*67e74705SXin Li case OMPC_capture:
3156*67e74705SXin Li EmitOMPAtomicCaptureExpr(CGF, IsSeqCst, IsPostfixUpdate, V, X, E, UE,
3157*67e74705SXin Li IsXLHSInRHSPart, Loc);
3158*67e74705SXin Li break;
3159*67e74705SXin Li case OMPC_if:
3160*67e74705SXin Li case OMPC_final:
3161*67e74705SXin Li case OMPC_num_threads:
3162*67e74705SXin Li case OMPC_private:
3163*67e74705SXin Li case OMPC_firstprivate:
3164*67e74705SXin Li case OMPC_lastprivate:
3165*67e74705SXin Li case OMPC_reduction:
3166*67e74705SXin Li case OMPC_safelen:
3167*67e74705SXin Li case OMPC_simdlen:
3168*67e74705SXin Li case OMPC_collapse:
3169*67e74705SXin Li case OMPC_default:
3170*67e74705SXin Li case OMPC_seq_cst:
3171*67e74705SXin Li case OMPC_shared:
3172*67e74705SXin Li case OMPC_linear:
3173*67e74705SXin Li case OMPC_aligned:
3174*67e74705SXin Li case OMPC_copyin:
3175*67e74705SXin Li case OMPC_copyprivate:
3176*67e74705SXin Li case OMPC_flush:
3177*67e74705SXin Li case OMPC_proc_bind:
3178*67e74705SXin Li case OMPC_schedule:
3179*67e74705SXin Li case OMPC_ordered:
3180*67e74705SXin Li case OMPC_nowait:
3181*67e74705SXin Li case OMPC_untied:
3182*67e74705SXin Li case OMPC_threadprivate:
3183*67e74705SXin Li case OMPC_depend:
3184*67e74705SXin Li case OMPC_mergeable:
3185*67e74705SXin Li case OMPC_device:
3186*67e74705SXin Li case OMPC_threads:
3187*67e74705SXin Li case OMPC_simd:
3188*67e74705SXin Li case OMPC_map:
3189*67e74705SXin Li case OMPC_num_teams:
3190*67e74705SXin Li case OMPC_thread_limit:
3191*67e74705SXin Li case OMPC_priority:
3192*67e74705SXin Li case OMPC_grainsize:
3193*67e74705SXin Li case OMPC_nogroup:
3194*67e74705SXin Li case OMPC_num_tasks:
3195*67e74705SXin Li case OMPC_hint:
3196*67e74705SXin Li case OMPC_dist_schedule:
3197*67e74705SXin Li case OMPC_defaultmap:
3198*67e74705SXin Li case OMPC_uniform:
3199*67e74705SXin Li case OMPC_to:
3200*67e74705SXin Li case OMPC_from:
3201*67e74705SXin Li case OMPC_use_device_ptr:
3202*67e74705SXin Li case OMPC_is_device_ptr:
3203*67e74705SXin Li llvm_unreachable("Clause is not allowed in 'omp atomic'.");
3204*67e74705SXin Li }
3205*67e74705SXin Li }
3206*67e74705SXin Li
EmitOMPAtomicDirective(const OMPAtomicDirective & S)3207*67e74705SXin Li void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &S) {
3208*67e74705SXin Li bool IsSeqCst = S.getSingleClause<OMPSeqCstClause>();
3209*67e74705SXin Li OpenMPClauseKind Kind = OMPC_unknown;
3210*67e74705SXin Li for (auto *C : S.clauses()) {
3211*67e74705SXin Li // Find first clause (skip seq_cst clause, if it is first).
3212*67e74705SXin Li if (C->getClauseKind() != OMPC_seq_cst) {
3213*67e74705SXin Li Kind = C->getClauseKind();
3214*67e74705SXin Li break;
3215*67e74705SXin Li }
3216*67e74705SXin Li }
3217*67e74705SXin Li
3218*67e74705SXin Li const auto *CS =
3219*67e74705SXin Li S.getAssociatedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
3220*67e74705SXin Li if (const auto *EWC = dyn_cast<ExprWithCleanups>(CS)) {
3221*67e74705SXin Li enterFullExpression(EWC);
3222*67e74705SXin Li }
3223*67e74705SXin Li // Processing for statements under 'atomic capture'.
3224*67e74705SXin Li if (const auto *Compound = dyn_cast<CompoundStmt>(CS)) {
3225*67e74705SXin Li for (const auto *C : Compound->body()) {
3226*67e74705SXin Li if (const auto *EWC = dyn_cast<ExprWithCleanups>(C)) {
3227*67e74705SXin Li enterFullExpression(EWC);
3228*67e74705SXin Li }
3229*67e74705SXin Li }
3230*67e74705SXin Li }
3231*67e74705SXin Li
3232*67e74705SXin Li auto &&CodeGen = [&S, Kind, IsSeqCst, CS](CodeGenFunction &CGF,
3233*67e74705SXin Li PrePostActionTy &) {
3234*67e74705SXin Li CGF.EmitStopPoint(CS);
3235*67e74705SXin Li EmitOMPAtomicExpr(CGF, Kind, IsSeqCst, S.isPostfixUpdate(), S.getX(),
3236*67e74705SXin Li S.getV(), S.getExpr(), S.getUpdateExpr(),
3237*67e74705SXin Li S.isXLHSInRHSPart(), S.getLocStart());
3238*67e74705SXin Li };
3239*67e74705SXin Li OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
3240*67e74705SXin Li CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_atomic, CodeGen);
3241*67e74705SXin Li }
3242*67e74705SXin Li
3243*67e74705SXin Li std::pair<llvm::Function * /*OutlinedFn*/, llvm::Constant * /*OutlinedFnID*/>
EmitOMPTargetDirectiveOutlinedFunction(CodeGenModule & CGM,const OMPTargetDirective & S,StringRef ParentName,bool IsOffloadEntry)3244*67e74705SXin Li CodeGenFunction::EmitOMPTargetDirectiveOutlinedFunction(
3245*67e74705SXin Li CodeGenModule &CGM, const OMPTargetDirective &S, StringRef ParentName,
3246*67e74705SXin Li bool IsOffloadEntry) {
3247*67e74705SXin Li llvm::Function *OutlinedFn = nullptr;
3248*67e74705SXin Li llvm::Constant *OutlinedFnID = nullptr;
3249*67e74705SXin Li auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
3250*67e74705SXin Li OMPPrivateScope PrivateScope(CGF);
3251*67e74705SXin Li (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
3252*67e74705SXin Li CGF.EmitOMPPrivateClause(S, PrivateScope);
3253*67e74705SXin Li (void)PrivateScope.Privatize();
3254*67e74705SXin Li
3255*67e74705SXin Li Action.Enter(CGF);
3256*67e74705SXin Li CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
3257*67e74705SXin Li };
3258*67e74705SXin Li // Emit target region as a standalone region.
3259*67e74705SXin Li CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
3260*67e74705SXin Li S, ParentName, OutlinedFn, OutlinedFnID, IsOffloadEntry, CodeGen);
3261*67e74705SXin Li return std::make_pair(OutlinedFn, OutlinedFnID);
3262*67e74705SXin Li }
3263*67e74705SXin Li
EmitOMPTargetDirective(const OMPTargetDirective & S)3264*67e74705SXin Li void CodeGenFunction::EmitOMPTargetDirective(const OMPTargetDirective &S) {
3265*67e74705SXin Li const CapturedStmt &CS = *cast<CapturedStmt>(S.getAssociatedStmt());
3266*67e74705SXin Li
3267*67e74705SXin Li llvm::SmallVector<llvm::Value *, 16> CapturedVars;
3268*67e74705SXin Li GenerateOpenMPCapturedVars(CS, CapturedVars);
3269*67e74705SXin Li
3270*67e74705SXin Li llvm::Function *Fn = nullptr;
3271*67e74705SXin Li llvm::Constant *FnID = nullptr;
3272*67e74705SXin Li
3273*67e74705SXin Li // Check if we have any if clause associated with the directive.
3274*67e74705SXin Li const Expr *IfCond = nullptr;
3275*67e74705SXin Li
3276*67e74705SXin Li if (auto *C = S.getSingleClause<OMPIfClause>()) {
3277*67e74705SXin Li IfCond = C->getCondition();
3278*67e74705SXin Li }
3279*67e74705SXin Li
3280*67e74705SXin Li // Check if we have any device clause associated with the directive.
3281*67e74705SXin Li const Expr *Device = nullptr;
3282*67e74705SXin Li if (auto *C = S.getSingleClause<OMPDeviceClause>()) {
3283*67e74705SXin Li Device = C->getDevice();
3284*67e74705SXin Li }
3285*67e74705SXin Li
3286*67e74705SXin Li // Check if we have an if clause whose conditional always evaluates to false
3287*67e74705SXin Li // or if we do not have any targets specified. If so the target region is not
3288*67e74705SXin Li // an offload entry point.
3289*67e74705SXin Li bool IsOffloadEntry = true;
3290*67e74705SXin Li if (IfCond) {
3291*67e74705SXin Li bool Val;
3292*67e74705SXin Li if (ConstantFoldsToSimpleInteger(IfCond, Val) && !Val)
3293*67e74705SXin Li IsOffloadEntry = false;
3294*67e74705SXin Li }
3295*67e74705SXin Li if (CGM.getLangOpts().OMPTargetTriples.empty())
3296*67e74705SXin Li IsOffloadEntry = false;
3297*67e74705SXin Li
3298*67e74705SXin Li assert(CurFuncDecl && "No parent declaration for target region!");
3299*67e74705SXin Li StringRef ParentName;
3300*67e74705SXin Li // In case we have Ctors/Dtors we use the complete type variant to produce
3301*67e74705SXin Li // the mangling of the device outlined kernel.
3302*67e74705SXin Li if (auto *D = dyn_cast<CXXConstructorDecl>(CurFuncDecl))
3303*67e74705SXin Li ParentName = CGM.getMangledName(GlobalDecl(D, Ctor_Complete));
3304*67e74705SXin Li else if (auto *D = dyn_cast<CXXDestructorDecl>(CurFuncDecl))
3305*67e74705SXin Li ParentName = CGM.getMangledName(GlobalDecl(D, Dtor_Complete));
3306*67e74705SXin Li else
3307*67e74705SXin Li ParentName =
3308*67e74705SXin Li CGM.getMangledName(GlobalDecl(cast<FunctionDecl>(CurFuncDecl)));
3309*67e74705SXin Li
3310*67e74705SXin Li std::tie(Fn, FnID) = EmitOMPTargetDirectiveOutlinedFunction(
3311*67e74705SXin Li CGM, S, ParentName, IsOffloadEntry);
3312*67e74705SXin Li OMPLexicalScope Scope(*this, S);
3313*67e74705SXin Li CGM.getOpenMPRuntime().emitTargetCall(*this, S, Fn, FnID, IfCond, Device,
3314*67e74705SXin Li CapturedVars);
3315*67e74705SXin Li }
3316*67e74705SXin Li
emitCommonOMPTeamsDirective(CodeGenFunction & CGF,const OMPExecutableDirective & S,OpenMPDirectiveKind InnermostKind,const RegionCodeGenTy & CodeGen)3317*67e74705SXin Li static void emitCommonOMPTeamsDirective(CodeGenFunction &CGF,
3318*67e74705SXin Li const OMPExecutableDirective &S,
3319*67e74705SXin Li OpenMPDirectiveKind InnermostKind,
3320*67e74705SXin Li const RegionCodeGenTy &CodeGen) {
3321*67e74705SXin Li auto CS = cast<CapturedStmt>(S.getAssociatedStmt());
3322*67e74705SXin Li auto OutlinedFn = CGF.CGM.getOpenMPRuntime().
3323*67e74705SXin Li emitParallelOrTeamsOutlinedFunction(S,
3324*67e74705SXin Li *CS->getCapturedDecl()->param_begin(), InnermostKind, CodeGen);
3325*67e74705SXin Li
3326*67e74705SXin Li const OMPTeamsDirective &TD = *dyn_cast<OMPTeamsDirective>(&S);
3327*67e74705SXin Li const OMPNumTeamsClause *NT = TD.getSingleClause<OMPNumTeamsClause>();
3328*67e74705SXin Li const OMPThreadLimitClause *TL = TD.getSingleClause<OMPThreadLimitClause>();
3329*67e74705SXin Li if (NT || TL) {
3330*67e74705SXin Li Expr *NumTeams = (NT) ? NT->getNumTeams() : nullptr;
3331*67e74705SXin Li Expr *ThreadLimit = (TL) ? TL->getThreadLimit() : nullptr;
3332*67e74705SXin Li
3333*67e74705SXin Li CGF.CGM.getOpenMPRuntime().emitNumTeamsClause(CGF, NumTeams, ThreadLimit,
3334*67e74705SXin Li S.getLocStart());
3335*67e74705SXin Li }
3336*67e74705SXin Li
3337*67e74705SXin Li OMPLexicalScope Scope(CGF, S);
3338*67e74705SXin Li llvm::SmallVector<llvm::Value *, 16> CapturedVars;
3339*67e74705SXin Li CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
3340*67e74705SXin Li CGF.CGM.getOpenMPRuntime().emitTeamsCall(CGF, S, S.getLocStart(), OutlinedFn,
3341*67e74705SXin Li CapturedVars);
3342*67e74705SXin Li }
3343*67e74705SXin Li
EmitOMPTeamsDirective(const OMPTeamsDirective & S)3344*67e74705SXin Li void CodeGenFunction::EmitOMPTeamsDirective(const OMPTeamsDirective &S) {
3345*67e74705SXin Li // Emit parallel region as a standalone region.
3346*67e74705SXin Li auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
3347*67e74705SXin Li OMPPrivateScope PrivateScope(CGF);
3348*67e74705SXin Li (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
3349*67e74705SXin Li CGF.EmitOMPPrivateClause(S, PrivateScope);
3350*67e74705SXin Li (void)PrivateScope.Privatize();
3351*67e74705SXin Li CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
3352*67e74705SXin Li };
3353*67e74705SXin Li emitCommonOMPTeamsDirective(*this, S, OMPD_teams, CodeGen);
3354*67e74705SXin Li }
3355*67e74705SXin Li
EmitOMPCancellationPointDirective(const OMPCancellationPointDirective & S)3356*67e74705SXin Li void CodeGenFunction::EmitOMPCancellationPointDirective(
3357*67e74705SXin Li const OMPCancellationPointDirective &S) {
3358*67e74705SXin Li CGM.getOpenMPRuntime().emitCancellationPointCall(*this, S.getLocStart(),
3359*67e74705SXin Li S.getCancelRegion());
3360*67e74705SXin Li }
3361*67e74705SXin Li
EmitOMPCancelDirective(const OMPCancelDirective & S)3362*67e74705SXin Li void CodeGenFunction::EmitOMPCancelDirective(const OMPCancelDirective &S) {
3363*67e74705SXin Li const Expr *IfCond = nullptr;
3364*67e74705SXin Li for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
3365*67e74705SXin Li if (C->getNameModifier() == OMPD_unknown ||
3366*67e74705SXin Li C->getNameModifier() == OMPD_cancel) {
3367*67e74705SXin Li IfCond = C->getCondition();
3368*67e74705SXin Li break;
3369*67e74705SXin Li }
3370*67e74705SXin Li }
3371*67e74705SXin Li CGM.getOpenMPRuntime().emitCancelCall(*this, S.getLocStart(), IfCond,
3372*67e74705SXin Li S.getCancelRegion());
3373*67e74705SXin Li }
3374*67e74705SXin Li
3375*67e74705SXin Li CodeGenFunction::JumpDest
getOMPCancelDestination(OpenMPDirectiveKind Kind)3376*67e74705SXin Li CodeGenFunction::getOMPCancelDestination(OpenMPDirectiveKind Kind) {
3377*67e74705SXin Li if (Kind == OMPD_parallel || Kind == OMPD_task)
3378*67e74705SXin Li return ReturnBlock;
3379*67e74705SXin Li assert(Kind == OMPD_for || Kind == OMPD_section || Kind == OMPD_sections ||
3380*67e74705SXin Li Kind == OMPD_parallel_sections || Kind == OMPD_parallel_for);
3381*67e74705SXin Li return BreakContinueStack.back().BreakBlock;
3382*67e74705SXin Li }
3383*67e74705SXin Li
3384*67e74705SXin Li // Generate the instructions for '#pragma omp target data' directive.
EmitOMPTargetDataDirective(const OMPTargetDataDirective & S)3385*67e74705SXin Li void CodeGenFunction::EmitOMPTargetDataDirective(
3386*67e74705SXin Li const OMPTargetDataDirective &S) {
3387*67e74705SXin Li // The target data enclosed region is implemented just by emitting the
3388*67e74705SXin Li // statement.
3389*67e74705SXin Li auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
3390*67e74705SXin Li CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
3391*67e74705SXin Li };
3392*67e74705SXin Li
3393*67e74705SXin Li // If we don't have target devices, don't bother emitting the data mapping
3394*67e74705SXin Li // code.
3395*67e74705SXin Li if (CGM.getLangOpts().OMPTargetTriples.empty()) {
3396*67e74705SXin Li OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
3397*67e74705SXin Li
3398*67e74705SXin Li CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_target_data,
3399*67e74705SXin Li CodeGen);
3400*67e74705SXin Li return;
3401*67e74705SXin Li }
3402*67e74705SXin Li
3403*67e74705SXin Li // Check if we have any if clause associated with the directive.
3404*67e74705SXin Li const Expr *IfCond = nullptr;
3405*67e74705SXin Li if (auto *C = S.getSingleClause<OMPIfClause>())
3406*67e74705SXin Li IfCond = C->getCondition();
3407*67e74705SXin Li
3408*67e74705SXin Li // Check if we have any device clause associated with the directive.
3409*67e74705SXin Li const Expr *Device = nullptr;
3410*67e74705SXin Li if (auto *C = S.getSingleClause<OMPDeviceClause>())
3411*67e74705SXin Li Device = C->getDevice();
3412*67e74705SXin Li
3413*67e74705SXin Li CGM.getOpenMPRuntime().emitTargetDataCalls(*this, S, IfCond, Device, CodeGen);
3414*67e74705SXin Li }
3415*67e74705SXin Li
EmitOMPTargetEnterDataDirective(const OMPTargetEnterDataDirective & S)3416*67e74705SXin Li void CodeGenFunction::EmitOMPTargetEnterDataDirective(
3417*67e74705SXin Li const OMPTargetEnterDataDirective &S) {
3418*67e74705SXin Li // If we don't have target devices, don't bother emitting the data mapping
3419*67e74705SXin Li // code.
3420*67e74705SXin Li if (CGM.getLangOpts().OMPTargetTriples.empty())
3421*67e74705SXin Li return;
3422*67e74705SXin Li
3423*67e74705SXin Li // Check if we have any if clause associated with the directive.
3424*67e74705SXin Li const Expr *IfCond = nullptr;
3425*67e74705SXin Li if (auto *C = S.getSingleClause<OMPIfClause>())
3426*67e74705SXin Li IfCond = C->getCondition();
3427*67e74705SXin Li
3428*67e74705SXin Li // Check if we have any device clause associated with the directive.
3429*67e74705SXin Li const Expr *Device = nullptr;
3430*67e74705SXin Li if (auto *C = S.getSingleClause<OMPDeviceClause>())
3431*67e74705SXin Li Device = C->getDevice();
3432*67e74705SXin Li
3433*67e74705SXin Li CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*this, S, IfCond, Device);
3434*67e74705SXin Li }
3435*67e74705SXin Li
EmitOMPTargetExitDataDirective(const OMPTargetExitDataDirective & S)3436*67e74705SXin Li void CodeGenFunction::EmitOMPTargetExitDataDirective(
3437*67e74705SXin Li const OMPTargetExitDataDirective &S) {
3438*67e74705SXin Li // If we don't have target devices, don't bother emitting the data mapping
3439*67e74705SXin Li // code.
3440*67e74705SXin Li if (CGM.getLangOpts().OMPTargetTriples.empty())
3441*67e74705SXin Li return;
3442*67e74705SXin Li
3443*67e74705SXin Li // Check if we have any if clause associated with the directive.
3444*67e74705SXin Li const Expr *IfCond = nullptr;
3445*67e74705SXin Li if (auto *C = S.getSingleClause<OMPIfClause>())
3446*67e74705SXin Li IfCond = C->getCondition();
3447*67e74705SXin Li
3448*67e74705SXin Li // Check if we have any device clause associated with the directive.
3449*67e74705SXin Li const Expr *Device = nullptr;
3450*67e74705SXin Li if (auto *C = S.getSingleClause<OMPDeviceClause>())
3451*67e74705SXin Li Device = C->getDevice();
3452*67e74705SXin Li
3453*67e74705SXin Li CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*this, S, IfCond, Device);
3454*67e74705SXin Li }
3455*67e74705SXin Li
EmitOMPTargetParallelDirective(const OMPTargetParallelDirective & S)3456*67e74705SXin Li void CodeGenFunction::EmitOMPTargetParallelDirective(
3457*67e74705SXin Li const OMPTargetParallelDirective &S) {
3458*67e74705SXin Li // TODO: codegen for target parallel.
3459*67e74705SXin Li }
3460*67e74705SXin Li
EmitOMPTargetParallelForDirective(const OMPTargetParallelForDirective & S)3461*67e74705SXin Li void CodeGenFunction::EmitOMPTargetParallelForDirective(
3462*67e74705SXin Li const OMPTargetParallelForDirective &S) {
3463*67e74705SXin Li // TODO: codegen for target parallel for.
3464*67e74705SXin Li }
3465*67e74705SXin Li
3466*67e74705SXin Li /// Emit a helper variable and return corresponding lvalue.
mapParam(CodeGenFunction & CGF,const DeclRefExpr * Helper,const ImplicitParamDecl * PVD,CodeGenFunction::OMPPrivateScope & Privates)3467*67e74705SXin Li static void mapParam(CodeGenFunction &CGF, const DeclRefExpr *Helper,
3468*67e74705SXin Li const ImplicitParamDecl *PVD,
3469*67e74705SXin Li CodeGenFunction::OMPPrivateScope &Privates) {
3470*67e74705SXin Li auto *VDecl = cast<VarDecl>(Helper->getDecl());
3471*67e74705SXin Li Privates.addPrivate(
3472*67e74705SXin Li VDecl, [&CGF, PVD]() -> Address { return CGF.GetAddrOfLocalVar(PVD); });
3473*67e74705SXin Li }
3474*67e74705SXin Li
EmitOMPTaskLoopBasedDirective(const OMPLoopDirective & S)3475*67e74705SXin Li void CodeGenFunction::EmitOMPTaskLoopBasedDirective(const OMPLoopDirective &S) {
3476*67e74705SXin Li assert(isOpenMPTaskLoopDirective(S.getDirectiveKind()));
3477*67e74705SXin Li // Emit outlined function for task construct.
3478*67e74705SXin Li auto CS = cast<CapturedStmt>(S.getAssociatedStmt());
3479*67e74705SXin Li auto CapturedStruct = GenerateCapturedStmtArgument(*CS);
3480*67e74705SXin Li auto SharedsTy = getContext().getRecordType(CS->getCapturedRecordDecl());
3481*67e74705SXin Li const Expr *IfCond = nullptr;
3482*67e74705SXin Li for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
3483*67e74705SXin Li if (C->getNameModifier() == OMPD_unknown ||
3484*67e74705SXin Li C->getNameModifier() == OMPD_taskloop) {
3485*67e74705SXin Li IfCond = C->getCondition();
3486*67e74705SXin Li break;
3487*67e74705SXin Li }
3488*67e74705SXin Li }
3489*67e74705SXin Li
3490*67e74705SXin Li OMPTaskDataTy Data;
3491*67e74705SXin Li // Check if taskloop must be emitted without taskgroup.
3492*67e74705SXin Li Data.Nogroup = S.getSingleClause<OMPNogroupClause>();
3493*67e74705SXin Li // TODO: Check if we should emit tied or untied task.
3494*67e74705SXin Li Data.Tied = true;
3495*67e74705SXin Li // Set scheduling for taskloop
3496*67e74705SXin Li if (const auto* Clause = S.getSingleClause<OMPGrainsizeClause>()) {
3497*67e74705SXin Li // grainsize clause
3498*67e74705SXin Li Data.Schedule.setInt(/*IntVal=*/false);
3499*67e74705SXin Li Data.Schedule.setPointer(EmitScalarExpr(Clause->getGrainsize()));
3500*67e74705SXin Li } else if (const auto* Clause = S.getSingleClause<OMPNumTasksClause>()) {
3501*67e74705SXin Li // num_tasks clause
3502*67e74705SXin Li Data.Schedule.setInt(/*IntVal=*/true);
3503*67e74705SXin Li Data.Schedule.setPointer(EmitScalarExpr(Clause->getNumTasks()));
3504*67e74705SXin Li }
3505*67e74705SXin Li
3506*67e74705SXin Li auto &&BodyGen = [CS, &S](CodeGenFunction &CGF, PrePostActionTy &) {
3507*67e74705SXin Li // if (PreCond) {
3508*67e74705SXin Li // for (IV in 0..LastIteration) BODY;
3509*67e74705SXin Li // <Final counter/linear vars updates>;
3510*67e74705SXin Li // }
3511*67e74705SXin Li //
3512*67e74705SXin Li
3513*67e74705SXin Li // Emit: if (PreCond) - begin.
3514*67e74705SXin Li // If the condition constant folds and can be elided, avoid emitting the
3515*67e74705SXin Li // whole loop.
3516*67e74705SXin Li bool CondConstant;
3517*67e74705SXin Li llvm::BasicBlock *ContBlock = nullptr;
3518*67e74705SXin Li OMPLoopScope PreInitScope(CGF, S);
3519*67e74705SXin Li if (CGF.ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
3520*67e74705SXin Li if (!CondConstant)
3521*67e74705SXin Li return;
3522*67e74705SXin Li } else {
3523*67e74705SXin Li auto *ThenBlock = CGF.createBasicBlock("taskloop.if.then");
3524*67e74705SXin Li ContBlock = CGF.createBasicBlock("taskloop.if.end");
3525*67e74705SXin Li emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
3526*67e74705SXin Li CGF.getProfileCount(&S));
3527*67e74705SXin Li CGF.EmitBlock(ThenBlock);
3528*67e74705SXin Li CGF.incrementProfileCounter(&S);
3529*67e74705SXin Li }
3530*67e74705SXin Li
3531*67e74705SXin Li if (isOpenMPSimdDirective(S.getDirectiveKind()))
3532*67e74705SXin Li CGF.EmitOMPSimdInit(S);
3533*67e74705SXin Li
3534*67e74705SXin Li OMPPrivateScope LoopScope(CGF);
3535*67e74705SXin Li // Emit helper vars inits.
3536*67e74705SXin Li enum { LowerBound = 5, UpperBound, Stride, LastIter };
3537*67e74705SXin Li auto *I = CS->getCapturedDecl()->param_begin();
3538*67e74705SXin Li auto *LBP = std::next(I, LowerBound);
3539*67e74705SXin Li auto *UBP = std::next(I, UpperBound);
3540*67e74705SXin Li auto *STP = std::next(I, Stride);
3541*67e74705SXin Li auto *LIP = std::next(I, LastIter);
3542*67e74705SXin Li mapParam(CGF, cast<DeclRefExpr>(S.getLowerBoundVariable()), *LBP,
3543*67e74705SXin Li LoopScope);
3544*67e74705SXin Li mapParam(CGF, cast<DeclRefExpr>(S.getUpperBoundVariable()), *UBP,
3545*67e74705SXin Li LoopScope);
3546*67e74705SXin Li mapParam(CGF, cast<DeclRefExpr>(S.getStrideVariable()), *STP, LoopScope);
3547*67e74705SXin Li mapParam(CGF, cast<DeclRefExpr>(S.getIsLastIterVariable()), *LIP,
3548*67e74705SXin Li LoopScope);
3549*67e74705SXin Li CGF.EmitOMPPrivateLoopCounters(S, LoopScope);
3550*67e74705SXin Li bool HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
3551*67e74705SXin Li (void)LoopScope.Privatize();
3552*67e74705SXin Li // Emit the loop iteration variable.
3553*67e74705SXin Li const Expr *IVExpr = S.getIterationVariable();
3554*67e74705SXin Li const VarDecl *IVDecl = cast<VarDecl>(cast<DeclRefExpr>(IVExpr)->getDecl());
3555*67e74705SXin Li CGF.EmitVarDecl(*IVDecl);
3556*67e74705SXin Li CGF.EmitIgnoredExpr(S.getInit());
3557*67e74705SXin Li
3558*67e74705SXin Li // Emit the iterations count variable.
3559*67e74705SXin Li // If it is not a variable, Sema decided to calculate iterations count on
3560*67e74705SXin Li // each iteration (e.g., it is foldable into a constant).
3561*67e74705SXin Li if (auto LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
3562*67e74705SXin Li CGF.EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
3563*67e74705SXin Li // Emit calculation of the iterations count.
3564*67e74705SXin Li CGF.EmitIgnoredExpr(S.getCalcLastIteration());
3565*67e74705SXin Li }
3566*67e74705SXin Li
3567*67e74705SXin Li CGF.EmitOMPInnerLoop(S, LoopScope.requiresCleanups(), S.getCond(),
3568*67e74705SXin Li S.getInc(),
3569*67e74705SXin Li [&S](CodeGenFunction &CGF) {
3570*67e74705SXin Li CGF.EmitOMPLoopBody(S, JumpDest());
3571*67e74705SXin Li CGF.EmitStopPoint(&S);
3572*67e74705SXin Li },
3573*67e74705SXin Li [](CodeGenFunction &) {});
3574*67e74705SXin Li // Emit: if (PreCond) - end.
3575*67e74705SXin Li if (ContBlock) {
3576*67e74705SXin Li CGF.EmitBranch(ContBlock);
3577*67e74705SXin Li CGF.EmitBlock(ContBlock, true);
3578*67e74705SXin Li }
3579*67e74705SXin Li // Emit final copy of the lastprivate variables if IsLastIter != 0.
3580*67e74705SXin Li if (HasLastprivateClause) {
3581*67e74705SXin Li CGF.EmitOMPLastprivateClauseFinal(
3582*67e74705SXin Li S, isOpenMPSimdDirective(S.getDirectiveKind()),
3583*67e74705SXin Li CGF.Builder.CreateIsNotNull(CGF.EmitLoadOfScalar(
3584*67e74705SXin Li CGF.GetAddrOfLocalVar(*LIP), /*Volatile=*/false,
3585*67e74705SXin Li (*LIP)->getType(), S.getLocStart())));
3586*67e74705SXin Li }
3587*67e74705SXin Li };
3588*67e74705SXin Li auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
3589*67e74705SXin Li IfCond](CodeGenFunction &CGF, llvm::Value *OutlinedFn,
3590*67e74705SXin Li const OMPTaskDataTy &Data) {
3591*67e74705SXin Li auto &&CodeGen = [&](CodeGenFunction &CGF, PrePostActionTy &) {
3592*67e74705SXin Li OMPLoopScope PreInitScope(CGF, S);
3593*67e74705SXin Li CGF.CGM.getOpenMPRuntime().emitTaskLoopCall(CGF, S.getLocStart(), S,
3594*67e74705SXin Li OutlinedFn, SharedsTy,
3595*67e74705SXin Li CapturedStruct, IfCond, Data);
3596*67e74705SXin Li };
3597*67e74705SXin Li CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_taskloop,
3598*67e74705SXin Li CodeGen);
3599*67e74705SXin Li };
3600*67e74705SXin Li EmitOMPTaskBasedDirective(S, BodyGen, TaskGen, Data);
3601*67e74705SXin Li }
3602*67e74705SXin Li
EmitOMPTaskLoopDirective(const OMPTaskLoopDirective & S)3603*67e74705SXin Li void CodeGenFunction::EmitOMPTaskLoopDirective(const OMPTaskLoopDirective &S) {
3604*67e74705SXin Li EmitOMPTaskLoopBasedDirective(S);
3605*67e74705SXin Li }
3606*67e74705SXin Li
EmitOMPTaskLoopSimdDirective(const OMPTaskLoopSimdDirective & S)3607*67e74705SXin Li void CodeGenFunction::EmitOMPTaskLoopSimdDirective(
3608*67e74705SXin Li const OMPTaskLoopSimdDirective &S) {
3609*67e74705SXin Li EmitOMPTaskLoopBasedDirective(S);
3610*67e74705SXin Li }
3611*67e74705SXin Li
3612*67e74705SXin Li // Generate the instructions for '#pragma omp target update' directive.
EmitOMPTargetUpdateDirective(const OMPTargetUpdateDirective & S)3613*67e74705SXin Li void CodeGenFunction::EmitOMPTargetUpdateDirective(
3614*67e74705SXin Li const OMPTargetUpdateDirective &S) {
3615*67e74705SXin Li // If we don't have target devices, don't bother emitting the data mapping
3616*67e74705SXin Li // code.
3617*67e74705SXin Li if (CGM.getLangOpts().OMPTargetTriples.empty())
3618*67e74705SXin Li return;
3619*67e74705SXin Li
3620*67e74705SXin Li // Check if we have any if clause associated with the directive.
3621*67e74705SXin Li const Expr *IfCond = nullptr;
3622*67e74705SXin Li if (auto *C = S.getSingleClause<OMPIfClause>())
3623*67e74705SXin Li IfCond = C->getCondition();
3624*67e74705SXin Li
3625*67e74705SXin Li // Check if we have any device clause associated with the directive.
3626*67e74705SXin Li const Expr *Device = nullptr;
3627*67e74705SXin Li if (auto *C = S.getSingleClause<OMPDeviceClause>())
3628*67e74705SXin Li Device = C->getDevice();
3629*67e74705SXin Li
3630*67e74705SXin Li CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*this, S, IfCond, Device);
3631*67e74705SXin Li }
3632