brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.9 KiB · 54ec9c5 Raw
261 lines · c
1//===-- Lower/OpenMP/ClauseProcessor.h --------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/10//11//===----------------------------------------------------------------------===//12#ifndef FORTRAN_LOWER_CLAUSEPROCESSOR_H13#define FORTRAN_LOWER_CLAUSEPROCESSOR_H14 15#include "ClauseFinder.h"16#include "Utils.h"17#include "flang/Lower/AbstractConverter.h"18#include "flang/Lower/Bridge.h"19#include "flang/Lower/DirectivesCommon.h"20#include "flang/Lower/OpenMP/Clauses.h"21#include "flang/Lower/Support/ReductionProcessor.h"22#include "flang/Optimizer/Builder/Todo.h"23#include "flang/Parser/parse-tree.h"24#include "mlir/Dialect/OpenMP/OpenMPDialect.h"25 26namespace fir {27class FirOpBuilder;28} // namespace fir29 30namespace Fortran {31namespace lower {32namespace omp {33 34// Container type for tracking user specified Defaultmaps for a target region35using DefaultMapsTy = std::map<clause::Defaultmap::VariableCategory,36                               clause::Defaultmap::ImplicitBehavior>;37 38/// Class that handles the processing of OpenMP clauses.39///40/// Its `process<ClauseName>()` methods perform MLIR code generation for their41/// corresponding clause if it is present in the clause list. Otherwise, they42/// will return `false` to signal that the clause was not found.43///44/// The intended use of this class is to move clause processing outside of45/// construct processing, since the same clauses can appear attached to46/// different constructs and constructs can be combined, so that code47/// duplication is minimized.48///49/// Each construct-lowering function only calls the `process<ClauseName>()`50/// methods that relate to clauses that can impact the lowering of that51/// construct.52class ClauseProcessor {53public:54  ClauseProcessor(lower::AbstractConverter &converter,55                  semantics::SemanticsContext &semaCtx,56                  const List<Clause> &clauses)57      : converter(converter), semaCtx(semaCtx), clauses(clauses) {}58 59  // 'Unique' clauses: They can appear at most once in the clause list.60  bool processBare(mlir::omp::BareClauseOps &result) const;61  bool processBind(mlir::omp::BindClauseOps &result) const;62  bool processCancelDirectiveName(63      mlir::omp::CancelDirectiveNameClauseOps &result) const;64  bool65  processCollapse(mlir::Location currentLocation, lower::pft::Evaluation &eval,66                  mlir::omp::LoopRelatedClauseOps &loopResult,67                  mlir::omp::CollapseClauseOps &collapseResult,68                  llvm::SmallVectorImpl<const semantics::Symbol *> &iv) const;69  bool processSizes(StatementContext &stmtCtx,70                    mlir::omp::SizesClauseOps &result) const;71  bool processDevice(lower::StatementContext &stmtCtx,72                     mlir::omp::DeviceClauseOps &result) const;73  bool processDeviceType(mlir::omp::DeviceTypeClauseOps &result) const;74  bool processDistSchedule(lower::StatementContext &stmtCtx,75                           mlir::omp::DistScheduleClauseOps &result) const;76  bool processExclusive(mlir::Location currentLocation,77                        mlir::omp::ExclusiveClauseOps &result) const;78  bool processFilter(lower::StatementContext &stmtCtx,79                     mlir::omp::FilterClauseOps &result) const;80  bool processFinal(lower::StatementContext &stmtCtx,81                    mlir::omp::FinalClauseOps &result) const;82  bool processGrainsize(lower::StatementContext &stmtCtx,83                        mlir::omp::GrainsizeClauseOps &result) const;84  bool processHasDeviceAddr(85      lower::StatementContext &stmtCtx,86      mlir::omp::HasDeviceAddrClauseOps &result,87      llvm::SmallVectorImpl<const semantics::Symbol *> &hasDeviceSyms) const;88  bool processHint(mlir::omp::HintClauseOps &result) const;89  bool processInclusive(mlir::Location currentLocation,90                        mlir::omp::InclusiveClauseOps &result) const;91  bool processInitializer(92      lower::SymMap &symMap, const parser::OmpClause::Initializer &inp,93      ReductionProcessor::GenInitValueCBTy &genInitValueCB) const;94  bool processMergeable(mlir::omp::MergeableClauseOps &result) const;95  bool processNogroup(mlir::omp::NogroupClauseOps &result) const;96  bool processNowait(mlir::omp::NowaitClauseOps &result) const;97  bool processNumTasks(lower::StatementContext &stmtCtx,98                       mlir::omp::NumTasksClauseOps &result) const;99  bool processNumTeams(lower::StatementContext &stmtCtx,100                       mlir::omp::NumTeamsClauseOps &result) const;101  bool processNumThreads(lower::StatementContext &stmtCtx,102                         mlir::omp::NumThreadsClauseOps &result) const;103  bool processOrder(mlir::omp::OrderClauseOps &result) const;104  bool processOrdered(mlir::omp::OrderedClauseOps &result) const;105  bool processPriority(lower::StatementContext &stmtCtx,106                       mlir::omp::PriorityClauseOps &result) const;107  bool processProcBind(mlir::omp::ProcBindClauseOps &result) const;108  bool processTileSizes(lower::pft::Evaluation &eval,109                        mlir::omp::LoopNestOperands &result) const;110  bool processSafelen(mlir::omp::SafelenClauseOps &result) const;111  bool processSchedule(lower::StatementContext &stmtCtx,112                       mlir::omp::ScheduleClauseOps &result) const;113  bool processSimdlen(mlir::omp::SimdlenClauseOps &result) const;114  bool processThreadLimit(lower::StatementContext &stmtCtx,115                          mlir::omp::ThreadLimitClauseOps &result) const;116  bool processUntied(mlir::omp::UntiedClauseOps &result) const;117 118  bool processDetach(mlir::omp::DetachClauseOps &result) const;119  // 'Repeatable' clauses: They can appear multiple times in the clause list.120  bool processAligned(mlir::omp::AlignedClauseOps &result) const;121  bool processAllocate(mlir::omp::AllocateClauseOps &result) const;122  bool processCopyin() const;123  bool processCopyprivate(mlir::Location currentLocation,124                          mlir::omp::CopyprivateClauseOps &result) const;125  bool processDefaultMap(lower::StatementContext &stmtCtx,126                         DefaultMapsTy &result) const;127  bool processDepend(lower::SymMap &symMap, lower::StatementContext &stmtCtx,128                     mlir::omp::DependClauseOps &result) const;129  bool130  processEnter(llvm::SmallVectorImpl<DeclareTargetCaptureInfo> &result) const;131  bool processIf(omp::clause::If::DirectiveNameModifier directiveName,132                 mlir::omp::IfClauseOps &result) const;133  bool processInReduction(134      mlir::Location currentLocation, mlir::omp::InReductionClauseOps &result,135      llvm::SmallVectorImpl<const semantics::Symbol *> &outReductionSyms) const;136  bool processIsDevicePtr(137      mlir::omp::IsDevicePtrClauseOps &result,138      llvm::SmallVectorImpl<const semantics::Symbol *> &isDeviceSyms) const;139  bool processLinear(mlir::omp::LinearClauseOps &result) const;140  bool141  processLink(llvm::SmallVectorImpl<DeclareTargetCaptureInfo> &result) const;142 143  // This method is used to process a map clause.144  // The optional parameter mapSyms is used to store the original Fortran symbol145  // for the map operands. It may be used later on to create the block_arguments146  // for some of the directives that require it.147  bool processMap(mlir::Location currentLocation,148                  lower::StatementContext &stmtCtx,149                  mlir::omp::MapClauseOps &result,150                  llvm::omp::Directive directive = llvm::omp::OMPD_unknown,151                  llvm::SmallVectorImpl<const semantics::Symbol *> *mapSyms =152                      nullptr) const;153  bool processMotionClauses(lower::StatementContext &stmtCtx,154                            mlir::omp::MapClauseOps &result);155  bool processNontemporal(mlir::omp::NontemporalClauseOps &result) const;156  bool processReduction(157      mlir::Location currentLocation, mlir::omp::ReductionClauseOps &result,158      llvm::SmallVectorImpl<const semantics::Symbol *> &reductionSyms) const;159  bool processTaskReduction(160      mlir::Location currentLocation, mlir::omp::TaskReductionClauseOps &result,161      llvm::SmallVectorImpl<const semantics::Symbol *> &outReductionSyms) const;162  bool processTo(llvm::SmallVectorImpl<DeclareTargetCaptureInfo> &result) const;163  bool processUseDeviceAddr(164      lower::StatementContext &stmtCtx,165      mlir::omp::UseDeviceAddrClauseOps &result,166      llvm::SmallVectorImpl<const semantics::Symbol *> &useDeviceSyms) const;167  bool processUseDevicePtr(168      lower::StatementContext &stmtCtx,169      mlir::omp::UseDevicePtrClauseOps &result,170      llvm::SmallVectorImpl<const semantics::Symbol *> &useDeviceSyms) const;171 172  // Call this method for these clauses that should be supported but are not173  // implemented yet. It triggers a compilation error if any of the given174  // clauses is found.175  template <typename... Ts>176  void processTODO(mlir::Location currentLocation,177                   llvm::omp::Directive directive) const;178 179private:180  using ClauseIterator = List<Clause>::const_iterator;181 182  /// Return the first instance of the given clause found in the clause list or183  /// `nullptr` if not present. If more than one instance is expected, use184  /// `findRepeatableClause` instead.185  template <typename T>186  const T *findUniqueClause(const parser::CharBlock **source = nullptr) const;187 188  /// Call `callbackFn` for each occurrence of the given clause. Return `true`189  /// if at least one instance was found.190  template <typename T>191  bool findRepeatableClause(192      std::function<void(const T &, const parser::CharBlock &source)>193          callbackFn) const;194 195  /// Set the `result` to a new `mlir::UnitAttr` if the clause is present.196  template <typename T>197  bool markClauseOccurrence(mlir::UnitAttr &result) const;198 199  void processMapObjects(200      lower::StatementContext &stmtCtx, mlir::Location clauseLocation,201      const omp::ObjectList &objects, mlir::omp::ClauseMapFlags mapTypeBits,202      std::map<Object, OmpMapParentAndMemberData> &parentMemberIndices,203      llvm::SmallVectorImpl<mlir::Value> &mapVars,204      llvm::SmallVectorImpl<const semantics::Symbol *> &mapSyms,205      llvm::StringRef mapperIdNameRef = "") const;206 207  lower::AbstractConverter &converter;208  semantics::SemanticsContext &semaCtx;209  List<Clause> clauses;210};211 212template <typename... Ts>213void ClauseProcessor::processTODO(mlir::Location currentLocation,214                                  llvm::omp::Directive directive) const {215  auto checkUnhandledClause = [&](llvm::omp::Clause id, const auto *x) {216    if (!x)217      return;218    unsigned version = semaCtx.langOptions().OpenMPVersion;219    bool isSimdDirective = llvm::omp::getOpenMPDirectiveName(directive, version)220                               .upper()221                               .find("SIMD") != llvm::StringRef::npos;222    if (!semaCtx.langOptions().OpenMPSimd || isSimdDirective)223      TODO(currentLocation,224           "Unhandled clause " + llvm::omp::getOpenMPClauseName(id).upper() +225               " in " +226               llvm::omp::getOpenMPDirectiveName(directive, version).upper() +227               " construct");228  };229 230  for (ClauseIterator it = clauses.begin(); it != clauses.end(); ++it)231    (checkUnhandledClause(it->id, std::get_if<Ts>(&it->u)), ...);232}233 234template <typename T>235const T *236ClauseProcessor::findUniqueClause(const parser::CharBlock **source) const {237  return ClauseFinder::findUniqueClause<T>(clauses, source);238}239 240template <typename T>241bool ClauseProcessor::findRepeatableClause(242    std::function<void(const T &, const parser::CharBlock &source)> callbackFn)243    const {244  return ClauseFinder::findRepeatableClause<T>(clauses, callbackFn);245}246 247template <typename T>248bool ClauseProcessor::markClauseOccurrence(mlir::UnitAttr &result) const {249  if (findUniqueClause<T>()) {250    result = converter.getFirOpBuilder().getUnitAttr();251    return true;252  }253  return false;254}255 256} // namespace omp257} // namespace lower258} // namespace Fortran259 260#endif // FORTRAN_LOWER_CLAUSEPROCESSOR_H261