From 1d328446bf92f76f1861d0e5f84d67732d76c8fd Mon Sep 17 00:00:00 2001 From: Sourabh Singh Tomar Date: Tue, 20 Oct 2020 12:08:27 +0530 Subject: [PATCH] [flang][OpenMP] Upstream lowering of `ParallelOp` clauses Note: This patch reflects the work that can be upstreamed from PR's(merged): 1. https://github.com/flang-compiler/f18-llvm-project/pull/456 2. https://github.com/flang-compiler/f18-llvm-project/pull/485 Also replaced TODO with new TODO. Reviewed By: kiranchandramohan Differential Revision: https://reviews.llvm.org/D89769 --- flang/lib/Lower/OpenMP.cpp | 191 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 150 insertions(+), 41 deletions(-) diff --git a/flang/lib/Lower/OpenMP.cpp b/flang/lib/Lower/OpenMP.cpp index 169e225..9c9c0a2 100644 --- a/flang/lib/Lower/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP.cpp @@ -11,15 +11,54 @@ //===----------------------------------------------------------------------===// #include "flang/Lower/OpenMP.h" +#include "flang/Common/idioms.h" #include "flang/Lower/Bridge.h" #include "flang/Lower/FIRBuilder.h" #include "flang/Lower/PFTBuilder.h" +#include "flang/Lower/Support/BoxValue.h" +#include "flang/Lower/Todo.h" #include "flang/Parser/parse-tree.h" #include "flang/Semantics/tools.h" #include "mlir/Dialect/OpenMP/OpenMPDialect.h" #include "llvm/Frontend/OpenMP/OMPConstants.h" -#define TODO() llvm_unreachable("not yet implemented") +static const Fortran::parser::Name * +getDesignatorNameIfDataRef(const Fortran::parser::Designator &designator) { + const auto *dataRef = std::get_if(&designator.u); + return dataRef ? std::get_if(&dataRef->u) : nullptr; +} + +static void genObjectList(const Fortran::parser::OmpObjectList &objectList, + Fortran::lower::AbstractConverter &converter, + SmallVectorImpl &operands) { + for (const auto &ompObject : objectList.v) { + std::visit( + Fortran::common::visitors{ + [&](const Fortran::parser::Designator &designator) { + if (const auto *name = getDesignatorNameIfDataRef(designator)) { + const auto variable = converter.getSymbolAddress(*name->symbol); + operands.push_back(variable); + } + }, + [&](const Fortran::parser::Name &name) { + const auto variable = converter.getSymbolAddress(*name.symbol); + operands.push_back(variable); + }}, + ompObject.u); + } +} + +template +static void createBodyOfOp(Op &op, Fortran::lower::FirOpBuilder &firOpBuilder, + mlir::Location &loc) { + firOpBuilder.createBlock(&op.getRegion()); + auto &block = op.getRegion().back(); + firOpBuilder.setInsertionPointToStart(&block); + // Ensure the block is well-formed. + firOpBuilder.create(loc); + // Reset the insertion point to the start of the first block. + firOpBuilder.setInsertionPointToStart(&block); +} static void genOMP(Fortran::lower::AbstractConverter &converter, Fortran::lower::pft::Evaluation &eval, @@ -44,13 +83,13 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, converter.getCurrentLocation()); break; case llvm::omp::Directive::OMPD_target_enter_data: - TODO(); + TODO(""); case llvm::omp::Directive::OMPD_target_exit_data: - TODO(); + TODO(""); case llvm::omp::Directive::OMPD_target_update: - TODO(); + TODO(""); case llvm::omp::Directive::OMPD_ordered: - TODO(); + TODO(""); } } @@ -68,10 +107,10 @@ genOMP(Fortran::lower::AbstractConverter &converter, TODO(); }, [&](const Fortran::parser::OpenMPCancelConstruct &cancelConstruct) { - TODO(); + TODO(""); }, [&](const Fortran::parser::OpenMPCancellationPointConstruct - &cancellationPointConstruct) { TODO(); }, + &cancellationPointConstruct) { TODO(""); }, }, standaloneConstruct.u); } @@ -80,45 +119,115 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, Fortran::lower::pft::Evaluation &eval, const Fortran::parser::OpenMPBlockConstruct &blockConstruct) { - const auto &blockDirective = + const auto &beginBlockDirective = std::get(blockConstruct.t); - const auto ¶llelDirective = - std::get(blockDirective.t); - if (parallelDirective.v == llvm::omp::OMPD_parallel) { - auto &firOpBuilder = converter.getFirOpBuilder(); - auto currentLocation = converter.getCurrentLocation(); + const auto &blockDirective = + std::get(beginBlockDirective.t); - // Clauses. - // FIXME: Add support for other clauses. - mlir::Value numThreads; + auto &firOpBuilder = converter.getFirOpBuilder(); + auto currentLocation = converter.getCurrentLocation(); + llvm::ArrayRef argTy; + if (blockDirective.v == llvm::omp::OMPD_parallel) { + + mlir::Value ifClauseOperand, numThreadsClauseOperand; + SmallVector privateClauseOperands, firstprivateClauseOperands, + sharedClauseOperands, copyinClauseOperands; + Attribute defaultClauseOperand, procBindClauseOperand; const auto ¶llelOpClauseList = - std::get(blockDirective.t); + std::get(beginBlockDirective.t); for (const auto &clause : parallelOpClauseList.v) { - if (const auto &numThreadsClause = - std::get_if(&clause.u)) { + if (const auto &ifClause = + std::get_if(&clause.u)) { + auto &expr = std::get(ifClause->t); + ifClauseOperand = fir::getBase( + converter.genExprValue(*Fortran::semantics::GetExpr(expr))); + } else if (const auto &numThreadsClause = + std::get_if( + &clause.u)) { // OMPIRBuilder expects `NUM_THREAD` clause as a `Value`. - numThreads = converter.genExprValue( - *Fortran::semantics::GetExpr(numThreadsClause->v)); + numThreadsClauseOperand = fir::getBase(converter.genExprValue( + *Fortran::semantics::GetExpr(numThreadsClause->v))); + } else if (const auto &privateClause = + std::get_if( + &clause.u)) { + const Fortran::parser::OmpObjectList &ompObjectList = privateClause->v; + genObjectList(ompObjectList, converter, privateClauseOperands); + } else if (const auto &firstprivateClause = + std::get_if( + &clause.u)) { + const Fortran::parser::OmpObjectList &ompObjectList = + firstprivateClause->v; + genObjectList(ompObjectList, converter, firstprivateClauseOperands); + } else if (const auto &sharedClause = + std::get_if( + &clause.u)) { + const Fortran::parser::OmpObjectList &ompObjectList = sharedClause->v; + genObjectList(ompObjectList, converter, sharedClauseOperands); + } else if (const auto ©inClause = + std::get_if( + &clause.u)) { + const Fortran::parser::OmpObjectList &ompObjectList = copyinClause->v; + genObjectList(ompObjectList, converter, copyinClauseOperands); } } - llvm::ArrayRef argTy; - Attribute defaultValue, procBindValue; // Create and insert the operation. - // Create the Op with empty ranges for clauses that are yet to be lowered. auto parallelOp = firOpBuilder.create( - currentLocation, argTy, Value(), numThreads, - defaultValue.dyn_cast_or_null(), ValueRange(), ValueRange(), - ValueRange(), ValueRange(), ValueRange(), ValueRange(), - procBindValue.dyn_cast_or_null()); - firOpBuilder.createBlock(¶llelOp.getRegion()); - auto &block = parallelOp.getRegion().back(); - firOpBuilder.setInsertionPointToStart(&block); - // Ensure the block is well-formed. - firOpBuilder.create(currentLocation); - - // Place the insertion point to the start of the first block. - firOpBuilder.setInsertionPointToStart(&block); + currentLocation, argTy, ifClauseOperand, numThreadsClauseOperand, + defaultClauseOperand.dyn_cast_or_null(), + privateClauseOperands, firstprivateClauseOperands, sharedClauseOperands, + copyinClauseOperands, ValueRange(), ValueRange(), + procBindClauseOperand.dyn_cast_or_null()); + // Handle attribute based clauses. + for (const auto &clause : parallelOpClauseList.v) { + if (const auto &defaultClause = + std::get_if(&clause.u)) { + switch (defaultClause->v) { + case Fortran::parser::OmpDefaultClause::Type::Private: + parallelOp.default_valAttr(firOpBuilder.getStringAttr( + omp::stringifyClauseDefault(omp::ClauseDefault::defprivate))); + break; + case Fortran::parser::OmpDefaultClause::Type::Firstprivate: + parallelOp.default_valAttr( + firOpBuilder.getStringAttr(omp::stringifyClauseDefault( + omp::ClauseDefault::deffirstprivate))); + break; + case Fortran::parser::OmpDefaultClause::Type::Shared: + parallelOp.default_valAttr(firOpBuilder.getStringAttr( + omp::stringifyClauseDefault(omp::ClauseDefault::defshared))); + break; + case Fortran::parser::OmpDefaultClause::Type::None: + parallelOp.default_valAttr(firOpBuilder.getStringAttr( + omp::stringifyClauseDefault(omp::ClauseDefault::defnone))); + break; + } + } + if (const auto &procBindClause = + std::get_if(&clause.u)) { + switch (procBindClause->v) { + case Fortran::parser::OmpProcBindClause::Type::Master: + parallelOp.proc_bind_valAttr( + firOpBuilder.getStringAttr(omp::stringifyClauseProcBindKind( + omp::ClauseProcBindKind::master))); + break; + case Fortran::parser::OmpProcBindClause::Type::Close: + parallelOp.proc_bind_valAttr( + firOpBuilder.getStringAttr(omp::stringifyClauseProcBindKind( + omp::ClauseProcBindKind::close))); + break; + case Fortran::parser::OmpProcBindClause::Type::Spread: + parallelOp.proc_bind_valAttr( + firOpBuilder.getStringAttr(omp::stringifyClauseProcBindKind( + omp::ClauseProcBindKind::spread))); + break; + } + } + } + createBodyOfOp(parallelOp, firOpBuilder, currentLocation); + } else if (blockDirective.v == llvm::omp::OMPD_master) { + auto masterOp = + firOpBuilder.create(currentLocation, argTy); + createBodyOfOp(masterOp, firOpBuilder, currentLocation); } } @@ -134,18 +243,18 @@ void Fortran::lower::genOpenMPConstruct( genOMP(converter, eval, standaloneConstruct); }, [&](const Fortran::parser::OpenMPSectionsConstruct - §ionsConstruct) { TODO(); }, + §ionsConstruct) { TODO(""); }, [&](const Fortran::parser::OpenMPLoopConstruct &loopConstruct) { - TODO(); + TODO(""); }, [&](const Fortran::parser::OpenMPBlockConstruct &blockConstruct) { genOMP(converter, eval, blockConstruct); }, [&](const Fortran::parser::OpenMPAtomicConstruct &atomicConstruct) { - TODO(); + TODO(""); }, [&](const Fortran::parser::OpenMPCriticalConstruct - &criticalConstruct) { TODO(); }, + &criticalConstruct) { TODO(""); }, }, ompConstruct.u); } @@ -153,5 +262,5 @@ void Fortran::lower::genOpenMPConstruct( void Fortran::lower::genOpenMPEndLoop( Fortran::lower::AbstractConverter &, Fortran::lower::pft::Evaluation &, const Fortran::parser::OmpEndLoopDirective &) { - TODO(); + TODO(""); } -- 2.7.4