1*0a6a1f1dSLionel Sambuc //===--- CGStmtOpenMP.cpp - Emit LLVM Code from Statements ----------------===//
2*0a6a1f1dSLionel Sambuc //
3*0a6a1f1dSLionel Sambuc // The LLVM Compiler Infrastructure
4*0a6a1f1dSLionel Sambuc //
5*0a6a1f1dSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6*0a6a1f1dSLionel Sambuc // License. See LICENSE.TXT for details.
7*0a6a1f1dSLionel Sambuc //
8*0a6a1f1dSLionel Sambuc //===----------------------------------------------------------------------===//
9*0a6a1f1dSLionel Sambuc //
10*0a6a1f1dSLionel Sambuc // This contains code to emit OpenMP nodes as LLVM code.
11*0a6a1f1dSLionel Sambuc //
12*0a6a1f1dSLionel Sambuc //===----------------------------------------------------------------------===//
13*0a6a1f1dSLionel Sambuc
14*0a6a1f1dSLionel Sambuc #include "CGOpenMPRuntime.h"
15*0a6a1f1dSLionel Sambuc #include "CodeGenFunction.h"
16*0a6a1f1dSLionel Sambuc #include "CodeGenModule.h"
17*0a6a1f1dSLionel Sambuc #include "TargetInfo.h"
18*0a6a1f1dSLionel Sambuc #include "clang/AST/Stmt.h"
19*0a6a1f1dSLionel Sambuc #include "clang/AST/StmtOpenMP.h"
20*0a6a1f1dSLionel Sambuc using namespace clang;
21*0a6a1f1dSLionel Sambuc using namespace CodeGen;
22*0a6a1f1dSLionel Sambuc
23*0a6a1f1dSLionel Sambuc namespace {
24*0a6a1f1dSLionel Sambuc /// \brief RAII for emitting code of CapturedStmt without function outlining.
25*0a6a1f1dSLionel Sambuc class InlinedOpenMPRegion {
26*0a6a1f1dSLionel Sambuc CodeGenFunction &CGF;
27*0a6a1f1dSLionel Sambuc CodeGenFunction::CGCapturedStmtInfo *PrevCapturedStmtInfo;
28*0a6a1f1dSLionel Sambuc const Decl *StoredCurCodeDecl;
29*0a6a1f1dSLionel Sambuc
30*0a6a1f1dSLionel Sambuc /// \brief A class to emit CapturedStmt construct as inlined statement without
31*0a6a1f1dSLionel Sambuc /// generating a function for outlined code.
32*0a6a1f1dSLionel Sambuc class CGInlinedOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo {
33*0a6a1f1dSLionel Sambuc public:
CGInlinedOpenMPRegionInfo()34*0a6a1f1dSLionel Sambuc CGInlinedOpenMPRegionInfo() : CGCapturedStmtInfo() {}
35*0a6a1f1dSLionel Sambuc };
36*0a6a1f1dSLionel Sambuc
37*0a6a1f1dSLionel Sambuc public:
InlinedOpenMPRegion(CodeGenFunction & CGF,const Stmt * S)38*0a6a1f1dSLionel Sambuc InlinedOpenMPRegion(CodeGenFunction &CGF, const Stmt *S)
39*0a6a1f1dSLionel Sambuc : CGF(CGF), PrevCapturedStmtInfo(CGF.CapturedStmtInfo),
40*0a6a1f1dSLionel Sambuc StoredCurCodeDecl(CGF.CurCodeDecl) {
41*0a6a1f1dSLionel Sambuc CGF.CurCodeDecl = cast<CapturedStmt>(S)->getCapturedDecl();
42*0a6a1f1dSLionel Sambuc CGF.CapturedStmtInfo = new CGInlinedOpenMPRegionInfo();
43*0a6a1f1dSLionel Sambuc }
~InlinedOpenMPRegion()44*0a6a1f1dSLionel Sambuc ~InlinedOpenMPRegion() {
45*0a6a1f1dSLionel Sambuc delete CGF.CapturedStmtInfo;
46*0a6a1f1dSLionel Sambuc CGF.CapturedStmtInfo = PrevCapturedStmtInfo;
47*0a6a1f1dSLionel Sambuc CGF.CurCodeDecl = StoredCurCodeDecl;
48*0a6a1f1dSLionel Sambuc }
49*0a6a1f1dSLionel Sambuc };
50*0a6a1f1dSLionel Sambuc } // namespace
51*0a6a1f1dSLionel Sambuc
52*0a6a1f1dSLionel Sambuc //===----------------------------------------------------------------------===//
53*0a6a1f1dSLionel Sambuc // OpenMP Directive Emission
54*0a6a1f1dSLionel Sambuc //===----------------------------------------------------------------------===//
55*0a6a1f1dSLionel Sambuc
56*0a6a1f1dSLionel Sambuc /// \brief Emits code for OpenMP 'if' clause using specified \a CodeGen
57*0a6a1f1dSLionel Sambuc /// function. Here is the logic:
58*0a6a1f1dSLionel Sambuc /// if (Cond) {
59*0a6a1f1dSLionel Sambuc /// CodeGen(true);
60*0a6a1f1dSLionel Sambuc /// } else {
61*0a6a1f1dSLionel Sambuc /// CodeGen(false);
62*0a6a1f1dSLionel Sambuc /// }
EmitOMPIfClause(CodeGenFunction & CGF,const Expr * Cond,const std::function<void (bool)> & CodeGen)63*0a6a1f1dSLionel Sambuc static void EmitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond,
64*0a6a1f1dSLionel Sambuc const std::function<void(bool)> &CodeGen) {
65*0a6a1f1dSLionel Sambuc CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange());
66*0a6a1f1dSLionel Sambuc
67*0a6a1f1dSLionel Sambuc // If the condition constant folds and can be elided, try to avoid emitting
68*0a6a1f1dSLionel Sambuc // the condition and the dead arm of the if/else.
69*0a6a1f1dSLionel Sambuc bool CondConstant;
70*0a6a1f1dSLionel Sambuc if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) {
71*0a6a1f1dSLionel Sambuc CodeGen(CondConstant);
72*0a6a1f1dSLionel Sambuc return;
73*0a6a1f1dSLionel Sambuc }
74*0a6a1f1dSLionel Sambuc
75*0a6a1f1dSLionel Sambuc // Otherwise, the condition did not fold, or we couldn't elide it. Just
76*0a6a1f1dSLionel Sambuc // emit the conditional branch.
77*0a6a1f1dSLionel Sambuc auto ThenBlock = CGF.createBasicBlock(/*name*/ "omp_if.then");
78*0a6a1f1dSLionel Sambuc auto ElseBlock = CGF.createBasicBlock(/*name*/ "omp_if.else");
79*0a6a1f1dSLionel Sambuc auto ContBlock = CGF.createBasicBlock(/*name*/ "omp_if.end");
80*0a6a1f1dSLionel Sambuc CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount*/ 0);
81*0a6a1f1dSLionel Sambuc
82*0a6a1f1dSLionel Sambuc // Emit the 'then' code.
83*0a6a1f1dSLionel Sambuc CGF.EmitBlock(ThenBlock);
84*0a6a1f1dSLionel Sambuc CodeGen(/*ThenBlock*/ true);
85*0a6a1f1dSLionel Sambuc CGF.EmitBranch(ContBlock);
86*0a6a1f1dSLionel Sambuc // Emit the 'else' code if present.
87*0a6a1f1dSLionel Sambuc {
88*0a6a1f1dSLionel Sambuc // There is no need to emit line number for unconditional branch.
89*0a6a1f1dSLionel Sambuc ApplyDebugLocation DL(CGF);
90*0a6a1f1dSLionel Sambuc CGF.EmitBlock(ElseBlock);
91*0a6a1f1dSLionel Sambuc }
92*0a6a1f1dSLionel Sambuc CodeGen(/*ThenBlock*/ false);
93*0a6a1f1dSLionel Sambuc {
94*0a6a1f1dSLionel Sambuc // There is no need to emit line number for unconditional branch.
95*0a6a1f1dSLionel Sambuc ApplyDebugLocation DL(CGF);
96*0a6a1f1dSLionel Sambuc CGF.EmitBranch(ContBlock);
97*0a6a1f1dSLionel Sambuc }
98*0a6a1f1dSLionel Sambuc // Emit the continuation block for code after the if.
99*0a6a1f1dSLionel Sambuc CGF.EmitBlock(ContBlock, /*IsFinished*/ true);
100*0a6a1f1dSLionel Sambuc }
101*0a6a1f1dSLionel Sambuc
EmitOMPAggregateAssign(LValue OriginalAddr,llvm::Value * PrivateAddr,const Expr * AssignExpr,QualType OriginalType,const VarDecl * VDInit)102*0a6a1f1dSLionel Sambuc void CodeGenFunction::EmitOMPAggregateAssign(LValue OriginalAddr,
103*0a6a1f1dSLionel Sambuc llvm::Value *PrivateAddr,
104*0a6a1f1dSLionel Sambuc const Expr *AssignExpr,
105*0a6a1f1dSLionel Sambuc QualType OriginalType,
106*0a6a1f1dSLionel Sambuc const VarDecl *VDInit) {
107*0a6a1f1dSLionel Sambuc EmitBlock(createBasicBlock(".omp.assign.begin."));
108*0a6a1f1dSLionel Sambuc if (!isa<CXXConstructExpr>(AssignExpr) || isTrivialInitializer(AssignExpr)) {
109*0a6a1f1dSLionel Sambuc // Perform simple memcpy.
110*0a6a1f1dSLionel Sambuc EmitAggregateAssign(PrivateAddr, OriginalAddr.getAddress(),
111*0a6a1f1dSLionel Sambuc AssignExpr->getType());
112*0a6a1f1dSLionel Sambuc } else {
113*0a6a1f1dSLionel Sambuc // Perform element-by-element initialization.
114*0a6a1f1dSLionel Sambuc QualType ElementTy;
115*0a6a1f1dSLionel Sambuc auto SrcBegin = OriginalAddr.getAddress();
116*0a6a1f1dSLionel Sambuc auto DestBegin = PrivateAddr;
117*0a6a1f1dSLionel Sambuc auto ArrayTy = OriginalType->getAsArrayTypeUnsafe();
118*0a6a1f1dSLionel Sambuc auto SrcNumElements = emitArrayLength(ArrayTy, ElementTy, SrcBegin);
119*0a6a1f1dSLionel Sambuc auto DestNumElements = emitArrayLength(ArrayTy, ElementTy, DestBegin);
120*0a6a1f1dSLionel Sambuc auto SrcEnd = Builder.CreateGEP(SrcBegin, SrcNumElements);
121*0a6a1f1dSLionel Sambuc auto DestEnd = Builder.CreateGEP(DestBegin, DestNumElements);
122*0a6a1f1dSLionel Sambuc // The basic structure here is a do-while loop, because we don't
123*0a6a1f1dSLionel Sambuc // need to check for the zero-element case.
124*0a6a1f1dSLionel Sambuc auto BodyBB = createBasicBlock("omp.arraycpy.body");
125*0a6a1f1dSLionel Sambuc auto DoneBB = createBasicBlock("omp.arraycpy.done");
126*0a6a1f1dSLionel Sambuc auto IsEmpty =
127*0a6a1f1dSLionel Sambuc Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arraycpy.isempty");
128*0a6a1f1dSLionel Sambuc Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
129*0a6a1f1dSLionel Sambuc
130*0a6a1f1dSLionel Sambuc // Enter the loop body, making that address the current address.
131*0a6a1f1dSLionel Sambuc auto EntryBB = Builder.GetInsertBlock();
132*0a6a1f1dSLionel Sambuc EmitBlock(BodyBB);
133*0a6a1f1dSLionel Sambuc auto SrcElementPast = Builder.CreatePHI(SrcBegin->getType(), 2,
134*0a6a1f1dSLionel Sambuc "omp.arraycpy.srcElementPast");
135*0a6a1f1dSLionel Sambuc SrcElementPast->addIncoming(SrcEnd, EntryBB);
136*0a6a1f1dSLionel Sambuc auto DestElementPast = Builder.CreatePHI(DestBegin->getType(), 2,
137*0a6a1f1dSLionel Sambuc "omp.arraycpy.destElementPast");
138*0a6a1f1dSLionel Sambuc DestElementPast->addIncoming(DestEnd, EntryBB);
139*0a6a1f1dSLionel Sambuc
140*0a6a1f1dSLionel Sambuc // Shift the address back by one element.
141*0a6a1f1dSLionel Sambuc auto NegativeOne = llvm::ConstantInt::get(SizeTy, -1, true);
142*0a6a1f1dSLionel Sambuc auto DestElement = Builder.CreateGEP(DestElementPast, NegativeOne,
143*0a6a1f1dSLionel Sambuc "omp.arraycpy.dest.element");
144*0a6a1f1dSLionel Sambuc auto SrcElement = Builder.CreateGEP(SrcElementPast, NegativeOne,
145*0a6a1f1dSLionel Sambuc "omp.arraycpy.src.element");
146*0a6a1f1dSLionel Sambuc {
147*0a6a1f1dSLionel Sambuc // Create RunCleanScope to cleanup possible temps.
148*0a6a1f1dSLionel Sambuc CodeGenFunction::RunCleanupsScope Init(*this);
149*0a6a1f1dSLionel Sambuc // Emit initialization for single element.
150*0a6a1f1dSLionel Sambuc LocalDeclMap[VDInit] = SrcElement;
151*0a6a1f1dSLionel Sambuc EmitAnyExprToMem(AssignExpr, DestElement,
152*0a6a1f1dSLionel Sambuc AssignExpr->getType().getQualifiers(),
153*0a6a1f1dSLionel Sambuc /*IsInitializer*/ false);
154*0a6a1f1dSLionel Sambuc LocalDeclMap.erase(VDInit);
155*0a6a1f1dSLionel Sambuc }
156*0a6a1f1dSLionel Sambuc
157*0a6a1f1dSLionel Sambuc // Check whether we've reached the end.
158*0a6a1f1dSLionel Sambuc auto Done =
159*0a6a1f1dSLionel Sambuc Builder.CreateICmpEQ(DestElement, DestBegin, "omp.arraycpy.done");
160*0a6a1f1dSLionel Sambuc Builder.CreateCondBr(Done, DoneBB, BodyBB);
161*0a6a1f1dSLionel Sambuc DestElementPast->addIncoming(DestElement, Builder.GetInsertBlock());
162*0a6a1f1dSLionel Sambuc SrcElementPast->addIncoming(SrcElement, Builder.GetInsertBlock());
163*0a6a1f1dSLionel Sambuc
164*0a6a1f1dSLionel Sambuc // Done.
165*0a6a1f1dSLionel Sambuc EmitBlock(DoneBB, true);
166*0a6a1f1dSLionel Sambuc }
167*0a6a1f1dSLionel Sambuc EmitBlock(createBasicBlock(".omp.assign.end."));
168*0a6a1f1dSLionel Sambuc }
169*0a6a1f1dSLionel Sambuc
EmitOMPFirstprivateClause(const OMPExecutableDirective & D,CodeGenFunction::OMPPrivateScope & PrivateScope)170*0a6a1f1dSLionel Sambuc void CodeGenFunction::EmitOMPFirstprivateClause(
171*0a6a1f1dSLionel Sambuc const OMPExecutableDirective &D,
172*0a6a1f1dSLionel Sambuc CodeGenFunction::OMPPrivateScope &PrivateScope) {
173*0a6a1f1dSLionel Sambuc auto PrivateFilter = [](const OMPClause *C) -> bool {
174*0a6a1f1dSLionel Sambuc return C->getClauseKind() == OMPC_firstprivate;
175*0a6a1f1dSLionel Sambuc };
176*0a6a1f1dSLionel Sambuc for (OMPExecutableDirective::filtered_clause_iterator<decltype(PrivateFilter)>
177*0a6a1f1dSLionel Sambuc I(D.clauses(), PrivateFilter); I; ++I) {
178*0a6a1f1dSLionel Sambuc auto *C = cast<OMPFirstprivateClause>(*I);
179*0a6a1f1dSLionel Sambuc auto IRef = C->varlist_begin();
180*0a6a1f1dSLionel Sambuc auto InitsRef = C->inits().begin();
181*0a6a1f1dSLionel Sambuc for (auto IInit : C->private_copies()) {
182*0a6a1f1dSLionel Sambuc auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
183*0a6a1f1dSLionel Sambuc auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
184*0a6a1f1dSLionel Sambuc bool IsRegistered;
185*0a6a1f1dSLionel Sambuc if (*InitsRef != nullptr) {
186*0a6a1f1dSLionel Sambuc // Emit VarDecl with copy init for arrays.
187*0a6a1f1dSLionel Sambuc auto *FD = CapturedStmtInfo->lookup(OrigVD);
188*0a6a1f1dSLionel Sambuc LValue Base = MakeNaturalAlignAddrLValue(
189*0a6a1f1dSLionel Sambuc CapturedStmtInfo->getContextValue(),
190*0a6a1f1dSLionel Sambuc getContext().getTagDeclType(FD->getParent()));
191*0a6a1f1dSLionel Sambuc auto OriginalAddr = EmitLValueForField(Base, FD);
192*0a6a1f1dSLionel Sambuc auto VDInit = cast<VarDecl>(cast<DeclRefExpr>(*InitsRef)->getDecl());
193*0a6a1f1dSLionel Sambuc IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> llvm::Value * {
194*0a6a1f1dSLionel Sambuc auto Emission = EmitAutoVarAlloca(*VD);
195*0a6a1f1dSLionel Sambuc // Emit initialization of aggregate firstprivate vars.
196*0a6a1f1dSLionel Sambuc EmitOMPAggregateAssign(OriginalAddr, Emission.getAllocatedAddress(),
197*0a6a1f1dSLionel Sambuc VD->getInit(), (*IRef)->getType(), VDInit);
198*0a6a1f1dSLionel Sambuc EmitAutoVarCleanups(Emission);
199*0a6a1f1dSLionel Sambuc return Emission.getAllocatedAddress();
200*0a6a1f1dSLionel Sambuc });
201*0a6a1f1dSLionel Sambuc } else
202*0a6a1f1dSLionel Sambuc IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> llvm::Value * {
203*0a6a1f1dSLionel Sambuc // Emit private VarDecl with copy init.
204*0a6a1f1dSLionel Sambuc EmitDecl(*VD);
205*0a6a1f1dSLionel Sambuc return GetAddrOfLocalVar(VD);
206*0a6a1f1dSLionel Sambuc });
207*0a6a1f1dSLionel Sambuc assert(IsRegistered && "counter already registered as private");
208*0a6a1f1dSLionel Sambuc // Silence the warning about unused variable.
209*0a6a1f1dSLionel Sambuc (void)IsRegistered;
210*0a6a1f1dSLionel Sambuc ++IRef, ++InitsRef;
211*0a6a1f1dSLionel Sambuc }
212*0a6a1f1dSLionel Sambuc }
213*0a6a1f1dSLionel Sambuc }
214*0a6a1f1dSLionel Sambuc
EmitOMPPrivateClause(const OMPExecutableDirective & D,CodeGenFunction::OMPPrivateScope & PrivateScope)215*0a6a1f1dSLionel Sambuc void CodeGenFunction::EmitOMPPrivateClause(
216*0a6a1f1dSLionel Sambuc const OMPExecutableDirective &D,
217*0a6a1f1dSLionel Sambuc CodeGenFunction::OMPPrivateScope &PrivateScope) {
218*0a6a1f1dSLionel Sambuc auto PrivateFilter = [](const OMPClause *C) -> bool {
219*0a6a1f1dSLionel Sambuc return C->getClauseKind() == OMPC_private;
220*0a6a1f1dSLionel Sambuc };
221*0a6a1f1dSLionel Sambuc for (OMPExecutableDirective::filtered_clause_iterator<decltype(PrivateFilter)>
222*0a6a1f1dSLionel Sambuc I(D.clauses(), PrivateFilter); I; ++I) {
223*0a6a1f1dSLionel Sambuc auto *C = cast<OMPPrivateClause>(*I);
224*0a6a1f1dSLionel Sambuc auto IRef = C->varlist_begin();
225*0a6a1f1dSLionel Sambuc for (auto IInit : C->private_copies()) {
226*0a6a1f1dSLionel Sambuc auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
227*0a6a1f1dSLionel Sambuc auto VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
228*0a6a1f1dSLionel Sambuc bool IsRegistered =
229*0a6a1f1dSLionel Sambuc PrivateScope.addPrivate(OrigVD, [&]() -> llvm::Value * {
230*0a6a1f1dSLionel Sambuc // Emit private VarDecl with copy init.
231*0a6a1f1dSLionel Sambuc EmitDecl(*VD);
232*0a6a1f1dSLionel Sambuc return GetAddrOfLocalVar(VD);
233*0a6a1f1dSLionel Sambuc });
234*0a6a1f1dSLionel Sambuc assert(IsRegistered && "counter already registered as private");
235*0a6a1f1dSLionel Sambuc // Silence the warning about unused variable.
236*0a6a1f1dSLionel Sambuc (void)IsRegistered;
237*0a6a1f1dSLionel Sambuc ++IRef;
238*0a6a1f1dSLionel Sambuc }
239*0a6a1f1dSLionel Sambuc }
240*0a6a1f1dSLionel Sambuc }
241*0a6a1f1dSLionel Sambuc
242*0a6a1f1dSLionel Sambuc /// \brief Emits code for OpenMP parallel directive in the parallel region.
EmitOMPParallelCall(CodeGenFunction & CGF,const OMPParallelDirective & S,llvm::Value * OutlinedFn,llvm::Value * CapturedStruct)243*0a6a1f1dSLionel Sambuc static void EmitOMPParallelCall(CodeGenFunction &CGF,
244*0a6a1f1dSLionel Sambuc const OMPParallelDirective &S,
245*0a6a1f1dSLionel Sambuc llvm::Value *OutlinedFn,
246*0a6a1f1dSLionel Sambuc llvm::Value *CapturedStruct) {
247*0a6a1f1dSLionel Sambuc if (auto C = S.getSingleClause(/*K*/ OMPC_num_threads)) {
248*0a6a1f1dSLionel Sambuc CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF);
249*0a6a1f1dSLionel Sambuc auto NumThreadsClause = cast<OMPNumThreadsClause>(C);
250*0a6a1f1dSLionel Sambuc auto NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads(),
251*0a6a1f1dSLionel Sambuc /*IgnoreResultAssign*/ true);
252*0a6a1f1dSLionel Sambuc CGF.CGM.getOpenMPRuntime().EmitOMPNumThreadsClause(
253*0a6a1f1dSLionel Sambuc CGF, NumThreads, NumThreadsClause->getLocStart());
254*0a6a1f1dSLionel Sambuc }
255*0a6a1f1dSLionel Sambuc CGF.CGM.getOpenMPRuntime().EmitOMPParallelCall(CGF, S.getLocStart(),
256*0a6a1f1dSLionel Sambuc OutlinedFn, CapturedStruct);
257*0a6a1f1dSLionel Sambuc }
258*0a6a1f1dSLionel Sambuc
EmitOMPParallelDirective(const OMPParallelDirective & S)259*0a6a1f1dSLionel Sambuc void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) {
260*0a6a1f1dSLionel Sambuc auto CS = cast<CapturedStmt>(S.getAssociatedStmt());
261*0a6a1f1dSLionel Sambuc auto CapturedStruct = GenerateCapturedStmtArgument(*CS);
262*0a6a1f1dSLionel Sambuc auto OutlinedFn = CGM.getOpenMPRuntime().EmitOpenMPOutlinedFunction(
263*0a6a1f1dSLionel Sambuc S, *CS->getCapturedDecl()->param_begin());
264*0a6a1f1dSLionel Sambuc if (auto C = S.getSingleClause(/*K*/ OMPC_if)) {
265*0a6a1f1dSLionel Sambuc auto Cond = cast<OMPIfClause>(C)->getCondition();
266*0a6a1f1dSLionel Sambuc EmitOMPIfClause(*this, Cond, [&](bool ThenBlock) {
267*0a6a1f1dSLionel Sambuc if (ThenBlock)
268*0a6a1f1dSLionel Sambuc EmitOMPParallelCall(*this, S, OutlinedFn, CapturedStruct);
269*0a6a1f1dSLionel Sambuc else
270*0a6a1f1dSLionel Sambuc CGM.getOpenMPRuntime().EmitOMPSerialCall(*this, S.getLocStart(),
271*0a6a1f1dSLionel Sambuc OutlinedFn, CapturedStruct);
272*0a6a1f1dSLionel Sambuc });
273*0a6a1f1dSLionel Sambuc } else
274*0a6a1f1dSLionel Sambuc EmitOMPParallelCall(*this, S, OutlinedFn, CapturedStruct);
275*0a6a1f1dSLionel Sambuc }
276*0a6a1f1dSLionel Sambuc
EmitOMPLoopBody(const OMPLoopDirective & S,bool SeparateIter)277*0a6a1f1dSLionel Sambuc void CodeGenFunction::EmitOMPLoopBody(const OMPLoopDirective &S,
278*0a6a1f1dSLionel Sambuc bool SeparateIter) {
279*0a6a1f1dSLionel Sambuc RunCleanupsScope BodyScope(*this);
280*0a6a1f1dSLionel Sambuc // Update counters values on current iteration.
281*0a6a1f1dSLionel Sambuc for (auto I : S.updates()) {
282*0a6a1f1dSLionel Sambuc EmitIgnoredExpr(I);
283*0a6a1f1dSLionel Sambuc }
284*0a6a1f1dSLionel Sambuc // On a continue in the body, jump to the end.
285*0a6a1f1dSLionel Sambuc auto Continue = getJumpDestInCurrentScope("omp.body.continue");
286*0a6a1f1dSLionel Sambuc BreakContinueStack.push_back(BreakContinue(JumpDest(), Continue));
287*0a6a1f1dSLionel Sambuc // Emit loop body.
288*0a6a1f1dSLionel Sambuc EmitStmt(S.getBody());
289*0a6a1f1dSLionel Sambuc // The end (updates/cleanups).
290*0a6a1f1dSLionel Sambuc EmitBlock(Continue.getBlock());
291*0a6a1f1dSLionel Sambuc BreakContinueStack.pop_back();
292*0a6a1f1dSLionel Sambuc if (SeparateIter) {
293*0a6a1f1dSLionel Sambuc // TODO: Update lastprivates if the SeparateIter flag is true.
294*0a6a1f1dSLionel Sambuc // This will be implemented in a follow-up OMPLastprivateClause patch, but
295*0a6a1f1dSLionel Sambuc // result should be still correct without it, as we do not make these
296*0a6a1f1dSLionel Sambuc // variables private yet.
297*0a6a1f1dSLionel Sambuc }
298*0a6a1f1dSLionel Sambuc }
299*0a6a1f1dSLionel Sambuc
EmitOMPInnerLoop(const OMPLoopDirective & S,OMPPrivateScope & LoopScope,bool SeparateIter)300*0a6a1f1dSLionel Sambuc void CodeGenFunction::EmitOMPInnerLoop(const OMPLoopDirective &S,
301*0a6a1f1dSLionel Sambuc OMPPrivateScope &LoopScope,
302*0a6a1f1dSLionel Sambuc bool SeparateIter) {
303*0a6a1f1dSLionel Sambuc auto LoopExit = getJumpDestInCurrentScope("omp.inner.for.end");
304*0a6a1f1dSLionel Sambuc auto Cnt = getPGORegionCounter(&S);
305*0a6a1f1dSLionel Sambuc
306*0a6a1f1dSLionel Sambuc // Start the loop with a block that tests the condition.
307*0a6a1f1dSLionel Sambuc auto CondBlock = createBasicBlock("omp.inner.for.cond");
308*0a6a1f1dSLionel Sambuc EmitBlock(CondBlock);
309*0a6a1f1dSLionel Sambuc LoopStack.push(CondBlock);
310*0a6a1f1dSLionel Sambuc
311*0a6a1f1dSLionel Sambuc // If there are any cleanups between here and the loop-exit scope,
312*0a6a1f1dSLionel Sambuc // create a block to stage a loop exit along.
313*0a6a1f1dSLionel Sambuc auto ExitBlock = LoopExit.getBlock();
314*0a6a1f1dSLionel Sambuc if (LoopScope.requiresCleanups())
315*0a6a1f1dSLionel Sambuc ExitBlock = createBasicBlock("omp.inner.for.cond.cleanup");
316*0a6a1f1dSLionel Sambuc
317*0a6a1f1dSLionel Sambuc auto LoopBody = createBasicBlock("omp.inner.for.body");
318*0a6a1f1dSLionel Sambuc
319*0a6a1f1dSLionel Sambuc // Emit condition: "IV < LastIteration + 1 [ - 1]"
320*0a6a1f1dSLionel Sambuc // ("- 1" when lastprivate clause is present - separate one iteration).
321*0a6a1f1dSLionel Sambuc llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond(SeparateIter));
322*0a6a1f1dSLionel Sambuc Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock,
323*0a6a1f1dSLionel Sambuc PGO.createLoopWeights(S.getCond(SeparateIter), Cnt));
324*0a6a1f1dSLionel Sambuc
325*0a6a1f1dSLionel Sambuc if (ExitBlock != LoopExit.getBlock()) {
326*0a6a1f1dSLionel Sambuc EmitBlock(ExitBlock);
327*0a6a1f1dSLionel Sambuc EmitBranchThroughCleanup(LoopExit);
328*0a6a1f1dSLionel Sambuc }
329*0a6a1f1dSLionel Sambuc
330*0a6a1f1dSLionel Sambuc EmitBlock(LoopBody);
331*0a6a1f1dSLionel Sambuc Cnt.beginRegion(Builder);
332*0a6a1f1dSLionel Sambuc
333*0a6a1f1dSLionel Sambuc // Create a block for the increment.
334*0a6a1f1dSLionel Sambuc auto Continue = getJumpDestInCurrentScope("omp.inner.for.inc");
335*0a6a1f1dSLionel Sambuc BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
336*0a6a1f1dSLionel Sambuc
337*0a6a1f1dSLionel Sambuc EmitOMPLoopBody(S);
338*0a6a1f1dSLionel Sambuc EmitStopPoint(&S);
339*0a6a1f1dSLionel Sambuc
340*0a6a1f1dSLionel Sambuc // Emit "IV = IV + 1" and a back-edge to the condition block.
341*0a6a1f1dSLionel Sambuc EmitBlock(Continue.getBlock());
342*0a6a1f1dSLionel Sambuc EmitIgnoredExpr(S.getInc());
343*0a6a1f1dSLionel Sambuc BreakContinueStack.pop_back();
344*0a6a1f1dSLionel Sambuc EmitBranch(CondBlock);
345*0a6a1f1dSLionel Sambuc LoopStack.pop();
346*0a6a1f1dSLionel Sambuc // Emit the fall-through block.
347*0a6a1f1dSLionel Sambuc EmitBlock(LoopExit.getBlock());
348*0a6a1f1dSLionel Sambuc }
349*0a6a1f1dSLionel Sambuc
EmitOMPSimdFinal(const OMPLoopDirective & S)350*0a6a1f1dSLionel Sambuc void CodeGenFunction::EmitOMPSimdFinal(const OMPLoopDirective &S) {
351*0a6a1f1dSLionel Sambuc auto IC = S.counters().begin();
352*0a6a1f1dSLionel Sambuc for (auto F : S.finals()) {
353*0a6a1f1dSLionel Sambuc if (LocalDeclMap.lookup(cast<DeclRefExpr>((*IC))->getDecl())) {
354*0a6a1f1dSLionel Sambuc EmitIgnoredExpr(F);
355*0a6a1f1dSLionel Sambuc }
356*0a6a1f1dSLionel Sambuc ++IC;
357*0a6a1f1dSLionel Sambuc }
358*0a6a1f1dSLionel Sambuc }
359*0a6a1f1dSLionel Sambuc
EmitOMPAlignedClause(CodeGenFunction & CGF,CodeGenModule & CGM,const OMPAlignedClause & Clause)360*0a6a1f1dSLionel Sambuc static void EmitOMPAlignedClause(CodeGenFunction &CGF, CodeGenModule &CGM,
361*0a6a1f1dSLionel Sambuc const OMPAlignedClause &Clause) {
362*0a6a1f1dSLionel Sambuc unsigned ClauseAlignment = 0;
363*0a6a1f1dSLionel Sambuc if (auto AlignmentExpr = Clause.getAlignment()) {
364*0a6a1f1dSLionel Sambuc auto AlignmentCI =
365*0a6a1f1dSLionel Sambuc cast<llvm::ConstantInt>(CGF.EmitScalarExpr(AlignmentExpr));
366*0a6a1f1dSLionel Sambuc ClauseAlignment = static_cast<unsigned>(AlignmentCI->getZExtValue());
367*0a6a1f1dSLionel Sambuc }
368*0a6a1f1dSLionel Sambuc for (auto E : Clause.varlists()) {
369*0a6a1f1dSLionel Sambuc unsigned Alignment = ClauseAlignment;
370*0a6a1f1dSLionel Sambuc if (Alignment == 0) {
371*0a6a1f1dSLionel Sambuc // OpenMP [2.8.1, Description]
372*0a6a1f1dSLionel Sambuc // If no optional parameter is specified, implementation-defined default
373*0a6a1f1dSLionel Sambuc // alignments for SIMD instructions on the target platforms are assumed.
374*0a6a1f1dSLionel Sambuc Alignment = CGM.getTargetCodeGenInfo().getOpenMPSimdDefaultAlignment(
375*0a6a1f1dSLionel Sambuc E->getType());
376*0a6a1f1dSLionel Sambuc }
377*0a6a1f1dSLionel Sambuc assert((Alignment == 0 || llvm::isPowerOf2_32(Alignment)) &&
378*0a6a1f1dSLionel Sambuc "alignment is not power of 2");
379*0a6a1f1dSLionel Sambuc if (Alignment != 0) {
380*0a6a1f1dSLionel Sambuc llvm::Value *PtrValue = CGF.EmitScalarExpr(E);
381*0a6a1f1dSLionel Sambuc CGF.EmitAlignmentAssumption(PtrValue, Alignment);
382*0a6a1f1dSLionel Sambuc }
383*0a6a1f1dSLionel Sambuc }
384*0a6a1f1dSLionel Sambuc }
385*0a6a1f1dSLionel Sambuc
EmitPrivateLoopCounters(CodeGenFunction & CGF,CodeGenFunction::OMPPrivateScope & LoopScope,ArrayRef<Expr * > Counters)386*0a6a1f1dSLionel Sambuc static void EmitPrivateLoopCounters(CodeGenFunction &CGF,
387*0a6a1f1dSLionel Sambuc CodeGenFunction::OMPPrivateScope &LoopScope,
388*0a6a1f1dSLionel Sambuc ArrayRef<Expr *> Counters) {
389*0a6a1f1dSLionel Sambuc for (auto *E : Counters) {
390*0a6a1f1dSLionel Sambuc auto VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
391*0a6a1f1dSLionel Sambuc bool IsRegistered = LoopScope.addPrivate(VD, [&]() -> llvm::Value * {
392*0a6a1f1dSLionel Sambuc // Emit var without initialization.
393*0a6a1f1dSLionel Sambuc auto VarEmission = CGF.EmitAutoVarAlloca(*VD);
394*0a6a1f1dSLionel Sambuc CGF.EmitAutoVarCleanups(VarEmission);
395*0a6a1f1dSLionel Sambuc return VarEmission.getAllocatedAddress();
396*0a6a1f1dSLionel Sambuc });
397*0a6a1f1dSLionel Sambuc assert(IsRegistered && "counter already registered as private");
398*0a6a1f1dSLionel Sambuc // Silence the warning about unused variable.
399*0a6a1f1dSLionel Sambuc (void)IsRegistered;
400*0a6a1f1dSLionel Sambuc }
401*0a6a1f1dSLionel Sambuc (void)LoopScope.Privatize();
402*0a6a1f1dSLionel Sambuc }
403*0a6a1f1dSLionel Sambuc
EmitOMPSimdDirective(const OMPSimdDirective & S)404*0a6a1f1dSLionel Sambuc void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) {
405*0a6a1f1dSLionel Sambuc // Pragma 'simd' code depends on presence of 'lastprivate'.
406*0a6a1f1dSLionel Sambuc // If present, we have to separate last iteration of the loop:
407*0a6a1f1dSLionel Sambuc //
408*0a6a1f1dSLionel Sambuc // if (LastIteration != 0) {
409*0a6a1f1dSLionel Sambuc // for (IV in 0..LastIteration-1) BODY;
410*0a6a1f1dSLionel Sambuc // BODY with updates of lastprivate vars;
411*0a6a1f1dSLionel Sambuc // <Final counter/linear vars updates>;
412*0a6a1f1dSLionel Sambuc // }
413*0a6a1f1dSLionel Sambuc //
414*0a6a1f1dSLionel Sambuc // otherwise (when there's no lastprivate):
415*0a6a1f1dSLionel Sambuc //
416*0a6a1f1dSLionel Sambuc // for (IV in 0..LastIteration) BODY;
417*0a6a1f1dSLionel Sambuc // <Final counter/linear vars updates>;
418*0a6a1f1dSLionel Sambuc //
419*0a6a1f1dSLionel Sambuc
420*0a6a1f1dSLionel Sambuc // Walk clauses and process safelen/lastprivate.
421*0a6a1f1dSLionel Sambuc bool SeparateIter = false;
422*0a6a1f1dSLionel Sambuc LoopStack.setParallel();
423*0a6a1f1dSLionel Sambuc LoopStack.setVectorizerEnable(true);
424*0a6a1f1dSLionel Sambuc for (auto C : S.clauses()) {
425*0a6a1f1dSLionel Sambuc switch (C->getClauseKind()) {
426*0a6a1f1dSLionel Sambuc case OMPC_safelen: {
427*0a6a1f1dSLionel Sambuc RValue Len = EmitAnyExpr(cast<OMPSafelenClause>(C)->getSafelen(),
428*0a6a1f1dSLionel Sambuc AggValueSlot::ignored(), true);
429*0a6a1f1dSLionel Sambuc llvm::ConstantInt *Val = cast<llvm::ConstantInt>(Len.getScalarVal());
430*0a6a1f1dSLionel Sambuc LoopStack.setVectorizerWidth(Val->getZExtValue());
431*0a6a1f1dSLionel Sambuc // In presence of finite 'safelen', it may be unsafe to mark all
432*0a6a1f1dSLionel Sambuc // the memory instructions parallel, because loop-carried
433*0a6a1f1dSLionel Sambuc // dependences of 'safelen' iterations are possible.
434*0a6a1f1dSLionel Sambuc LoopStack.setParallel(false);
435*0a6a1f1dSLionel Sambuc break;
436*0a6a1f1dSLionel Sambuc }
437*0a6a1f1dSLionel Sambuc case OMPC_aligned:
438*0a6a1f1dSLionel Sambuc EmitOMPAlignedClause(*this, CGM, cast<OMPAlignedClause>(*C));
439*0a6a1f1dSLionel Sambuc break;
440*0a6a1f1dSLionel Sambuc case OMPC_lastprivate:
441*0a6a1f1dSLionel Sambuc SeparateIter = true;
442*0a6a1f1dSLionel Sambuc break;
443*0a6a1f1dSLionel Sambuc default:
444*0a6a1f1dSLionel Sambuc // Not handled yet
445*0a6a1f1dSLionel Sambuc ;
446*0a6a1f1dSLionel Sambuc }
447*0a6a1f1dSLionel Sambuc }
448*0a6a1f1dSLionel Sambuc
449*0a6a1f1dSLionel Sambuc InlinedOpenMPRegion Region(*this, S.getAssociatedStmt());
450*0a6a1f1dSLionel Sambuc RunCleanupsScope DirectiveScope(*this);
451*0a6a1f1dSLionel Sambuc
452*0a6a1f1dSLionel Sambuc CGDebugInfo *DI = getDebugInfo();
453*0a6a1f1dSLionel Sambuc if (DI)
454*0a6a1f1dSLionel Sambuc DI->EmitLexicalBlockStart(Builder, S.getSourceRange().getBegin());
455*0a6a1f1dSLionel Sambuc
456*0a6a1f1dSLionel Sambuc // Emit the loop iteration variable.
457*0a6a1f1dSLionel Sambuc const Expr *IVExpr = S.getIterationVariable();
458*0a6a1f1dSLionel Sambuc const VarDecl *IVDecl = cast<VarDecl>(cast<DeclRefExpr>(IVExpr)->getDecl());
459*0a6a1f1dSLionel Sambuc EmitVarDecl(*IVDecl);
460*0a6a1f1dSLionel Sambuc EmitIgnoredExpr(S.getInit());
461*0a6a1f1dSLionel Sambuc
462*0a6a1f1dSLionel Sambuc // Emit the iterations count variable.
463*0a6a1f1dSLionel Sambuc // If it is not a variable, Sema decided to calculate iterations count on each
464*0a6a1f1dSLionel Sambuc // iteration (e.g., it is foldable into a constant).
465*0a6a1f1dSLionel Sambuc if (auto LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
466*0a6a1f1dSLionel Sambuc EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
467*0a6a1f1dSLionel Sambuc // Emit calculation of the iterations count.
468*0a6a1f1dSLionel Sambuc EmitIgnoredExpr(S.getCalcLastIteration());
469*0a6a1f1dSLionel Sambuc }
470*0a6a1f1dSLionel Sambuc
471*0a6a1f1dSLionel Sambuc if (SeparateIter) {
472*0a6a1f1dSLionel Sambuc // Emit: if (LastIteration > 0) - begin.
473*0a6a1f1dSLionel Sambuc RegionCounter Cnt = getPGORegionCounter(&S);
474*0a6a1f1dSLionel Sambuc auto ThenBlock = createBasicBlock("simd.if.then");
475*0a6a1f1dSLionel Sambuc auto ContBlock = createBasicBlock("simd.if.end");
476*0a6a1f1dSLionel Sambuc EmitBranchOnBoolExpr(S.getPreCond(), ThenBlock, ContBlock, Cnt.getCount());
477*0a6a1f1dSLionel Sambuc EmitBlock(ThenBlock);
478*0a6a1f1dSLionel Sambuc Cnt.beginRegion(Builder);
479*0a6a1f1dSLionel Sambuc // Emit 'then' code.
480*0a6a1f1dSLionel Sambuc {
481*0a6a1f1dSLionel Sambuc OMPPrivateScope LoopScope(*this);
482*0a6a1f1dSLionel Sambuc EmitPrivateLoopCounters(*this, LoopScope, S.counters());
483*0a6a1f1dSLionel Sambuc EmitOMPInnerLoop(S, LoopScope, /* SeparateIter */ true);
484*0a6a1f1dSLionel Sambuc EmitOMPLoopBody(S, /* SeparateIter */ true);
485*0a6a1f1dSLionel Sambuc }
486*0a6a1f1dSLionel Sambuc EmitOMPSimdFinal(S);
487*0a6a1f1dSLionel Sambuc // Emit: if (LastIteration != 0) - end.
488*0a6a1f1dSLionel Sambuc EmitBranch(ContBlock);
489*0a6a1f1dSLionel Sambuc EmitBlock(ContBlock, true);
490*0a6a1f1dSLionel Sambuc } else {
491*0a6a1f1dSLionel Sambuc {
492*0a6a1f1dSLionel Sambuc OMPPrivateScope LoopScope(*this);
493*0a6a1f1dSLionel Sambuc EmitPrivateLoopCounters(*this, LoopScope, S.counters());
494*0a6a1f1dSLionel Sambuc EmitOMPInnerLoop(S, LoopScope);
495*0a6a1f1dSLionel Sambuc }
496*0a6a1f1dSLionel Sambuc EmitOMPSimdFinal(S);
497*0a6a1f1dSLionel Sambuc }
498*0a6a1f1dSLionel Sambuc
499*0a6a1f1dSLionel Sambuc if (DI)
500*0a6a1f1dSLionel Sambuc DI->EmitLexicalBlockEnd(Builder, S.getSourceRange().getEnd());
501*0a6a1f1dSLionel Sambuc }
502*0a6a1f1dSLionel Sambuc
503*0a6a1f1dSLionel Sambuc /// \brief Emit a helper variable and return corresponding lvalue.
EmitOMPHelperVar(CodeGenFunction & CGF,const DeclRefExpr * Helper)504*0a6a1f1dSLionel Sambuc static LValue EmitOMPHelperVar(CodeGenFunction &CGF,
505*0a6a1f1dSLionel Sambuc const DeclRefExpr *Helper) {
506*0a6a1f1dSLionel Sambuc auto VDecl = cast<VarDecl>(Helper->getDecl());
507*0a6a1f1dSLionel Sambuc CGF.EmitVarDecl(*VDecl);
508*0a6a1f1dSLionel Sambuc return CGF.EmitLValue(Helper);
509*0a6a1f1dSLionel Sambuc }
510*0a6a1f1dSLionel Sambuc
EmitOMPWorksharingLoop(const OMPLoopDirective & S)511*0a6a1f1dSLionel Sambuc void CodeGenFunction::EmitOMPWorksharingLoop(const OMPLoopDirective &S) {
512*0a6a1f1dSLionel Sambuc // Emit the loop iteration variable.
513*0a6a1f1dSLionel Sambuc auto IVExpr = cast<DeclRefExpr>(S.getIterationVariable());
514*0a6a1f1dSLionel Sambuc auto IVDecl = cast<VarDecl>(IVExpr->getDecl());
515*0a6a1f1dSLionel Sambuc EmitVarDecl(*IVDecl);
516*0a6a1f1dSLionel Sambuc
517*0a6a1f1dSLionel Sambuc // Emit the iterations count variable.
518*0a6a1f1dSLionel Sambuc // If it is not a variable, Sema decided to calculate iterations count on each
519*0a6a1f1dSLionel Sambuc // iteration (e.g., it is foldable into a constant).
520*0a6a1f1dSLionel Sambuc if (auto LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
521*0a6a1f1dSLionel Sambuc EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
522*0a6a1f1dSLionel Sambuc // Emit calculation of the iterations count.
523*0a6a1f1dSLionel Sambuc EmitIgnoredExpr(S.getCalcLastIteration());
524*0a6a1f1dSLionel Sambuc }
525*0a6a1f1dSLionel Sambuc
526*0a6a1f1dSLionel Sambuc auto &RT = CGM.getOpenMPRuntime();
527*0a6a1f1dSLionel Sambuc
528*0a6a1f1dSLionel Sambuc // Check pre-condition.
529*0a6a1f1dSLionel Sambuc {
530*0a6a1f1dSLionel Sambuc // Skip the entire loop if we don't meet the precondition.
531*0a6a1f1dSLionel Sambuc RegionCounter Cnt = getPGORegionCounter(&S);
532*0a6a1f1dSLionel Sambuc auto ThenBlock = createBasicBlock("omp.precond.then");
533*0a6a1f1dSLionel Sambuc auto ContBlock = createBasicBlock("omp.precond.end");
534*0a6a1f1dSLionel Sambuc EmitBranchOnBoolExpr(S.getPreCond(), ThenBlock, ContBlock, Cnt.getCount());
535*0a6a1f1dSLionel Sambuc EmitBlock(ThenBlock);
536*0a6a1f1dSLionel Sambuc Cnt.beginRegion(Builder);
537*0a6a1f1dSLionel Sambuc // Emit 'then' code.
538*0a6a1f1dSLionel Sambuc {
539*0a6a1f1dSLionel Sambuc // Emit helper vars inits.
540*0a6a1f1dSLionel Sambuc LValue LB =
541*0a6a1f1dSLionel Sambuc EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getLowerBoundVariable()));
542*0a6a1f1dSLionel Sambuc LValue UB =
543*0a6a1f1dSLionel Sambuc EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getUpperBoundVariable()));
544*0a6a1f1dSLionel Sambuc LValue ST =
545*0a6a1f1dSLionel Sambuc EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getStrideVariable()));
546*0a6a1f1dSLionel Sambuc LValue IL =
547*0a6a1f1dSLionel Sambuc EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getIsLastIterVariable()));
548*0a6a1f1dSLionel Sambuc
549*0a6a1f1dSLionel Sambuc OMPPrivateScope LoopScope(*this);
550*0a6a1f1dSLionel Sambuc EmitPrivateLoopCounters(*this, LoopScope, S.counters());
551*0a6a1f1dSLionel Sambuc
552*0a6a1f1dSLionel Sambuc // Detect the loop schedule kind and chunk.
553*0a6a1f1dSLionel Sambuc auto ScheduleKind = OMPC_SCHEDULE_unknown;
554*0a6a1f1dSLionel Sambuc llvm::Value *Chunk = nullptr;
555*0a6a1f1dSLionel Sambuc if (auto C = cast_or_null<OMPScheduleClause>(
556*0a6a1f1dSLionel Sambuc S.getSingleClause(OMPC_schedule))) {
557*0a6a1f1dSLionel Sambuc ScheduleKind = C->getScheduleKind();
558*0a6a1f1dSLionel Sambuc if (auto Ch = C->getChunkSize()) {
559*0a6a1f1dSLionel Sambuc Chunk = EmitScalarExpr(Ch);
560*0a6a1f1dSLionel Sambuc Chunk = EmitScalarConversion(Chunk, Ch->getType(),
561*0a6a1f1dSLionel Sambuc S.getIterationVariable()->getType());
562*0a6a1f1dSLionel Sambuc }
563*0a6a1f1dSLionel Sambuc }
564*0a6a1f1dSLionel Sambuc const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
565*0a6a1f1dSLionel Sambuc const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
566*0a6a1f1dSLionel Sambuc if (RT.isStaticNonchunked(ScheduleKind,
567*0a6a1f1dSLionel Sambuc /* Chunked */ Chunk != nullptr)) {
568*0a6a1f1dSLionel Sambuc // OpenMP [2.7.1, Loop Construct, Description, table 2-1]
569*0a6a1f1dSLionel Sambuc // When no chunk_size is specified, the iteration space is divided into
570*0a6a1f1dSLionel Sambuc // chunks that are approximately equal in size, and at most one chunk is
571*0a6a1f1dSLionel Sambuc // distributed to each thread. Note that the size of the chunks is
572*0a6a1f1dSLionel Sambuc // unspecified in this case.
573*0a6a1f1dSLionel Sambuc RT.EmitOMPForInit(*this, S.getLocStart(), ScheduleKind, IVSize, IVSigned,
574*0a6a1f1dSLionel Sambuc IL.getAddress(), LB.getAddress(), UB.getAddress(),
575*0a6a1f1dSLionel Sambuc ST.getAddress());
576*0a6a1f1dSLionel Sambuc // UB = min(UB, GlobalUB);
577*0a6a1f1dSLionel Sambuc EmitIgnoredExpr(S.getEnsureUpperBound());
578*0a6a1f1dSLionel Sambuc // IV = LB;
579*0a6a1f1dSLionel Sambuc EmitIgnoredExpr(S.getInit());
580*0a6a1f1dSLionel Sambuc // while (idx <= UB) { BODY; ++idx; }
581*0a6a1f1dSLionel Sambuc EmitOMPInnerLoop(S, LoopScope);
582*0a6a1f1dSLionel Sambuc // Tell the runtime we are done.
583*0a6a1f1dSLionel Sambuc RT.EmitOMPForFinish(*this, S.getLocStart(), ScheduleKind);
584*0a6a1f1dSLionel Sambuc } else
585*0a6a1f1dSLionel Sambuc ErrorUnsupported(&S, "OpenMP loop with requested schedule");
586*0a6a1f1dSLionel Sambuc }
587*0a6a1f1dSLionel Sambuc // We're now done with the loop, so jump to the continuation block.
588*0a6a1f1dSLionel Sambuc EmitBranch(ContBlock);
589*0a6a1f1dSLionel Sambuc EmitBlock(ContBlock, true);
590*0a6a1f1dSLionel Sambuc }
591*0a6a1f1dSLionel Sambuc }
592*0a6a1f1dSLionel Sambuc
EmitOMPForDirective(const OMPForDirective & S)593*0a6a1f1dSLionel Sambuc void CodeGenFunction::EmitOMPForDirective(const OMPForDirective &S) {
594*0a6a1f1dSLionel Sambuc InlinedOpenMPRegion Region(*this, S.getAssociatedStmt());
595*0a6a1f1dSLionel Sambuc RunCleanupsScope DirectiveScope(*this);
596*0a6a1f1dSLionel Sambuc
597*0a6a1f1dSLionel Sambuc CGDebugInfo *DI = getDebugInfo();
598*0a6a1f1dSLionel Sambuc if (DI)
599*0a6a1f1dSLionel Sambuc DI->EmitLexicalBlockStart(Builder, S.getSourceRange().getBegin());
600*0a6a1f1dSLionel Sambuc
601*0a6a1f1dSLionel Sambuc EmitOMPWorksharingLoop(S);
602*0a6a1f1dSLionel Sambuc
603*0a6a1f1dSLionel Sambuc // Emit an implicit barrier at the end.
604*0a6a1f1dSLionel Sambuc CGM.getOpenMPRuntime().EmitOMPBarrierCall(*this, S.getLocStart(),
605*0a6a1f1dSLionel Sambuc /*IsExplicit*/ false);
606*0a6a1f1dSLionel Sambuc if (DI)
607*0a6a1f1dSLionel Sambuc DI->EmitLexicalBlockEnd(Builder, S.getSourceRange().getEnd());
608*0a6a1f1dSLionel Sambuc }
609*0a6a1f1dSLionel Sambuc
EmitOMPForSimdDirective(const OMPForSimdDirective &)610*0a6a1f1dSLionel Sambuc void CodeGenFunction::EmitOMPForSimdDirective(const OMPForSimdDirective &) {
611*0a6a1f1dSLionel Sambuc llvm_unreachable("CodeGen for 'omp for simd' is not supported yet.");
612*0a6a1f1dSLionel Sambuc }
613*0a6a1f1dSLionel Sambuc
EmitOMPSectionsDirective(const OMPSectionsDirective &)614*0a6a1f1dSLionel Sambuc void CodeGenFunction::EmitOMPSectionsDirective(const OMPSectionsDirective &) {
615*0a6a1f1dSLionel Sambuc llvm_unreachable("CodeGen for 'omp sections' is not supported yet.");
616*0a6a1f1dSLionel Sambuc }
617*0a6a1f1dSLionel Sambuc
EmitOMPSectionDirective(const OMPSectionDirective &)618*0a6a1f1dSLionel Sambuc void CodeGenFunction::EmitOMPSectionDirective(const OMPSectionDirective &) {
619*0a6a1f1dSLionel Sambuc llvm_unreachable("CodeGen for 'omp section' is not supported yet.");
620*0a6a1f1dSLionel Sambuc }
621*0a6a1f1dSLionel Sambuc
EmitOMPSingleDirective(const OMPSingleDirective &)622*0a6a1f1dSLionel Sambuc void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &) {
623*0a6a1f1dSLionel Sambuc llvm_unreachable("CodeGen for 'omp single' is not supported yet.");
624*0a6a1f1dSLionel Sambuc }
625*0a6a1f1dSLionel Sambuc
EmitOMPMasterDirective(const OMPMasterDirective & S)626*0a6a1f1dSLionel Sambuc void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &S) {
627*0a6a1f1dSLionel Sambuc CGM.getOpenMPRuntime().EmitOMPMasterRegion(*this, [&]() -> void {
628*0a6a1f1dSLionel Sambuc InlinedOpenMPRegion Region(*this, S.getAssociatedStmt());
629*0a6a1f1dSLionel Sambuc RunCleanupsScope Scope(*this);
630*0a6a1f1dSLionel Sambuc EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
631*0a6a1f1dSLionel Sambuc EnsureInsertPoint();
632*0a6a1f1dSLionel Sambuc }, S.getLocStart());
633*0a6a1f1dSLionel Sambuc }
634*0a6a1f1dSLionel Sambuc
EmitOMPCriticalDirective(const OMPCriticalDirective & S)635*0a6a1f1dSLionel Sambuc void CodeGenFunction::EmitOMPCriticalDirective(const OMPCriticalDirective &S) {
636*0a6a1f1dSLionel Sambuc CGM.getOpenMPRuntime().EmitOMPCriticalRegion(
637*0a6a1f1dSLionel Sambuc *this, S.getDirectiveName().getAsString(), [&]() -> void {
638*0a6a1f1dSLionel Sambuc InlinedOpenMPRegion Region(*this, S.getAssociatedStmt());
639*0a6a1f1dSLionel Sambuc RunCleanupsScope Scope(*this);
640*0a6a1f1dSLionel Sambuc EmitStmt(
641*0a6a1f1dSLionel Sambuc cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
642*0a6a1f1dSLionel Sambuc EnsureInsertPoint();
643*0a6a1f1dSLionel Sambuc }, S.getLocStart());
644*0a6a1f1dSLionel Sambuc }
645*0a6a1f1dSLionel Sambuc
646*0a6a1f1dSLionel Sambuc void
EmitOMPParallelForDirective(const OMPParallelForDirective &)647*0a6a1f1dSLionel Sambuc CodeGenFunction::EmitOMPParallelForDirective(const OMPParallelForDirective &) {
648*0a6a1f1dSLionel Sambuc llvm_unreachable("CodeGen for 'omp parallel for' is not supported yet.");
649*0a6a1f1dSLionel Sambuc }
650*0a6a1f1dSLionel Sambuc
EmitOMPParallelForSimdDirective(const OMPParallelForSimdDirective &)651*0a6a1f1dSLionel Sambuc void CodeGenFunction::EmitOMPParallelForSimdDirective(
652*0a6a1f1dSLionel Sambuc const OMPParallelForSimdDirective &) {
653*0a6a1f1dSLionel Sambuc llvm_unreachable("CodeGen for 'omp parallel for simd' is not supported yet.");
654*0a6a1f1dSLionel Sambuc }
655*0a6a1f1dSLionel Sambuc
EmitOMPParallelSectionsDirective(const OMPParallelSectionsDirective &)656*0a6a1f1dSLionel Sambuc void CodeGenFunction::EmitOMPParallelSectionsDirective(
657*0a6a1f1dSLionel Sambuc const OMPParallelSectionsDirective &) {
658*0a6a1f1dSLionel Sambuc llvm_unreachable("CodeGen for 'omp parallel sections' is not supported yet.");
659*0a6a1f1dSLionel Sambuc }
660*0a6a1f1dSLionel Sambuc
EmitOMPTaskDirective(const OMPTaskDirective &)661*0a6a1f1dSLionel Sambuc void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &) {
662*0a6a1f1dSLionel Sambuc llvm_unreachable("CodeGen for 'omp task' is not supported yet.");
663*0a6a1f1dSLionel Sambuc }
664*0a6a1f1dSLionel Sambuc
EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &)665*0a6a1f1dSLionel Sambuc void CodeGenFunction::EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &) {
666*0a6a1f1dSLionel Sambuc llvm_unreachable("CodeGen for 'omp taskyield' is not supported yet.");
667*0a6a1f1dSLionel Sambuc }
668*0a6a1f1dSLionel Sambuc
EmitOMPBarrierDirective(const OMPBarrierDirective & S)669*0a6a1f1dSLionel Sambuc void CodeGenFunction::EmitOMPBarrierDirective(const OMPBarrierDirective &S) {
670*0a6a1f1dSLionel Sambuc CGM.getOpenMPRuntime().EmitOMPBarrierCall(*this, S.getLocStart());
671*0a6a1f1dSLionel Sambuc }
672*0a6a1f1dSLionel Sambuc
EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &)673*0a6a1f1dSLionel Sambuc void CodeGenFunction::EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &) {
674*0a6a1f1dSLionel Sambuc llvm_unreachable("CodeGen for 'omp taskwait' is not supported yet.");
675*0a6a1f1dSLionel Sambuc }
676*0a6a1f1dSLionel Sambuc
EmitOMPFlushDirective(const OMPFlushDirective & S)677*0a6a1f1dSLionel Sambuc void CodeGenFunction::EmitOMPFlushDirective(const OMPFlushDirective &S) {
678*0a6a1f1dSLionel Sambuc CGM.getOpenMPRuntime().EmitOMPFlush(
679*0a6a1f1dSLionel Sambuc *this, [&]() -> ArrayRef<const Expr *> {
680*0a6a1f1dSLionel Sambuc if (auto C = S.getSingleClause(/*K*/ OMPC_flush)) {
681*0a6a1f1dSLionel Sambuc auto FlushClause = cast<OMPFlushClause>(C);
682*0a6a1f1dSLionel Sambuc return llvm::makeArrayRef(FlushClause->varlist_begin(),
683*0a6a1f1dSLionel Sambuc FlushClause->varlist_end());
684*0a6a1f1dSLionel Sambuc }
685*0a6a1f1dSLionel Sambuc return llvm::None;
686*0a6a1f1dSLionel Sambuc }(),
687*0a6a1f1dSLionel Sambuc S.getLocStart());
688*0a6a1f1dSLionel Sambuc }
689*0a6a1f1dSLionel Sambuc
EmitOMPOrderedDirective(const OMPOrderedDirective &)690*0a6a1f1dSLionel Sambuc void CodeGenFunction::EmitOMPOrderedDirective(const OMPOrderedDirective &) {
691*0a6a1f1dSLionel Sambuc llvm_unreachable("CodeGen for 'omp ordered' is not supported yet.");
692*0a6a1f1dSLionel Sambuc }
693*0a6a1f1dSLionel Sambuc
EmitOMPAtomicDirective(const OMPAtomicDirective &)694*0a6a1f1dSLionel Sambuc void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &) {
695*0a6a1f1dSLionel Sambuc llvm_unreachable("CodeGen for 'omp atomic' is not supported yet.");
696*0a6a1f1dSLionel Sambuc }
697*0a6a1f1dSLionel Sambuc
EmitOMPTargetDirective(const OMPTargetDirective &)698*0a6a1f1dSLionel Sambuc void CodeGenFunction::EmitOMPTargetDirective(const OMPTargetDirective &) {
699*0a6a1f1dSLionel Sambuc llvm_unreachable("CodeGen for 'omp target' is not supported yet.");
700*0a6a1f1dSLionel Sambuc }
701*0a6a1f1dSLionel Sambuc
EmitOMPTeamsDirective(const OMPTeamsDirective &)702*0a6a1f1dSLionel Sambuc void CodeGenFunction::EmitOMPTeamsDirective(const OMPTeamsDirective &) {
703*0a6a1f1dSLionel Sambuc llvm_unreachable("CodeGen for 'omp teams' is not supported yet.");
704*0a6a1f1dSLionel Sambuc }
705*0a6a1f1dSLionel Sambuc
706