1ae6e499dSEric Schweitz //===-- OpenMP.cpp -- Open MP directive lowering --------------------------===//
2ae6e499dSEric Schweitz //
3ae6e499dSEric Schweitz // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4ae6e499dSEric Schweitz // See https://llvm.org/LICENSE.txt for license information.
5ae6e499dSEric Schweitz // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ae6e499dSEric Schweitz //
7ae6e499dSEric Schweitz //===----------------------------------------------------------------------===//
83d0b7602SSourabh Singh Tomar //
93d0b7602SSourabh Singh Tomar // Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
103d0b7602SSourabh Singh Tomar //
113d0b7602SSourabh Singh Tomar //===----------------------------------------------------------------------===//
12ae6e499dSEric Schweitz
13ae6e499dSEric Schweitz #include "flang/Lower/OpenMP.h"
141d328446SSourabh Singh Tomar #include "flang/Common/idioms.h"
15c3477c51SEric Schweitz #include "flang/Lower/Bridge.h"
16dc4bf2c3SMats Petersson #include "flang/Lower/ConvertExpr.h"
17ae6e499dSEric Schweitz #include "flang/Lower/PFTBuilder.h"
18d0b70a07SValentin Clement #include "flang/Lower/StatementContext.h"
198a0d0a3aSValentin Clement #include "flang/Optimizer/Builder/BoxValue.h"
208a0d0a3aSValentin Clement #include "flang/Optimizer/Builder/FIRBuilder.h"
215b66cc10SValentin Clement #include "flang/Optimizer/Builder/Todo.h"
22ae6e499dSEric Schweitz #include "flang/Parser/parse-tree.h"
2334b08487SSourabh Singh Tomar #include "flang/Semantics/tools.h"
243d0b7602SSourabh Singh Tomar #include "mlir/Dialect/OpenMP/OpenMPDialect.h"
2517d9bdf4SArnamoy Bhattacharyya #include "mlir/Dialect/SCF/IR/SCF.h"
263d0b7602SSourabh Singh Tomar #include "llvm/Frontend/OpenMP/OMPConstants.h"
27ae6e499dSEric Schweitz
28092601d4SAndrzej Warzynski using namespace mlir;
29092601d4SAndrzej Warzynski
getCollapseValue(const Fortran::parser::OmpClauseList & clauseList)303b390a16SMats Petersson int64_t Fortran::lower::getCollapseValue(
313b390a16SMats Petersson const Fortran::parser::OmpClauseList &clauseList) {
323b390a16SMats Petersson for (const auto &clause : clauseList.v) {
333b390a16SMats Petersson if (const auto &collapseClause =
343b390a16SMats Petersson std::get_if<Fortran::parser::OmpClause::Collapse>(&clause.u)) {
353b390a16SMats Petersson const auto *expr = Fortran::semantics::GetExpr(collapseClause->v);
363b390a16SMats Petersson return Fortran::evaluate::ToInt64(*expr).value();
373b390a16SMats Petersson }
383b390a16SMats Petersson }
393b390a16SMats Petersson return 1;
403b390a16SMats Petersson }
413b390a16SMats Petersson
421d328446SSourabh Singh Tomar static const Fortran::parser::Name *
getDesignatorNameIfDataRef(const Fortran::parser::Designator & designator)431d328446SSourabh Singh Tomar getDesignatorNameIfDataRef(const Fortran::parser::Designator &designator) {
441d328446SSourabh Singh Tomar const auto *dataRef = std::get_if<Fortran::parser::DataRef>(&designator.u);
451d328446SSourabh Singh Tomar return dataRef ? std::get_if<Fortran::parser::Name>(&dataRef->u) : nullptr;
461d328446SSourabh Singh Tomar }
471d328446SSourabh Singh Tomar
48bc99d565SPeixinQiao static Fortran::semantics::Symbol *
getOmpObjectSymbol(const Fortran::parser::OmpObject & ompObject)49bc99d565SPeixinQiao getOmpObjectSymbol(const Fortran::parser::OmpObject &ompObject) {
5007e16a2aSKiran Chandramohan Fortran::semantics::Symbol *sym = nullptr;
51bc99d565SPeixinQiao std::visit(Fortran::common::visitors{
521d328446SSourabh Singh Tomar [&](const Fortran::parser::Designator &designator) {
5307e16a2aSKiran Chandramohan if (const Fortran::parser::Name *name =
5407e16a2aSKiran Chandramohan getDesignatorNameIfDataRef(designator)) {
5507e16a2aSKiran Chandramohan sym = name->symbol;
5607e16a2aSKiran Chandramohan }
5707e16a2aSKiran Chandramohan },
5807e16a2aSKiran Chandramohan [&](const Fortran::parser::Name &name) { sym = name.symbol; }},
5907e16a2aSKiran Chandramohan ompObject.u);
60bc99d565SPeixinQiao return sym;
61bc99d565SPeixinQiao }
6207e16a2aSKiran Chandramohan
63bc99d565SPeixinQiao template <typename T>
createPrivateVarSyms(Fortran::lower::AbstractConverter & converter,const T * clause,Block * lastPrivBlock=nullptr)64bc99d565SPeixinQiao static void createPrivateVarSyms(Fortran::lower::AbstractConverter &converter,
6517d9bdf4SArnamoy Bhattacharyya const T *clause,
6617d9bdf4SArnamoy Bhattacharyya Block *lastPrivBlock = nullptr) {
67bc99d565SPeixinQiao const Fortran::parser::OmpObjectList &ompObjectList = clause->v;
68bc99d565SPeixinQiao for (const Fortran::parser::OmpObject &ompObject : ompObjectList.v) {
69bc99d565SPeixinQiao Fortran::semantics::Symbol *sym = getOmpObjectSymbol(ompObject);
7007e16a2aSKiran Chandramohan // Privatization for symbols which are pre-determined (like loop index
71c030f467SKiran Chandramohan // variables) happen separately, for everything else privatize here.
72c030f467SKiran Chandramohan if (sym->test(Fortran::semantics::Symbol::Flag::OmpPreDetermined))
73c030f467SKiran Chandramohan continue;
7407e16a2aSKiran Chandramohan bool success = converter.createHostAssociateVarClone(*sym);
7507e16a2aSKiran Chandramohan (void)success;
7607e16a2aSKiran Chandramohan assert(success && "Privatization failed due to existing binding");
7727afb362SPeixin-Qiao if constexpr (std::is_same_v<T, Fortran::parser::OmpClause::Firstprivate>) {
7827afb362SPeixin-Qiao converter.copyHostAssociateVar(*sym);
7917d9bdf4SArnamoy Bhattacharyya } else if constexpr (std::is_same_v<
8017d9bdf4SArnamoy Bhattacharyya T, Fortran::parser::OmpClause::Lastprivate>) {
8117d9bdf4SArnamoy Bhattacharyya converter.copyHostAssociateVar(*sym, lastPrivBlock);
8207e16a2aSKiran Chandramohan }
8307e16a2aSKiran Chandramohan }
8407e16a2aSKiran Chandramohan }
8507e16a2aSKiran Chandramohan
8617d9bdf4SArnamoy Bhattacharyya template <typename Op>
privatizeVars(Op & op,Fortran::lower::AbstractConverter & converter,const Fortran::parser::OmpClauseList & opClauseList)8717d9bdf4SArnamoy Bhattacharyya static bool privatizeVars(Op &op, Fortran::lower::AbstractConverter &converter,
88*f2b7f18eSShraiysh Vaishay const Fortran::parser::OmpClauseList &opClauseList) {
8907e16a2aSKiran Chandramohan fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
9007e16a2aSKiran Chandramohan auto insPt = firOpBuilder.saveInsertionPoint();
9107e16a2aSKiran Chandramohan firOpBuilder.setInsertionPointToStart(firOpBuilder.getAllocaBlock());
92c858f4dbSShraiysh Vaishay bool hasFirstPrivateOp = false;
9317d9bdf4SArnamoy Bhattacharyya bool hasLastPrivateOp = false;
9417d9bdf4SArnamoy Bhattacharyya // We need just one ICmpOp for multiple LastPrivate clauses.
9517d9bdf4SArnamoy Bhattacharyya mlir::arith::CmpIOp cmpOp;
96*f2b7f18eSShraiysh Vaishay
9707e16a2aSKiran Chandramohan for (const Fortran::parser::OmpClause &clause : opClauseList.v) {
9807e16a2aSKiran Chandramohan if (const auto &privateClause =
9907e16a2aSKiran Chandramohan std::get_if<Fortran::parser::OmpClause::Private>(&clause.u)) {
100*f2b7f18eSShraiysh Vaishay createPrivateVarSyms(converter, privateClause);
10107e16a2aSKiran Chandramohan } else if (const auto &firstPrivateClause =
10207e16a2aSKiran Chandramohan std::get_if<Fortran::parser::OmpClause::Firstprivate>(
10307e16a2aSKiran Chandramohan &clause.u)) {
104*f2b7f18eSShraiysh Vaishay createPrivateVarSyms(converter, firstPrivateClause);
105c858f4dbSShraiysh Vaishay hasFirstPrivateOp = true;
10617d9bdf4SArnamoy Bhattacharyya } else if (const auto &lastPrivateClause =
10717d9bdf4SArnamoy Bhattacharyya std::get_if<Fortran::parser::OmpClause::Lastprivate>(
10817d9bdf4SArnamoy Bhattacharyya &clause.u)) {
10917d9bdf4SArnamoy Bhattacharyya // TODO: Add lastprivate support for sections construct, simd construct
11017d9bdf4SArnamoy Bhattacharyya if (std::is_same_v<Op, omp::WsLoopOp>) {
11117d9bdf4SArnamoy Bhattacharyya omp::WsLoopOp *wsLoopOp = dyn_cast<omp::WsLoopOp>(&op);
11217d9bdf4SArnamoy Bhattacharyya fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
11317d9bdf4SArnamoy Bhattacharyya auto insPt = firOpBuilder.saveInsertionPoint();
11417d9bdf4SArnamoy Bhattacharyya
11517d9bdf4SArnamoy Bhattacharyya // Our goal here is to introduce the following control flow
11617d9bdf4SArnamoy Bhattacharyya // just before exiting the worksharing loop.
11717d9bdf4SArnamoy Bhattacharyya // Say our wsloop is as follows:
11817d9bdf4SArnamoy Bhattacharyya //
11917d9bdf4SArnamoy Bhattacharyya // omp.wsloop {
12017d9bdf4SArnamoy Bhattacharyya // ...
12117d9bdf4SArnamoy Bhattacharyya // store
12217d9bdf4SArnamoy Bhattacharyya // omp.yield
12317d9bdf4SArnamoy Bhattacharyya // }
12417d9bdf4SArnamoy Bhattacharyya //
12517d9bdf4SArnamoy Bhattacharyya // We want to convert it to the following:
12617d9bdf4SArnamoy Bhattacharyya //
12717d9bdf4SArnamoy Bhattacharyya // omp.wsloop {
12817d9bdf4SArnamoy Bhattacharyya // ...
12917d9bdf4SArnamoy Bhattacharyya // store
13017d9bdf4SArnamoy Bhattacharyya // %cmp = llvm.icmp "eq" %iv %ub
13117d9bdf4SArnamoy Bhattacharyya // scf.if %cmp {
13217d9bdf4SArnamoy Bhattacharyya // ^%lpv_update_blk:
13317d9bdf4SArnamoy Bhattacharyya // }
13417d9bdf4SArnamoy Bhattacharyya // omp.yield
13517d9bdf4SArnamoy Bhattacharyya // }
13617d9bdf4SArnamoy Bhattacharyya
13717d9bdf4SArnamoy Bhattacharyya Operation *lastOper = wsLoopOp->region().back().getTerminator();
13817d9bdf4SArnamoy Bhattacharyya
13917d9bdf4SArnamoy Bhattacharyya firOpBuilder.setInsertionPoint(lastOper);
14017d9bdf4SArnamoy Bhattacharyya
14117d9bdf4SArnamoy Bhattacharyya // TODO: The following will not work when there is collapse present.
14217d9bdf4SArnamoy Bhattacharyya // Have to modify this in future.
14317d9bdf4SArnamoy Bhattacharyya for (const Fortran::parser::OmpClause &clause : opClauseList.v)
14417d9bdf4SArnamoy Bhattacharyya if (const auto &collapseClause =
14517d9bdf4SArnamoy Bhattacharyya std::get_if<Fortran::parser::OmpClause::Collapse>(&clause.u))
14617d9bdf4SArnamoy Bhattacharyya TODO(converter.getCurrentLocation(),
14717d9bdf4SArnamoy Bhattacharyya "Collapse clause with lastprivate");
14817d9bdf4SArnamoy Bhattacharyya // Only generate the compare once in presence of multiple LastPrivate
14917d9bdf4SArnamoy Bhattacharyya // clauses
15017d9bdf4SArnamoy Bhattacharyya if (!hasLastPrivateOp) {
15117d9bdf4SArnamoy Bhattacharyya cmpOp = firOpBuilder.create<mlir::arith::CmpIOp>(
15217d9bdf4SArnamoy Bhattacharyya wsLoopOp->getLoc(), mlir::arith::CmpIPredicate::eq,
15317d9bdf4SArnamoy Bhattacharyya wsLoopOp->getRegion().front().getArguments()[0],
15417d9bdf4SArnamoy Bhattacharyya wsLoopOp->upperBound()[0]);
15517d9bdf4SArnamoy Bhattacharyya }
15617d9bdf4SArnamoy Bhattacharyya mlir::scf::IfOp ifOp = firOpBuilder.create<mlir::scf::IfOp>(
15717d9bdf4SArnamoy Bhattacharyya wsLoopOp->getLoc(), cmpOp, /*else*/ false);
15817d9bdf4SArnamoy Bhattacharyya
15917d9bdf4SArnamoy Bhattacharyya firOpBuilder.restoreInsertionPoint(insPt);
16017d9bdf4SArnamoy Bhattacharyya createPrivateVarSyms(converter, lastPrivateClause,
16117d9bdf4SArnamoy Bhattacharyya &(ifOp.getThenRegion().front()));
16217d9bdf4SArnamoy Bhattacharyya } else {
16317d9bdf4SArnamoy Bhattacharyya TODO(converter.getCurrentLocation(),
16417d9bdf4SArnamoy Bhattacharyya "lastprivate clause in constructs other than work-share loop");
16517d9bdf4SArnamoy Bhattacharyya }
16617d9bdf4SArnamoy Bhattacharyya hasLastPrivateOp = true;
16707e16a2aSKiran Chandramohan }
16807e16a2aSKiran Chandramohan }
169*f2b7f18eSShraiysh Vaishay if (hasFirstPrivateOp)
170c858f4dbSShraiysh Vaishay firOpBuilder.create<mlir::omp::BarrierOp>(converter.getCurrentLocation());
17107e16a2aSKiran Chandramohan firOpBuilder.restoreInsertionPoint(insPt);
17217d9bdf4SArnamoy Bhattacharyya return hasLastPrivateOp;
17307e16a2aSKiran Chandramohan }
17407e16a2aSKiran Chandramohan
175411bd2d4SPeixin-Qiao /// The COMMON block is a global structure. \p commonValue is the base address
176411bd2d4SPeixin-Qiao /// of the the COMMON block. As the offset from the symbol \p sym, generate the
177411bd2d4SPeixin-Qiao /// COMMON block member value (commonValue + offset) for the symbol.
178411bd2d4SPeixin-Qiao /// FIXME: Share the code with `instantiateCommon` in ConvertVariable.cpp.
179411bd2d4SPeixin-Qiao static mlir::Value
genCommonBlockMember(Fortran::lower::AbstractConverter & converter,const Fortran::semantics::Symbol & sym,mlir::Value commonValue)180411bd2d4SPeixin-Qiao genCommonBlockMember(Fortran::lower::AbstractConverter &converter,
181411bd2d4SPeixin-Qiao const Fortran::semantics::Symbol &sym,
182411bd2d4SPeixin-Qiao mlir::Value commonValue) {
183411bd2d4SPeixin-Qiao auto &firOpBuilder = converter.getFirOpBuilder();
184411bd2d4SPeixin-Qiao mlir::Location currentLocation = converter.getCurrentLocation();
185411bd2d4SPeixin-Qiao mlir::IntegerType i8Ty = firOpBuilder.getIntegerType(8);
186411bd2d4SPeixin-Qiao mlir::Type i8Ptr = firOpBuilder.getRefType(i8Ty);
187411bd2d4SPeixin-Qiao mlir::Type seqTy = firOpBuilder.getRefType(firOpBuilder.getVarLenSeqTy(i8Ty));
188411bd2d4SPeixin-Qiao mlir::Value base =
189411bd2d4SPeixin-Qiao firOpBuilder.createConvert(currentLocation, seqTy, commonValue);
190411bd2d4SPeixin-Qiao std::size_t byteOffset = sym.GetUltimate().offset();
191411bd2d4SPeixin-Qiao mlir::Value offs = firOpBuilder.createIntegerConstant(
192411bd2d4SPeixin-Qiao currentLocation, firOpBuilder.getIndexType(), byteOffset);
193411bd2d4SPeixin-Qiao mlir::Value varAddr = firOpBuilder.create<fir::CoordinateOp>(
194411bd2d4SPeixin-Qiao currentLocation, i8Ptr, base, mlir::ValueRange{offs});
195411bd2d4SPeixin-Qiao mlir::Type symType = converter.genType(sym);
196411bd2d4SPeixin-Qiao return firOpBuilder.createConvert(currentLocation,
197411bd2d4SPeixin-Qiao firOpBuilder.getRefType(symType), varAddr);
198411bd2d4SPeixin-Qiao }
199411bd2d4SPeixin-Qiao
200411bd2d4SPeixin-Qiao // Get the extended value for \p val by extracting additional variable
201411bd2d4SPeixin-Qiao // information from \p base.
getExtendedValue(fir::ExtendedValue base,mlir::Value val)202411bd2d4SPeixin-Qiao static fir::ExtendedValue getExtendedValue(fir::ExtendedValue base,
203411bd2d4SPeixin-Qiao mlir::Value val) {
204411bd2d4SPeixin-Qiao return base.match(
205411bd2d4SPeixin-Qiao [&](const fir::MutableBoxValue &box) -> fir::ExtendedValue {
206411bd2d4SPeixin-Qiao return fir::MutableBoxValue(val, box.nonDeferredLenParams(), {});
207411bd2d4SPeixin-Qiao },
208411bd2d4SPeixin-Qiao [&](const auto &) -> fir::ExtendedValue {
209411bd2d4SPeixin-Qiao return fir::substBase(base, val);
210411bd2d4SPeixin-Qiao });
211411bd2d4SPeixin-Qiao }
212411bd2d4SPeixin-Qiao
threadPrivatizeVars(Fortran::lower::AbstractConverter & converter,Fortran::lower::pft::Evaluation & eval)213411bd2d4SPeixin-Qiao static void threadPrivatizeVars(Fortran::lower::AbstractConverter &converter,
214411bd2d4SPeixin-Qiao Fortran::lower::pft::Evaluation &eval) {
215411bd2d4SPeixin-Qiao auto &firOpBuilder = converter.getFirOpBuilder();
216411bd2d4SPeixin-Qiao mlir::Location currentLocation = converter.getCurrentLocation();
217411bd2d4SPeixin-Qiao auto insPt = firOpBuilder.saveInsertionPoint();
218411bd2d4SPeixin-Qiao firOpBuilder.setInsertionPointToStart(firOpBuilder.getAllocaBlock());
219411bd2d4SPeixin-Qiao
220411bd2d4SPeixin-Qiao // Get the original ThreadprivateOp corresponding to the symbol and use the
221411bd2d4SPeixin-Qiao // symbol value from that opeartion to create one ThreadprivateOp copy
222411bd2d4SPeixin-Qiao // operation inside the parallel region.
223411bd2d4SPeixin-Qiao auto genThreadprivateOp = [&](Fortran::lower::SymbolRef sym) -> mlir::Value {
224411bd2d4SPeixin-Qiao mlir::Value symOriThreadprivateValue = converter.getSymbolAddress(sym);
225411bd2d4SPeixin-Qiao mlir::Operation *op = symOriThreadprivateValue.getDefiningOp();
226411bd2d4SPeixin-Qiao assert(mlir::isa<mlir::omp::ThreadprivateOp>(op) &&
227411bd2d4SPeixin-Qiao "The threadprivate operation not created");
228411bd2d4SPeixin-Qiao mlir::Value symValue =
229411bd2d4SPeixin-Qiao mlir::dyn_cast<mlir::omp::ThreadprivateOp>(op).sym_addr();
230411bd2d4SPeixin-Qiao return firOpBuilder.create<mlir::omp::ThreadprivateOp>(
231411bd2d4SPeixin-Qiao currentLocation, symValue.getType(), symValue);
232411bd2d4SPeixin-Qiao };
233411bd2d4SPeixin-Qiao
234411bd2d4SPeixin-Qiao llvm::SetVector<const Fortran::semantics::Symbol *> threadprivateSyms;
23527afb362SPeixin-Qiao converter.collectSymbolSet(eval, threadprivateSyms,
23627afb362SPeixin-Qiao Fortran::semantics::Symbol::Flag::OmpThreadprivate,
23727afb362SPeixin-Qiao /*isUltimateSymbol=*/false);
23827afb362SPeixin-Qiao std::set<Fortran::semantics::SourceName> threadprivateSymNames;
239411bd2d4SPeixin-Qiao
240411bd2d4SPeixin-Qiao // For a COMMON block, the ThreadprivateOp is generated for itself instead of
241411bd2d4SPeixin-Qiao // its members, so only bind the value of the new copied ThreadprivateOp
242411bd2d4SPeixin-Qiao // inside the parallel region to the common block symbol only once for
243411bd2d4SPeixin-Qiao // multiple members in one COMMON block.
244411bd2d4SPeixin-Qiao llvm::SetVector<const Fortran::semantics::Symbol *> commonSyms;
245411bd2d4SPeixin-Qiao for (std::size_t i = 0; i < threadprivateSyms.size(); i++) {
246411bd2d4SPeixin-Qiao auto sym = threadprivateSyms[i];
247411bd2d4SPeixin-Qiao mlir::Value symThreadprivateValue;
24827afb362SPeixin-Qiao // The variable may be used more than once, and each reference has one
24927afb362SPeixin-Qiao // symbol with the same name. Only do once for references of one variable.
25027afb362SPeixin-Qiao if (threadprivateSymNames.find(sym->name()) != threadprivateSymNames.end())
25127afb362SPeixin-Qiao continue;
25227afb362SPeixin-Qiao threadprivateSymNames.insert(sym->name());
253411bd2d4SPeixin-Qiao if (const Fortran::semantics::Symbol *common =
254411bd2d4SPeixin-Qiao Fortran::semantics::FindCommonBlockContaining(sym->GetUltimate())) {
255411bd2d4SPeixin-Qiao mlir::Value commonThreadprivateValue;
256411bd2d4SPeixin-Qiao if (commonSyms.contains(common)) {
257411bd2d4SPeixin-Qiao commonThreadprivateValue = converter.getSymbolAddress(*common);
258411bd2d4SPeixin-Qiao } else {
259411bd2d4SPeixin-Qiao commonThreadprivateValue = genThreadprivateOp(*common);
260411bd2d4SPeixin-Qiao converter.bindSymbol(*common, commonThreadprivateValue);
261411bd2d4SPeixin-Qiao commonSyms.insert(common);
262411bd2d4SPeixin-Qiao }
263411bd2d4SPeixin-Qiao symThreadprivateValue =
264411bd2d4SPeixin-Qiao genCommonBlockMember(converter, *sym, commonThreadprivateValue);
265411bd2d4SPeixin-Qiao } else {
266411bd2d4SPeixin-Qiao symThreadprivateValue = genThreadprivateOp(*sym);
267411bd2d4SPeixin-Qiao }
268411bd2d4SPeixin-Qiao
269411bd2d4SPeixin-Qiao fir::ExtendedValue sexv = converter.getSymbolExtendedValue(*sym);
270411bd2d4SPeixin-Qiao fir::ExtendedValue symThreadprivateExv =
271411bd2d4SPeixin-Qiao getExtendedValue(sexv, symThreadprivateValue);
272411bd2d4SPeixin-Qiao converter.bindSymbol(*sym, symThreadprivateExv);
273411bd2d4SPeixin-Qiao }
274411bd2d4SPeixin-Qiao
275411bd2d4SPeixin-Qiao firOpBuilder.restoreInsertionPoint(insPt);
276411bd2d4SPeixin-Qiao }
277411bd2d4SPeixin-Qiao
27827afb362SPeixin-Qiao static void
genCopyinClause(Fortran::lower::AbstractConverter & converter,const Fortran::parser::OmpClauseList & opClauseList)27927afb362SPeixin-Qiao genCopyinClause(Fortran::lower::AbstractConverter &converter,
28027afb362SPeixin-Qiao const Fortran::parser::OmpClauseList &opClauseList) {
28127afb362SPeixin-Qiao fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
28227afb362SPeixin-Qiao mlir::OpBuilder::InsertPoint insPt = firOpBuilder.saveInsertionPoint();
28327afb362SPeixin-Qiao firOpBuilder.setInsertionPointToStart(firOpBuilder.getAllocaBlock());
28427afb362SPeixin-Qiao bool hasCopyin = false;
28527afb362SPeixin-Qiao for (const Fortran::parser::OmpClause &clause : opClauseList.v) {
28627afb362SPeixin-Qiao if (const auto ©inClause =
28727afb362SPeixin-Qiao std::get_if<Fortran::parser::OmpClause::Copyin>(&clause.u)) {
28827afb362SPeixin-Qiao hasCopyin = true;
28927afb362SPeixin-Qiao const Fortran::parser::OmpObjectList &ompObjectList = copyinClause->v;
29027afb362SPeixin-Qiao for (const Fortran::parser::OmpObject &ompObject : ompObjectList.v) {
29127afb362SPeixin-Qiao Fortran::semantics::Symbol *sym = getOmpObjectSymbol(ompObject);
29227afb362SPeixin-Qiao if (sym->has<Fortran::semantics::CommonBlockDetails>())
29327afb362SPeixin-Qiao TODO(converter.getCurrentLocation(), "common block in Copyin clause");
29427afb362SPeixin-Qiao if (Fortran::semantics::IsAllocatableOrPointer(sym->GetUltimate()))
29527afb362SPeixin-Qiao TODO(converter.getCurrentLocation(),
29627afb362SPeixin-Qiao "pointer or allocatable variables in Copyin clause");
29727afb362SPeixin-Qiao assert(sym->has<Fortran::semantics::HostAssocDetails>() &&
29827afb362SPeixin-Qiao "No host-association found");
29927afb362SPeixin-Qiao converter.copyHostAssociateVar(*sym);
30027afb362SPeixin-Qiao }
30127afb362SPeixin-Qiao }
30227afb362SPeixin-Qiao }
30313019955SPeixin Qiao // [OMP 5.0, 2.19.6.1] The copy is done after the team is formed and prior to
30413019955SPeixin Qiao // the execution of the associated structured block. Emit implicit barrier to
30513019955SPeixin Qiao // synchronize threads and avoid data races on propagation master's thread
30613019955SPeixin Qiao // values of threadprivate variables to local instances of that variables of
30713019955SPeixin Qiao // all other implicit threads.
30827afb362SPeixin-Qiao if (hasCopyin)
30927afb362SPeixin-Qiao firOpBuilder.create<mlir::omp::BarrierOp>(converter.getCurrentLocation());
31027afb362SPeixin-Qiao firOpBuilder.restoreInsertionPoint(insPt);
31127afb362SPeixin-Qiao }
31227afb362SPeixin-Qiao
genObjectList(const Fortran::parser::OmpObjectList & objectList,Fortran::lower::AbstractConverter & converter,llvm::SmallVectorImpl<Value> & operands)31307e16a2aSKiran Chandramohan static void genObjectList(const Fortran::parser::OmpObjectList &objectList,
31407e16a2aSKiran Chandramohan Fortran::lower::AbstractConverter &converter,
31507e16a2aSKiran Chandramohan llvm::SmallVectorImpl<Value> &operands) {
31607e16a2aSKiran Chandramohan auto addOperands = [&](Fortran::lower::SymbolRef sym) {
31707e16a2aSKiran Chandramohan const mlir::Value variable = converter.getSymbolAddress(sym);
31807e16a2aSKiran Chandramohan if (variable) {
3191d328446SSourabh Singh Tomar operands.push_back(variable);
32007e16a2aSKiran Chandramohan } else {
32107e16a2aSKiran Chandramohan if (const auto *details =
32207e16a2aSKiran Chandramohan sym->detailsIf<Fortran::semantics::HostAssocDetails>()) {
32307e16a2aSKiran Chandramohan operands.push_back(converter.getSymbolAddress(details->symbol()));
32407e16a2aSKiran Chandramohan converter.copySymbolBinding(details->symbol(), sym);
32507e16a2aSKiran Chandramohan }
32607e16a2aSKiran Chandramohan }
32707e16a2aSKiran Chandramohan };
32807e16a2aSKiran Chandramohan for (const Fortran::parser::OmpObject &ompObject : objectList.v) {
329bc99d565SPeixinQiao Fortran::semantics::Symbol *sym = getOmpObjectSymbol(ompObject);
330bc99d565SPeixinQiao addOperands(*sym);
3311d328446SSourabh Singh Tomar }
3321d328446SSourabh Singh Tomar }
3331d328446SSourabh Singh Tomar
getLoopVarType(Fortran::lower::AbstractConverter & converter,std::size_t loopVarTypeSize)334870f4421SPeixin-Qiao static mlir::Type getLoopVarType(Fortran::lower::AbstractConverter &converter,
335870f4421SPeixin-Qiao std::size_t loopVarTypeSize) {
336870f4421SPeixin-Qiao // OpenMP runtime requires 32-bit or 64-bit loop variables.
337870f4421SPeixin-Qiao loopVarTypeSize = loopVarTypeSize * 8;
338870f4421SPeixin-Qiao if (loopVarTypeSize < 32) {
339870f4421SPeixin-Qiao loopVarTypeSize = 32;
340870f4421SPeixin-Qiao } else if (loopVarTypeSize > 64) {
341870f4421SPeixin-Qiao loopVarTypeSize = 64;
342870f4421SPeixin-Qiao mlir::emitWarning(converter.getCurrentLocation(),
343870f4421SPeixin-Qiao "OpenMP loop iteration variable cannot have more than 64 "
344870f4421SPeixin-Qiao "bits size and will be narrowed into 64 bits.");
345870f4421SPeixin-Qiao }
346870f4421SPeixin-Qiao assert((loopVarTypeSize == 32 || loopVarTypeSize == 64) &&
347870f4421SPeixin-Qiao "OpenMP loop iteration variable size must be transformed into 32-bit "
348870f4421SPeixin-Qiao "or 64-bit");
349870f4421SPeixin-Qiao return converter.getFirOpBuilder().getIntegerType(loopVarTypeSize);
350870f4421SPeixin-Qiao }
351870f4421SPeixin-Qiao
35229f167abSKiran Chandramohan /// Create empty blocks for the current region.
35329f167abSKiran Chandramohan /// These blocks replace blocks parented to an enclosing region.
createEmptyRegionBlocks(fir::FirOpBuilder & firOpBuilder,std::list<Fortran::lower::pft::Evaluation> & evaluationList)35429f167abSKiran Chandramohan void createEmptyRegionBlocks(
35529f167abSKiran Chandramohan fir::FirOpBuilder &firOpBuilder,
35629f167abSKiran Chandramohan std::list<Fortran::lower::pft::Evaluation> &evaluationList) {
35729f167abSKiran Chandramohan auto *region = &firOpBuilder.getRegion();
35829f167abSKiran Chandramohan for (auto &eval : evaluationList) {
35929f167abSKiran Chandramohan if (eval.block) {
36029f167abSKiran Chandramohan if (eval.block->empty()) {
36129f167abSKiran Chandramohan eval.block->erase();
36229f167abSKiran Chandramohan eval.block = firOpBuilder.createBlock(region);
36329f167abSKiran Chandramohan } else {
36429f167abSKiran Chandramohan [[maybe_unused]] auto &terminatorOp = eval.block->back();
36529f167abSKiran Chandramohan assert((mlir::isa<mlir::omp::TerminatorOp>(terminatorOp) ||
36629f167abSKiran Chandramohan mlir::isa<mlir::omp::YieldOp>(terminatorOp)) &&
36729f167abSKiran Chandramohan "expected terminator op");
36829f167abSKiran Chandramohan }
36929f167abSKiran Chandramohan }
370b501503cSkiranchandramohan if (!eval.isDirective() && eval.hasNestedEvaluations())
37129f167abSKiran Chandramohan createEmptyRegionBlocks(firOpBuilder, eval.getNestedEvaluations());
37229f167abSKiran Chandramohan }
37329f167abSKiran Chandramohan }
37429f167abSKiran Chandramohan
resetBeforeTerminator(fir::FirOpBuilder & firOpBuilder,mlir::Operation * storeOp,mlir::Block & block)37517d9bdf4SArnamoy Bhattacharyya void resetBeforeTerminator(fir::FirOpBuilder &firOpBuilder,
37617d9bdf4SArnamoy Bhattacharyya mlir::Operation *storeOp, mlir::Block &block) {
37717d9bdf4SArnamoy Bhattacharyya if (storeOp)
37817d9bdf4SArnamoy Bhattacharyya firOpBuilder.setInsertionPointAfter(storeOp);
37917d9bdf4SArnamoy Bhattacharyya else
38017d9bdf4SArnamoy Bhattacharyya firOpBuilder.setInsertionPointToStart(&block);
38117d9bdf4SArnamoy Bhattacharyya }
38217d9bdf4SArnamoy Bhattacharyya
3833b390a16SMats Petersson /// Create the body (block) for an OpenMP Operation.
3843b390a16SMats Petersson ///
3853b390a16SMats Petersson /// \param [in] op - the operation the body belongs to.
3863b390a16SMats Petersson /// \param [inout] converter - converter to use for the clauses.
3873b390a16SMats Petersson /// \param [in] loc - location in source code.
38829f167abSKiran Chandramohan /// \param [in] eval - current PFT node/evaluation.
3893b390a16SMats Petersson /// \oaran [in] clauses - list of clauses to process.
3903b390a16SMats Petersson /// \param [in] args - block arguments (induction variable[s]) for the
3913b390a16SMats Petersson //// region.
3923b390a16SMats Petersson /// \param [in] outerCombined - is this an outer operation - prevents
3933b390a16SMats Petersson /// privatization.
3941d328446SSourabh Singh Tomar template <typename Op>
39507e16a2aSKiran Chandramohan static void
createBodyOfOp(Op & op,Fortran::lower::AbstractConverter & converter,mlir::Location & loc,Fortran::lower::pft::Evaluation & eval,const Fortran::parser::OmpClauseList * clauses=nullptr,const SmallVector<const Fortran::semantics::Symbol * > & args={},bool outerCombined=false)39607e16a2aSKiran Chandramohan createBodyOfOp(Op &op, Fortran::lower::AbstractConverter &converter,
39729f167abSKiran Chandramohan mlir::Location &loc, Fortran::lower::pft::Evaluation &eval,
39807e16a2aSKiran Chandramohan const Fortran::parser::OmpClauseList *clauses = nullptr,
3993b390a16SMats Petersson const SmallVector<const Fortran::semantics::Symbol *> &args = {},
40007e16a2aSKiran Chandramohan bool outerCombined = false) {
401b501503cSkiranchandramohan fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
40229f167abSKiran Chandramohan // If an argument for the region is provided then create the block with that
40329f167abSKiran Chandramohan // argument. Also update the symbol's address with the mlir argument value.
40429f167abSKiran Chandramohan // e.g. For loops the argument is the induction variable. And all further
405b85c39ddSKiran Chandramohan // uses of the induction variable should use this mlir value.
406dc4bf2c3SMats Petersson mlir::Operation *storeOp = nullptr;
4073b390a16SMats Petersson if (args.size()) {
408870f4421SPeixin-Qiao std::size_t loopVarTypeSize = 0;
409870f4421SPeixin-Qiao for (const Fortran::semantics::Symbol *arg : args)
410870f4421SPeixin-Qiao loopVarTypeSize = std::max(loopVarTypeSize, arg->GetUltimate().size());
411870f4421SPeixin-Qiao mlir::Type loopVarType = getLoopVarType(converter, loopVarTypeSize);
4123b390a16SMats Petersson SmallVector<Type> tiv;
4133b390a16SMats Petersson SmallVector<Location> locs;
414870f4421SPeixin-Qiao for (int i = 0; i < (int)args.size(); i++) {
415870f4421SPeixin-Qiao tiv.push_back(loopVarType);
4163b390a16SMats Petersson locs.push_back(loc);
4173b390a16SMats Petersson }
4183b390a16SMats Petersson firOpBuilder.createBlock(&op.getRegion(), {}, tiv, locs);
419870f4421SPeixin-Qiao int argIndex = 0;
420dc4bf2c3SMats Petersson // The argument is not currently in memory, so make a temporary for the
421dc4bf2c3SMats Petersson // argument, and store it there, then bind that location to the argument.
422870f4421SPeixin-Qiao for (const Fortran::semantics::Symbol *arg : args) {
423dc4bf2c3SMats Petersson mlir::Value val =
424dc4bf2c3SMats Petersson fir::getBase(op.getRegion().front().getArgument(argIndex));
425dc4bf2c3SMats Petersson mlir::Value temp = firOpBuilder.createTemporary(
426dc4bf2c3SMats Petersson loc, loopVarType,
427dc4bf2c3SMats Petersson llvm::ArrayRef<mlir::NamedAttribute>{
428dc4bf2c3SMats Petersson Fortran::lower::getAdaptToByRefAttr(firOpBuilder)});
429dc4bf2c3SMats Petersson storeOp = firOpBuilder.create<fir::StoreOp>(loc, val, temp);
430dc4bf2c3SMats Petersson converter.bindSymbol(*arg, temp);
4313b390a16SMats Petersson argIndex++;
4323b390a16SMats Petersson }
433b85c39ddSKiran Chandramohan } else {
4341d328446SSourabh Singh Tomar firOpBuilder.createBlock(&op.getRegion());
435b85c39ddSKiran Chandramohan }
436dc4bf2c3SMats Petersson // Set the insert for the terminator operation to go at the end of the
437dc4bf2c3SMats Petersson // block - this is either empty or the block with the stores above,
438dc4bf2c3SMats Petersson // the end of the block works for both.
439b501503cSkiranchandramohan mlir::Block &block = op.getRegion().back();
440b501503cSkiranchandramohan firOpBuilder.setInsertionPointToEnd(&block);
441b85c39ddSKiran Chandramohan
442b501503cSkiranchandramohan // If it is an unstructured region and is not the outer region of a combined
443b501503cSkiranchandramohan // construct, create empty blocks for all evaluations.
444b501503cSkiranchandramohan if (eval.lowerAsUnstructured() && !outerCombined)
44529f167abSKiran Chandramohan createEmptyRegionBlocks(firOpBuilder, eval.getNestedEvaluations());
44629f167abSKiran Chandramohan
447b501503cSkiranchandramohan // Insert the terminator.
4483f4a63e5SArnamoy Bhattacharyya if constexpr (std::is_same_v<Op, omp::WsLoopOp> ||
4493f4a63e5SArnamoy Bhattacharyya std::is_same_v<Op, omp::SimdLoopOp>) {
450b85c39ddSKiran Chandramohan mlir::ValueRange results;
451b85c39ddSKiran Chandramohan firOpBuilder.create<mlir::omp::YieldOp>(loc, results);
452b85c39ddSKiran Chandramohan } else {
4531d328446SSourabh Singh Tomar firOpBuilder.create<mlir::omp::TerminatorOp>(loc);
454b85c39ddSKiran Chandramohan }
455b85c39ddSKiran Chandramohan
456dc4bf2c3SMats Petersson // Reset the insert point to before the terminator.
45717d9bdf4SArnamoy Bhattacharyya resetBeforeTerminator(firOpBuilder, storeOp, block);
458b501503cSkiranchandramohan
45907e16a2aSKiran Chandramohan // Handle privatization. Do not privatize if this is the outer operation.
46017d9bdf4SArnamoy Bhattacharyya if (clauses && !outerCombined) {
461*f2b7f18eSShraiysh Vaishay bool lastPrivateOp = privatizeVars(op, converter, *clauses);
46217d9bdf4SArnamoy Bhattacharyya // LastPrivatization, due to introduction of
46317d9bdf4SArnamoy Bhattacharyya // new control flow, changes the insertion point,
46417d9bdf4SArnamoy Bhattacharyya // thus restore it.
46517d9bdf4SArnamoy Bhattacharyya // TODO: Clean up later a bit to avoid this many sets and resets.
46617d9bdf4SArnamoy Bhattacharyya if (lastPrivateOp)
46717d9bdf4SArnamoy Bhattacharyya resetBeforeTerminator(firOpBuilder, storeOp, block);
46817d9bdf4SArnamoy Bhattacharyya }
469411bd2d4SPeixin-Qiao
470794b3bf7SPeixin-Qiao if constexpr (std::is_same_v<Op, omp::ParallelOp>) {
471411bd2d4SPeixin-Qiao threadPrivatizeVars(converter, eval);
47227afb362SPeixin-Qiao if (clauses)
47327afb362SPeixin-Qiao genCopyinClause(converter, *clauses);
47427afb362SPeixin-Qiao }
4751d328446SSourabh Singh Tomar }
476ae6e499dSEric Schweitz
genOMP(Fortran::lower::AbstractConverter & converter,Fortran::lower::pft::Evaluation & eval,const Fortran::parser::OpenMPSimpleStandaloneConstruct & simpleStandaloneConstruct)477dfa9065aSSourabh Singh Tomar static void genOMP(Fortran::lower::AbstractConverter &converter,
4783d0b7602SSourabh Singh Tomar Fortran::lower::pft::Evaluation &eval,
4793d0b7602SSourabh Singh Tomar const Fortran::parser::OpenMPSimpleStandaloneConstruct
4803d0b7602SSourabh Singh Tomar &simpleStandaloneConstruct) {
4813d0b7602SSourabh Singh Tomar const auto &directive =
4823d0b7602SSourabh Singh Tomar std::get<Fortran::parser::OmpSimpleStandaloneDirective>(
4833d0b7602SSourabh Singh Tomar simpleStandaloneConstruct.t);
4843d0b7602SSourabh Singh Tomar switch (directive.v) {
4853d0b7602SSourabh Singh Tomar default:
4863d0b7602SSourabh Singh Tomar break;
4873d0b7602SSourabh Singh Tomar case llvm::omp::Directive::OMPD_barrier:
488dfa9065aSSourabh Singh Tomar converter.getFirOpBuilder().create<mlir::omp::BarrierOp>(
489dfa9065aSSourabh Singh Tomar converter.getCurrentLocation());
4903d0b7602SSourabh Singh Tomar break;
4913d0b7602SSourabh Singh Tomar case llvm::omp::Directive::OMPD_taskwait:
492dfa9065aSSourabh Singh Tomar converter.getFirOpBuilder().create<mlir::omp::TaskwaitOp>(
493dfa9065aSSourabh Singh Tomar converter.getCurrentLocation());
494079b49b3SSourabh Singh Tomar break;
4953d0b7602SSourabh Singh Tomar case llvm::omp::Directive::OMPD_taskyield:
496dfa9065aSSourabh Singh Tomar converter.getFirOpBuilder().create<mlir::omp::TaskyieldOp>(
497dfa9065aSSourabh Singh Tomar converter.getCurrentLocation());
4989e4ab439SSourabh Singh Tomar break;
4993d0b7602SSourabh Singh Tomar case llvm::omp::Directive::OMPD_target_enter_data:
50036ea1cacSJean Perier TODO(converter.getCurrentLocation(), "OMPD_target_enter_data");
5013d0b7602SSourabh Singh Tomar case llvm::omp::Directive::OMPD_target_exit_data:
50236ea1cacSJean Perier TODO(converter.getCurrentLocation(), "OMPD_target_exit_data");
5033d0b7602SSourabh Singh Tomar case llvm::omp::Directive::OMPD_target_update:
50436ea1cacSJean Perier TODO(converter.getCurrentLocation(), "OMPD_target_update");
5053d0b7602SSourabh Singh Tomar case llvm::omp::Directive::OMPD_ordered:
50636ea1cacSJean Perier TODO(converter.getCurrentLocation(), "OMPD_ordered");
5073d0b7602SSourabh Singh Tomar }
5083d0b7602SSourabh Singh Tomar }
5093d0b7602SSourabh Singh Tomar
5103d0b7602SSourabh Singh Tomar static void
genAllocateClause(Fortran::lower::AbstractConverter & converter,const Fortran::parser::OmpAllocateClause & ompAllocateClause,SmallVector<Value> & allocatorOperands,SmallVector<Value> & allocateOperands)51188d5289fSNimish Mishra genAllocateClause(Fortran::lower::AbstractConverter &converter,
51288d5289fSNimish Mishra const Fortran::parser::OmpAllocateClause &ompAllocateClause,
51388d5289fSNimish Mishra SmallVector<Value> &allocatorOperands,
51488d5289fSNimish Mishra SmallVector<Value> &allocateOperands) {
51588d5289fSNimish Mishra auto &firOpBuilder = converter.getFirOpBuilder();
51688d5289fSNimish Mishra auto currentLocation = converter.getCurrentLocation();
51788d5289fSNimish Mishra Fortran::lower::StatementContext stmtCtx;
51888d5289fSNimish Mishra
51988d5289fSNimish Mishra mlir::Value allocatorOperand;
52088d5289fSNimish Mishra const Fortran::parser::OmpObjectList &ompObjectList =
52188d5289fSNimish Mishra std::get<Fortran::parser::OmpObjectList>(ompAllocateClause.t);
52288d5289fSNimish Mishra const auto &allocatorValue =
52388d5289fSNimish Mishra std::get<std::optional<Fortran::parser::OmpAllocateClause::Allocator>>(
52488d5289fSNimish Mishra ompAllocateClause.t);
52588d5289fSNimish Mishra // Check if allocate clause has allocator specified. If so, add it
52688d5289fSNimish Mishra // to list of allocators, otherwise, add default allocator to
52788d5289fSNimish Mishra // list of allocators.
52888d5289fSNimish Mishra if (allocatorValue) {
52988d5289fSNimish Mishra allocatorOperand = fir::getBase(converter.genExprValue(
53088d5289fSNimish Mishra *Fortran::semantics::GetExpr(allocatorValue->v), stmtCtx));
53188d5289fSNimish Mishra allocatorOperands.insert(allocatorOperands.end(), ompObjectList.v.size(),
53288d5289fSNimish Mishra allocatorOperand);
53388d5289fSNimish Mishra } else {
53488d5289fSNimish Mishra allocatorOperand = firOpBuilder.createIntegerConstant(
53588d5289fSNimish Mishra currentLocation, firOpBuilder.getI32Type(), 1);
53688d5289fSNimish Mishra allocatorOperands.insert(allocatorOperands.end(), ompObjectList.v.size(),
53788d5289fSNimish Mishra allocatorOperand);
53888d5289fSNimish Mishra }
53988d5289fSNimish Mishra genObjectList(ompObjectList, converter, allocateOperands);
54088d5289fSNimish Mishra }
54188d5289fSNimish Mishra
54288d5289fSNimish Mishra static void
genOMP(Fortran::lower::AbstractConverter & converter,Fortran::lower::pft::Evaluation & eval,const Fortran::parser::OpenMPStandaloneConstruct & standaloneConstruct)543dfa9065aSSourabh Singh Tomar genOMP(Fortran::lower::AbstractConverter &converter,
5443d0b7602SSourabh Singh Tomar Fortran::lower::pft::Evaluation &eval,
5453d0b7602SSourabh Singh Tomar const Fortran::parser::OpenMPStandaloneConstruct &standaloneConstruct) {
5463d0b7602SSourabh Singh Tomar std::visit(
5473d0b7602SSourabh Singh Tomar Fortran::common::visitors{
5483d0b7602SSourabh Singh Tomar [&](const Fortran::parser::OpenMPSimpleStandaloneConstruct
5493d0b7602SSourabh Singh Tomar &simpleStandaloneConstruct) {
550dfa9065aSSourabh Singh Tomar genOMP(converter, eval, simpleStandaloneConstruct);
5513d0b7602SSourabh Singh Tomar },
5523d0b7602SSourabh Singh Tomar [&](const Fortran::parser::OpenMPFlushConstruct &flushConstruct) {
553e7d37742SSourabh Singh Tomar SmallVector<Value, 4> operandRange;
554e7d37742SSourabh Singh Tomar if (const auto &ompObjectList =
555e7d37742SSourabh Singh Tomar std::get<std::optional<Fortran::parser::OmpObjectList>>(
556e7d37742SSourabh Singh Tomar flushConstruct.t))
557e7d37742SSourabh Singh Tomar genObjectList(*ompObjectList, converter, operandRange);
55851433662SShraiysh Vaishay const auto &memOrderClause = std::get<std::optional<
559f1569b1eSsameeran joshi std::list<Fortran::parser::OmpMemoryOrderClause>>>(
56051433662SShraiysh Vaishay flushConstruct.t);
56151433662SShraiysh Vaishay if (memOrderClause.has_value() && memOrderClause->size() > 0)
56236ea1cacSJean Perier TODO(converter.getCurrentLocation(),
56336ea1cacSJean Perier "Handle OmpMemoryOrderClause");
564e7d37742SSourabh Singh Tomar converter.getFirOpBuilder().create<mlir::omp::FlushOp>(
565e7d37742SSourabh Singh Tomar converter.getCurrentLocation(), operandRange);
5663d0b7602SSourabh Singh Tomar },
5673d0b7602SSourabh Singh Tomar [&](const Fortran::parser::OpenMPCancelConstruct &cancelConstruct) {
56836ea1cacSJean Perier TODO(converter.getCurrentLocation(), "OpenMPCancelConstruct");
5693d0b7602SSourabh Singh Tomar },
5703d0b7602SSourabh Singh Tomar [&](const Fortran::parser::OpenMPCancellationPointConstruct
57136ea1cacSJean Perier &cancellationPointConstruct) {
57236ea1cacSJean Perier TODO(converter.getCurrentLocation(), "OpenMPCancelConstruct");
57336ea1cacSJean Perier },
5743d0b7602SSourabh Singh Tomar },
5753d0b7602SSourabh Singh Tomar standaloneConstruct.u);
5763d0b7602SSourabh Singh Tomar }
5773d0b7602SSourabh Singh Tomar
genProcBindKindAttr(fir::FirOpBuilder & firOpBuilder,const Fortran::parser::OmpClause::ProcBind * procBindClause)5784202d69dSKiran Chandramohan static omp::ClauseProcBindKindAttr genProcBindKindAttr(
5794202d69dSKiran Chandramohan fir::FirOpBuilder &firOpBuilder,
5804202d69dSKiran Chandramohan const Fortran::parser::OmpClause::ProcBind *procBindClause) {
5814202d69dSKiran Chandramohan omp::ClauseProcBindKind pbKind;
5824202d69dSKiran Chandramohan switch (procBindClause->v.v) {
5834202d69dSKiran Chandramohan case Fortran::parser::OmpProcBindClause::Type::Master:
5844202d69dSKiran Chandramohan pbKind = omp::ClauseProcBindKind::Master;
5854202d69dSKiran Chandramohan break;
5864202d69dSKiran Chandramohan case Fortran::parser::OmpProcBindClause::Type::Close:
5874202d69dSKiran Chandramohan pbKind = omp::ClauseProcBindKind::Close;
5884202d69dSKiran Chandramohan break;
5894202d69dSKiran Chandramohan case Fortran::parser::OmpProcBindClause::Type::Spread:
5904202d69dSKiran Chandramohan pbKind = omp::ClauseProcBindKind::Spread;
5914202d69dSKiran Chandramohan break;
5924202d69dSKiran Chandramohan case Fortran::parser::OmpProcBindClause::Type::Primary:
5934202d69dSKiran Chandramohan pbKind = omp::ClauseProcBindKind::Primary;
5944202d69dSKiran Chandramohan break;
5954202d69dSKiran Chandramohan }
5964202d69dSKiran Chandramohan return omp::ClauseProcBindKindAttr::get(firOpBuilder.getContext(), pbKind);
5974202d69dSKiran Chandramohan }
5984202d69dSKiran Chandramohan
5992c915e3bSDominik Adamski static mlir::Value
getIfClauseOperand(Fortran::lower::AbstractConverter & converter,Fortran::lower::StatementContext & stmtCtx,const Fortran::parser::OmpClause::If * ifClause)6002c915e3bSDominik Adamski getIfClauseOperand(Fortran::lower::AbstractConverter &converter,
6012c915e3bSDominik Adamski Fortran::lower::StatementContext &stmtCtx,
6022c915e3bSDominik Adamski const Fortran::parser::OmpClause::If *ifClause) {
6032c915e3bSDominik Adamski fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
6042c915e3bSDominik Adamski mlir::Location currentLocation = converter.getCurrentLocation();
6052c915e3bSDominik Adamski auto &expr = std::get<Fortran::parser::ScalarLogicalExpr>(ifClause->v.t);
6062c915e3bSDominik Adamski mlir::Value ifVal = fir::getBase(
6072c915e3bSDominik Adamski converter.genExprValue(*Fortran::semantics::GetExpr(expr), stmtCtx));
6082c915e3bSDominik Adamski return firOpBuilder.createConvert(currentLocation, firOpBuilder.getI1Type(),
6092c915e3bSDominik Adamski ifVal);
6102c915e3bSDominik Adamski }
6112c915e3bSDominik Adamski
6124202d69dSKiran Chandramohan /* When parallel is used in a combined construct, then use this function to
6134202d69dSKiran Chandramohan * create the parallel operation. It handles the parallel specific clauses
6144202d69dSKiran Chandramohan * and leaves the rest for handling at the inner operations.
6154202d69dSKiran Chandramohan * TODO: Refactor clause handling
6164202d69dSKiran Chandramohan */
6174202d69dSKiran Chandramohan template <typename Directive>
6184202d69dSKiran Chandramohan static void
createCombinedParallelOp(Fortran::lower::AbstractConverter & converter,Fortran::lower::pft::Evaluation & eval,const Directive & directive)6194202d69dSKiran Chandramohan createCombinedParallelOp(Fortran::lower::AbstractConverter &converter,
6204202d69dSKiran Chandramohan Fortran::lower::pft::Evaluation &eval,
6214202d69dSKiran Chandramohan const Directive &directive) {
6224202d69dSKiran Chandramohan fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
6234202d69dSKiran Chandramohan mlir::Location currentLocation = converter.getCurrentLocation();
6244202d69dSKiran Chandramohan Fortran::lower::StatementContext stmtCtx;
6254202d69dSKiran Chandramohan llvm::ArrayRef<mlir::Type> argTy;
6264202d69dSKiran Chandramohan mlir::Value ifClauseOperand, numThreadsClauseOperand;
6274202d69dSKiran Chandramohan SmallVector<Value> allocatorOperands, allocateOperands;
6284202d69dSKiran Chandramohan mlir::omp::ClauseProcBindKindAttr procBindKindAttr;
6294202d69dSKiran Chandramohan const auto &opClauseList =
6304202d69dSKiran Chandramohan std::get<Fortran::parser::OmpClauseList>(directive.t);
6314202d69dSKiran Chandramohan // TODO: Handle the following clauses
6324202d69dSKiran Chandramohan // 1. default
6334202d69dSKiran Chandramohan // Note: rest of the clauses are handled when the inner operation is created
6344202d69dSKiran Chandramohan for (const Fortran::parser::OmpClause &clause : opClauseList.v) {
6354202d69dSKiran Chandramohan if (const auto &ifClause =
6364202d69dSKiran Chandramohan std::get_if<Fortran::parser::OmpClause::If>(&clause.u)) {
6372c915e3bSDominik Adamski ifClauseOperand = getIfClauseOperand(converter, stmtCtx, ifClause);
6384202d69dSKiran Chandramohan } else if (const auto &numThreadsClause =
6394202d69dSKiran Chandramohan std::get_if<Fortran::parser::OmpClause::NumThreads>(
6404202d69dSKiran Chandramohan &clause.u)) {
6414202d69dSKiran Chandramohan numThreadsClauseOperand = fir::getBase(converter.genExprValue(
6424202d69dSKiran Chandramohan *Fortran::semantics::GetExpr(numThreadsClause->v), stmtCtx));
6434202d69dSKiran Chandramohan } else if (const auto &procBindClause =
6444202d69dSKiran Chandramohan std::get_if<Fortran::parser::OmpClause::ProcBind>(
6454202d69dSKiran Chandramohan &clause.u)) {
6464202d69dSKiran Chandramohan procBindKindAttr = genProcBindKindAttr(firOpBuilder, procBindClause);
6474202d69dSKiran Chandramohan }
6484202d69dSKiran Chandramohan }
6494202d69dSKiran Chandramohan // Create and insert the operation.
6504202d69dSKiran Chandramohan auto parallelOp = firOpBuilder.create<mlir::omp::ParallelOp>(
6514202d69dSKiran Chandramohan currentLocation, argTy, ifClauseOperand, numThreadsClauseOperand,
6524202d69dSKiran Chandramohan allocateOperands, allocatorOperands, /*reduction_vars=*/ValueRange(),
6534202d69dSKiran Chandramohan /*reductions=*/nullptr, procBindKindAttr);
6544202d69dSKiran Chandramohan
65529f167abSKiran Chandramohan createBodyOfOp<omp::ParallelOp>(parallelOp, converter, currentLocation, eval,
6564202d69dSKiran Chandramohan &opClauseList, /*iv=*/{},
6574202d69dSKiran Chandramohan /*isCombined=*/true);
6584202d69dSKiran Chandramohan }
6594202d69dSKiran Chandramohan
660bf812c14SSourabh Singh Tomar static void
genOMP(Fortran::lower::AbstractConverter & converter,Fortran::lower::pft::Evaluation & eval,const Fortran::parser::OpenMPBlockConstruct & blockConstruct)661dfa9065aSSourabh Singh Tomar genOMP(Fortran::lower::AbstractConverter &converter,
662bf812c14SSourabh Singh Tomar Fortran::lower::pft::Evaluation &eval,
663bf812c14SSourabh Singh Tomar const Fortran::parser::OpenMPBlockConstruct &blockConstruct) {
6641d328446SSourabh Singh Tomar const auto &beginBlockDirective =
665bf812c14SSourabh Singh Tomar std::get<Fortran::parser::OmpBeginBlockDirective>(blockConstruct.t);
6661d328446SSourabh Singh Tomar const auto &blockDirective =
6671d328446SSourabh Singh Tomar std::get<Fortran::parser::OmpBlockDirective>(beginBlockDirective.t);
668cd28353eSShraiysh Vaishay const auto &endBlockDirective =
669cd28353eSShraiysh Vaishay std::get<Fortran::parser::OmpEndBlockDirective>(blockConstruct.t);
67007e16a2aSKiran Chandramohan fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
67107e16a2aSKiran Chandramohan mlir::Location currentLocation = converter.getCurrentLocation();
6721d328446SSourabh Singh Tomar
673d0b70a07SValentin Clement Fortran::lower::StatementContext stmtCtx;
6741d328446SSourabh Singh Tomar llvm::ArrayRef<mlir::Type> argTy;
67504cb01cfSShraiysh Vaishay mlir::Value ifClauseOperand, numThreadsClauseOperand, finalClauseOperand,
67604cb01cfSShraiysh Vaishay priorityClauseOperand;
677fa4b1e1eSShraiysh Vaishay mlir::omp::ClauseProcBindKindAttr procBindKindAttr;
678fa4b1e1eSShraiysh Vaishay SmallVector<Value> allocateOperands, allocatorOperands;
67904cb01cfSShraiysh Vaishay mlir::UnitAttr nowaitAttr, untiedAttr, mergeableAttr;
68034b08487SSourabh Singh Tomar
68107e16a2aSKiran Chandramohan const auto &opClauseList =
68207e16a2aSKiran Chandramohan std::get<Fortran::parser::OmpClauseList>(beginBlockDirective.t);
68307e16a2aSKiran Chandramohan for (const auto &clause : opClauseList.v) {
6841d328446SSourabh Singh Tomar if (const auto &ifClause =
6856bd0a445SValentin Clement std::get_if<Fortran::parser::OmpClause::If>(&clause.u)) {
6862c915e3bSDominik Adamski ifClauseOperand = getIfClauseOperand(converter, stmtCtx, ifClause);
6871d328446SSourabh Singh Tomar } else if (const auto &numThreadsClause =
6881d328446SSourabh Singh Tomar std::get_if<Fortran::parser::OmpClause::NumThreads>(
6891d328446SSourabh Singh Tomar &clause.u)) {
69034b08487SSourabh Singh Tomar // OMPIRBuilder expects `NUM_THREAD` clause as a `Value`.
6911d328446SSourabh Singh Tomar numThreadsClauseOperand = fir::getBase(converter.genExprValue(
692d0b70a07SValentin Clement *Fortran::semantics::GetExpr(numThreadsClause->v), stmtCtx));
693fa4b1e1eSShraiysh Vaishay } else if (const auto &procBindClause =
694fa4b1e1eSShraiysh Vaishay std::get_if<Fortran::parser::OmpClause::ProcBind>(
695fa4b1e1eSShraiysh Vaishay &clause.u)) {
6964202d69dSKiran Chandramohan procBindKindAttr = genProcBindKindAttr(firOpBuilder, procBindClause);
697fa4b1e1eSShraiysh Vaishay } else if (const auto &allocateClause =
698fa4b1e1eSShraiysh Vaishay std::get_if<Fortran::parser::OmpClause::Allocate>(
699fa4b1e1eSShraiysh Vaishay &clause.u)) {
700fa4b1e1eSShraiysh Vaishay genAllocateClause(converter, allocateClause->v, allocatorOperands,
701fa4b1e1eSShraiysh Vaishay allocateOperands);
70207e16a2aSKiran Chandramohan } else if (std::get_if<Fortran::parser::OmpClause::Private>(&clause.u) ||
70307e16a2aSKiran Chandramohan std::get_if<Fortran::parser::OmpClause::Firstprivate>(
70427afb362SPeixin-Qiao &clause.u) ||
70527afb362SPeixin-Qiao std::get_if<Fortran::parser::OmpClause::Copyin>(&clause.u)) {
70627afb362SPeixin-Qiao // Privatisation and copyin clauses are handled elsewhere.
70707e16a2aSKiran Chandramohan continue;
708051dea82SKiran Chandramohan } else if (std::get_if<Fortran::parser::OmpClause::Shared>(&clause.u)) {
709051dea82SKiran Chandramohan // Shared is the default behavior in the IR, so no handling is required.
710051dea82SKiran Chandramohan continue;
711051dea82SKiran Chandramohan } else if (const auto &defaultClause =
712051dea82SKiran Chandramohan std::get_if<Fortran::parser::OmpClause::Default>(
713051dea82SKiran Chandramohan &clause.u)) {
714051dea82SKiran Chandramohan if ((defaultClause->v.v ==
715051dea82SKiran Chandramohan Fortran::parser::OmpDefaultClause::Type::Shared) ||
716051dea82SKiran Chandramohan (defaultClause->v.v ==
717051dea82SKiran Chandramohan Fortran::parser::OmpDefaultClause::Type::None)) {
718051dea82SKiran Chandramohan // Default clause with shared or none do not require any handling since
719051dea82SKiran Chandramohan // Shared is the default behavior in the IR and None is only required
720051dea82SKiran Chandramohan // for semantic checks.
721051dea82SKiran Chandramohan continue;
722051dea82SKiran Chandramohan }
7238964a17dSPeixinQiao } else if (std::get_if<Fortran::parser::OmpClause::Threads>(&clause.u)) {
7248964a17dSPeixinQiao // Nothing needs to be done for threads clause.
7258964a17dSPeixinQiao continue;
72604cb01cfSShraiysh Vaishay } else if (const auto &finalClause =
72704cb01cfSShraiysh Vaishay std::get_if<Fortran::parser::OmpClause::Final>(&clause.u)) {
72804cb01cfSShraiysh Vaishay mlir::Value finalVal = fir::getBase(converter.genExprValue(
72904cb01cfSShraiysh Vaishay *Fortran::semantics::GetExpr(finalClause->v), stmtCtx));
73004cb01cfSShraiysh Vaishay finalClauseOperand = firOpBuilder.createConvert(
73104cb01cfSShraiysh Vaishay currentLocation, firOpBuilder.getI1Type(), finalVal);
73204cb01cfSShraiysh Vaishay } else if (std::get_if<Fortran::parser::OmpClause::Untied>(&clause.u)) {
73304cb01cfSShraiysh Vaishay untiedAttr = firOpBuilder.getUnitAttr();
73404cb01cfSShraiysh Vaishay } else if (std::get_if<Fortran::parser::OmpClause::Mergeable>(&clause.u)) {
73504cb01cfSShraiysh Vaishay mergeableAttr = firOpBuilder.getUnitAttr();
73604cb01cfSShraiysh Vaishay } else if (const auto &priorityClause =
73704cb01cfSShraiysh Vaishay std::get_if<Fortran::parser::OmpClause::Priority>(
73804cb01cfSShraiysh Vaishay &clause.u)) {
73904cb01cfSShraiysh Vaishay priorityClauseOperand = fir::getBase(converter.genExprValue(
74004cb01cfSShraiysh Vaishay *Fortran::semantics::GetExpr(priorityClause->v), stmtCtx));
741fa4b1e1eSShraiysh Vaishay } else {
742fa4b1e1eSShraiysh Vaishay TODO(currentLocation, "OpenMP Block construct clauses");
7431d328446SSourabh Singh Tomar }
7441d328446SSourabh Singh Tomar }
745fa4b1e1eSShraiysh Vaishay
746fa4b1e1eSShraiysh Vaishay for (const auto &clause :
747fa4b1e1eSShraiysh Vaishay std::get<Fortran::parser::OmpClauseList>(endBlockDirective.t).v) {
748fa4b1e1eSShraiysh Vaishay if (std::get_if<Fortran::parser::OmpClause::Nowait>(&clause.u))
749fa4b1e1eSShraiysh Vaishay nowaitAttr = firOpBuilder.getUnitAttr();
750fa4b1e1eSShraiysh Vaishay }
751fa4b1e1eSShraiysh Vaishay
752fa4b1e1eSShraiysh Vaishay if (blockDirective.v == llvm::omp::OMPD_parallel) {
753fa4b1e1eSShraiysh Vaishay // Create and insert the operation.
754fa4b1e1eSShraiysh Vaishay auto parallelOp = firOpBuilder.create<mlir::omp::ParallelOp>(
755fa4b1e1eSShraiysh Vaishay currentLocation, argTy, ifClauseOperand, numThreadsClauseOperand,
756fa4b1e1eSShraiysh Vaishay allocateOperands, allocatorOperands, /*reduction_vars=*/ValueRange(),
757fa4b1e1eSShraiysh Vaishay /*reductions=*/nullptr, procBindKindAttr);
75807e16a2aSKiran Chandramohan createBodyOfOp<omp::ParallelOp>(parallelOp, converter, currentLocation,
75929f167abSKiran Chandramohan eval, &opClauseList);
7601d328446SSourabh Singh Tomar } else if (blockDirective.v == llvm::omp::OMPD_master) {
7611d328446SSourabh Singh Tomar auto masterOp =
7621d328446SSourabh Singh Tomar firOpBuilder.create<mlir::omp::MasterOp>(currentLocation, argTy);
76329f167abSKiran Chandramohan createBodyOfOp<omp::MasterOp>(masterOp, converter, currentLocation, eval);
764cd28353eSShraiysh Vaishay } else if (blockDirective.v == llvm::omp::OMPD_single) {
765cd28353eSShraiysh Vaishay auto singleOp = firOpBuilder.create<mlir::omp::SingleOp>(
766fa4b1e1eSShraiysh Vaishay currentLocation, allocateOperands, allocatorOperands, nowaitAttr);
76729f167abSKiran Chandramohan createBodyOfOp<omp::SingleOp>(singleOp, converter, currentLocation, eval);
7688964a17dSPeixinQiao } else if (blockDirective.v == llvm::omp::OMPD_ordered) {
7698964a17dSPeixinQiao auto orderedOp = firOpBuilder.create<mlir::omp::OrderedRegionOp>(
7708964a17dSPeixinQiao currentLocation, /*simd=*/nullptr);
77129f167abSKiran Chandramohan createBodyOfOp<omp::OrderedRegionOp>(orderedOp, converter, currentLocation,
77229f167abSKiran Chandramohan eval);
77304cb01cfSShraiysh Vaishay } else if (blockDirective.v == llvm::omp::OMPD_task) {
77404cb01cfSShraiysh Vaishay auto taskOp = firOpBuilder.create<mlir::omp::TaskOp>(
77504cb01cfSShraiysh Vaishay currentLocation, ifClauseOperand, finalClauseOperand, untiedAttr,
77604cb01cfSShraiysh Vaishay mergeableAttr, /*in_reduction_vars=*/ValueRange(),
77704cb01cfSShraiysh Vaishay /*in_reductions=*/nullptr, priorityClauseOperand, allocateOperands,
77804cb01cfSShraiysh Vaishay allocatorOperands);
77929f167abSKiran Chandramohan createBodyOfOp(taskOp, converter, currentLocation, eval, &opClauseList);
78007e16a2aSKiran Chandramohan } else {
78107e16a2aSKiran Chandramohan TODO(converter.getCurrentLocation(), "Unhandled block directive");
782bf812c14SSourabh Singh Tomar }
783bf812c14SSourabh Singh Tomar }
784bf812c14SSourabh Singh Tomar
7857bb1151bSKiran Chandramohan /// Creates an OpenMP reduction declaration and inserts it into the provided
7867bb1151bSKiran Chandramohan /// symbol table. The declaration has a constant initializer with the neutral
7877bb1151bSKiran Chandramohan /// value `initValue`, and the reduction combiner carried over from `reduce`.
7887bb1151bSKiran Chandramohan /// TODO: Generalize this for non-integer types, add atomic region.
createReductionDecl(fir::FirOpBuilder & builder,llvm::StringRef name,mlir::Type type,mlir::Location loc)7897bb1151bSKiran Chandramohan static omp::ReductionDeclareOp createReductionDecl(fir::FirOpBuilder &builder,
7907bb1151bSKiran Chandramohan llvm::StringRef name,
7917bb1151bSKiran Chandramohan mlir::Type type,
7927bb1151bSKiran Chandramohan mlir::Location loc) {
7937bb1151bSKiran Chandramohan OpBuilder::InsertionGuard guard(builder);
7947bb1151bSKiran Chandramohan mlir::ModuleOp module = builder.getModule();
7957bb1151bSKiran Chandramohan mlir::OpBuilder modBuilder(module.getBodyRegion());
7967bb1151bSKiran Chandramohan auto decl = module.lookupSymbol<mlir::omp::ReductionDeclareOp>(name);
7977bb1151bSKiran Chandramohan if (!decl)
7987bb1151bSKiran Chandramohan decl = modBuilder.create<omp::ReductionDeclareOp>(loc, name, type);
7997bb1151bSKiran Chandramohan else
8007bb1151bSKiran Chandramohan return decl;
8017bb1151bSKiran Chandramohan
8027bb1151bSKiran Chandramohan builder.createBlock(&decl.initializerRegion(), decl.initializerRegion().end(),
8037bb1151bSKiran Chandramohan {type}, {loc});
8047bb1151bSKiran Chandramohan builder.setInsertionPointToEnd(&decl.initializerRegion().back());
8057bb1151bSKiran Chandramohan Value init = builder.create<mlir::arith::ConstantOp>(
8067bb1151bSKiran Chandramohan loc, type, builder.getIntegerAttr(type, 0));
8077bb1151bSKiran Chandramohan builder.create<omp::YieldOp>(loc, init);
8087bb1151bSKiran Chandramohan
8097bb1151bSKiran Chandramohan builder.createBlock(&decl.reductionRegion(), decl.reductionRegion().end(),
8107bb1151bSKiran Chandramohan {type, type}, {loc, loc});
8117bb1151bSKiran Chandramohan builder.setInsertionPointToEnd(&decl.reductionRegion().back());
8127bb1151bSKiran Chandramohan mlir::Value op1 = decl.reductionRegion().front().getArgument(0);
8137bb1151bSKiran Chandramohan mlir::Value op2 = decl.reductionRegion().front().getArgument(1);
8147bb1151bSKiran Chandramohan Value addRes = builder.create<mlir::arith::AddIOp>(loc, op1, op2);
8157bb1151bSKiran Chandramohan builder.create<omp::YieldOp>(loc, addRes);
8167bb1151bSKiran Chandramohan return decl;
8177bb1151bSKiran Chandramohan }
8187bb1151bSKiran Chandramohan
8198b951e64SKiran Chandramohan static mlir::omp::ScheduleModifier
translateModifier(const Fortran::parser::OmpScheduleModifierType & m)8208b951e64SKiran Chandramohan translateModifier(const Fortran::parser::OmpScheduleModifierType &m) {
8218b951e64SKiran Chandramohan switch (m.v) {
8228b951e64SKiran Chandramohan case Fortran::parser::OmpScheduleModifierType::ModType::Monotonic:
8238b951e64SKiran Chandramohan return mlir::omp::ScheduleModifier::monotonic;
8248b951e64SKiran Chandramohan case Fortran::parser::OmpScheduleModifierType::ModType::Nonmonotonic:
8258b951e64SKiran Chandramohan return mlir::omp::ScheduleModifier::nonmonotonic;
8268b951e64SKiran Chandramohan case Fortran::parser::OmpScheduleModifierType::ModType::Simd:
8278b951e64SKiran Chandramohan return mlir::omp::ScheduleModifier::simd;
8288b951e64SKiran Chandramohan }
8298b951e64SKiran Chandramohan return mlir::omp::ScheduleModifier::none;
8308b951e64SKiran Chandramohan }
8318b951e64SKiran Chandramohan
8328b951e64SKiran Chandramohan static mlir::omp::ScheduleModifier
getScheduleModifier(const Fortran::parser::OmpScheduleClause & x)8338b951e64SKiran Chandramohan getScheduleModifier(const Fortran::parser::OmpScheduleClause &x) {
8348b951e64SKiran Chandramohan const auto &modifier =
8358b951e64SKiran Chandramohan std::get<std::optional<Fortran::parser::OmpScheduleModifier>>(x.t);
8368b951e64SKiran Chandramohan // The input may have the modifier any order, so we look for one that isn't
8378b951e64SKiran Chandramohan // SIMD. If modifier is not set at all, fall down to the bottom and return
8388b951e64SKiran Chandramohan // "none".
8398b951e64SKiran Chandramohan if (modifier) {
8408b951e64SKiran Chandramohan const auto &modType1 =
8418b951e64SKiran Chandramohan std::get<Fortran::parser::OmpScheduleModifier::Modifier1>(modifier->t);
8428b951e64SKiran Chandramohan if (modType1.v.v ==
8438b951e64SKiran Chandramohan Fortran::parser::OmpScheduleModifierType::ModType::Simd) {
8448b951e64SKiran Chandramohan const auto &modType2 = std::get<
8458b951e64SKiran Chandramohan std::optional<Fortran::parser::OmpScheduleModifier::Modifier2>>(
8468b951e64SKiran Chandramohan modifier->t);
8478b951e64SKiran Chandramohan if (modType2 &&
8488b951e64SKiran Chandramohan modType2->v.v !=
8498b951e64SKiran Chandramohan Fortran::parser::OmpScheduleModifierType::ModType::Simd)
8508b951e64SKiran Chandramohan return translateModifier(modType2->v);
8518b951e64SKiran Chandramohan
8528b951e64SKiran Chandramohan return mlir::omp::ScheduleModifier::none;
8538b951e64SKiran Chandramohan }
8548b951e64SKiran Chandramohan
8558b951e64SKiran Chandramohan return translateModifier(modType1.v);
8568b951e64SKiran Chandramohan }
8578b951e64SKiran Chandramohan return mlir::omp::ScheduleModifier::none;
8588b951e64SKiran Chandramohan }
8598b951e64SKiran Chandramohan
8608b951e64SKiran Chandramohan static mlir::omp::ScheduleModifier
getSIMDModifier(const Fortran::parser::OmpScheduleClause & x)8618b951e64SKiran Chandramohan getSIMDModifier(const Fortran::parser::OmpScheduleClause &x) {
8628b951e64SKiran Chandramohan const auto &modifier =
8638b951e64SKiran Chandramohan std::get<std::optional<Fortran::parser::OmpScheduleModifier>>(x.t);
8648b951e64SKiran Chandramohan // Either of the two possible modifiers in the input can be the SIMD modifier,
8658b951e64SKiran Chandramohan // so look in either one, and return simd if we find one. Not found = return
8668b951e64SKiran Chandramohan // "none".
8678b951e64SKiran Chandramohan if (modifier) {
8688b951e64SKiran Chandramohan const auto &modType1 =
8698b951e64SKiran Chandramohan std::get<Fortran::parser::OmpScheduleModifier::Modifier1>(modifier->t);
8708b951e64SKiran Chandramohan if (modType1.v.v == Fortran::parser::OmpScheduleModifierType::ModType::Simd)
8718b951e64SKiran Chandramohan return mlir::omp::ScheduleModifier::simd;
8728b951e64SKiran Chandramohan
8738b951e64SKiran Chandramohan const auto &modType2 = std::get<
8748b951e64SKiran Chandramohan std::optional<Fortran::parser::OmpScheduleModifier::Modifier2>>(
8758b951e64SKiran Chandramohan modifier->t);
8768b951e64SKiran Chandramohan if (modType2 && modType2->v.v ==
8778b951e64SKiran Chandramohan Fortran::parser::OmpScheduleModifierType::ModType::Simd)
8788b951e64SKiran Chandramohan return mlir::omp::ScheduleModifier::simd;
8798b951e64SKiran Chandramohan }
8808b951e64SKiran Chandramohan return mlir::omp::ScheduleModifier::none;
8818b951e64SKiran Chandramohan }
8828b951e64SKiran Chandramohan
getReductionName(Fortran::parser::DefinedOperator::IntrinsicOperator intrinsicOp,mlir::Type ty)8837bb1151bSKiran Chandramohan static std::string getReductionName(
8847bb1151bSKiran Chandramohan Fortran::parser::DefinedOperator::IntrinsicOperator intrinsicOp,
8857bb1151bSKiran Chandramohan mlir::Type ty) {
8867bb1151bSKiran Chandramohan std::string reductionName;
8877bb1151bSKiran Chandramohan if (intrinsicOp == Fortran::parser::DefinedOperator::IntrinsicOperator::Add)
8887bb1151bSKiran Chandramohan reductionName = "add_reduction";
8897bb1151bSKiran Chandramohan else
8907bb1151bSKiran Chandramohan reductionName = "other_reduction";
8917bb1151bSKiran Chandramohan
8927bb1151bSKiran Chandramohan return (llvm::Twine(reductionName) +
8937bb1151bSKiran Chandramohan (ty.isIntOrIndex() ? llvm::Twine("_i_") : llvm::Twine("_f_")) +
8947bb1151bSKiran Chandramohan llvm::Twine(ty.getIntOrFloatBitWidth()))
8957bb1151bSKiran Chandramohan .str();
8967bb1151bSKiran Chandramohan }
8977bb1151bSKiran Chandramohan
genOMP(Fortran::lower::AbstractConverter & converter,Fortran::lower::pft::Evaluation & eval,const Fortran::parser::OpenMPLoopConstruct & loopConstruct)898b85c39ddSKiran Chandramohan static void genOMP(Fortran::lower::AbstractConverter &converter,
899b85c39ddSKiran Chandramohan Fortran::lower::pft::Evaluation &eval,
900b85c39ddSKiran Chandramohan const Fortran::parser::OpenMPLoopConstruct &loopConstruct) {
901b85c39ddSKiran Chandramohan
902b85c39ddSKiran Chandramohan fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
903b85c39ddSKiran Chandramohan mlir::Location currentLocation = converter.getCurrentLocation();
904b85c39ddSKiran Chandramohan llvm::SmallVector<mlir::Value> lowerBound, upperBound, step, linearVars,
905b85c39ddSKiran Chandramohan linearStepVars, reductionVars;
9062c915e3bSDominik Adamski mlir::Value scheduleChunkClauseOperand, ifClauseOperand;
9071795f8cdSPeixin-Qiao mlir::Attribute scheduleClauseOperand, noWaitClauseOperand,
9081795f8cdSPeixin-Qiao orderedClauseOperand, orderClauseOperand;
9097bb1151bSKiran Chandramohan SmallVector<Attribute> reductionDeclSymbols;
9102c915e3bSDominik Adamski Fortran::lower::StatementContext stmtCtx;
9113f4a63e5SArnamoy Bhattacharyya const auto &loopOpClauseList = std::get<Fortran::parser::OmpClauseList>(
912b85c39ddSKiran Chandramohan std::get<Fortran::parser::OmpBeginLoopDirective>(loopConstruct.t).t);
9134202d69dSKiran Chandramohan
9144202d69dSKiran Chandramohan const auto ompDirective =
915b85c39ddSKiran Chandramohan std::get<Fortran::parser::OmpLoopDirective>(
916b85c39ddSKiran Chandramohan std::get<Fortran::parser::OmpBeginLoopDirective>(loopConstruct.t).t)
9174202d69dSKiran Chandramohan .v;
9184202d69dSKiran Chandramohan if (llvm::omp::OMPD_parallel_do == ompDirective) {
9194202d69dSKiran Chandramohan createCombinedParallelOp<Fortran::parser::OmpBeginLoopDirective>(
9204202d69dSKiran Chandramohan converter, eval,
9214202d69dSKiran Chandramohan std::get<Fortran::parser::OmpBeginLoopDirective>(loopConstruct.t));
9223f4a63e5SArnamoy Bhattacharyya } else if (llvm::omp::OMPD_do != ompDirective &&
9233f4a63e5SArnamoy Bhattacharyya llvm::omp::OMPD_simd != ompDirective) {
9244202d69dSKiran Chandramohan TODO(converter.getCurrentLocation(), "Construct enclosing do loop");
925b85c39ddSKiran Chandramohan }
926b85c39ddSKiran Chandramohan
9273b390a16SMats Petersson // Collect the loops to collapse.
9283b390a16SMats Petersson auto *doConstructEval = &eval.getFirstNestedEvaluation();
9293b390a16SMats Petersson
930870f4421SPeixin-Qiao std::int64_t collapseValue =
9313f4a63e5SArnamoy Bhattacharyya Fortran::lower::getCollapseValue(loopOpClauseList);
932870f4421SPeixin-Qiao std::size_t loopVarTypeSize = 0;
9333b390a16SMats Petersson SmallVector<const Fortran::semantics::Symbol *> iv;
9343b390a16SMats Petersson do {
9353b390a16SMats Petersson auto *doLoop = &doConstructEval->getFirstNestedEvaluation();
936b85c39ddSKiran Chandramohan auto *doStmt = doLoop->getIf<Fortran::parser::NonLabelDoStmt>();
937b85c39ddSKiran Chandramohan assert(doStmt && "Expected do loop to be in the nested evaluation");
938b85c39ddSKiran Chandramohan const auto &loopControl =
939b85c39ddSKiran Chandramohan std::get<std::optional<Fortran::parser::LoopControl>>(doStmt->t);
940b85c39ddSKiran Chandramohan const Fortran::parser::LoopControl::Bounds *bounds =
941b85c39ddSKiran Chandramohan std::get_if<Fortran::parser::LoopControl::Bounds>(&loopControl->u);
942b85c39ddSKiran Chandramohan assert(bounds && "Expected bounds for worksharing do loop");
943b85c39ddSKiran Chandramohan Fortran::lower::StatementContext stmtCtx;
944b85c39ddSKiran Chandramohan lowerBound.push_back(fir::getBase(converter.genExprValue(
945b85c39ddSKiran Chandramohan *Fortran::semantics::GetExpr(bounds->lower), stmtCtx)));
946b85c39ddSKiran Chandramohan upperBound.push_back(fir::getBase(converter.genExprValue(
947b85c39ddSKiran Chandramohan *Fortran::semantics::GetExpr(bounds->upper), stmtCtx)));
948b85c39ddSKiran Chandramohan if (bounds->step) {
949b85c39ddSKiran Chandramohan step.push_back(fir::getBase(converter.genExprValue(
950b85c39ddSKiran Chandramohan *Fortran::semantics::GetExpr(bounds->step), stmtCtx)));
951b85c39ddSKiran Chandramohan } else { // If `step` is not present, assume it as `1`.
952b85c39ddSKiran Chandramohan step.push_back(firOpBuilder.createIntegerConstant(
953b85c39ddSKiran Chandramohan currentLocation, firOpBuilder.getIntegerType(32), 1));
954b85c39ddSKiran Chandramohan }
9553b390a16SMats Petersson iv.push_back(bounds->name.thing.symbol);
956870f4421SPeixin-Qiao loopVarTypeSize = std::max(loopVarTypeSize,
957870f4421SPeixin-Qiao bounds->name.thing.symbol->GetUltimate().size());
9583b390a16SMats Petersson
9593b390a16SMats Petersson collapseValue--;
9603b390a16SMats Petersson doConstructEval =
9613b390a16SMats Petersson &*std::next(doConstructEval->getNestedEvaluations().begin());
9623b390a16SMats Petersson } while (collapseValue > 0);
963b85c39ddSKiran Chandramohan
9643f4a63e5SArnamoy Bhattacharyya for (const auto &clause : loopOpClauseList.v) {
965820146abSMats Petersson if (const auto &scheduleClause =
966820146abSMats Petersson std::get_if<Fortran::parser::OmpClause::Schedule>(&clause.u)) {
967820146abSMats Petersson if (const auto &chunkExpr =
968820146abSMats Petersson std::get<std::optional<Fortran::parser::ScalarIntExpr>>(
969820146abSMats Petersson scheduleClause->v.t)) {
970820146abSMats Petersson if (const auto *expr = Fortran::semantics::GetExpr(*chunkExpr)) {
971820146abSMats Petersson scheduleChunkClauseOperand =
972820146abSMats Petersson fir::getBase(converter.genExprValue(*expr, stmtCtx));
973820146abSMats Petersson }
974820146abSMats Petersson }
9752c915e3bSDominik Adamski } else if (const auto &ifClause =
9762c915e3bSDominik Adamski std::get_if<Fortran::parser::OmpClause::If>(&clause.u)) {
9772c915e3bSDominik Adamski ifClauseOperand = getIfClauseOperand(converter, stmtCtx, ifClause);
9787bb1151bSKiran Chandramohan } else if (const auto &reductionClause =
9797bb1151bSKiran Chandramohan std::get_if<Fortran::parser::OmpClause::Reduction>(
9807bb1151bSKiran Chandramohan &clause.u)) {
9817bb1151bSKiran Chandramohan omp::ReductionDeclareOp decl;
9827bb1151bSKiran Chandramohan const auto &redOperator{std::get<Fortran::parser::OmpReductionOperator>(
9837bb1151bSKiran Chandramohan reductionClause->v.t)};
9847bb1151bSKiran Chandramohan const auto &objectList{
9857bb1151bSKiran Chandramohan std::get<Fortran::parser::OmpObjectList>(reductionClause->v.t)};
9867bb1151bSKiran Chandramohan if (const auto &redDefinedOp =
9877bb1151bSKiran Chandramohan std::get_if<Fortran::parser::DefinedOperator>(&redOperator.u)) {
9887bb1151bSKiran Chandramohan const auto &intrinsicOp{
9897bb1151bSKiran Chandramohan std::get<Fortran::parser::DefinedOperator::IntrinsicOperator>(
9907bb1151bSKiran Chandramohan redDefinedOp->u)};
9917bb1151bSKiran Chandramohan if (intrinsicOp !=
9927bb1151bSKiran Chandramohan Fortran::parser::DefinedOperator::IntrinsicOperator::Add)
9937bb1151bSKiran Chandramohan TODO(currentLocation,
9947bb1151bSKiran Chandramohan "Reduction of some intrinsic operators is not supported");
9957bb1151bSKiran Chandramohan for (const auto &ompObject : objectList.v) {
9967bb1151bSKiran Chandramohan if (const auto *name{
9977bb1151bSKiran Chandramohan Fortran::parser::Unwrap<Fortran::parser::Name>(ompObject)}) {
9987bb1151bSKiran Chandramohan if (const auto *symbol{name->symbol}) {
9997bb1151bSKiran Chandramohan mlir::Value symVal = converter.getSymbolAddress(*symbol);
10007bb1151bSKiran Chandramohan mlir::Type redType =
10017bb1151bSKiran Chandramohan symVal.getType().cast<fir::ReferenceType>().getEleTy();
10027bb1151bSKiran Chandramohan reductionVars.push_back(symVal);
10037bb1151bSKiran Chandramohan if (redType.isIntOrIndex()) {
10047bb1151bSKiran Chandramohan decl = createReductionDecl(
10057bb1151bSKiran Chandramohan firOpBuilder, getReductionName(intrinsicOp, redType),
10067bb1151bSKiran Chandramohan redType, currentLocation);
10077bb1151bSKiran Chandramohan } else {
10087bb1151bSKiran Chandramohan TODO(currentLocation,
10097bb1151bSKiran Chandramohan "Reduction of some types is not supported");
10107bb1151bSKiran Chandramohan }
10117bb1151bSKiran Chandramohan reductionDeclSymbols.push_back(SymbolRefAttr::get(
10127bb1151bSKiran Chandramohan firOpBuilder.getContext(), decl.sym_name()));
10137bb1151bSKiran Chandramohan }
10147bb1151bSKiran Chandramohan }
10157bb1151bSKiran Chandramohan }
10167bb1151bSKiran Chandramohan } else {
10177bb1151bSKiran Chandramohan TODO(currentLocation,
10187bb1151bSKiran Chandramohan "Reduction of intrinsic procedures is not supported");
10197bb1151bSKiran Chandramohan }
1020820146abSMats Petersson }
1021820146abSMats Petersson }
1022820146abSMats Petersson
1023870f4421SPeixin-Qiao // The types of lower bound, upper bound, and step are converted into the
1024870f4421SPeixin-Qiao // type of the loop variable if necessary.
1025870f4421SPeixin-Qiao mlir::Type loopVarType = getLoopVarType(converter, loopVarTypeSize);
1026870f4421SPeixin-Qiao for (unsigned it = 0; it < (unsigned)lowerBound.size(); it++) {
1027870f4421SPeixin-Qiao lowerBound[it] = firOpBuilder.createConvert(currentLocation, loopVarType,
1028870f4421SPeixin-Qiao lowerBound[it]);
1029870f4421SPeixin-Qiao upperBound[it] = firOpBuilder.createConvert(currentLocation, loopVarType,
1030870f4421SPeixin-Qiao upperBound[it]);
1031870f4421SPeixin-Qiao step[it] =
1032870f4421SPeixin-Qiao firOpBuilder.createConvert(currentLocation, loopVarType, step[it]);
1033870f4421SPeixin-Qiao }
1034870f4421SPeixin-Qiao
10353f4a63e5SArnamoy Bhattacharyya // 2.9.3.1 SIMD construct
10363f4a63e5SArnamoy Bhattacharyya // TODO: Support all the clauses
10373f4a63e5SArnamoy Bhattacharyya if (llvm::omp::OMPD_simd == ompDirective) {
10383f4a63e5SArnamoy Bhattacharyya TypeRange resultType;
10393f4a63e5SArnamoy Bhattacharyya auto SimdLoopOp = firOpBuilder.create<mlir::omp::SimdLoopOp>(
10402c915e3bSDominik Adamski currentLocation, resultType, lowerBound, upperBound, step,
10412c915e3bSDominik Adamski ifClauseOperand, /*inclusive=*/firOpBuilder.getUnitAttr());
10423f4a63e5SArnamoy Bhattacharyya createBodyOfOp<omp::SimdLoopOp>(SimdLoopOp, converter, currentLocation,
10433f4a63e5SArnamoy Bhattacharyya eval, &loopOpClauseList, iv);
10443f4a63e5SArnamoy Bhattacharyya return;
10453f4a63e5SArnamoy Bhattacharyya }
10463f4a63e5SArnamoy Bhattacharyya
1047b85c39ddSKiran Chandramohan // FIXME: Add support for following clauses:
1048b85c39ddSKiran Chandramohan // 1. linear
1049b85c39ddSKiran Chandramohan // 2. order
1050b85c39ddSKiran Chandramohan auto wsLoopOp = firOpBuilder.create<mlir::omp::WsLoopOp>(
1051b85c39ddSKiran Chandramohan currentLocation, lowerBound, upperBound, step, linearVars, linearStepVars,
10527bb1151bSKiran Chandramohan reductionVars,
10537bb1151bSKiran Chandramohan reductionDeclSymbols.empty()
10547bb1151bSKiran Chandramohan ? nullptr
10557bb1151bSKiran Chandramohan : mlir::ArrayAttr::get(firOpBuilder.getContext(),
10567bb1151bSKiran Chandramohan reductionDeclSymbols),
1057b85c39ddSKiran Chandramohan scheduleClauseOperand.dyn_cast_or_null<omp::ClauseScheduleKindAttr>(),
1058b85c39ddSKiran Chandramohan scheduleChunkClauseOperand, /*schedule_modifiers=*/nullptr,
1059b85c39ddSKiran Chandramohan /*simd_modifier=*/nullptr,
1060b85c39ddSKiran Chandramohan noWaitClauseOperand.dyn_cast_or_null<UnitAttr>(),
1061b85c39ddSKiran Chandramohan orderedClauseOperand.dyn_cast_or_null<IntegerAttr>(),
1062b85c39ddSKiran Chandramohan orderClauseOperand.dyn_cast_or_null<omp::ClauseOrderKindAttr>(),
1063b85c39ddSKiran Chandramohan /*inclusive=*/firOpBuilder.getUnitAttr());
1064b85c39ddSKiran Chandramohan
1065b85c39ddSKiran Chandramohan // Handle attribute based clauses.
10663f4a63e5SArnamoy Bhattacharyya for (const Fortran::parser::OmpClause &clause : loopOpClauseList.v) {
1067f305ac3dSPeixin-Qiao if (const auto &orderedClause =
1068f305ac3dSPeixin-Qiao std::get_if<Fortran::parser::OmpClause::Ordered>(&clause.u)) {
1069f305ac3dSPeixin-Qiao if (orderedClause->v.has_value()) {
1070f305ac3dSPeixin-Qiao const auto *expr = Fortran::semantics::GetExpr(orderedClause->v);
1071f305ac3dSPeixin-Qiao const std::optional<std::int64_t> orderedClauseValue =
1072f305ac3dSPeixin-Qiao Fortran::evaluate::ToInt64(*expr);
1073f305ac3dSPeixin-Qiao wsLoopOp.ordered_valAttr(
1074f305ac3dSPeixin-Qiao firOpBuilder.getI64IntegerAttr(*orderedClauseValue));
1075f305ac3dSPeixin-Qiao } else {
1076f305ac3dSPeixin-Qiao wsLoopOp.ordered_valAttr(firOpBuilder.getI64IntegerAttr(0));
1077f305ac3dSPeixin-Qiao }
1078f305ac3dSPeixin-Qiao } else if (const auto &scheduleClause =
1079f305ac3dSPeixin-Qiao std::get_if<Fortran::parser::OmpClause::Schedule>(
1080f305ac3dSPeixin-Qiao &clause.u)) {
1081b85c39ddSKiran Chandramohan mlir::MLIRContext *context = firOpBuilder.getContext();
1082b85c39ddSKiran Chandramohan const auto &scheduleType = scheduleClause->v;
1083b85c39ddSKiran Chandramohan const auto &scheduleKind =
1084b85c39ddSKiran Chandramohan std::get<Fortran::parser::OmpScheduleClause::ScheduleType>(
1085b85c39ddSKiran Chandramohan scheduleType.t);
1086b85c39ddSKiran Chandramohan switch (scheduleKind) {
1087b85c39ddSKiran Chandramohan case Fortran::parser::OmpScheduleClause::ScheduleType::Static:
1088b85c39ddSKiran Chandramohan wsLoopOp.schedule_valAttr(omp::ClauseScheduleKindAttr::get(
1089b85c39ddSKiran Chandramohan context, omp::ClauseScheduleKind::Static));
1090b85c39ddSKiran Chandramohan break;
1091b85c39ddSKiran Chandramohan case Fortran::parser::OmpScheduleClause::ScheduleType::Dynamic:
1092b85c39ddSKiran Chandramohan wsLoopOp.schedule_valAttr(omp::ClauseScheduleKindAttr::get(
1093b85c39ddSKiran Chandramohan context, omp::ClauseScheduleKind::Dynamic));
1094b85c39ddSKiran Chandramohan break;
1095b85c39ddSKiran Chandramohan case Fortran::parser::OmpScheduleClause::ScheduleType::Guided:
1096b85c39ddSKiran Chandramohan wsLoopOp.schedule_valAttr(omp::ClauseScheduleKindAttr::get(
1097b85c39ddSKiran Chandramohan context, omp::ClauseScheduleKind::Guided));
1098b85c39ddSKiran Chandramohan break;
1099b85c39ddSKiran Chandramohan case Fortran::parser::OmpScheduleClause::ScheduleType::Auto:
1100b85c39ddSKiran Chandramohan wsLoopOp.schedule_valAttr(omp::ClauseScheduleKindAttr::get(
1101b85c39ddSKiran Chandramohan context, omp::ClauseScheduleKind::Auto));
1102b85c39ddSKiran Chandramohan break;
1103b85c39ddSKiran Chandramohan case Fortran::parser::OmpScheduleClause::ScheduleType::Runtime:
1104b85c39ddSKiran Chandramohan wsLoopOp.schedule_valAttr(omp::ClauseScheduleKindAttr::get(
1105b85c39ddSKiran Chandramohan context, omp::ClauseScheduleKind::Runtime));
1106b85c39ddSKiran Chandramohan break;
1107b85c39ddSKiran Chandramohan }
11088b951e64SKiran Chandramohan mlir::omp::ScheduleModifier scheduleModifier =
11098b951e64SKiran Chandramohan getScheduleModifier(scheduleClause->v);
11108b951e64SKiran Chandramohan if (scheduleModifier != mlir::omp::ScheduleModifier::none)
11118b951e64SKiran Chandramohan wsLoopOp.schedule_modifierAttr(
11128b951e64SKiran Chandramohan omp::ScheduleModifierAttr::get(context, scheduleModifier));
11138b951e64SKiran Chandramohan if (getSIMDModifier(scheduleClause->v) !=
11148b951e64SKiran Chandramohan mlir::omp::ScheduleModifier::none)
11158b951e64SKiran Chandramohan wsLoopOp.simd_modifierAttr(firOpBuilder.getUnitAttr());
1116b85c39ddSKiran Chandramohan }
1117b85c39ddSKiran Chandramohan }
1118b85c39ddSKiran Chandramohan // In FORTRAN `nowait` clause occur at the end of `omp do` directive.
1119b85c39ddSKiran Chandramohan // i.e
1120b85c39ddSKiran Chandramohan // !$omp do
1121b85c39ddSKiran Chandramohan // <...>
1122b85c39ddSKiran Chandramohan // !$omp end do nowait
1123b85c39ddSKiran Chandramohan if (const auto &endClauseList =
1124b85c39ddSKiran Chandramohan std::get<std::optional<Fortran::parser::OmpEndLoopDirective>>(
1125b85c39ddSKiran Chandramohan loopConstruct.t)) {
1126b85c39ddSKiran Chandramohan const auto &clauseList =
1127b85c39ddSKiran Chandramohan std::get<Fortran::parser::OmpClauseList>((*endClauseList).t);
1128b85c39ddSKiran Chandramohan for (const Fortran::parser::OmpClause &clause : clauseList.v)
1129b85c39ddSKiran Chandramohan if (std::get_if<Fortran::parser::OmpClause::Nowait>(&clause.u))
1130b85c39ddSKiran Chandramohan wsLoopOp.nowaitAttr(firOpBuilder.getUnitAttr());
1131b85c39ddSKiran Chandramohan }
1132b85c39ddSKiran Chandramohan
113329f167abSKiran Chandramohan createBodyOfOp<omp::WsLoopOp>(wsLoopOp, converter, currentLocation, eval,
11343f4a63e5SArnamoy Bhattacharyya &loopOpClauseList, iv);
1135b85c39ddSKiran Chandramohan }
1136b85c39ddSKiran Chandramohan
1137ebec5e5cSShraiysh Vaishay static void
genOMP(Fortran::lower::AbstractConverter & converter,Fortran::lower::pft::Evaluation & eval,const Fortran::parser::OpenMPCriticalConstruct & criticalConstruct)1138ebec5e5cSShraiysh Vaishay genOMP(Fortran::lower::AbstractConverter &converter,
1139ebec5e5cSShraiysh Vaishay Fortran::lower::pft::Evaluation &eval,
1140ebec5e5cSShraiysh Vaishay const Fortran::parser::OpenMPCriticalConstruct &criticalConstruct) {
1141ebec5e5cSShraiysh Vaishay fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
1142ebec5e5cSShraiysh Vaishay mlir::Location currentLocation = converter.getCurrentLocation();
1143ebec5e5cSShraiysh Vaishay std::string name;
1144ebec5e5cSShraiysh Vaishay const Fortran::parser::OmpCriticalDirective &cd =
1145ebec5e5cSShraiysh Vaishay std::get<Fortran::parser::OmpCriticalDirective>(criticalConstruct.t);
1146ebec5e5cSShraiysh Vaishay if (std::get<std::optional<Fortran::parser::Name>>(cd.t).has_value()) {
1147ebec5e5cSShraiysh Vaishay name =
1148ebec5e5cSShraiysh Vaishay std::get<std::optional<Fortran::parser::Name>>(cd.t).value().ToString();
1149ebec5e5cSShraiysh Vaishay }
1150ebec5e5cSShraiysh Vaishay
1151ebec5e5cSShraiysh Vaishay uint64_t hint = 0;
1152ebec5e5cSShraiysh Vaishay const auto &clauseList = std::get<Fortran::parser::OmpClauseList>(cd.t);
1153ebec5e5cSShraiysh Vaishay for (const Fortran::parser::OmpClause &clause : clauseList.v)
1154ebec5e5cSShraiysh Vaishay if (auto hintClause =
1155ebec5e5cSShraiysh Vaishay std::get_if<Fortran::parser::OmpClause::Hint>(&clause.u)) {
1156ebec5e5cSShraiysh Vaishay const auto *expr = Fortran::semantics::GetExpr(hintClause->v);
1157ebec5e5cSShraiysh Vaishay hint = *Fortran::evaluate::ToInt64(*expr);
1158ebec5e5cSShraiysh Vaishay break;
1159ebec5e5cSShraiysh Vaishay }
1160ebec5e5cSShraiysh Vaishay
1161ebec5e5cSShraiysh Vaishay mlir::omp::CriticalOp criticalOp = [&]() {
1162ebec5e5cSShraiysh Vaishay if (name.empty()) {
1163ebec5e5cSShraiysh Vaishay return firOpBuilder.create<mlir::omp::CriticalOp>(currentLocation,
1164ebec5e5cSShraiysh Vaishay FlatSymbolRefAttr());
1165ebec5e5cSShraiysh Vaishay } else {
1166ebec5e5cSShraiysh Vaishay mlir::ModuleOp module = firOpBuilder.getModule();
1167ebec5e5cSShraiysh Vaishay mlir::OpBuilder modBuilder(module.getBodyRegion());
1168ebec5e5cSShraiysh Vaishay auto global = module.lookupSymbol<mlir::omp::CriticalDeclareOp>(name);
1169ebec5e5cSShraiysh Vaishay if (!global)
1170ebec5e5cSShraiysh Vaishay global = modBuilder.create<mlir::omp::CriticalDeclareOp>(
1171ebec5e5cSShraiysh Vaishay currentLocation, name, hint);
1172ebec5e5cSShraiysh Vaishay return firOpBuilder.create<mlir::omp::CriticalOp>(
1173ebec5e5cSShraiysh Vaishay currentLocation, mlir::FlatSymbolRefAttr::get(
1174ebec5e5cSShraiysh Vaishay firOpBuilder.getContext(), global.sym_name()));
1175ebec5e5cSShraiysh Vaishay }
1176ebec5e5cSShraiysh Vaishay }();
117729f167abSKiran Chandramohan createBodyOfOp<omp::CriticalOp>(criticalOp, converter, currentLocation, eval);
1178ebec5e5cSShraiysh Vaishay }
1179ebec5e5cSShraiysh Vaishay
118088d5289fSNimish Mishra static void
genOMP(Fortran::lower::AbstractConverter & converter,Fortran::lower::pft::Evaluation & eval,const Fortran::parser::OpenMPSectionConstruct & sectionConstruct)118188d5289fSNimish Mishra genOMP(Fortran::lower::AbstractConverter &converter,
118288d5289fSNimish Mishra Fortran::lower::pft::Evaluation &eval,
118388d5289fSNimish Mishra const Fortran::parser::OpenMPSectionConstruct §ionConstruct) {
118488d5289fSNimish Mishra
118588d5289fSNimish Mishra auto &firOpBuilder = converter.getFirOpBuilder();
118688d5289fSNimish Mishra auto currentLocation = converter.getCurrentLocation();
118788d5289fSNimish Mishra mlir::omp::SectionOp sectionOp =
118888d5289fSNimish Mishra firOpBuilder.create<mlir::omp::SectionOp>(currentLocation);
118929f167abSKiran Chandramohan createBodyOfOp<omp::SectionOp>(sectionOp, converter, currentLocation, eval);
119088d5289fSNimish Mishra }
119188d5289fSNimish Mishra
119288d5289fSNimish Mishra // TODO: Add support for reduction
119388d5289fSNimish Mishra static void
genOMP(Fortran::lower::AbstractConverter & converter,Fortran::lower::pft::Evaluation & eval,const Fortran::parser::OpenMPSectionsConstruct & sectionsConstruct)119488d5289fSNimish Mishra genOMP(Fortran::lower::AbstractConverter &converter,
119588d5289fSNimish Mishra Fortran::lower::pft::Evaluation &eval,
119688d5289fSNimish Mishra const Fortran::parser::OpenMPSectionsConstruct §ionsConstruct) {
119788d5289fSNimish Mishra auto &firOpBuilder = converter.getFirOpBuilder();
119888d5289fSNimish Mishra auto currentLocation = converter.getCurrentLocation();
119988d5289fSNimish Mishra SmallVector<Value> reductionVars, allocateOperands, allocatorOperands;
120088d5289fSNimish Mishra mlir::UnitAttr noWaitClauseOperand;
120188d5289fSNimish Mishra const auto §ionsClauseList = std::get<Fortran::parser::OmpClauseList>(
120288d5289fSNimish Mishra std::get<Fortran::parser::OmpBeginSectionsDirective>(sectionsConstruct.t)
120388d5289fSNimish Mishra .t);
120488d5289fSNimish Mishra for (const Fortran::parser::OmpClause &clause : sectionsClauseList.v) {
12051fe4b968SShraiysh Vaishay
12061fe4b968SShraiysh Vaishay // Reduction Clause
120788d5289fSNimish Mishra if (std::get_if<Fortran::parser::OmpClause::Reduction>(&clause.u)) {
120888d5289fSNimish Mishra TODO(currentLocation, "OMPC_Reduction");
12091fe4b968SShraiysh Vaishay
12101fe4b968SShraiysh Vaishay // Allocate clause
121188d5289fSNimish Mishra } else if (const auto &allocateClause =
121288d5289fSNimish Mishra std::get_if<Fortran::parser::OmpClause::Allocate>(
121388d5289fSNimish Mishra &clause.u)) {
121488d5289fSNimish Mishra genAllocateClause(converter, allocateClause->v, allocatorOperands,
121588d5289fSNimish Mishra allocateOperands);
121688d5289fSNimish Mishra }
121788d5289fSNimish Mishra }
121888d5289fSNimish Mishra const auto &endSectionsClauseList =
121988d5289fSNimish Mishra std::get<Fortran::parser::OmpEndSectionsDirective>(sectionsConstruct.t);
122088d5289fSNimish Mishra const auto &clauseList =
122188d5289fSNimish Mishra std::get<Fortran::parser::OmpClauseList>(endSectionsClauseList.t);
122288d5289fSNimish Mishra for (const auto &clause : clauseList.v) {
12231fe4b968SShraiysh Vaishay // Nowait clause
122488d5289fSNimish Mishra if (std::get_if<Fortran::parser::OmpClause::Nowait>(&clause.u)) {
122588d5289fSNimish Mishra noWaitClauseOperand = firOpBuilder.getUnitAttr();
122688d5289fSNimish Mishra }
122788d5289fSNimish Mishra }
122888d5289fSNimish Mishra
12291fe4b968SShraiysh Vaishay llvm::omp::Directive dir =
12301fe4b968SShraiysh Vaishay std::get<Fortran::parser::OmpSectionsDirective>(
12311fe4b968SShraiysh Vaishay std::get<Fortran::parser::OmpBeginSectionsDirective>(
12321fe4b968SShraiysh Vaishay sectionsConstruct.t)
12331fe4b968SShraiysh Vaishay .t)
12341fe4b968SShraiysh Vaishay .v;
12351fe4b968SShraiysh Vaishay
12361fe4b968SShraiysh Vaishay // Parallel Sections Construct
12371fe4b968SShraiysh Vaishay if (dir == llvm::omp::Directive::OMPD_parallel_sections) {
12384202d69dSKiran Chandramohan createCombinedParallelOp<Fortran::parser::OmpBeginSectionsDirective>(
12394202d69dSKiran Chandramohan converter, eval,
12404202d69dSKiran Chandramohan std::get<Fortran::parser::OmpBeginSectionsDirective>(
12414202d69dSKiran Chandramohan sectionsConstruct.t));
12421fe4b968SShraiysh Vaishay auto sectionsOp = firOpBuilder.create<mlir::omp::SectionsOp>(
12431fe4b968SShraiysh Vaishay currentLocation, /*reduction_vars*/ ValueRange(),
12444202d69dSKiran Chandramohan /*reductions=*/nullptr, allocateOperands, allocatorOperands,
12454202d69dSKiran Chandramohan /*nowait=*/nullptr);
124629f167abSKiran Chandramohan createBodyOfOp(sectionsOp, converter, currentLocation, eval);
12471fe4b968SShraiysh Vaishay
12481fe4b968SShraiysh Vaishay // Sections Construct
12491fe4b968SShraiysh Vaishay } else if (dir == llvm::omp::Directive::OMPD_sections) {
12501fe4b968SShraiysh Vaishay auto sectionsOp = firOpBuilder.create<mlir::omp::SectionsOp>(
125188d5289fSNimish Mishra currentLocation, reductionVars, /*reductions = */ nullptr,
125288d5289fSNimish Mishra allocateOperands, allocatorOperands, noWaitClauseOperand);
125329f167abSKiran Chandramohan createBodyOfOp<omp::SectionsOp>(sectionsOp, converter, currentLocation,
125429f167abSKiran Chandramohan eval);
125588d5289fSNimish Mishra }
12561fe4b968SShraiysh Vaishay }
125788d5289fSNimish Mishra
genOmpAtomicHintAndMemoryOrderClauses(Fortran::lower::AbstractConverter & converter,const Fortran::parser::OmpAtomicClauseList & clauseList,mlir::IntegerAttr & hint,mlir::omp::ClauseMemoryOrderKindAttr & memory_order)125800c511b3SNimish Mishra static void genOmpAtomicHintAndMemoryOrderClauses(
125900c511b3SNimish Mishra Fortran::lower::AbstractConverter &converter,
126000c511b3SNimish Mishra const Fortran::parser::OmpAtomicClauseList &clauseList,
126100c511b3SNimish Mishra mlir::IntegerAttr &hint,
126200c511b3SNimish Mishra mlir::omp::ClauseMemoryOrderKindAttr &memory_order) {
126300c511b3SNimish Mishra auto &firOpBuilder = converter.getFirOpBuilder();
126400c511b3SNimish Mishra for (const auto &clause : clauseList.v) {
126500c511b3SNimish Mishra if (auto ompClause = std::get_if<Fortran::parser::OmpClause>(&clause.u)) {
126600c511b3SNimish Mishra if (auto hintClause =
126700c511b3SNimish Mishra std::get_if<Fortran::parser::OmpClause::Hint>(&ompClause->u)) {
126800c511b3SNimish Mishra const auto *expr = Fortran::semantics::GetExpr(hintClause->v);
126900c511b3SNimish Mishra uint64_t hintExprValue = *Fortran::evaluate::ToInt64(*expr);
127000c511b3SNimish Mishra hint = firOpBuilder.getI64IntegerAttr(hintExprValue);
127100c511b3SNimish Mishra }
127200c511b3SNimish Mishra } else if (auto ompMemoryOrderClause =
127300c511b3SNimish Mishra std::get_if<Fortran::parser::OmpMemoryOrderClause>(
127400c511b3SNimish Mishra &clause.u)) {
127500c511b3SNimish Mishra if (std::get_if<Fortran::parser::OmpClause::Acquire>(
127600c511b3SNimish Mishra &ompMemoryOrderClause->v.u)) {
127700c511b3SNimish Mishra memory_order = mlir::omp::ClauseMemoryOrderKindAttr::get(
127800c511b3SNimish Mishra firOpBuilder.getContext(), omp::ClauseMemoryOrderKind::Acquire);
127900c511b3SNimish Mishra } else if (std::get_if<Fortran::parser::OmpClause::Relaxed>(
128000c511b3SNimish Mishra &ompMemoryOrderClause->v.u)) {
128100c511b3SNimish Mishra memory_order = mlir::omp::ClauseMemoryOrderKindAttr::get(
128200c511b3SNimish Mishra firOpBuilder.getContext(), omp::ClauseMemoryOrderKind::Relaxed);
128300c511b3SNimish Mishra } else if (std::get_if<Fortran::parser::OmpClause::SeqCst>(
128400c511b3SNimish Mishra &ompMemoryOrderClause->v.u)) {
128500c511b3SNimish Mishra memory_order = mlir::omp::ClauseMemoryOrderKindAttr::get(
128600c511b3SNimish Mishra firOpBuilder.getContext(), omp::ClauseMemoryOrderKind::Seq_cst);
128700c511b3SNimish Mishra } else if (std::get_if<Fortran::parser::OmpClause::Release>(
128800c511b3SNimish Mishra &ompMemoryOrderClause->v.u)) {
128900c511b3SNimish Mishra memory_order = mlir::omp::ClauseMemoryOrderKindAttr::get(
129000c511b3SNimish Mishra firOpBuilder.getContext(), omp::ClauseMemoryOrderKind::Release);
129100c511b3SNimish Mishra }
129200c511b3SNimish Mishra }
129300c511b3SNimish Mishra }
129400c511b3SNimish Mishra }
129500c511b3SNimish Mishra
genOmpAtomicUpdateStatement(Fortran::lower::AbstractConverter & converter,Fortran::lower::pft::Evaluation & eval,const Fortran::parser::Variable & assignmentStmtVariable,const Fortran::parser::Expr & assignmentStmtExpr,const Fortran::parser::OmpAtomicClauseList * leftHandClauseList,const Fortran::parser::OmpAtomicClauseList * rightHandClauseList)1296a56b76d9SNimish Mishra static void genOmpAtomicUpdateStatement(
1297a56b76d9SNimish Mishra Fortran::lower::AbstractConverter &converter,
1298a56b76d9SNimish Mishra Fortran::lower::pft::Evaluation &eval,
1299a56b76d9SNimish Mishra const Fortran::parser::Variable &assignmentStmtVariable,
1300a56b76d9SNimish Mishra const Fortran::parser::Expr &assignmentStmtExpr,
1301a56b76d9SNimish Mishra const Fortran::parser::OmpAtomicClauseList *leftHandClauseList,
1302a56b76d9SNimish Mishra const Fortran::parser::OmpAtomicClauseList *rightHandClauseList) {
1303a56b76d9SNimish Mishra // Generate `omp.atomic.update` operation for atomic assignment statements
1304a56b76d9SNimish Mishra auto &firOpBuilder = converter.getFirOpBuilder();
1305a56b76d9SNimish Mishra auto currentLocation = converter.getCurrentLocation();
1306a56b76d9SNimish Mishra Fortran::lower::StatementContext stmtCtx;
1307a56b76d9SNimish Mishra
1308a56b76d9SNimish Mishra mlir::Value address = fir::getBase(converter.genExprAddr(
1309a56b76d9SNimish Mishra *Fortran::semantics::GetExpr(assignmentStmtVariable), stmtCtx));
1310a56b76d9SNimish Mishra // If no hint clause is specified, the effect is as if
1311a56b76d9SNimish Mishra // hint(omp_sync_hint_none) had been specified.
1312a56b76d9SNimish Mishra mlir::IntegerAttr hint = nullptr;
1313a56b76d9SNimish Mishra mlir::omp::ClauseMemoryOrderKindAttr memory_order = nullptr;
1314a56b76d9SNimish Mishra if (leftHandClauseList)
1315a56b76d9SNimish Mishra genOmpAtomicHintAndMemoryOrderClauses(converter, *leftHandClauseList, hint,
1316a56b76d9SNimish Mishra memory_order);
1317a56b76d9SNimish Mishra if (rightHandClauseList)
1318a56b76d9SNimish Mishra genOmpAtomicHintAndMemoryOrderClauses(converter, *rightHandClauseList, hint,
1319a56b76d9SNimish Mishra memory_order);
1320a56b76d9SNimish Mishra auto atomicUpdateOp = firOpBuilder.create<mlir::omp::AtomicUpdateOp>(
1321a56b76d9SNimish Mishra currentLocation, address, hint, memory_order);
1322a56b76d9SNimish Mishra
1323a56b76d9SNimish Mishra //// Generate body of Atomic Update operation
1324a56b76d9SNimish Mishra // If an argument for the region is provided then create the block with that
1325a56b76d9SNimish Mishra // argument. Also update the symbol's address with the argument mlir value.
1326a56b76d9SNimish Mishra mlir::Type varType =
1327a56b76d9SNimish Mishra fir::getBase(
1328a56b76d9SNimish Mishra converter.genExprValue(
1329a56b76d9SNimish Mishra *Fortran::semantics::GetExpr(assignmentStmtVariable), stmtCtx))
1330a56b76d9SNimish Mishra .getType();
1331a56b76d9SNimish Mishra SmallVector<Type> varTys = {varType};
1332a56b76d9SNimish Mishra SmallVector<Location> locs = {currentLocation};
1333a56b76d9SNimish Mishra firOpBuilder.createBlock(&atomicUpdateOp.getRegion(), {}, varTys, locs);
1334a56b76d9SNimish Mishra mlir::Value val =
1335a56b76d9SNimish Mishra fir::getBase(atomicUpdateOp.getRegion().front().getArgument(0));
133658753deaSNimish Mishra auto varDesignator =
133758753deaSNimish Mishra std::get_if<Fortran::common::Indirection<Fortran::parser::Designator>>(
133858753deaSNimish Mishra &assignmentStmtVariable.u);
133958753deaSNimish Mishra assert(varDesignator && "Variable designator for atomic update assignment "
134058753deaSNimish Mishra "statement does not exist");
134158753deaSNimish Mishra const auto *name = getDesignatorNameIfDataRef(varDesignator->value());
134258753deaSNimish Mishra assert(name && name->symbol &&
134358753deaSNimish Mishra "No symbol attached to atomic update variable");
134458753deaSNimish Mishra converter.bindSymbol(*name->symbol, val);
1345a56b76d9SNimish Mishra // Set the insert for the terminator operation to go at the end of the
1346a56b76d9SNimish Mishra // block.
1347a56b76d9SNimish Mishra mlir::Block &block = atomicUpdateOp.getRegion().back();
1348a56b76d9SNimish Mishra firOpBuilder.setInsertionPointToEnd(&block);
1349a56b76d9SNimish Mishra
1350a56b76d9SNimish Mishra mlir::Value result = fir::getBase(converter.genExprValue(
1351a56b76d9SNimish Mishra *Fortran::semantics::GetExpr(assignmentStmtExpr), stmtCtx));
1352a56b76d9SNimish Mishra // Insert the terminator: YieldOp.
1353a56b76d9SNimish Mishra firOpBuilder.create<mlir::omp::YieldOp>(currentLocation, result);
1354a56b76d9SNimish Mishra // Reset the insert point to before the terminator.
1355a56b76d9SNimish Mishra firOpBuilder.setInsertionPointToStart(&block);
1356a56b76d9SNimish Mishra }
1357a56b76d9SNimish Mishra
135800c511b3SNimish Mishra static void
genOmpAtomicWrite(Fortran::lower::AbstractConverter & converter,Fortran::lower::pft::Evaluation & eval,const Fortran::parser::OmpAtomicWrite & atomicWrite)135900c511b3SNimish Mishra genOmpAtomicWrite(Fortran::lower::AbstractConverter &converter,
136000c511b3SNimish Mishra Fortran::lower::pft::Evaluation &eval,
136100c511b3SNimish Mishra const Fortran::parser::OmpAtomicWrite &atomicWrite) {
136200c511b3SNimish Mishra auto &firOpBuilder = converter.getFirOpBuilder();
136300c511b3SNimish Mishra auto currentLocation = converter.getCurrentLocation();
136466073306SPeixin-Qiao // Get the value and address of atomic write operands.
136500c511b3SNimish Mishra const Fortran::parser::OmpAtomicClauseList &rightHandClauseList =
136600c511b3SNimish Mishra std::get<2>(atomicWrite.t);
136700c511b3SNimish Mishra const Fortran::parser::OmpAtomicClauseList &leftHandClauseList =
136800c511b3SNimish Mishra std::get<0>(atomicWrite.t);
136900c511b3SNimish Mishra const auto &assignmentStmtExpr =
137000c511b3SNimish Mishra std::get<Fortran::parser::Expr>(std::get<3>(atomicWrite.t).statement.t);
137100c511b3SNimish Mishra const auto &assignmentStmtVariable = std::get<Fortran::parser::Variable>(
137200c511b3SNimish Mishra std::get<3>(atomicWrite.t).statement.t);
137300c511b3SNimish Mishra Fortran::lower::StatementContext stmtCtx;
137466073306SPeixin-Qiao mlir::Value value = fir::getBase(converter.genExprValue(
137500c511b3SNimish Mishra *Fortran::semantics::GetExpr(assignmentStmtExpr), stmtCtx));
137666073306SPeixin-Qiao mlir::Value address = fir::getBase(converter.genExprAddr(
137766073306SPeixin-Qiao *Fortran::semantics::GetExpr(assignmentStmtVariable), stmtCtx));
137866073306SPeixin-Qiao // If no hint clause is specified, the effect is as if
137966073306SPeixin-Qiao // hint(omp_sync_hint_none) had been specified.
138066073306SPeixin-Qiao mlir::IntegerAttr hint = nullptr;
138166073306SPeixin-Qiao mlir::omp::ClauseMemoryOrderKindAttr memory_order = nullptr;
138200c511b3SNimish Mishra genOmpAtomicHintAndMemoryOrderClauses(converter, leftHandClauseList, hint,
138300c511b3SNimish Mishra memory_order);
138400c511b3SNimish Mishra genOmpAtomicHintAndMemoryOrderClauses(converter, rightHandClauseList, hint,
138500c511b3SNimish Mishra memory_order);
138600c511b3SNimish Mishra firOpBuilder.create<mlir::omp::AtomicWriteOp>(currentLocation, address, value,
138700c511b3SNimish Mishra hint, memory_order);
138800c511b3SNimish Mishra }
138900c511b3SNimish Mishra
genOmpAtomicRead(Fortran::lower::AbstractConverter & converter,Fortran::lower::pft::Evaluation & eval,const Fortran::parser::OmpAtomicRead & atomicRead)139000c511b3SNimish Mishra static void genOmpAtomicRead(Fortran::lower::AbstractConverter &converter,
139100c511b3SNimish Mishra Fortran::lower::pft::Evaluation &eval,
139200c511b3SNimish Mishra const Fortran::parser::OmpAtomicRead &atomicRead) {
139300c511b3SNimish Mishra auto &firOpBuilder = converter.getFirOpBuilder();
139400c511b3SNimish Mishra auto currentLocation = converter.getCurrentLocation();
139566073306SPeixin-Qiao // Get the address of atomic read operands.
139600c511b3SNimish Mishra const Fortran::parser::OmpAtomicClauseList &rightHandClauseList =
139700c511b3SNimish Mishra std::get<2>(atomicRead.t);
139800c511b3SNimish Mishra const Fortran::parser::OmpAtomicClauseList &leftHandClauseList =
139900c511b3SNimish Mishra std::get<0>(atomicRead.t);
140000c511b3SNimish Mishra const auto &assignmentStmtExpr =
140100c511b3SNimish Mishra std::get<Fortran::parser::Expr>(std::get<3>(atomicRead.t).statement.t);
140200c511b3SNimish Mishra const auto &assignmentStmtVariable = std::get<Fortran::parser::Variable>(
140300c511b3SNimish Mishra std::get<3>(atomicRead.t).statement.t);
140466073306SPeixin-Qiao Fortran::lower::StatementContext stmtCtx;
140566073306SPeixin-Qiao mlir::Value from_address = fir::getBase(converter.genExprAddr(
140666073306SPeixin-Qiao *Fortran::semantics::GetExpr(assignmentStmtExpr), stmtCtx));
140766073306SPeixin-Qiao mlir::Value to_address = fir::getBase(converter.genExprAddr(
140866073306SPeixin-Qiao *Fortran::semantics::GetExpr(assignmentStmtVariable), stmtCtx));
140966073306SPeixin-Qiao // If no hint clause is specified, the effect is as if
141066073306SPeixin-Qiao // hint(omp_sync_hint_none) had been specified.
141166073306SPeixin-Qiao mlir::IntegerAttr hint = nullptr;
141266073306SPeixin-Qiao mlir::omp::ClauseMemoryOrderKindAttr memory_order = nullptr;
141300c511b3SNimish Mishra genOmpAtomicHintAndMemoryOrderClauses(converter, leftHandClauseList, hint,
141400c511b3SNimish Mishra memory_order);
141500c511b3SNimish Mishra genOmpAtomicHintAndMemoryOrderClauses(converter, rightHandClauseList, hint,
141600c511b3SNimish Mishra memory_order);
141700c511b3SNimish Mishra firOpBuilder.create<mlir::omp::AtomicReadOp>(currentLocation, from_address,
141800c511b3SNimish Mishra to_address, hint, memory_order);
141900c511b3SNimish Mishra }
142000c511b3SNimish Mishra
142100c511b3SNimish Mishra static void
genOmpAtomicUpdate(Fortran::lower::AbstractConverter & converter,Fortran::lower::pft::Evaluation & eval,const Fortran::parser::OmpAtomicUpdate & atomicUpdate)1422a56b76d9SNimish Mishra genOmpAtomicUpdate(Fortran::lower::AbstractConverter &converter,
1423a56b76d9SNimish Mishra Fortran::lower::pft::Evaluation &eval,
1424a56b76d9SNimish Mishra const Fortran::parser::OmpAtomicUpdate &atomicUpdate) {
1425a56b76d9SNimish Mishra const Fortran::parser::OmpAtomicClauseList &rightHandClauseList =
1426a56b76d9SNimish Mishra std::get<2>(atomicUpdate.t);
1427a56b76d9SNimish Mishra const Fortran::parser::OmpAtomicClauseList &leftHandClauseList =
1428a56b76d9SNimish Mishra std::get<0>(atomicUpdate.t);
1429a56b76d9SNimish Mishra const auto &assignmentStmtExpr =
1430a56b76d9SNimish Mishra std::get<Fortran::parser::Expr>(std::get<3>(atomicUpdate.t).statement.t);
1431a56b76d9SNimish Mishra const auto &assignmentStmtVariable = std::get<Fortran::parser::Variable>(
1432a56b76d9SNimish Mishra std::get<3>(atomicUpdate.t).statement.t);
1433a56b76d9SNimish Mishra
1434a56b76d9SNimish Mishra genOmpAtomicUpdateStatement(converter, eval, assignmentStmtVariable,
1435a56b76d9SNimish Mishra assignmentStmtExpr, &leftHandClauseList,
1436a56b76d9SNimish Mishra &rightHandClauseList);
1437a56b76d9SNimish Mishra }
1438a56b76d9SNimish Mishra
genOmpAtomic(Fortran::lower::AbstractConverter & converter,Fortran::lower::pft::Evaluation & eval,const Fortran::parser::OmpAtomic & atomicConstruct)1439a56b76d9SNimish Mishra static void genOmpAtomic(Fortran::lower::AbstractConverter &converter,
1440a56b76d9SNimish Mishra Fortran::lower::pft::Evaluation &eval,
1441a56b76d9SNimish Mishra const Fortran::parser::OmpAtomic &atomicConstruct) {
1442a56b76d9SNimish Mishra const Fortran::parser::OmpAtomicClauseList &atomicClauseList =
1443a56b76d9SNimish Mishra std::get<Fortran::parser::OmpAtomicClauseList>(atomicConstruct.t);
1444a56b76d9SNimish Mishra const auto &assignmentStmtExpr = std::get<Fortran::parser::Expr>(
1445a56b76d9SNimish Mishra std::get<Fortran::parser::Statement<Fortran::parser::AssignmentStmt>>(
1446a56b76d9SNimish Mishra atomicConstruct.t)
1447a56b76d9SNimish Mishra .statement.t);
1448a56b76d9SNimish Mishra const auto &assignmentStmtVariable = std::get<Fortran::parser::Variable>(
1449a56b76d9SNimish Mishra std::get<Fortran::parser::Statement<Fortran::parser::AssignmentStmt>>(
1450a56b76d9SNimish Mishra atomicConstruct.t)
1451a56b76d9SNimish Mishra .statement.t);
1452a56b76d9SNimish Mishra // If atomic-clause is not present on the construct, the behaviour is as if
1453a56b76d9SNimish Mishra // the update clause is specified
1454a56b76d9SNimish Mishra genOmpAtomicUpdateStatement(converter, eval, assignmentStmtVariable,
1455a56b76d9SNimish Mishra assignmentStmtExpr, &atomicClauseList, nullptr);
1456a56b76d9SNimish Mishra }
1457a56b76d9SNimish Mishra
1458a56b76d9SNimish Mishra static void
genOMP(Fortran::lower::AbstractConverter & converter,Fortran::lower::pft::Evaluation & eval,const Fortran::parser::OpenMPAtomicConstruct & atomicConstruct)145900c511b3SNimish Mishra genOMP(Fortran::lower::AbstractConverter &converter,
146000c511b3SNimish Mishra Fortran::lower::pft::Evaluation &eval,
146100c511b3SNimish Mishra const Fortran::parser::OpenMPAtomicConstruct &atomicConstruct) {
146200c511b3SNimish Mishra std::visit(Fortran::common::visitors{
146300c511b3SNimish Mishra [&](const Fortran::parser::OmpAtomicRead &atomicRead) {
146400c511b3SNimish Mishra genOmpAtomicRead(converter, eval, atomicRead);
146500c511b3SNimish Mishra },
146600c511b3SNimish Mishra [&](const Fortran::parser::OmpAtomicWrite &atomicWrite) {
146700c511b3SNimish Mishra genOmpAtomicWrite(converter, eval, atomicWrite);
146800c511b3SNimish Mishra },
1469a56b76d9SNimish Mishra [&](const Fortran::parser::OmpAtomic &atomicConstruct) {
1470a56b76d9SNimish Mishra genOmpAtomic(converter, eval, atomicConstruct);
1471a56b76d9SNimish Mishra },
1472a56b76d9SNimish Mishra [&](const Fortran::parser::OmpAtomicUpdate &atomicUpdate) {
1473a56b76d9SNimish Mishra genOmpAtomicUpdate(converter, eval, atomicUpdate);
1474a56b76d9SNimish Mishra },
147500c511b3SNimish Mishra [&](const auto &) {
1476a56b76d9SNimish Mishra TODO(converter.getCurrentLocation(), "Atomic capture");
147700c511b3SNimish Mishra },
147800c511b3SNimish Mishra },
147900c511b3SNimish Mishra atomicConstruct.u);
148000c511b3SNimish Mishra }
148100c511b3SNimish Mishra
genOpenMPConstruct(Fortran::lower::AbstractConverter & converter,Fortran::lower::pft::Evaluation & eval,const Fortran::parser::OpenMPConstruct & ompConstruct)14823d0b7602SSourabh Singh Tomar void Fortran::lower::genOpenMPConstruct(
1483dfa9065aSSourabh Singh Tomar Fortran::lower::AbstractConverter &converter,
14843d0b7602SSourabh Singh Tomar Fortran::lower::pft::Evaluation &eval,
14853d0b7602SSourabh Singh Tomar const Fortran::parser::OpenMPConstruct &ompConstruct) {
14863d0b7602SSourabh Singh Tomar
14873d0b7602SSourabh Singh Tomar std::visit(
14883d0b7602SSourabh Singh Tomar common::visitors{
14893d0b7602SSourabh Singh Tomar [&](const Fortran::parser::OpenMPStandaloneConstruct
14903d0b7602SSourabh Singh Tomar &standaloneConstruct) {
1491dfa9065aSSourabh Singh Tomar genOMP(converter, eval, standaloneConstruct);
14923d0b7602SSourabh Singh Tomar },
14933d0b7602SSourabh Singh Tomar [&](const Fortran::parser::OpenMPSectionsConstruct
149436ea1cacSJean Perier §ionsConstruct) {
149588d5289fSNimish Mishra genOMP(converter, eval, sectionsConstruct);
149636ea1cacSJean Perier },
1497ae1623b3SShraiysh Vaishay [&](const Fortran::parser::OpenMPSectionConstruct §ionConstruct) {
149888d5289fSNimish Mishra genOMP(converter, eval, sectionConstruct);
1499ae1623b3SShraiysh Vaishay },
15003d0b7602SSourabh Singh Tomar [&](const Fortran::parser::OpenMPLoopConstruct &loopConstruct) {
1501b85c39ddSKiran Chandramohan genOMP(converter, eval, loopConstruct);
15023d0b7602SSourabh Singh Tomar },
1503c9e967afSIrina Dobrescu [&](const Fortran::parser::OpenMPDeclarativeAllocate
150436ea1cacSJean Perier &execAllocConstruct) {
150536ea1cacSJean Perier TODO(converter.getCurrentLocation(), "OpenMPDeclarativeAllocate");
150636ea1cacSJean Perier },
1507c9e967afSIrina Dobrescu [&](const Fortran::parser::OpenMPExecutableAllocate
150836ea1cacSJean Perier &execAllocConstruct) {
150936ea1cacSJean Perier TODO(converter.getCurrentLocation(), "OpenMPExecutableAllocate");
151036ea1cacSJean Perier },
15113d0b7602SSourabh Singh Tomar [&](const Fortran::parser::OpenMPBlockConstruct &blockConstruct) {
1512dfa9065aSSourabh Singh Tomar genOMP(converter, eval, blockConstruct);
15133d0b7602SSourabh Singh Tomar },
15143d0b7602SSourabh Singh Tomar [&](const Fortran::parser::OpenMPAtomicConstruct &atomicConstruct) {
151500c511b3SNimish Mishra genOMP(converter, eval, atomicConstruct);
15163d0b7602SSourabh Singh Tomar },
15173d0b7602SSourabh Singh Tomar [&](const Fortran::parser::OpenMPCriticalConstruct
151836ea1cacSJean Perier &criticalConstruct) {
1519ebec5e5cSShraiysh Vaishay genOMP(converter, eval, criticalConstruct);
152036ea1cacSJean Perier },
15213d0b7602SSourabh Singh Tomar },
15223d0b7602SSourabh Singh Tomar ompConstruct.u);
1523ae6e499dSEric Schweitz }
1524b6b8d345SPeixin-Qiao
genThreadprivateOp(Fortran::lower::AbstractConverter & converter,const Fortran::lower::pft::Variable & var)1525411bd2d4SPeixin-Qiao void Fortran::lower::genThreadprivateOp(
1526411bd2d4SPeixin-Qiao Fortran::lower::AbstractConverter &converter,
1527411bd2d4SPeixin-Qiao const Fortran::lower::pft::Variable &var) {
1528411bd2d4SPeixin-Qiao fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
1529411bd2d4SPeixin-Qiao mlir::Location currentLocation = converter.getCurrentLocation();
1530411bd2d4SPeixin-Qiao
1531411bd2d4SPeixin-Qiao const Fortran::semantics::Symbol &sym = var.getSymbol();
1532411bd2d4SPeixin-Qiao mlir::Value symThreadprivateValue;
1533411bd2d4SPeixin-Qiao if (const Fortran::semantics::Symbol *common =
1534411bd2d4SPeixin-Qiao Fortran::semantics::FindCommonBlockContaining(sym.GetUltimate())) {
1535411bd2d4SPeixin-Qiao mlir::Value commonValue = converter.getSymbolAddress(*common);
1536411bd2d4SPeixin-Qiao if (mlir::isa<mlir::omp::ThreadprivateOp>(commonValue.getDefiningOp())) {
1537411bd2d4SPeixin-Qiao // Generate ThreadprivateOp for a common block instead of its members and
1538411bd2d4SPeixin-Qiao // only do it once for a common block.
1539411bd2d4SPeixin-Qiao return;
1540411bd2d4SPeixin-Qiao }
1541411bd2d4SPeixin-Qiao // Generate ThreadprivateOp and rebind the common block.
1542411bd2d4SPeixin-Qiao mlir::Value commonThreadprivateValue =
1543411bd2d4SPeixin-Qiao firOpBuilder.create<mlir::omp::ThreadprivateOp>(
1544411bd2d4SPeixin-Qiao currentLocation, commonValue.getType(), commonValue);
1545411bd2d4SPeixin-Qiao converter.bindSymbol(*common, commonThreadprivateValue);
1546411bd2d4SPeixin-Qiao // Generate the threadprivate value for the common block member.
1547411bd2d4SPeixin-Qiao symThreadprivateValue =
1548411bd2d4SPeixin-Qiao genCommonBlockMember(converter, sym, commonThreadprivateValue);
1549411bd2d4SPeixin-Qiao } else {
1550411bd2d4SPeixin-Qiao mlir::Value symValue = converter.getSymbolAddress(sym);
1551411bd2d4SPeixin-Qiao symThreadprivateValue = firOpBuilder.create<mlir::omp::ThreadprivateOp>(
1552411bd2d4SPeixin-Qiao currentLocation, symValue.getType(), symValue);
1553411bd2d4SPeixin-Qiao }
1554411bd2d4SPeixin-Qiao
1555411bd2d4SPeixin-Qiao fir::ExtendedValue sexv = converter.getSymbolExtendedValue(sym);
1556411bd2d4SPeixin-Qiao fir::ExtendedValue symThreadprivateExv =
1557411bd2d4SPeixin-Qiao getExtendedValue(sexv, symThreadprivateValue);
1558411bd2d4SPeixin-Qiao converter.bindSymbol(sym, symThreadprivateExv);
1559411bd2d4SPeixin-Qiao }
1560411bd2d4SPeixin-Qiao
genOpenMPDeclarativeConstruct(Fortran::lower::AbstractConverter & converter,Fortran::lower::pft::Evaluation & eval,const Fortran::parser::OpenMPDeclarativeConstruct & ompDeclConstruct)1561b6b8d345SPeixin-Qiao void Fortran::lower::genOpenMPDeclarativeConstruct(
1562b6b8d345SPeixin-Qiao Fortran::lower::AbstractConverter &converter,
1563b6b8d345SPeixin-Qiao Fortran::lower::pft::Evaluation &eval,
1564b6b8d345SPeixin-Qiao const Fortran::parser::OpenMPDeclarativeConstruct &ompDeclConstruct) {
1565b6b8d345SPeixin-Qiao
1566b6b8d345SPeixin-Qiao std::visit(
1567b6b8d345SPeixin-Qiao common::visitors{
1568b6b8d345SPeixin-Qiao [&](const Fortran::parser::OpenMPDeclarativeAllocate
1569b6b8d345SPeixin-Qiao &declarativeAllocate) {
1570b6b8d345SPeixin-Qiao TODO(converter.getCurrentLocation(), "OpenMPDeclarativeAllocate");
1571b6b8d345SPeixin-Qiao },
1572b6b8d345SPeixin-Qiao [&](const Fortran::parser::OpenMPDeclareReductionConstruct
1573b6b8d345SPeixin-Qiao &declareReductionConstruct) {
1574b6b8d345SPeixin-Qiao TODO(converter.getCurrentLocation(),
1575b6b8d345SPeixin-Qiao "OpenMPDeclareReductionConstruct");
1576b6b8d345SPeixin-Qiao },
1577b6b8d345SPeixin-Qiao [&](const Fortran::parser::OpenMPDeclareSimdConstruct
1578b6b8d345SPeixin-Qiao &declareSimdConstruct) {
1579b6b8d345SPeixin-Qiao TODO(converter.getCurrentLocation(), "OpenMPDeclareSimdConstruct");
1580b6b8d345SPeixin-Qiao },
1581b6b8d345SPeixin-Qiao [&](const Fortran::parser::OpenMPDeclareTargetConstruct
1582b6b8d345SPeixin-Qiao &declareTargetConstruct) {
1583b6b8d345SPeixin-Qiao TODO(converter.getCurrentLocation(),
1584b6b8d345SPeixin-Qiao "OpenMPDeclareTargetConstruct");
1585b6b8d345SPeixin-Qiao },
1586b6b8d345SPeixin-Qiao [&](const Fortran::parser::OpenMPThreadprivate &threadprivate) {
1587411bd2d4SPeixin-Qiao // The directive is lowered when instantiating the variable to
1588411bd2d4SPeixin-Qiao // support the case of threadprivate variable declared in module.
1589b6b8d345SPeixin-Qiao },
1590b6b8d345SPeixin-Qiao },
1591b6b8d345SPeixin-Qiao ompDeclConstruct.u);
1592b6b8d345SPeixin-Qiao }
15937bb1151bSKiran Chandramohan
15947bb1151bSKiran Chandramohan // Generate an OpenMP reduction operation. This implementation finds the chain :
15957bb1151bSKiran Chandramohan // load reduction var -> reduction_operation -> store reduction var and replaces
15967bb1151bSKiran Chandramohan // it with the reduction operation.
15977bb1151bSKiran Chandramohan // TODO: Currently assumes it is an integer addition reduction. Generalize this
15987bb1151bSKiran Chandramohan // for various reduction operation types.
15997bb1151bSKiran Chandramohan // TODO: Generate the reduction operation during lowering instead of creating
16007bb1151bSKiran Chandramohan // and removing operations since this is not a robust approach. Also, removing
16017bb1151bSKiran Chandramohan // ops in the builder (instead of a rewriter) is probably not the best approach.
genOpenMPReduction(Fortran::lower::AbstractConverter & converter,const Fortran::parser::OmpClauseList & clauseList)16027bb1151bSKiran Chandramohan void Fortran::lower::genOpenMPReduction(
16037bb1151bSKiran Chandramohan Fortran::lower::AbstractConverter &converter,
16047bb1151bSKiran Chandramohan const Fortran::parser::OmpClauseList &clauseList) {
16057bb1151bSKiran Chandramohan fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
16067bb1151bSKiran Chandramohan
16077bb1151bSKiran Chandramohan for (const auto &clause : clauseList.v) {
16087bb1151bSKiran Chandramohan if (const auto &reductionClause =
16097bb1151bSKiran Chandramohan std::get_if<Fortran::parser::OmpClause::Reduction>(&clause.u)) {
16107bb1151bSKiran Chandramohan const auto &redOperator{std::get<Fortran::parser::OmpReductionOperator>(
16117bb1151bSKiran Chandramohan reductionClause->v.t)};
16127bb1151bSKiran Chandramohan const auto &objectList{
16137bb1151bSKiran Chandramohan std::get<Fortran::parser::OmpObjectList>(reductionClause->v.t)};
16147bb1151bSKiran Chandramohan if (auto reductionOp =
16157bb1151bSKiran Chandramohan std::get_if<Fortran::parser::DefinedOperator>(&redOperator.u)) {
16167bb1151bSKiran Chandramohan const auto &intrinsicOp{
16177bb1151bSKiran Chandramohan std::get<Fortran::parser::DefinedOperator::IntrinsicOperator>(
16187bb1151bSKiran Chandramohan reductionOp->u)};
16197bb1151bSKiran Chandramohan if (intrinsicOp !=
16207bb1151bSKiran Chandramohan Fortran::parser::DefinedOperator::IntrinsicOperator::Add)
16217bb1151bSKiran Chandramohan continue;
16227bb1151bSKiran Chandramohan for (const auto &ompObject : objectList.v) {
16237bb1151bSKiran Chandramohan if (const auto *name{
16247bb1151bSKiran Chandramohan Fortran::parser::Unwrap<Fortran::parser::Name>(ompObject)}) {
16257bb1151bSKiran Chandramohan if (const auto *symbol{name->symbol}) {
16267bb1151bSKiran Chandramohan mlir::Value symVal = converter.getSymbolAddress(*symbol);
16277bb1151bSKiran Chandramohan mlir::Type redType =
16287bb1151bSKiran Chandramohan symVal.getType().cast<fir::ReferenceType>().getEleTy();
16297bb1151bSKiran Chandramohan if (!redType.isIntOrIndex())
16307bb1151bSKiran Chandramohan continue;
16317bb1151bSKiran Chandramohan for (mlir::OpOperand &use1 : symVal.getUses()) {
16327bb1151bSKiran Chandramohan if (auto load = mlir::dyn_cast<fir::LoadOp>(use1.getOwner())) {
16337bb1151bSKiran Chandramohan mlir::Value loadVal = load.getRes();
16347bb1151bSKiran Chandramohan for (mlir::OpOperand &use2 : loadVal.getUses()) {
16357bb1151bSKiran Chandramohan if (auto add = mlir::dyn_cast<mlir::arith::AddIOp>(
16367bb1151bSKiran Chandramohan use2.getOwner())) {
16377bb1151bSKiran Chandramohan mlir::Value addRes = add.getResult();
16387bb1151bSKiran Chandramohan for (mlir::OpOperand &use3 : addRes.getUses()) {
16397bb1151bSKiran Chandramohan if (auto store =
16407bb1151bSKiran Chandramohan mlir::dyn_cast<fir::StoreOp>(use3.getOwner())) {
16417bb1151bSKiran Chandramohan if (store.getMemref() == symVal) {
16427bb1151bSKiran Chandramohan // Chain found! Now replace load->reduction->store
16437bb1151bSKiran Chandramohan // with the OpenMP reduction operation.
16447bb1151bSKiran Chandramohan mlir::OpBuilder::InsertPoint insertPtDel =
16457bb1151bSKiran Chandramohan firOpBuilder.saveInsertionPoint();
16467bb1151bSKiran Chandramohan firOpBuilder.setInsertionPoint(add);
16477bb1151bSKiran Chandramohan if (add.getLhs() == loadVal) {
16487bb1151bSKiran Chandramohan firOpBuilder.create<mlir::omp::ReductionOp>(
16497bb1151bSKiran Chandramohan add.getLoc(), add.getRhs(), symVal);
16507bb1151bSKiran Chandramohan } else {
16517bb1151bSKiran Chandramohan firOpBuilder.create<mlir::omp::ReductionOp>(
16527bb1151bSKiran Chandramohan add.getLoc(), add.getLhs(), symVal);
16537bb1151bSKiran Chandramohan }
16547bb1151bSKiran Chandramohan store.erase();
16557bb1151bSKiran Chandramohan add.erase();
16567bb1151bSKiran Chandramohan load.erase();
16577bb1151bSKiran Chandramohan firOpBuilder.restoreInsertionPoint(insertPtDel);
16587bb1151bSKiran Chandramohan }
16597bb1151bSKiran Chandramohan }
16607bb1151bSKiran Chandramohan }
16617bb1151bSKiran Chandramohan }
16627bb1151bSKiran Chandramohan }
16637bb1151bSKiran Chandramohan }
16647bb1151bSKiran Chandramohan }
16657bb1151bSKiran Chandramohan }
16667bb1151bSKiran Chandramohan }
16677bb1151bSKiran Chandramohan }
16687bb1151bSKiran Chandramohan }
16697bb1151bSKiran Chandramohan }
16707bb1151bSKiran Chandramohan }
16717bb1151bSKiran Chandramohan }
1672