diff options
Diffstat (limited to 'flang/lib/Lower')
| -rw-r--r-- | flang/lib/Lower/Bridge.cpp | 132 | ||||
| -rw-r--r-- | flang/lib/Lower/ConvertCall.cpp | 13 | ||||
| -rw-r--r-- | flang/lib/Lower/OpenMP/Clauses.cpp | 15 |
3 files changed, 153 insertions, 7 deletions
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp index a516a44..0f4b39a 100644 --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -1884,6 +1884,26 @@ private: setCurrentPosition(stmt.source); assert(stmt.typedCall && "Call was not analyzed"); mlir::Value res{}; + + // Set 'no_inline', 'inline_hint' or 'always_inline' to true on the + // ProcedureRef. The NoInline and AlwaysInline attribute will be set in + // genProcedureRef later. + for (const auto *dir : eval.dirs) { + Fortran::common::visit( + Fortran::common::visitors{ + [&](const Fortran::parser::CompilerDirective::ForceInline &) { + stmt.typedCall->setAlwaysInline(true); + }, + [&](const Fortran::parser::CompilerDirective::Inline &) { + stmt.typedCall->setInlineHint(true); + }, + [&](const Fortran::parser::CompilerDirective::NoInline &) { + stmt.typedCall->setNoInline(true); + }, + [&](const auto &) {}}, + dir->u); + } + if (lowerToHighLevelFIR()) { std::optional<mlir::Type> resultType; if (stmt.typedCall->hasAlternateReturns()) @@ -2200,6 +2220,50 @@ private: // so no clean-up needs to be generated for these entities. } + void attachInlineAttributes( + mlir::Operation &op, + const llvm::ArrayRef<const Fortran::parser::CompilerDirective *> &dirs) { + if (dirs.empty()) + return; + + for (mlir::Value operand : op.getOperands()) { + if (operand.getDefiningOp()) + attachInlineAttributes(*operand.getDefiningOp(), dirs); + } + + if (fir::CallOp callOp = mlir::dyn_cast<fir::CallOp>(op)) { + for (const auto *dir : dirs) { + Fortran::common::visit( + Fortran::common::visitors{ + [&](const Fortran::parser::CompilerDirective::NoInline &) { + callOp.setInlineAttr(fir::FortranInlineEnum::no_inline); + }, + [&](const Fortran::parser::CompilerDirective::Inline &) { + callOp.setInlineAttr(fir::FortranInlineEnum::inline_hint); + }, + [&](const Fortran::parser::CompilerDirective::ForceInline &) { + callOp.setInlineAttr(fir::FortranInlineEnum::always_inline); + }, + [&](const auto &) {}}, + dir->u); + } + } + } + + void attachAttributesToDoLoopOperations( + fir::DoLoopOp &doLoop, + llvm::SmallVectorImpl<const Fortran::parser::CompilerDirective *> &dirs) { + if (!doLoop.getOperation() || dirs.empty()) + return; + + for (mlir::Block &block : doLoop.getRegion()) { + for (mlir::Operation &op : block.getOperations()) { + if (!dirs.empty()) + attachInlineAttributes(op, dirs); + } + } + } + /// Generate FIR for a DO construct. There are six variants: /// - unstructured infinite and while loops /// - structured and unstructured increment loops @@ -2351,6 +2415,11 @@ private: if (!incrementLoopNestInfo.empty() && incrementLoopNestInfo.back().isConcurrent) localSymbols.popScope(); + + // Add attribute(s) on operations in fir::DoLoopOp if necessary + for (IncrementLoopInfo &info : incrementLoopNestInfo) + if (auto loopOp = mlir::dyn_cast_if_present<fir::DoLoopOp>(info.loopOp)) + attachAttributesToDoLoopOperations(loopOp, doStmtEval.dirs); } /// Generate FIR to evaluate loop control values (lower, upper and step). @@ -3154,6 +3223,26 @@ private: e->dirs.push_back(&dir); } + void + attachInliningDirectiveToStmt(const Fortran::parser::CompilerDirective &dir, + Fortran::lower::pft::Evaluation *e) { + while (e->isDirective()) + e = e->lexicalSuccessor; + + // If the successor is a statement or a do loop, the compiler + // will perform inlining. + if (e->isA<Fortran::parser::CallStmt>() || + e->isA<Fortran::parser::NonLabelDoStmt>() || + e->isA<Fortran::parser::AssignmentStmt>()) { + e->dirs.push_back(&dir); + } else { + mlir::Location loc = toLocation(); + mlir::emitWarning(loc, + "Inlining directive not in front of loops, function" + "call or assignment.\n"); + } + } + void genFIR(const Fortran::parser::CompilerDirective &dir) { Fortran::lower::pft::Evaluation &eval = getEval(); @@ -3177,6 +3266,15 @@ private: [&](const Fortran::parser::CompilerDirective::NoUnrollAndJam &) { attachDirectiveToLoop(dir, &eval); }, + [&](const Fortran::parser::CompilerDirective::ForceInline &) { + attachInliningDirectiveToStmt(dir, &eval); + }, + [&](const Fortran::parser::CompilerDirective::Inline &) { + attachInliningDirectiveToStmt(dir, &eval); + }, + [&](const Fortran::parser::CompilerDirective::NoInline &) { + attachInliningDirectiveToStmt(dir, &eval); + }, [&](const auto &) {}}, dir.u); } @@ -4778,6 +4876,10 @@ private: mlir::Value shape = builder->genShape(loc, lbounds, extents); rhsBox = fir::ReboxOp::create(*builder, loc, lhsBoxType, rhsBox, shape, /*slice=*/mlir::Value{}); + } else if (fir::isClassStarType(lhsBoxType) && + !fir::ConvertOp::canBeConverted(rhsBoxType, lhsBoxType)) { + rhsBox = fir::ReboxOp::create(*builder, loc, lhsBoxType, rhsBox, + mlir::Value{}, mlir::Value{}); } return rhsBox; } @@ -5086,7 +5188,9 @@ private: void genDataAssignment( const Fortran::evaluate::Assignment &assign, - const Fortran::evaluate::ProcedureRef *userDefinedAssignment) { + const Fortran::evaluate::ProcedureRef *userDefinedAssignment, + const llvm::ArrayRef<const Fortran::parser::CompilerDirective *> &dirs = + {}) { mlir::Location loc = getCurrentLocation(); fir::FirOpBuilder &builder = getFirOpBuilder(); @@ -5166,10 +5270,20 @@ private: genCUDADataTransfer(builder, loc, assign, lhs, rhs, isWholeAllocatableAssignment, keepLhsLengthInAllocatableAssignment); - else + else { + // If RHS or LHS have a CallOp in their expression, this operation will + // have the 'no_inline' or 'always_inline' attribute if there is a + // directive just before the assignement. + if (!dirs.empty()) { + if (rhs.getDefiningOp()) + attachInlineAttributes(*rhs.getDefiningOp(), dirs); + if (lhs.getDefiningOp()) + attachInlineAttributes(*lhs.getDefiningOp(), dirs); + } hlfir::AssignOp::create(builder, loc, rhs, lhs, isWholeAllocatableAssignment, keepLhsLengthInAllocatableAssignment); + } if (hasCUDAImplicitTransfer && !isInDeviceContext) { localSymbols.popScope(); for (mlir::Value temp : implicitTemps) @@ -5237,16 +5351,21 @@ private: } /// Shared for both assignments and pointer assignments. - void genAssignment(const Fortran::evaluate::Assignment &assign) { + void + genAssignment(const Fortran::evaluate::Assignment &assign, + const llvm::ArrayRef<const Fortran::parser::CompilerDirective *> + &dirs = {}) { mlir::Location loc = toLocation(); if (lowerToHighLevelFIR()) { Fortran::common::visit( Fortran::common::visitors{ [&](const Fortran::evaluate::Assignment::Intrinsic &) { - genDataAssignment(assign, /*userDefinedAssignment=*/nullptr); + genDataAssignment(assign, /*userDefinedAssignment=*/nullptr, + dirs); }, [&](const Fortran::evaluate::ProcedureRef &procRef) { - genDataAssignment(assign, /*userDefinedAssignment=*/&procRef); + genDataAssignment(assign, /*userDefinedAssignment=*/&procRef, + dirs); }, [&](const Fortran::evaluate::Assignment::BoundsSpec &lbExprs) { if (isInsideHlfirForallOrWhere()) @@ -5651,7 +5770,8 @@ private: } void genFIR(const Fortran::parser::AssignmentStmt &stmt) { - genAssignment(*stmt.typedAssignment->v); + Fortran::lower::pft::Evaluation &eval = getEval(); + genAssignment(*stmt.typedAssignment->v, eval.dirs); } void genFIR(const Fortran::parser::SyncAllStmt &stmt) { diff --git a/flang/lib/Lower/ConvertCall.cpp b/flang/lib/Lower/ConvertCall.cpp index fb72040..9bf994e 100644 --- a/flang/lib/Lower/ConvertCall.cpp +++ b/flang/lib/Lower/ConvertCall.cpp @@ -700,9 +700,20 @@ Fortran::lower::genCallOpAndResult( callResult = dispatch.getResult(0); } else { // Standard procedure call with fir.call. + fir::FortranInlineEnumAttr inlineAttr; + + if (caller.getCallDescription().hasNoInline()) + inlineAttr = fir::FortranInlineEnumAttr::get( + builder.getContext(), fir::FortranInlineEnum::no_inline); + else if (caller.getCallDescription().hasInlineHint()) + inlineAttr = fir::FortranInlineEnumAttr::get( + builder.getContext(), fir::FortranInlineEnum::inline_hint); + else if (caller.getCallDescription().hasAlwaysInline()) + inlineAttr = fir::FortranInlineEnumAttr::get( + builder.getContext(), fir::FortranInlineEnum::always_inline); auto call = fir::CallOp::create( builder, loc, funcType.getResults(), funcSymbolAttr, operands, - /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr, procAttrs); + /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr, procAttrs, inlineAttr); callNumResults = call.getNumResults(); if (callNumResults != 0) diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp index d39f9dd..0f60b47 100644 --- a/flang/lib/Lower/OpenMP/Clauses.cpp +++ b/flang/lib/Lower/OpenMP/Clauses.cpp @@ -1482,6 +1482,21 @@ ThreadLimit make(const parser::OmpClause::ThreadLimit &inp, return ThreadLimit{/*Threadlim=*/makeExpr(inp.v, semaCtx)}; } +Threadset make(const parser::OmpClause::Threadset &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpThreadsetClause + using wrapped = parser::OmpThreadsetClause; + + CLAUSET_ENUM_CONVERT( // + convert, wrapped::ThreadsetPolicy, Threadset::ThreadsetPolicy, + // clang-format off + MS(Omp_Pool, Omp_Pool) + MS(Omp_Team, Omp_Team) + // clang-format on + ); + return Threadset{/*ThreadsetPolicy=*/convert(inp.v.v)}; +} + // Threadprivate: empty // Threads: empty |
