xref: /minix3/external/bsd/llvm/dist/clang/lib/CodeGen/CGStmtOpenMP.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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