brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.5 KiB · c2036c4 Raw
159 lines · cpp
1//===-- lib/Utisl/OpenMP.cpp ------------------------------------*- 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#include "flang/Utils/OpenMP.h"10 11#include "flang/Lower/ConvertExprToHLFIR.h"12#include "flang/Optimizer/Builder/DirectivesCommon.h"13#include "flang/Optimizer/Builder/FIRBuilder.h"14#include "flang/Optimizer/Dialect/FIROps.h"15#include "flang/Optimizer/Dialect/FIRType.h"16 17#include "mlir/Dialect/OpenMP/OpenMPDialect.h"18#include "mlir/Transforms/RegionUtils.h"19 20namespace Fortran::utils::openmp {21mlir::omp::MapInfoOp createMapInfoOp(mlir::OpBuilder &builder,22    mlir::Location loc, mlir::Value baseAddr, mlir::Value varPtrPtr,23    llvm::StringRef name, llvm::ArrayRef<mlir::Value> bounds,24    llvm::ArrayRef<mlir::Value> members, mlir::ArrayAttr membersIndex,25    mlir::omp::ClauseMapFlags mapType,26    mlir::omp::VariableCaptureKind mapCaptureType, mlir::Type retTy,27    bool partialMap, mlir::FlatSymbolRefAttr mapperId) {28 29  if (auto boxTy = llvm::dyn_cast<fir::BaseBoxType>(baseAddr.getType())) {30    baseAddr = fir::BoxAddrOp::create(builder, loc, baseAddr);31    retTy = baseAddr.getType();32  }33 34  mlir::TypeAttr varType = mlir::TypeAttr::get(35      llvm::cast<mlir::omp::PointerLikeType>(retTy).getElementType());36 37  // For types with unknown extents such as <2x?xi32> we discard the incomplete38  // type info and only retain the base type. The correct dimensions are later39  // recovered through the bounds info.40  if (auto seqType = llvm::dyn_cast<fir::SequenceType>(varType.getValue()))41    if (seqType.hasDynamicExtents())42      varType = mlir::TypeAttr::get(seqType.getEleTy());43 44  mlir::omp::MapInfoOp op =45      mlir::omp::MapInfoOp::create(builder, loc, retTy, baseAddr, varType,46          builder.getAttr<mlir::omp::ClauseMapFlagsAttr>(mapType),47          builder.getAttr<mlir::omp::VariableCaptureKindAttr>(mapCaptureType),48          varPtrPtr, members, membersIndex, bounds, mapperId,49          builder.getStringAttr(name), builder.getBoolAttr(partialMap));50  return op;51}52 53mlir::Value mapTemporaryValue(fir::FirOpBuilder &firOpBuilder,54    mlir::omp::TargetOp targetOp, mlir::Value val, llvm::StringRef name) {55  mlir::OpBuilder::InsertionGuard guard(firOpBuilder);56  mlir::Operation *valOp = val.getDefiningOp();57 58  if (valOp)59    firOpBuilder.setInsertionPointAfter(valOp);60  else61    // This means val is a block argument62    firOpBuilder.setInsertionPoint(targetOp);63 64  auto copyVal = firOpBuilder.createTemporary(val.getLoc(), val.getType());65  firOpBuilder.createStoreWithConvert(copyVal.getLoc(), val, copyVal);66 67  fir::factory::AddrAndBoundsInfo info = fir::factory::getDataOperandBaseAddr(68      firOpBuilder, val, /*isOptional=*/false, val.getLoc());69  llvm::SmallVector<mlir::Value> bounds =70      fir::factory::genImplicitBoundsOps<mlir::omp::MapBoundsOp,71          mlir::omp::MapBoundsType>(firOpBuilder, info,72          hlfir::translateToExtendedValue(73              val.getLoc(), firOpBuilder, hlfir::Entity{val})74              .first,75          /*dataExvIsAssumedSize=*/false, val.getLoc());76 77  firOpBuilder.setInsertionPoint(targetOp);78 79  mlir::omp::ClauseMapFlags mapFlag = mlir::omp::ClauseMapFlags::implicit;80  mlir::omp::VariableCaptureKind captureKind =81      mlir::omp::VariableCaptureKind::ByRef;82 83  mlir::Type eleType = copyVal.getType();84  if (auto refType = mlir::dyn_cast<fir::ReferenceType>(copyVal.getType())) {85    eleType = refType.getElementType();86  }87 88  if (fir::isa_trivial(eleType) || fir::isa_char(eleType)) {89    captureKind = mlir::omp::VariableCaptureKind::ByCopy;90  } else if (!fir::isa_builtin_cptr_type(eleType)) {91    mapFlag |= mlir::omp::ClauseMapFlags::to;92  }93 94  mlir::Value mapOp = createMapInfoOp(firOpBuilder, copyVal.getLoc(), copyVal,95      /*varPtrPtr=*/mlir::Value{}, name.str(), bounds,96      /*members=*/llvm::SmallVector<mlir::Value>{},97      /*membersIndex=*/mlir::ArrayAttr{}, mapFlag, captureKind,98      copyVal.getType());99 100  auto argIface = llvm::cast<mlir::omp::BlockArgOpenMPOpInterface>(*targetOp);101  mlir::Region &region = targetOp.getRegion();102 103  // Get the index of the first non-map argument before modifying mapVars,104  // then append an element to mapVars and an associated entry block105  // argument at that index.106  unsigned insertIndex =107      argIface.getMapBlockArgsStart() + argIface.numMapBlockArgs();108  targetOp.getMapVarsMutable().append(mapOp);109  mlir::Value clonedValArg =110      region.insertArgument(insertIndex, copyVal.getType(), copyVal.getLoc());111 112  mlir::Block *entryBlock = &region.getBlocks().front();113  firOpBuilder.setInsertionPointToStart(entryBlock);114  auto loadOp =115      fir::LoadOp::create(firOpBuilder, clonedValArg.getLoc(), clonedValArg);116  return loadOp.getResult();117}118 119void cloneOrMapRegionOutsiders(120    fir::FirOpBuilder &firOpBuilder, mlir::omp::TargetOp targetOp) {121  mlir::Region &region = targetOp.getRegion();122  mlir::Block *entryBlock = &region.getBlocks().front();123 124  llvm::SetVector<mlir::Value> valuesDefinedAbove;125  mlir::getUsedValuesDefinedAbove(region, valuesDefinedAbove);126  while (!valuesDefinedAbove.empty()) {127    for (mlir::Value val : valuesDefinedAbove) {128      mlir::Operation *valOp = val.getDefiningOp();129 130      // NOTE: We skip BoxDimsOp's as the lesser of two evils is to map the131      // indices separately, as the alternative is to eventually map the Box,132      // which comes with a fairly large overhead comparatively. We could be133      // more robust about this and check using a BackwardsSlice to see if we134      // run the risk of mapping a box.135      if (valOp && mlir::isMemoryEffectFree(valOp) &&136          !mlir::isa<fir::BoxDimsOp>(valOp)) {137        mlir::Operation *clonedOp = valOp->clone();138        entryBlock->push_front(clonedOp);139 140        auto replace = [entryBlock](mlir::OpOperand &use) {141          return use.getOwner()->getBlock() == entryBlock;142        };143 144        valOp->getResults().replaceUsesWithIf(clonedOp->getResults(), replace);145        valOp->replaceUsesWithIf(clonedOp, replace);146      } else {147        mlir::Value mappedTemp = mapTemporaryValue(firOpBuilder, targetOp, val,148            /*name=*/{});149        val.replaceUsesWithIf(mappedTemp, [entryBlock](mlir::OpOperand &use) {150          return use.getOwner()->getBlock() == entryBlock;151        });152      }153    }154    valuesDefinedAbove.clear();155    mlir::getUsedValuesDefinedAbove(region, valuesDefinedAbove);156  }157}158} // namespace Fortran::utils::openmp159