brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.3 KiB · 5793d46 Raw
155 lines · cpp
1//===- AutomapToTargetData.cpp -------------------------------------------===//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/Optimizer/Builder/DirectivesCommon.h"10#include "flang/Optimizer/Builder/FIRBuilder.h"11#include "flang/Optimizer/Builder/HLFIRTools.h"12#include "flang/Optimizer/Dialect/FIROps.h"13#include "flang/Optimizer/Dialect/FIRType.h"14#include "flang/Optimizer/Dialect/Support/KindMapping.h"15#include "flang/Optimizer/HLFIR/HLFIROps.h"16 17#include "mlir/Dialect/OpenMP/OpenMPDialect.h"18#include "mlir/Dialect/OpenMP/OpenMPInterfaces.h"19#include "mlir/IR/BuiltinAttributes.h"20#include "mlir/IR/Operation.h"21#include "mlir/Pass/Pass.h"22 23namespace flangomp {24#define GEN_PASS_DEF_AUTOMAPTOTARGETDATAPASS25#include "flang/Optimizer/OpenMP/Passes.h.inc"26} // namespace flangomp27 28using namespace mlir;29 30namespace {31class AutomapToTargetDataPass32    : public flangomp::impl::AutomapToTargetDataPassBase<33          AutomapToTargetDataPass> {34 35  // Returns true if the variable has a dynamic size and therefore requires36  // bounds operations to describe its extents.37  inline bool needsBoundsOps(mlir::Value var) {38    assert(mlir::isa<mlir::omp::PointerLikeType>(var.getType()) &&39           "only pointer like types expected");40    mlir::Type t = fir::unwrapRefType(var.getType());41    if (mlir::Type inner = fir::dyn_cast_ptrOrBoxEleTy(t))42      return fir::hasDynamicSize(inner);43    return fir::hasDynamicSize(t);44  }45 46  // Generate MapBoundsOp operations for the variable if required.47  inline void genBoundsOps(fir::FirOpBuilder &builder, mlir::Value var,48                           llvm::SmallVectorImpl<mlir::Value> &boundsOps) {49    mlir::Location loc = var.getLoc();50    fir::factory::AddrAndBoundsInfo info =51        fir::factory::getDataOperandBaseAddr(builder, var,52                                             /*isOptional=*/false, loc);53    fir::ExtendedValue exv =54        hlfir::translateToExtendedValue(loc, builder, hlfir::Entity{info.addr},55                                        /*contiguousHint=*/true)56            .first;57    llvm::SmallVector<mlir::Value> tmp =58        fir::factory::genImplicitBoundsOps<mlir::omp::MapBoundsOp,59                                           mlir::omp::MapBoundsType>(60            builder, info, exv, /*dataExvIsAssumedSize=*/false, loc);61    llvm::append_range(boundsOps, tmp);62  }63 64  void findRelatedAllocmemFreemem(fir::AddrOfOp addressOfOp,65                                  llvm::DenseSet<fir::StoreOp> &allocmems,66                                  llvm::DenseSet<fir::LoadOp> &freemems) {67    assert(addressOfOp->hasOneUse() && "op must have single use");68 69    auto declaredRef =70        cast<hlfir::DeclareOp>(*addressOfOp->getUsers().begin())->getResult(0);71 72    for (Operation *refUser : declaredRef.getUsers()) {73      if (auto storeOp = dyn_cast<fir::StoreOp>(refUser))74        if (auto emboxOp = storeOp.getValue().getDefiningOp<fir::EmboxOp>())75          if (auto allocmemOp =76                  emboxOp.getOperand(0).getDefiningOp<fir::AllocMemOp>())77            allocmems.insert(storeOp);78 79      if (auto loadOp = dyn_cast<fir::LoadOp>(refUser))80        for (Operation *loadUser : loadOp.getResult().getUsers())81          if (auto boxAddrOp = dyn_cast<fir::BoxAddrOp>(loadUser))82            for (Operation *boxAddrUser : boxAddrOp.getResult().getUsers())83              if (auto freememOp = dyn_cast<fir::FreeMemOp>(boxAddrUser))84                freemems.insert(loadOp);85    }86  }87 88  void runOnOperation() override {89    ModuleOp module = getOperation()->getParentOfType<ModuleOp>();90    if (!module)91      module = dyn_cast<ModuleOp>(getOperation());92    if (!module)93      return;94 95    // Build FIR builder for helper utilities.96    fir::KindMapping kindMap = fir::getKindMapping(module);97    fir::FirOpBuilder builder{module, std::move(kindMap)};98 99    // Collect global variables with AUTOMAP flag.100    llvm::DenseSet<fir::GlobalOp> automapGlobals;101    module.walk([&](fir::GlobalOp globalOp) {102      if (auto iface =103              dyn_cast<omp::DeclareTargetInterface>(globalOp.getOperation()))104        if (iface.isDeclareTarget() && iface.getDeclareTargetAutomap() &&105            iface.getDeclareTargetDeviceType() !=106                omp::DeclareTargetDeviceType::host)107          automapGlobals.insert(globalOp);108    });109 110    auto addMapInfo = [&](auto globalOp, auto memOp) {111      builder.setInsertionPointAfter(memOp);112      SmallVector<Value> bounds;113      if (needsBoundsOps(memOp.getMemref()))114        genBoundsOps(builder, memOp.getMemref(), bounds);115 116      omp::TargetEnterExitUpdateDataOperands clauses;117      mlir::omp::MapInfoOp mapInfo = mlir::omp::MapInfoOp::create(118          builder, memOp.getLoc(), memOp.getMemref().getType(),119          memOp.getMemref(),120          TypeAttr::get(fir::unwrapRefType(memOp.getMemref().getType())),121          builder.getAttr<omp::ClauseMapFlagsAttr>(122              isa<fir::StoreOp>(memOp) ? omp::ClauseMapFlags::to123                                       : omp::ClauseMapFlags::del),124          builder.getAttr<omp::VariableCaptureKindAttr>(125              omp::VariableCaptureKind::ByCopy),126          /*var_ptr_ptr=*/mlir::Value{},127          /*members=*/SmallVector<Value>{},128          /*members_index=*/ArrayAttr{}, bounds,129          /*mapperId=*/mlir::FlatSymbolRefAttr(), globalOp.getSymNameAttr(),130          builder.getBoolAttr(false));131      clauses.mapVars.push_back(mapInfo);132      isa<fir::StoreOp>(memOp)133          ? omp::TargetEnterDataOp::create(builder, memOp.getLoc(), clauses)134          : omp::TargetExitDataOp::create(builder, memOp.getLoc(), clauses);135    };136 137    for (fir::GlobalOp globalOp : automapGlobals) {138      if (auto uses = globalOp.getSymbolUses(module.getOperation())) {139        llvm::DenseSet<fir::StoreOp> allocmemStores;140        llvm::DenseSet<fir::LoadOp> freememLoads;141        for (auto &x : *uses)142          if (auto addrOp = dyn_cast<fir::AddrOfOp>(x.getUser()))143            findRelatedAllocmemFreemem(addrOp, allocmemStores, freememLoads);144 145        for (auto storeOp : allocmemStores)146          addMapInfo(globalOp, storeOp);147 148        for (auto loadOp : freememLoads)149          addMapInfo(globalOp, loadOp);150      }151    }152  }153};154} // namespace155