173 lines · cpp
1//===-- FIROpenACCOpsInterfaces.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// Implementation of external operation interfaces for FIR.10//11//===----------------------------------------------------------------------===//12 13#include "flang/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.h"14 15#include "flang/Optimizer/Dialect/FIROps.h"16#include "flang/Optimizer/HLFIR/HLFIROps.h"17#include "flang/Optimizer/Support/InternalNames.h"18#include "mlir/IR/SymbolTable.h"19#include "llvm/ADT/SmallSet.h"20 21namespace fir::acc {22 23template <>24mlir::Value PartialEntityAccessModel<fir::ArrayCoorOp>::getBaseEntity(25 mlir::Operation *op) const {26 return mlir::cast<fir::ArrayCoorOp>(op).getMemref();27}28 29template <>30mlir::Value PartialEntityAccessModel<fir::CoordinateOp>::getBaseEntity(31 mlir::Operation *op) const {32 return mlir::cast<fir::CoordinateOp>(op).getRef();33}34 35template <>36mlir::Value PartialEntityAccessModel<hlfir::DesignateOp>::getBaseEntity(37 mlir::Operation *op) const {38 return mlir::cast<hlfir::DesignateOp>(op).getMemref();39}40 41mlir::Value PartialEntityAccessModel<fir::DeclareOp>::getBaseEntity(42 mlir::Operation *op) const {43 return mlir::cast<fir::DeclareOp>(op).getStorage();44}45 46bool PartialEntityAccessModel<fir::DeclareOp>::isCompleteView(47 mlir::Operation *op) const {48 // Return false (partial view) only if storage is present49 // Return true (complete view) if storage is absent50 return !getBaseEntity(op);51}52 53mlir::Value PartialEntityAccessModel<hlfir::DeclareOp>::getBaseEntity(54 mlir::Operation *op) const {55 return mlir::cast<hlfir::DeclareOp>(op).getStorage();56}57 58bool PartialEntityAccessModel<hlfir::DeclareOp>::isCompleteView(59 mlir::Operation *op) const {60 // Return false (partial view) only if storage is present61 // Return true (complete view) if storage is absent62 return !getBaseEntity(op);63}64 65mlir::SymbolRefAttr AddressOfGlobalModel::getSymbol(mlir::Operation *op) const {66 return mlir::cast<fir::AddrOfOp>(op).getSymbolAttr();67}68 69bool GlobalVariableModel::isConstant(mlir::Operation *op) const {70 auto globalOp = mlir::cast<fir::GlobalOp>(op);71 return globalOp.getConstant().has_value();72}73 74mlir::Region *GlobalVariableModel::getInitRegion(mlir::Operation *op) const {75 auto globalOp = mlir::cast<fir::GlobalOp>(op);76 return globalOp.hasInitializationBody() ? &globalOp.getRegion() : nullptr;77}78 79// Helper to recursively process address-of operations in derived type80// descriptors and collect all needed fir.globals.81static void processAddrOfOpInDerivedTypeDescriptor(82 fir::AddrOfOp addrOfOp, mlir::SymbolTable &symTab,83 llvm::SmallSet<mlir::Operation *, 16> &globalsSet,84 llvm::SmallVectorImpl<mlir::SymbolRefAttr> &symbols) {85 if (auto globalOp = symTab.lookup<fir::GlobalOp>(86 addrOfOp.getSymbol().getLeafReference().getValue())) {87 if (globalsSet.contains(globalOp))88 return;89 globalsSet.insert(globalOp);90 symbols.push_back(addrOfOp.getSymbolAttr());91 globalOp.walk([&](fir::AddrOfOp op) {92 processAddrOfOpInDerivedTypeDescriptor(op, symTab, globalsSet, symbols);93 });94 }95}96 97// Utility to collect referenced symbols for type descriptors of derived types.98// This is the common logic for operations that may require type descriptor99// globals.100static void collectReferencedSymbolsForType(101 mlir::Type ty, mlir::Operation *op,102 llvm::SmallVectorImpl<mlir::SymbolRefAttr> &symbols,103 mlir::SymbolTable *symbolTable) {104 ty = fir::getDerivedType(fir::unwrapRefType(ty));105 106 // Look for type descriptor globals only if it's a derived (record) type107 if (auto recTy = mlir::dyn_cast_if_present<fir::RecordType>(ty)) {108 // If no symbol table provided, simply add the type descriptor name109 if (!symbolTable) {110 symbols.push_back(mlir::SymbolRefAttr::get(111 op->getContext(),112 fir::NameUniquer::getTypeDescriptorName(recTy.getName())));113 return;114 }115 116 // Otherwise, do full lookup and recursive processing117 llvm::SmallSet<mlir::Operation *, 16> globalsSet;118 119 fir::GlobalOp globalOp = symbolTable->lookup<fir::GlobalOp>(120 fir::NameUniquer::getTypeDescriptorName(recTy.getName()));121 if (!globalOp)122 globalOp = symbolTable->lookup<fir::GlobalOp>(123 fir::NameUniquer::getTypeDescriptorAssemblyName(recTy.getName()));124 125 if (globalOp) {126 globalsSet.insert(globalOp);127 symbols.push_back(128 mlir::SymbolRefAttr::get(op->getContext(), globalOp.getSymName()));129 globalOp.walk([&](fir::AddrOfOp addrOp) {130 processAddrOfOpInDerivedTypeDescriptor(addrOp, *symbolTable, globalsSet,131 symbols);132 });133 }134 }135}136 137template <>138void IndirectGlobalAccessModel<fir::AllocaOp>::getReferencedSymbols(139 mlir::Operation *op, llvm::SmallVectorImpl<mlir::SymbolRefAttr> &symbols,140 mlir::SymbolTable *symbolTable) const {141 auto allocaOp = mlir::cast<fir::AllocaOp>(op);142 collectReferencedSymbolsForType(allocaOp.getType(), op, symbols, symbolTable);143}144 145template <>146void IndirectGlobalAccessModel<fir::EmboxOp>::getReferencedSymbols(147 mlir::Operation *op, llvm::SmallVectorImpl<mlir::SymbolRefAttr> &symbols,148 mlir::SymbolTable *symbolTable) const {149 auto emboxOp = mlir::cast<fir::EmboxOp>(op);150 collectReferencedSymbolsForType(emboxOp.getMemref().getType(), op, symbols,151 symbolTable);152}153 154template <>155void IndirectGlobalAccessModel<fir::ReboxOp>::getReferencedSymbols(156 mlir::Operation *op, llvm::SmallVectorImpl<mlir::SymbolRefAttr> &symbols,157 mlir::SymbolTable *symbolTable) const {158 auto reboxOp = mlir::cast<fir::ReboxOp>(op);159 collectReferencedSymbolsForType(reboxOp.getBox().getType(), op, symbols,160 symbolTable);161}162 163template <>164void IndirectGlobalAccessModel<fir::TypeDescOp>::getReferencedSymbols(165 mlir::Operation *op, llvm::SmallVectorImpl<mlir::SymbolRefAttr> &symbols,166 mlir::SymbolTable *symbolTable) const {167 auto typeDescOp = mlir::cast<fir::TypeDescOp>(op);168 collectReferencedSymbolsForType(typeDescOp.getInType(), op, symbols,169 symbolTable);170}171 172} // namespace fir::acc173