brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.8 KiB · e5b8123 Raw
270 lines · cpp
1//===- FIROpenACCUtils.cpp - FIR OpenACC Utilities ------------------------===//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// This file implements utility functions for FIR OpenACC support.10//11//===----------------------------------------------------------------------===//12 13#include "flang/Optimizer/OpenACC/Support/FIROpenACCUtils.h"14#include "flang/Optimizer/Dialect/FIROps.h"15#include "flang/Optimizer/Dialect/FIROpsSupport.h"16#include "flang/Optimizer/Dialect/FIRType.h"17#include "flang/Optimizer/Dialect/Support/FIRContext.h"18#include "flang/Optimizer/Dialect/Support/KindMapping.h"19#include "flang/Optimizer/HLFIR/HLFIROps.h"20#include "flang/Optimizer/Support/InternalNames.h"21#include "mlir/Dialect/OpenACC/OpenACC.h"22#include "mlir/IR/Matchers.h"23#include "mlir/Interfaces/ViewLikeInterface.h"24#include "llvm/ADT/TypeSwitch.h"25#include "llvm/Support/raw_ostream.h"26 27using namespace mlir;28 29namespace fir {30namespace acc {31 32std::string getVariableName(Value v, bool preferDemangledName) {33  std::string srcName;34  std::string prefix;35  llvm::SmallVector<std::string, 4> arrayIndices;36  bool iterate = true;37  mlir::Operation *defOp;38 39  // For integer constants, no need to further iterate - print their value40  // immediately.41  if (v.getDefiningOp()) {42    IntegerAttr::ValueType val;43    if (matchPattern(v.getDefiningOp(), m_ConstantInt(&val))) {44      llvm::raw_string_ostream os(prefix);45      val.print(os, /*isSigned=*/true);46      return prefix;47    }48  }49 50  while (v && (defOp = v.getDefiningOp()) && iterate) {51    iterate =52        llvm::TypeSwitch<mlir::Operation *, bool>(defOp)53            .Case<mlir::ViewLikeOpInterface>(54                [&v](mlir::ViewLikeOpInterface op) {55                  v = op.getViewSource();56                  return true;57                })58            .Case<fir::ReboxOp>([&v](fir::ReboxOp op) {59              v = op.getBox();60              return true;61            })62            .Case<fir::EmboxOp>([&v](fir::EmboxOp op) {63              v = op.getMemref();64              return true;65            })66            .Case<fir::ConvertOp>([&v](fir::ConvertOp op) {67              v = op.getValue();68              return true;69            })70            .Case<fir::LoadOp>([&v](fir::LoadOp op) {71              v = op.getMemref();72              return true;73            })74            .Case<fir::BoxAddrOp>([&v](fir::BoxAddrOp op) {75              // The box holds the name of the variable.76              v = op.getVal();77              return true;78            })79            .Case<fir::AddrOfOp>([&](fir::AddrOfOp op) {80              // Only use address_of symbol if mangled name is preferred81              if (!preferDemangledName) {82                auto symRef = op.getSymbol();83                srcName = symRef.getLeafReference().getValue().str();84              }85              return false;86            })87            .Case<fir::ArrayCoorOp>([&](fir::ArrayCoorOp op) {88              v = op.getMemref();89              for (auto coor : op.getIndices()) {90                auto idxName = getVariableName(coor, preferDemangledName);91                arrayIndices.push_back(idxName.empty() ? "?" : idxName);92              }93              return true;94            })95            .Case<fir::CoordinateOp>([&](fir::CoordinateOp op) {96              std::optional<llvm::ArrayRef<int32_t>> fieldIndices =97                  op.getFieldIndices();98              if (fieldIndices && fieldIndices->size() > 0 &&99                  (*fieldIndices)[0] != fir::CoordinateOp::kDynamicIndex) {100                int fieldId = (*fieldIndices)[0];101                mlir::Type baseType =102                    fir::getFortranElementType(op.getRef().getType());103                if (auto recType = llvm::dyn_cast<fir::RecordType>(baseType)) {104                  srcName = recType.getTypeList()[fieldId].first;105                }106              }107              if (!srcName.empty()) {108                // If the field name is known - attempt to continue building109                // name by looking at its parents.110                prefix =111                    getVariableName(op.getRef(), preferDemangledName) + "%";112              }113              return false;114            })115            .Case<hlfir::DesignateOp>([&](hlfir::DesignateOp op) {116              if (op.getComponent()) {117                srcName = op.getComponent().value().str();118                prefix =119                    getVariableName(op.getMemref(), preferDemangledName) + "%";120                return false;121              }122              for (auto coor : op.getIndices()) {123                auto idxName = getVariableName(coor, preferDemangledName);124                arrayIndices.push_back(idxName.empty() ? "?" : idxName);125              }126              v = op.getMemref();127              return true;128            })129            .Case<fir::DeclareOp, hlfir::DeclareOp>([&](auto op) {130              srcName = op.getUniqName().str();131              return false;132            })133            .Case<fir::AllocaOp>([&](fir::AllocaOp op) {134              if (preferDemangledName) {135                // Prefer demangled name (bindc_name over uniq_name)136                srcName = op.getBindcName()  ? *op.getBindcName()137                          : op.getUniqName() ? *op.getUniqName()138                                             : "";139              } else {140                // Prefer mangled name (uniq_name over bindc_name)141                srcName = op.getUniqName()    ? *op.getUniqName()142                          : op.getBindcName() ? *op.getBindcName()143                                              : "";144              }145              return false;146            })147            .Default([](mlir::Operation *) { return false; });148  }149 150  // Fallback to the default implementation.151  if (srcName.empty())152    return acc::getVariableName(v);153 154  // Build array index suffix if present155  std::string suffix;156  if (!arrayIndices.empty()) {157    llvm::raw_string_ostream os(suffix);158    os << "(";159    llvm::interleaveComma(arrayIndices, os);160    os << ")";161  }162 163  // Names from FIR operations may be mangled.164  // When the demangled name is requested - demangle it.165  if (preferDemangledName) {166    auto [kind, deconstructed] = fir::NameUniquer::deconstruct(srcName);167    if (kind != fir::NameUniquer::NameKind::NOT_UNIQUED)168      return prefix + deconstructed.name + suffix;169  }170 171  return prefix + srcName + suffix;172}173 174bool areAllBoundsConstant(llvm::ArrayRef<Value> bounds) {175  for (auto bound : bounds) {176    auto dataBound =177        mlir::dyn_cast<mlir::acc::DataBoundsOp>(bound.getDefiningOp());178    if (!dataBound)179      return false;180 181    // Check if this bound has constant values182    bool hasConstant = false;183    if (dataBound.getLowerbound() && dataBound.getUpperbound())184      hasConstant =185          fir::getIntIfConstant(dataBound.getLowerbound()).has_value() &&186          fir::getIntIfConstant(dataBound.getUpperbound()).has_value();187    else if (dataBound.getExtent())188      hasConstant = fir::getIntIfConstant(dataBound.getExtent()).has_value();189 190    if (!hasConstant)191      return false;192  }193  return true;194}195 196static std::string getBoundsString(llvm::ArrayRef<Value> bounds) {197  if (bounds.empty())198    return "";199 200  std::string boundStr;201  llvm::raw_string_ostream os(boundStr);202  os << "_section_";203 204  llvm::interleave(205      bounds,206      [&](Value bound) {207        auto boundsOp =208            mlir::cast<mlir::acc::DataBoundsOp>(bound.getDefiningOp());209        if (boundsOp.getLowerbound() &&210            fir::getIntIfConstant(boundsOp.getLowerbound()) &&211            boundsOp.getUpperbound() &&212            fir::getIntIfConstant(boundsOp.getUpperbound())) {213          os << "lb" << *fir::getIntIfConstant(boundsOp.getLowerbound())214             << ".ub" << *fir::getIntIfConstant(boundsOp.getUpperbound());215        } else if (boundsOp.getExtent() &&216                   fir::getIntIfConstant(boundsOp.getExtent())) {217          os << "ext" << *fir::getIntIfConstant(boundsOp.getExtent());218        } else {219          os << "?";220        }221      },222      [&] { os << "x"; });223 224  return os.str();225}226 227std::string getRecipeName(mlir::acc::RecipeKind kind, Type type, Value var,228                          llvm::ArrayRef<Value> bounds,229                          mlir::acc::ReductionOperator reductionOp) {230  assert(fir::isa_fir_type(type) && "getRecipeName expects a FIR type");231 232  // Build the complete prefix with all components before calling233  // getTypeAsString234  std::string prefixStr;235  llvm::raw_string_ostream prefixOS(prefixStr);236 237  switch (kind) {238  case mlir::acc::RecipeKind::private_recipe:239    prefixOS << "privatization";240    // Private recipes do not currently include bounds in the name241    // TODO: They should include them - but lowering tests would need to242    // be updated.243    break;244  case mlir::acc::RecipeKind::firstprivate_recipe:245    prefixOS << "firstprivatization";246    // Add bounds to the prefix if applicable (only for firstprivate)247    if (!bounds.empty() && areAllBoundsConstant(bounds))248      prefixOS << getBoundsString(bounds);249    break;250  case mlir::acc::RecipeKind::reduction_recipe:251    prefixOS << "reduction";252    // Embed the reduction operator in the prefix253    if (reductionOp != mlir::acc::ReductionOperator::AccNone)254      prefixOS << "_"255               << mlir::acc::stringifyReductionOperator(reductionOp).str();256    // Add bounds to the prefix if applicable (only for reduction)257    if (!bounds.empty() && areAllBoundsConstant(bounds))258      prefixOS << getBoundsString(bounds);259    break;260  }261 262  auto kindMap = var && var.getDefiningOp()263                     ? fir::getKindMapping(var.getDefiningOp())264                     : fir::KindMapping(type.getContext());265  return fir::getTypeAsString(type, kindMap, prefixOS.str());266}267 268} // namespace acc269} // namespace fir270