diff --git a/flang/lib/Lower/OpenMP.cpp b/flang/lib/Lower/OpenMP.cpp --- a/flang/lib/Lower/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP.cpp @@ -21,6 +21,7 @@ #include "flang/Optimizer/Builder/FIRBuilder.h" #include "flang/Optimizer/Builder/Todo.h" #include "flang/Optimizer/HLFIR/HLFIROps.h" +#include "flang/Parser/dump-parse-tree.h" #include "flang/Parser/parse-tree.h" #include "flang/Semantics/openmp-directive-sets.h" #include "flang/Semantics/tools.h" @@ -549,15 +550,23 @@ llvm::SmallVectorImpl &useDeviceSymbols) const; + // Call this method for these clauses that should be supported but are not + // implemented yet. It triggers a compilation error if any of the given + // clauses is found. + template + void processTODO(mlir::Location currentLocation, + llvm::omp::Directive directive) const; + private: using ClauseIterator = std::list::const_iterator; /// Utility to find a clause within a range in the clause list. template static ClauseIterator findClause(ClauseIterator begin, ClauseIterator end) { - for (ClauseIterator it = begin; it != end; ++it) + for (ClauseIterator it = begin; it != end; ++it) { if (std::get_if(&it->u)) return it; + } return end; } @@ -1773,6 +1782,24 @@ }); } +template +void ClauseProcessor::processTODO(mlir::Location currentLocation, + llvm::omp::Directive directive) const { + auto checkUnhandledClause = [&](const auto *x) { + if (!x) + return; + TODO(currentLocation, + "Unhandled clause " + + llvm::StringRef(Fortran::parser::ParseTreeDumper::GetNodeName(*x)) + .upper() + + " in " + llvm::omp::getOpenMPDirectiveName(directive).upper() + + " construct"); + }; + + for (ClauseIterator it = clauses.v.begin(); it != clauses.v.end(); ++it) + (checkUnhandledClause(std::get_if(&it->u)), ...); +} + //===----------------------------------------------------------------------===// // Code generation helper functions //===----------------------------------------------------------------------===// @@ -2213,8 +2240,11 @@ llvm::SmallVector allocateOperands, allocatorOperands; mlir::UnitAttr nowaitAttr; - ClauseProcessor(converter, beginClauseList) - .processAllocate(allocatorOperands, allocateOperands); + ClauseProcessor cp(converter, beginClauseList); + cp.processAllocate(allocatorOperands, allocateOperands); + cp.processTODO( + currentLocation, llvm::omp::Directive::OMPD_single); + ClauseProcessor(converter, endClauseList).processNowait(nowaitAttr); return genOpWithBody( @@ -2244,6 +2274,10 @@ cp.processMergeable(mergeableAttr); cp.processPriority(stmtCtx, priorityClauseOperand); cp.processDepend(dependTypeOperands, dependOperands); + cp.processTODO( + currentLocation, llvm::omp::Directive::OMPD_task); return genOpWithBody( converter, eval, currentLocation, /*outerCombined=*/false, &clauseList, @@ -2263,9 +2297,10 @@ mlir::Location currentLocation, const Fortran::parser::OmpClauseList &clauseList) { llvm::SmallVector allocateOperands, allocatorOperands; - // TODO: Add task_reduction support - ClauseProcessor(converter, clauseList) - .processAllocate(allocatorOperands, allocateOperands); + ClauseProcessor cp(converter, clauseList); + cp.processAllocate(allocatorOperands, allocateOperands); + cp.processTODO( + currentLocation, llvm::omp::Directive::OMPD_taskgroup); return genOpWithBody( converter, eval, currentLocation, /*outerCombined=*/false, &clauseList, /*task_reduction_vars=*/mlir::ValueRange(), @@ -2323,12 +2358,15 @@ llvm::SmallVector mapTypes; Fortran::parser::OmpIfClause::DirectiveNameModifier directiveName; + llvm::omp::Directive directive; if constexpr (std::is_same_v) { directiveName = Fortran::parser::OmpIfClause::DirectiveNameModifier::TargetEnterData; + directive = llvm::omp::Directive::OMPD_target_enter_data; } else if constexpr (std::is_same_v) { directiveName = Fortran::parser::OmpIfClause::DirectiveNameModifier::TargetExitData; + directive = llvm::omp::Directive::OMPD_target_exit_data; } else { return nullptr; } @@ -2338,6 +2376,8 @@ cp.processDevice(stmtCtx, deviceOperand); cp.processNowait(nowaitAttr); cp.processMap(mapOperands, mapTypes); + cp.processTODO(currentLocation, + directive); llvm::SmallVector mapTypesAttr(mapTypes.begin(), mapTypes.end()); @@ -2370,6 +2410,17 @@ cp.processThreadLimit(stmtCtx, threadLimitOperand); cp.processNowait(nowaitAttr); cp.processMap(mapOperands, mapTypes); + cp.processTODO( + currentLocation, llvm::omp::Directive::OMPD_target); llvm::SmallVector mapTypesAttr(mapTypes.begin(), mapTypes.end()); @@ -2402,8 +2453,8 @@ cp.processDefault(); cp.processNumTeams(stmtCtx, numTeamsClauseOperand); cp.processThreadLimit(stmtCtx, threadLimitClauseOperand); - if (cp.processReduction(currentLocation, reductionVars, reductionDeclSymbols)) - TODO(currentLocation, "Reduction of TEAMS directive"); + cp.processTODO( + currentLocation, llvm::omp::Directive::OMPD_teams); return genOpWithBody( converter, eval, currentLocation, outerCombined, &clauseList, @@ -2420,10 +2471,11 @@ // genOMP() Code generation helper functions //===----------------------------------------------------------------------===// -static void genOMP(Fortran::lower::AbstractConverter &converter, - Fortran::lower::pft::Evaluation &eval, - const Fortran::parser::OpenMPSimpleStandaloneConstruct - &simpleStandaloneConstruct) { +static void +genOmpSimpleStandalone(Fortran::lower::AbstractConverter &converter, + Fortran::lower::pft::Evaluation &eval, + const Fortran::parser::OpenMPSimpleStandaloneConstruct + &simpleStandaloneConstruct) { const auto &directive = std::get( simpleStandaloneConstruct.t); @@ -2439,6 +2491,10 @@ firOpBuilder.create(currentLocation); break; case llvm::omp::Directive::OMPD_taskwait: + ClauseProcessor(converter, opClauseList) + .processTODO( + currentLocation, llvm::omp::Directive::OMPD_taskwait); firOpBuilder.create(currentLocation); break; case llvm::omp::Directive::OMPD_taskyield: @@ -2462,6 +2518,24 @@ } } +static void +genOmpFlush(Fortran::lower::AbstractConverter &converter, + Fortran::lower::pft::Evaluation &eval, + const Fortran::parser::OpenMPFlushConstruct &flushConstruct) { + llvm::SmallVector operandRange; + if (const auto &ompObjectList = + std::get>( + flushConstruct.t)) + genObjectList(*ompObjectList, converter, operandRange); + const auto &memOrderClause = + std::get>>( + flushConstruct.t); + if (memOrderClause && memOrderClause->size() > 0) + TODO(converter.getCurrentLocation(), "Handle OmpMemoryOrderClause"); + converter.getFirOpBuilder().create( + converter.getCurrentLocation(), operandRange); +} + static void genOMP(Fortran::lower::AbstractConverter &converter, Fortran::lower::pft::Evaluation &eval, @@ -2470,22 +2544,10 @@ Fortran::common::visitors{ [&](const Fortran::parser::OpenMPSimpleStandaloneConstruct &simpleStandaloneConstruct) { - genOMP(converter, eval, simpleStandaloneConstruct); + genOmpSimpleStandalone(converter, eval, simpleStandaloneConstruct); }, [&](const Fortran::parser::OpenMPFlushConstruct &flushConstruct) { - llvm::SmallVector operandRange; - if (const auto &ompObjectList = - std::get>( - flushConstruct.t)) - genObjectList(*ompObjectList, converter, operandRange); - const auto &memOrderClause = std::get>>( - flushConstruct.t); - if (memOrderClause && memOrderClause->size() > 0) - TODO(converter.getCurrentLocation(), - "Handle OmpMemoryOrderClause"); - converter.getFirOpBuilder().create( - converter.getCurrentLocation(), operandRange); + genOmpFlush(converter, eval, flushConstruct); }, [&](const Fortran::parser::OpenMPCancelConstruct &cancelConstruct) { TODO(converter.getCurrentLocation(), "OpenMPCancelConstruct"); @@ -2503,14 +2565,13 @@ const Fortran::parser::OpenMPLoopConstruct &loopConstruct) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); llvm::SmallVector lowerBound, upperBound, step, linearVars, - linearStepVars, reductionVars, alignedVars, nontemporalVars; - mlir::Value scheduleChunkClauseOperand, ifClauseOperand; + linearStepVars, reductionVars; + mlir::Value scheduleChunkClauseOperand; mlir::IntegerAttr orderedClauseOperand; mlir::omp::ClauseOrderKindAttr orderClauseOperand; mlir::omp::ClauseScheduleKindAttr scheduleValClauseOperand; mlir::omp::ScheduleModifierAttr scheduleModClauseOperand; mlir::UnitAttr nowaitClauseOperand, scheduleSimdClauseOperand; - mlir::IntegerAttr simdlenClauseOperand, safelenClauseOperand; llvm::SmallVector reductionDeclSymbols; Fortran::lower::StatementContext stmtCtx; std::size_t loopVarTypeSize; @@ -2570,12 +2631,10 @@ cp.processCollapse(currentLocation, eval, lowerBound, upperBound, step, iv, loopVarTypeSize); cp.processScheduleChunk(stmtCtx, scheduleChunkClauseOperand); - cp.processIf(stmtCtx, - Fortran::parser::OmpIfClause::DirectiveNameModifier::Simd, - ifClauseOperand); cp.processReduction(currentLocation, reductionVars, reductionDeclSymbols); - cp.processSimdlen(simdlenClauseOperand); - cp.processSafelen(safelenClauseOperand); + cp.processTODO(currentLocation, + ompDirective); // The types of lower bound, upper bound, and step are converted into the // type of the loop variable if necessary. @@ -2590,8 +2649,20 @@ } // 2.9.3.1 SIMD construct - // TODO: Support all the clauses if (llvm::omp::allSimdSet.test(ompDirective)) { + llvm::SmallVector alignedVars, nontemporalVars; + mlir::Value ifClauseOperand; + mlir::IntegerAttr simdlenClauseOperand, safelenClauseOperand; + cp.processIf(stmtCtx, + Fortran::parser::OmpIfClause::DirectiveNameModifier::Simd, + ifClauseOperand); + cp.processSimdlen(simdlenClauseOperand); + cp.processSafelen(safelenClauseOperand); + cp.processTODO(currentLocation, + ompDirective); + mlir::TypeRange resultType; auto simdLoopOp = firOpBuilder.create( currentLocation, resultType, lowerBound, upperBound, step, alignedVars, @@ -2604,9 +2675,6 @@ return; } - // FIXME: Add support for following clauses: - // 1. linear - // 2. order auto wsLoopOp = firOpBuilder.create( currentLocation, lowerBound, upperBound, step, linearVars, linearStepVars, reductionVars, @@ -3340,6 +3408,9 @@ cp.processTo(symbolAndClause); cp.processLink(symbolAndClause); cp.processDeviceType(deviceType); + cp.processTODO( + converter.getCurrentLocation(), + llvm::omp::Directive::OMPD_declare_target); } for (const DeclareTargetCapturePair &symClause : symbolAndClause) { diff --git a/flang/test/Lower/OpenMP/Todo/firstprivate-target.f90 b/flang/test/Lower/OpenMP/Todo/firstprivate-target.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Lower/OpenMP/Todo/firstprivate-target.f90 @@ -0,0 +1,9 @@ +! RUN: %not_todo_cmd bbc -emit-fir -fopenmp -o - %s 2>&1 | FileCheck %s +! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -o - %s 2>&1 | FileCheck %s + +integer :: i +! CHECK: not yet implemented: Unhandled clause FIRSTPRIVATE in TARGET construct +!$omp target firstprivate(i) +!$omp end target + +end program diff --git a/flang/test/Lower/OpenMP/Todo/reduction-teams.f90 b/flang/test/Lower/OpenMP/Todo/reduction-teams.f90 --- a/flang/test/Lower/OpenMP/Todo/reduction-teams.f90 +++ b/flang/test/Lower/OpenMP/Todo/reduction-teams.f90 @@ -1,7 +1,7 @@ ! RUN: %not_todo_cmd bbc -emit-fir -fopenmp -o - %s 2>&1 | FileCheck %s ! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -o - %s 2>&1 | FileCheck %s -! CHECK: not yet implemented: Reduction of TEAMS directive +! CHECK: not yet implemented: Unhandled clause REDUCTION in TEAMS construct subroutine reduction_teams() integer :: i i = 0