1044d5b5dSValentin Clement //===-- CodeGen.cpp -- bridge to lower to LLVM ----------------------------===// 2044d5b5dSValentin Clement // 3044d5b5dSValentin Clement // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4044d5b5dSValentin Clement // See https://llvm.org/LICENSE.txt for license information. 5044d5b5dSValentin Clement // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6044d5b5dSValentin Clement // 7044d5b5dSValentin Clement //===----------------------------------------------------------------------===// 8044d5b5dSValentin Clement // 9044d5b5dSValentin Clement // Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/ 10044d5b5dSValentin Clement // 11044d5b5dSValentin Clement //===----------------------------------------------------------------------===// 12044d5b5dSValentin Clement 13044d5b5dSValentin Clement #include "flang/Optimizer/CodeGen/CodeGen.h" 1467d0d7acSMichele Scuttari 15cd5ee271SAbid Qadeer #include "flang/Optimizer/CodeGen/CGOps.h" 1695fe47caSagozillon #include "flang/Optimizer/CodeGen/CodeGenOpenMP.h" 17e9639e9cSValentin Clement (バレンタイン クレメン) #include "flang/Optimizer/CodeGen/FIROpPatterns.h" 18e9639e9cSValentin Clement (バレンタイン クレメン) #include "flang/Optimizer/CodeGen/TypeConverter.h" 1939f4ef81SValentin Clement #include "flang/Optimizer/Dialect/FIRAttr.h" 20044d5b5dSValentin Clement #include "flang/Optimizer/Dialect/FIROps.h" 210538bfe7SRenaud-K #include "flang/Optimizer/Dialect/FIRType.h" 2227d9a479SjeanPerier #include "flang/Optimizer/Support/DataLayout.h" 237dd7ccd2SJean Perier #include "flang/Optimizer/Support/InternalNames.h" 24af6ee580SValentin Clement #include "flang/Optimizer/Support/TypeCode.h" 250538bfe7SRenaud-K #include "flang/Optimizer/Support/Utils.h" 265e1f87e8SValentin Clement (バレンタイン クレメン) #include "flang/Runtime/CUDA/descriptor.h" 274530273dSValentin Clement (バレンタイン クレメン) #include "flang/Runtime/CUDA/memory.h" 28c91ba043SMichael Kruse #include "flang/Runtime/allocator-registry-consts.h" 29c91ba043SMichael Kruse #include "flang/Runtime/descriptor-consts.h" 307dd7ccd2SJean Perier #include "flang/Semantics/runtime-type-info.h" 31bc955caeSSlava Zakharin #include "mlir/Conversion/ArithCommon/AttrToLLVMConverter.h" 326c8d8d10SJakub Kuderski #include "mlir/Conversion/ArithToLLVM/ArithToLLVM.h" 33000de666SDavid Truby #include "mlir/Conversion/ComplexToLLVM/ComplexToLLVM.h" 34000de666SDavid Truby #include "mlir/Conversion/ComplexToStandard/ComplexToStandard.h" 35ace01605SRiver Riddle #include "mlir/Conversion/ControlFlowToLLVM/ControlFlowToLLVM.h" 365a7b9194SRiver Riddle #include "mlir/Conversion/FuncToLLVM/ConvertFuncToLLVM.h" 37044d5b5dSValentin Clement #include "mlir/Conversion/LLVMCommon/Pattern.h" 38bac3aedaSSlava Zakharin #include "mlir/Conversion/MathToFuncs/MathToFuncs.h" 399f356579SSlava Zakharin #include "mlir/Conversion/MathToLLVM/MathToLLVM.h" 409f356579SSlava Zakharin #include "mlir/Conversion/MathToLibm/MathToLibm.h" 414290e34eSJan Leyonberg #include "mlir/Conversion/MathToROCDL/MathToROCDL.h" 42c6ac9370SKiran Chandramohan #include "mlir/Conversion/OpenMPToLLVM/ConvertOpenMPToLLVM.h" 43a9e1d2e7SKelvin Li #include "mlir/Conversion/VectorToLLVM/ConvertVectorToLLVM.h" 446be0e979STom Eccles #include "mlir/Dialect/Arith/IR/Arith.h" 4527d9a479SjeanPerier #include "mlir/Dialect/DLTI/DLTI.h" 46e5092c30SValentin Clement (バレンタイン クレメン) #include "mlir/Dialect/GPU/IR/GPUDialect.h" 4785d7fef6SValentin Clement (バレンタイン クレメン) #include "mlir/Dialect/LLVMIR/LLVMAttrs.h" 4867d0d7acSMichele Scuttari #include "mlir/Dialect/LLVMIR/LLVMDialect.h" 495f476b80SDavid Truby #include "mlir/Dialect/LLVMIR/Transforms/AddComdats.h" 50cd9cdc68SValentin Clement #include "mlir/Dialect/OpenACC/OpenACC.h" 5167d0d7acSMichele Scuttari #include "mlir/Dialect/OpenMP/OpenMPDialect.h" 52044d5b5dSValentin Clement #include "mlir/IR/BuiltinTypes.h" 533ae8e442SValentin Clement #include "mlir/IR/Matchers.h" 54044d5b5dSValentin Clement #include "mlir/Pass/Pass.h" 55bac3aedaSSlava Zakharin #include "mlir/Pass/PassManager.h" 56abeb6c9fSagozillon #include "mlir/Target/LLVMIR/Import.h" 57853e79d8SValentin Clement #include "mlir/Target/LLVMIR/ModuleTranslation.h" 58044d5b5dSValentin Clement #include "llvm/ADT/ArrayRef.h" 59dfcc0a70SValentin Clement #include "llvm/ADT/TypeSwitch.h" 60044d5b5dSValentin Clement 6167d0d7acSMichele Scuttari namespace fir { 6267d0d7acSMichele Scuttari #define GEN_PASS_DEF_FIRTOLLVMLOWERING 6367d0d7acSMichele Scuttari #include "flang/Optimizer/CodeGen/CGPasses.h.inc" 6467d0d7acSMichele Scuttari } // namespace fir 6567d0d7acSMichele Scuttari 66044d5b5dSValentin Clement #define DEBUG_TYPE "flang-codegen" 67044d5b5dSValentin Clement 68af6ee580SValentin Clement // TODO: This should really be recovered from the specified target. 69af6ee580SValentin Clement static constexpr unsigned defaultAlign = 8; 70af6ee580SValentin Clement 71b6e44ecdSValentin Clement /// `fir.box` attribute values as defined for CFI_attribute_t in 72b6e44ecdSValentin Clement /// flang/ISO_Fortran_binding.h. 73b6e44ecdSValentin Clement static constexpr unsigned kAttrPointer = CFI_attribute_pointer; 74b6e44ecdSValentin Clement static constexpr unsigned kAttrAllocatable = CFI_attribute_allocatable; 75b6e44ecdSValentin Clement 76abeb6c9fSagozillon static inline mlir::Type getLlvmPtrType(mlir::MLIRContext *context, 77abeb6c9fSagozillon unsigned addressSpace = 0) { 78abeb6c9fSagozillon return mlir::LLVM::LLVMPointerType::get(context, addressSpace); 798a1ce2d6SjeanPerier } 808a1ce2d6SjeanPerier 818a1ce2d6SjeanPerier static inline mlir::Type getI8Type(mlir::MLIRContext *context) { 828a1ce2d6SjeanPerier return mlir::IntegerType::get(context, 8); 83fa517555SKiran Chandramohan } 84fa517555SKiran Chandramohan 851e6d9c06SDiana Picus static mlir::LLVM::ConstantOp 861e6d9c06SDiana Picus genConstantIndex(mlir::Location loc, mlir::Type ity, 871e6d9c06SDiana Picus mlir::ConversionPatternRewriter &rewriter, 881e6d9c06SDiana Picus std::int64_t offset) { 8965923012SJeff Niu auto cattr = rewriter.getI64IntegerAttr(offset); 9065923012SJeff Niu return rewriter.create<mlir::LLVM::ConstantOp>(loc, ity, cattr); 911e6d9c06SDiana Picus } 921e6d9c06SDiana Picus 9344e58509SEric Schweitz static mlir::Block *createBlock(mlir::ConversionPatternRewriter &rewriter, 9439f4ef81SValentin Clement mlir::Block *insertBefore) { 9539f4ef81SValentin Clement assert(insertBefore && "expected valid insertion block"); 9639f4ef81SValentin Clement return rewriter.createBlock(insertBefore->getParent(), 9739f4ef81SValentin Clement mlir::Region::iterator(insertBefore)); 9839f4ef81SValentin Clement } 9939f4ef81SValentin Clement 100f9e995b4SSlava Zakharin /// Extract constant from a value that must be the result of one of the 101f9e995b4SSlava Zakharin /// ConstantOp operations. 102f9e995b4SSlava Zakharin static int64_t getConstantIntValue(mlir::Value val) { 103a5ae54abSTom Eccles if (auto constVal = fir::getIntIfConstant(val)) 104f9e995b4SSlava Zakharin return *constVal; 105af40f99eSJean Perier fir::emitFatalError(val.getLoc(), "must be a constant"); 106af40f99eSJean Perier } 107af40f99eSJean Perier 108016fbc40SValentin Clement static unsigned getTypeDescFieldId(mlir::Type ty) { 109fac349a1SChristian Sigg auto isArray = mlir::isa<fir::SequenceType>(fir::dyn_cast_ptrOrBoxEleTy(ty)); 110016fbc40SValentin Clement return isArray ? kOptTypePtrPosInBox : kDimsPosInBox; 111016fbc40SValentin Clement } 112d26a6464SjeanPerier static unsigned getLenParamFieldId(mlir::Type ty) { 113d26a6464SjeanPerier return getTypeDescFieldId(ty) + 1; 114d26a6464SjeanPerier } 115016fbc40SValentin Clement 116fde3c16aSSirui Mu static llvm::SmallVector<mlir::NamedAttribute> 117fde3c16aSSirui Mu addLLVMOpBundleAttrs(mlir::ConversionPatternRewriter &rewriter, 118fde3c16aSSirui Mu llvm::ArrayRef<mlir::NamedAttribute> attrs, 119fde3c16aSSirui Mu int32_t numCallOperands) { 120fde3c16aSSirui Mu llvm::SmallVector<mlir::NamedAttribute> newAttrs; 121fde3c16aSSirui Mu newAttrs.reserve(attrs.size() + 2); 122fde3c16aSSirui Mu 123fde3c16aSSirui Mu for (mlir::NamedAttribute attr : attrs) { 124fde3c16aSSirui Mu if (attr.getName() != "operandSegmentSizes") 125fde3c16aSSirui Mu newAttrs.push_back(attr); 126fde3c16aSSirui Mu } 127fde3c16aSSirui Mu 128fde3c16aSSirui Mu newAttrs.push_back(rewriter.getNamedAttr( 129fde3c16aSSirui Mu "operandSegmentSizes", 130fde3c16aSSirui Mu rewriter.getDenseI32ArrayAttr({numCallOperands, 0}))); 131fde3c16aSSirui Mu newAttrs.push_back(rewriter.getNamedAttr("op_bundle_sizes", 132fde3c16aSSirui Mu rewriter.getDenseI32ArrayAttr({}))); 133fde3c16aSSirui Mu return newAttrs; 134fde3c16aSSirui Mu } 135fde3c16aSSirui Mu 136044d5b5dSValentin Clement namespace { 137575c9d6dSValentin Clement /// Lower `fir.address_of` operation to `llvm.address_of` operation. 138e9639e9cSValentin Clement (バレンタイン クレメン) struct AddrOfOpConversion : public fir::FIROpConversion<fir::AddrOfOp> { 139044d5b5dSValentin Clement using FIROpConversion::FIROpConversion; 140044d5b5dSValentin Clement 141db791b27SRamkumar Ramachandra llvm::LogicalResult 142044d5b5dSValentin Clement matchAndRewrite(fir::AddrOfOp addr, OpAdaptor adaptor, 143044d5b5dSValentin Clement mlir::ConversionPatternRewriter &rewriter) const override { 144044d5b5dSValentin Clement auto ty = convertType(addr.getType()); 145044d5b5dSValentin Clement rewriter.replaceOpWithNewOp<mlir::LLVM::AddressOfOp>( 146149ad3d5SShraiysh Vaishay addr, ty, addr.getSymbol().getRootReference().getValue()); 14744e58509SEric Schweitz return mlir::success(); 148044d5b5dSValentin Clement } 149044d5b5dSValentin Clement }; 1501e6d9c06SDiana Picus } // namespace 1511e6d9c06SDiana Picus 1521e6d9c06SDiana Picus /// Lookup the function to compute the memory size of this parametric derived 1531e6d9c06SDiana Picus /// type. The size of the object may depend on the LEN type parameters of the 1541e6d9c06SDiana Picus /// derived type. 1551e6d9c06SDiana Picus static mlir::LLVM::LLVMFuncOp 1561e6d9c06SDiana Picus getDependentTypeMemSizeFn(fir::RecordType recTy, fir::AllocaOp op, 1571e6d9c06SDiana Picus mlir::ConversionPatternRewriter &rewriter) { 1581e6d9c06SDiana Picus auto module = op->getParentOfType<mlir::ModuleOp>(); 1591e6d9c06SDiana Picus std::string name = recTy.getName().str() + "P.mem.size"; 160575c9d6dSValentin Clement if (auto memSizeFunc = module.lookupSymbol<mlir::LLVM::LLVMFuncOp>(name)) 161575c9d6dSValentin Clement return memSizeFunc; 162575c9d6dSValentin Clement TODO(op.getLoc(), "did not find allocation function"); 1631e6d9c06SDiana Picus } 1641e6d9c06SDiana Picus 165ac0f4c8fSPeixinQiao // Compute the alloc scale size (constant factors encoded in the array type). 166ac0f4c8fSPeixinQiao // We do this for arrays without a constant interior or arrays of character with 167ac0f4c8fSPeixinQiao // dynamic length arrays, since those are the only ones that get decayed to a 168ac0f4c8fSPeixinQiao // pointer to the element type. 169ac0f4c8fSPeixinQiao template <typename OP> 170ac0f4c8fSPeixinQiao static mlir::Value 171ac0f4c8fSPeixinQiao genAllocationScaleSize(OP op, mlir::Type ity, 172ac0f4c8fSPeixinQiao mlir::ConversionPatternRewriter &rewriter) { 173ac0f4c8fSPeixinQiao mlir::Location loc = op.getLoc(); 174ac0f4c8fSPeixinQiao mlir::Type dataTy = op.getInType(); 175fac349a1SChristian Sigg auto seqTy = mlir::dyn_cast<fir::SequenceType>(dataTy); 176ac0f4c8fSPeixinQiao fir::SequenceType::Extent constSize = 1; 1777ae39114SMats Petersson if (seqTy) { 1787ae39114SMats Petersson int constRows = seqTy.getConstantRows(); 1797ae39114SMats Petersson const fir::SequenceType::ShapeRef &shape = seqTy.getShape(); 1807ae39114SMats Petersson if (constRows != static_cast<int>(shape.size())) { 1817ae39114SMats Petersson for (auto extent : shape) { 1827ae39114SMats Petersson if (constRows-- > 0) 1837ae39114SMats Petersson continue; 184ac0f4c8fSPeixinQiao if (extent != fir::SequenceType::getUnknownExtent()) 185ac0f4c8fSPeixinQiao constSize *= extent; 1867ae39114SMats Petersson } 1877ae39114SMats Petersson } 1887ae39114SMats Petersson } 1897ae39114SMats Petersson 190ac0f4c8fSPeixinQiao if (constSize != 1) { 191ac0f4c8fSPeixinQiao mlir::Value constVal{ 192ac0f4c8fSPeixinQiao genConstantIndex(loc, ity, rewriter, constSize).getResult()}; 193ac0f4c8fSPeixinQiao return constVal; 194ac0f4c8fSPeixinQiao } 195ac0f4c8fSPeixinQiao return nullptr; 196ac0f4c8fSPeixinQiao } 197ac0f4c8fSPeixinQiao 1981e6d9c06SDiana Picus namespace { 199cd5ee271SAbid Qadeer struct DeclareOpConversion : public fir::FIROpConversion<fir::cg::XDeclareOp> { 200cd5ee271SAbid Qadeer public: 201cd5ee271SAbid Qadeer using FIROpConversion::FIROpConversion; 202db791b27SRamkumar Ramachandra llvm::LogicalResult 203cd5ee271SAbid Qadeer matchAndRewrite(fir::cg::XDeclareOp declareOp, OpAdaptor adaptor, 204cd5ee271SAbid Qadeer mlir::ConversionPatternRewriter &rewriter) const override { 205cd5ee271SAbid Qadeer auto memRef = adaptor.getOperands()[0]; 206cd5ee271SAbid Qadeer if (auto fusedLoc = mlir::dyn_cast<mlir::FusedLoc>(declareOp.getLoc())) { 207cd5ee271SAbid Qadeer if (auto varAttr = 208cd5ee271SAbid Qadeer mlir::dyn_cast_or_null<mlir::LLVM::DILocalVariableAttr>( 209cd5ee271SAbid Qadeer fusedLoc.getMetadata())) { 210cd5ee271SAbid Qadeer rewriter.create<mlir::LLVM::DbgDeclareOp>(memRef.getLoc(), memRef, 211cd5ee271SAbid Qadeer varAttr, nullptr); 212cd5ee271SAbid Qadeer } 213cd5ee271SAbid Qadeer } 214cd5ee271SAbid Qadeer rewriter.replaceOp(declareOp, memRef); 215cd5ee271SAbid Qadeer return mlir::success(); 216cd5ee271SAbid Qadeer } 217cd5ee271SAbid Qadeer }; 218cd5ee271SAbid Qadeer } // namespace 219cd5ee271SAbid Qadeer 220cd5ee271SAbid Qadeer namespace { 2211e6d9c06SDiana Picus /// convert to LLVM IR dialect `alloca` 222e9639e9cSValentin Clement (バレンタイン クレメン) struct AllocaOpConversion : public fir::FIROpConversion<fir::AllocaOp> { 2231e6d9c06SDiana Picus using FIROpConversion::FIROpConversion; 2241e6d9c06SDiana Picus 225db791b27SRamkumar Ramachandra llvm::LogicalResult 2261e6d9c06SDiana Picus matchAndRewrite(fir::AllocaOp alloc, OpAdaptor adaptor, 2271e6d9c06SDiana Picus mlir::ConversionPatternRewriter &rewriter) const override { 2281e6d9c06SDiana Picus mlir::ValueRange operands = adaptor.getOperands(); 2291e6d9c06SDiana Picus auto loc = alloc.getLoc(); 2301e6d9c06SDiana Picus mlir::Type ity = lowerTy().indexType(); 2311e6d9c06SDiana Picus unsigned i = 0; 2321e6d9c06SDiana Picus mlir::Value size = genConstantIndex(loc, ity, rewriter, 1).getResult(); 2338a1ce2d6SjeanPerier mlir::Type firObjType = fir::unwrapRefType(alloc.getType()); 2348a1ce2d6SjeanPerier mlir::Type llvmObjectType = convertObjectType(firObjType); 2351e6d9c06SDiana Picus if (alloc.hasLenParams()) { 2361e6d9c06SDiana Picus unsigned end = alloc.numLenParams(); 2371e6d9c06SDiana Picus llvm::SmallVector<mlir::Value> lenParams; 2381e6d9c06SDiana Picus for (; i < end; ++i) 2391e6d9c06SDiana Picus lenParams.push_back(operands[i]); 2401e6d9c06SDiana Picus mlir::Type scalarType = fir::unwrapSequenceType(alloc.getInType()); 241fac349a1SChristian Sigg if (auto chrTy = mlir::dyn_cast<fir::CharacterType>(scalarType)) { 2421e6d9c06SDiana Picus fir::CharacterType rawCharTy = fir::CharacterType::getUnknownLen( 2431e6d9c06SDiana Picus chrTy.getContext(), chrTy.getFKind()); 2448a1ce2d6SjeanPerier llvmObjectType = convertType(rawCharTy); 2451e6d9c06SDiana Picus assert(end == 1); 246c0cba519SVijay Kandiah size = integerCast(loc, rewriter, ity, lenParams[0], /*fold=*/true); 247fac349a1SChristian Sigg } else if (auto recTy = mlir::dyn_cast<fir::RecordType>(scalarType)) { 2481e6d9c06SDiana Picus mlir::LLVM::LLVMFuncOp memSizeFn = 2491e6d9c06SDiana Picus getDependentTypeMemSizeFn(recTy, alloc, rewriter); 2501e6d9c06SDiana Picus if (!memSizeFn) 2511e6d9c06SDiana Picus emitError(loc, "did not find allocation function"); 2521e6d9c06SDiana Picus mlir::NamedAttribute attr = rewriter.getNamedAttr( 2531e6d9c06SDiana Picus "callee", mlir::SymbolRefAttr::get(memSizeFn)); 2541e6d9c06SDiana Picus auto call = rewriter.create<mlir::LLVM::CallOp>( 255fde3c16aSSirui Mu loc, ity, lenParams, 256fde3c16aSSirui Mu addLLVMOpBundleAttrs(rewriter, {attr}, lenParams.size())); 2574e0a2bd6SJeff Niu size = call.getResult(); 2588a1ce2d6SjeanPerier llvmObjectType = ::getI8Type(alloc.getContext()); 2591e6d9c06SDiana Picus } else { 2601e6d9c06SDiana Picus return emitError(loc, "unexpected type ") 2611e6d9c06SDiana Picus << scalarType << " with type parameters"; 2621e6d9c06SDiana Picus } 2631e6d9c06SDiana Picus } 264ac0f4c8fSPeixinQiao if (auto scaleSize = genAllocationScaleSize(alloc, ity, rewriter)) 265c0cba519SVijay Kandiah size = 266c0cba519SVijay Kandiah rewriter.createOrFold<mlir::LLVM::MulOp>(loc, ity, size, scaleSize); 2671e6d9c06SDiana Picus if (alloc.hasShapeOperands()) { 2681e6d9c06SDiana Picus unsigned end = operands.size(); 2691e6d9c06SDiana Picus for (; i < end; ++i) 270c0cba519SVijay Kandiah size = rewriter.createOrFold<mlir::LLVM::MulOp>( 271c0cba519SVijay Kandiah loc, ity, size, 272c0cba519SVijay Kandiah integerCast(loc, rewriter, ity, operands[i], /*fold=*/true)); 2731e6d9c06SDiana Picus } 274abeb6c9fSagozillon 275abeb6c9fSagozillon unsigned allocaAs = getAllocaAddressSpace(rewriter); 276abeb6c9fSagozillon unsigned programAs = getProgramAddressSpace(rewriter); 277abeb6c9fSagozillon 278c0cba519SVijay Kandiah if (mlir::isa<mlir::LLVM::ConstantOp>(size.getDefiningOp())) { 279c0cba519SVijay Kandiah // Set the Block in which the llvm alloca should be inserted. 280c0cba519SVijay Kandiah mlir::Operation *parentOp = rewriter.getInsertionBlock()->getParentOp(); 281c0cba519SVijay Kandiah mlir::Region *parentRegion = rewriter.getInsertionBlock()->getParent(); 282c0cba519SVijay Kandiah mlir::Block *insertBlock = 283c0cba519SVijay Kandiah getBlockForAllocaInsert(parentOp, parentRegion); 284e9fc2fafSTom Eccles 285e9fc2fafSTom Eccles // The old size might have had multiple users, some at a broader scope 286e9fc2fafSTom Eccles // than we can safely outline the alloca to. As it is only an 287e9fc2fafSTom Eccles // llvm.constant operation, it is faster to clone it than to calculate the 288e9fc2fafSTom Eccles // dominance to see if it really should be moved. 289e9fc2fafSTom Eccles mlir::Operation *clonedSize = rewriter.clone(*size.getDefiningOp()); 290e9fc2fafSTom Eccles size = clonedSize->getResult(0); 291e9fc2fafSTom Eccles clonedSize->moveBefore(&insertBlock->front()); 292c0cba519SVijay Kandiah rewriter.setInsertionPointAfter(size.getDefiningOp()); 293c0cba519SVijay Kandiah } 294c0cba519SVijay Kandiah 2958a1ce2d6SjeanPerier // NOTE: we used to pass alloc->getAttrs() in the builder for non opaque 2968a1ce2d6SjeanPerier // pointers! Only propagate pinned and bindc_name to help debugging, but 2978a1ce2d6SjeanPerier // this should have no functional purpose (and passing the operand segment 2988a1ce2d6SjeanPerier // attribute like before is certainly bad). 2998a1ce2d6SjeanPerier auto llvmAlloc = rewriter.create<mlir::LLVM::AllocaOp>( 300abeb6c9fSagozillon loc, ::getLlvmPtrType(alloc.getContext(), allocaAs), llvmObjectType, 301abeb6c9fSagozillon size); 3028a1ce2d6SjeanPerier if (alloc.getPinned()) 3038a1ce2d6SjeanPerier llvmAlloc->setDiscardableAttr(alloc.getPinnedAttrName(), 3048a1ce2d6SjeanPerier alloc.getPinnedAttr()); 3058a1ce2d6SjeanPerier if (alloc.getBindcName()) 3068a1ce2d6SjeanPerier llvmAlloc->setDiscardableAttr(alloc.getBindcNameAttrName(), 3078a1ce2d6SjeanPerier alloc.getBindcNameAttr()); 308abeb6c9fSagozillon if (allocaAs == programAs) { 3098a1ce2d6SjeanPerier rewriter.replaceOp(alloc, llvmAlloc); 310abeb6c9fSagozillon } else { 311abeb6c9fSagozillon // if our allocation address space, is not the same as the program address 312abeb6c9fSagozillon // space, then we must emit a cast to the program address space before 313abeb6c9fSagozillon // use. An example case would be on AMDGPU, where the allocation address 314abeb6c9fSagozillon // space is the numeric value 5 (private), and the program address space 315abeb6c9fSagozillon // is 0 (generic). 316abeb6c9fSagozillon rewriter.replaceOpWithNewOp<mlir::LLVM::AddrSpaceCastOp>( 317abeb6c9fSagozillon alloc, ::getLlvmPtrType(alloc.getContext(), programAs), llvmAlloc); 318abeb6c9fSagozillon } 31944e58509SEric Schweitz return mlir::success(); 3201e6d9c06SDiana Picus } 3211e6d9c06SDiana Picus }; 322dc48849fSKiran Chandramohan } // namespace 323044d5b5dSValentin Clement 324dc48849fSKiran Chandramohan namespace { 325df3b9810SValentin Clement /// Lower `fir.box_addr` to the sequence of operations to extract the first 326df3b9810SValentin Clement /// element of the box. 327e9639e9cSValentin Clement (バレンタイン クレメン) struct BoxAddrOpConversion : public fir::FIROpConversion<fir::BoxAddrOp> { 328df3b9810SValentin Clement using FIROpConversion::FIROpConversion; 329df3b9810SValentin Clement 330db791b27SRamkumar Ramachandra llvm::LogicalResult 331df3b9810SValentin Clement matchAndRewrite(fir::BoxAddrOp boxaddr, OpAdaptor adaptor, 332df3b9810SValentin Clement mlir::ConversionPatternRewriter &rewriter) const override { 333df3b9810SValentin Clement mlir::Value a = adaptor.getOperands()[0]; 334df3b9810SValentin Clement auto loc = boxaddr.getLoc(); 335fac349a1SChristian Sigg if (auto argty = 336fac349a1SChristian Sigg mlir::dyn_cast<fir::BaseBoxType>(boxaddr.getVal().getType())) { 3378a1ce2d6SjeanPerier TypePair boxTyPair = getBoxTypePair(argty); 3389c84d20fSSlava Zakharin rewriter.replaceOp(boxaddr, 3398a1ce2d6SjeanPerier getBaseAddrFromBox(loc, boxTyPair, a, rewriter)); 340df3b9810SValentin Clement } else { 3415c5af910SJeff Niu rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractValueOp>(boxaddr, a, 0); 342df3b9810SValentin Clement } 34344e58509SEric Schweitz return mlir::success(); 344df3b9810SValentin Clement } 345df3b9810SValentin Clement }; 346df3b9810SValentin Clement 347dc48849fSKiran Chandramohan /// Convert `!fir.boxchar_len` to `!llvm.extractvalue` for the 2nd part of the 348dc48849fSKiran Chandramohan /// boxchar. 349e9639e9cSValentin Clement (バレンタイン クレメン) struct BoxCharLenOpConversion : public fir::FIROpConversion<fir::BoxCharLenOp> { 350dc48849fSKiran Chandramohan using FIROpConversion::FIROpConversion; 351dc48849fSKiran Chandramohan 352db791b27SRamkumar Ramachandra llvm::LogicalResult 353dc48849fSKiran Chandramohan matchAndRewrite(fir::BoxCharLenOp boxCharLen, OpAdaptor adaptor, 354dc48849fSKiran Chandramohan mlir::ConversionPatternRewriter &rewriter) const override { 355dc48849fSKiran Chandramohan mlir::Value boxChar = adaptor.getOperands()[0]; 356dc48849fSKiran Chandramohan mlir::Location loc = boxChar.getLoc(); 357dc48849fSKiran Chandramohan mlir::Type returnValTy = boxCharLen.getResult().getType(); 358dc48849fSKiran Chandramohan 359dc48849fSKiran Chandramohan constexpr int boxcharLenIdx = 1; 3605c5af910SJeff Niu auto len = rewriter.create<mlir::LLVM::ExtractValueOp>(loc, boxChar, 3615c5af910SJeff Niu boxcharLenIdx); 362dc48849fSKiran Chandramohan mlir::Value lenAfterCast = integerCast(loc, rewriter, returnValTy, len); 363dc48849fSKiran Chandramohan rewriter.replaceOp(boxCharLen, lenAfterCast); 364dc48849fSKiran Chandramohan 36544e58509SEric Schweitz return mlir::success(); 366dc48849fSKiran Chandramohan } 367dc48849fSKiran Chandramohan }; 368dc48849fSKiran Chandramohan 369df3b9810SValentin Clement /// Lower `fir.box_dims` to a sequence of operations to extract the requested 3709c84d20fSSlava Zakharin /// dimension information from the boxed value. 371df3b9810SValentin Clement /// Result in a triple set of GEPs and loads. 372e9639e9cSValentin Clement (バレンタイン クレメン) struct BoxDimsOpConversion : public fir::FIROpConversion<fir::BoxDimsOp> { 373df3b9810SValentin Clement using FIROpConversion::FIROpConversion; 374df3b9810SValentin Clement 375db791b27SRamkumar Ramachandra llvm::LogicalResult 376df3b9810SValentin Clement matchAndRewrite(fir::BoxDimsOp boxdims, OpAdaptor adaptor, 377df3b9810SValentin Clement mlir::ConversionPatternRewriter &rewriter) const override { 37844e58509SEric Schweitz llvm::SmallVector<mlir::Type, 3> resultTypes = { 379df3b9810SValentin Clement convertType(boxdims.getResult(0).getType()), 380df3b9810SValentin Clement convertType(boxdims.getResult(1).getType()), 381df3b9810SValentin Clement convertType(boxdims.getResult(2).getType()), 382df3b9810SValentin Clement }; 3838a1ce2d6SjeanPerier TypePair boxTyPair = getBoxTypePair(boxdims.getVal().getType()); 3848a1ce2d6SjeanPerier auto results = getDimsFromBox(boxdims.getLoc(), resultTypes, boxTyPair, 3858a1ce2d6SjeanPerier adaptor.getOperands()[0], 3868a1ce2d6SjeanPerier adaptor.getOperands()[1], rewriter); 387df3b9810SValentin Clement rewriter.replaceOp(boxdims, results); 38844e58509SEric Schweitz return mlir::success(); 389df3b9810SValentin Clement } 390df3b9810SValentin Clement }; 391df3b9810SValentin Clement 392df3b9810SValentin Clement /// Lower `fir.box_elesize` to a sequence of operations ro extract the size of 393df3b9810SValentin Clement /// an element in the boxed value. 394e9639e9cSValentin Clement (バレンタイン クレメン) struct BoxEleSizeOpConversion : public fir::FIROpConversion<fir::BoxEleSizeOp> { 395df3b9810SValentin Clement using FIROpConversion::FIROpConversion; 396df3b9810SValentin Clement 397db791b27SRamkumar Ramachandra llvm::LogicalResult 398df3b9810SValentin Clement matchAndRewrite(fir::BoxEleSizeOp boxelesz, OpAdaptor adaptor, 399df3b9810SValentin Clement mlir::ConversionPatternRewriter &rewriter) const override { 4009c84d20fSSlava Zakharin mlir::Value box = adaptor.getOperands()[0]; 401df3b9810SValentin Clement auto loc = boxelesz.getLoc(); 402df3b9810SValentin Clement auto ty = convertType(boxelesz.getType()); 4038a1ce2d6SjeanPerier TypePair boxTyPair = getBoxTypePair(boxelesz.getVal().getType()); 4048a1ce2d6SjeanPerier auto elemSize = getElementSizeFromBox(loc, ty, boxTyPair, box, rewriter); 405b6e44ecdSValentin Clement rewriter.replaceOp(boxelesz, elemSize); 40644e58509SEric Schweitz return mlir::success(); 407b6e44ecdSValentin Clement } 408b6e44ecdSValentin Clement }; 409b6e44ecdSValentin Clement 410b6e44ecdSValentin Clement /// Lower `fir.box_isalloc` to a sequence of operations to determine if the 411b6e44ecdSValentin Clement /// boxed value was from an ALLOCATABLE entity. 412e9639e9cSValentin Clement (バレンタイン クレメン) struct BoxIsAllocOpConversion : public fir::FIROpConversion<fir::BoxIsAllocOp> { 413b6e44ecdSValentin Clement using FIROpConversion::FIROpConversion; 414b6e44ecdSValentin Clement 415db791b27SRamkumar Ramachandra llvm::LogicalResult 416b6e44ecdSValentin Clement matchAndRewrite(fir::BoxIsAllocOp boxisalloc, OpAdaptor adaptor, 417b6e44ecdSValentin Clement mlir::ConversionPatternRewriter &rewriter) const override { 418b6e44ecdSValentin Clement mlir::Value box = adaptor.getOperands()[0]; 419b6e44ecdSValentin Clement auto loc = boxisalloc.getLoc(); 4208a1ce2d6SjeanPerier TypePair boxTyPair = getBoxTypePair(boxisalloc.getVal().getType()); 4218a1ce2d6SjeanPerier mlir::Value check = 4228a1ce2d6SjeanPerier genBoxAttributeCheck(loc, boxTyPair, box, rewriter, kAttrAllocatable); 423b6e44ecdSValentin Clement rewriter.replaceOp(boxisalloc, check); 42444e58509SEric Schweitz return mlir::success(); 425b6e44ecdSValentin Clement } 426b6e44ecdSValentin Clement }; 427b6e44ecdSValentin Clement 428b6e44ecdSValentin Clement /// Lower `fir.box_isarray` to a sequence of operations to determine if the 429b6e44ecdSValentin Clement /// boxed is an array. 430e9639e9cSValentin Clement (バレンタイン クレメン) struct BoxIsArrayOpConversion : public fir::FIROpConversion<fir::BoxIsArrayOp> { 431b6e44ecdSValentin Clement using FIROpConversion::FIROpConversion; 432b6e44ecdSValentin Clement 433db791b27SRamkumar Ramachandra llvm::LogicalResult 434b6e44ecdSValentin Clement matchAndRewrite(fir::BoxIsArrayOp boxisarray, OpAdaptor adaptor, 435b6e44ecdSValentin Clement mlir::ConversionPatternRewriter &rewriter) const override { 436b6e44ecdSValentin Clement mlir::Value a = adaptor.getOperands()[0]; 437b6e44ecdSValentin Clement auto loc = boxisarray.getLoc(); 4388a1ce2d6SjeanPerier TypePair boxTyPair = getBoxTypePair(boxisarray.getVal().getType()); 43926e0ce0bSjeanPerier mlir::Value rank = getRankFromBox(loc, boxTyPair, a, rewriter); 44026e0ce0bSjeanPerier mlir::Value c0 = genConstantIndex(loc, rank.getType(), rewriter, 0); 441b6e44ecdSValentin Clement rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>( 442b6e44ecdSValentin Clement boxisarray, mlir::LLVM::ICmpPredicate::ne, rank, c0); 44344e58509SEric Schweitz return mlir::success(); 444b6e44ecdSValentin Clement } 445b6e44ecdSValentin Clement }; 446b6e44ecdSValentin Clement 447b6e44ecdSValentin Clement /// Lower `fir.box_isptr` to a sequence of operations to determined if the 448b6e44ecdSValentin Clement /// boxed value was from a POINTER entity. 449e9639e9cSValentin Clement (バレンタイン クレメン) struct BoxIsPtrOpConversion : public fir::FIROpConversion<fir::BoxIsPtrOp> { 450b6e44ecdSValentin Clement using FIROpConversion::FIROpConversion; 451b6e44ecdSValentin Clement 452db791b27SRamkumar Ramachandra llvm::LogicalResult 453b6e44ecdSValentin Clement matchAndRewrite(fir::BoxIsPtrOp boxisptr, OpAdaptor adaptor, 454b6e44ecdSValentin Clement mlir::ConversionPatternRewriter &rewriter) const override { 455b6e44ecdSValentin Clement mlir::Value box = adaptor.getOperands()[0]; 456b6e44ecdSValentin Clement auto loc = boxisptr.getLoc(); 4578a1ce2d6SjeanPerier TypePair boxTyPair = getBoxTypePair(boxisptr.getVal().getType()); 4588a1ce2d6SjeanPerier mlir::Value check = 4598a1ce2d6SjeanPerier genBoxAttributeCheck(loc, boxTyPair, box, rewriter, kAttrPointer); 460b6e44ecdSValentin Clement rewriter.replaceOp(boxisptr, check); 46144e58509SEric Schweitz return mlir::success(); 462df3b9810SValentin Clement } 463df3b9810SValentin Clement }; 464df3b9810SValentin Clement 465df3b9810SValentin Clement /// Lower `fir.box_rank` to the sequence of operation to extract the rank from 466df3b9810SValentin Clement /// the box. 467e9639e9cSValentin Clement (バレンタイン クレメン) struct BoxRankOpConversion : public fir::FIROpConversion<fir::BoxRankOp> { 468df3b9810SValentin Clement using FIROpConversion::FIROpConversion; 469df3b9810SValentin Clement 470db791b27SRamkumar Ramachandra llvm::LogicalResult 471df3b9810SValentin Clement matchAndRewrite(fir::BoxRankOp boxrank, OpAdaptor adaptor, 472df3b9810SValentin Clement mlir::ConversionPatternRewriter &rewriter) const override { 473df3b9810SValentin Clement mlir::Value a = adaptor.getOperands()[0]; 474df3b9810SValentin Clement auto loc = boxrank.getLoc(); 475df3b9810SValentin Clement mlir::Type ty = convertType(boxrank.getType()); 476fd8b2d20SjeanPerier TypePair boxTyPair = 477fd8b2d20SjeanPerier getBoxTypePair(fir::unwrapRefType(boxrank.getBox().getType())); 47826e0ce0bSjeanPerier mlir::Value rank = getRankFromBox(loc, boxTyPair, a, rewriter); 47926e0ce0bSjeanPerier mlir::Value result = integerCast(loc, rewriter, ty, rank); 480df3b9810SValentin Clement rewriter.replaceOp(boxrank, result); 48144e58509SEric Schweitz return mlir::success(); 482df3b9810SValentin Clement } 483df3b9810SValentin Clement }; 484df3b9810SValentin Clement 485cc505c0bSKiran Chandramohan /// Lower `fir.boxproc_host` operation. Extracts the host pointer from the 486cc505c0bSKiran Chandramohan /// boxproc. 487cc505c0bSKiran Chandramohan /// TODO: Part of supporting Fortran 2003 procedure pointers. 488e9639e9cSValentin Clement (バレンタイン クレメン) struct BoxProcHostOpConversion 489e9639e9cSValentin Clement (バレンタイン クレメン) : public fir::FIROpConversion<fir::BoxProcHostOp> { 490cc505c0bSKiran Chandramohan using FIROpConversion::FIROpConversion; 491cc505c0bSKiran Chandramohan 492db791b27SRamkumar Ramachandra llvm::LogicalResult 493cc505c0bSKiran Chandramohan matchAndRewrite(fir::BoxProcHostOp boxprochost, OpAdaptor adaptor, 494cc505c0bSKiran Chandramohan mlir::ConversionPatternRewriter &rewriter) const override { 4957ce8c6fcSKiran Chandramohan TODO(boxprochost.getLoc(), "fir.boxproc_host codegen"); 49644e58509SEric Schweitz return mlir::failure(); 497cc505c0bSKiran Chandramohan } 498cc505c0bSKiran Chandramohan }; 499cc505c0bSKiran Chandramohan 500e38ef2ffSValentin Clement /// Lower `fir.box_tdesc` to the sequence of operations to extract the type 501e38ef2ffSValentin Clement /// descriptor from the box. 502e9639e9cSValentin Clement (バレンタイン クレメン) struct BoxTypeDescOpConversion 503e9639e9cSValentin Clement (バレンタイン クレメン) : public fir::FIROpConversion<fir::BoxTypeDescOp> { 504e38ef2ffSValentin Clement using FIROpConversion::FIROpConversion; 505e38ef2ffSValentin Clement 506db791b27SRamkumar Ramachandra llvm::LogicalResult 507e38ef2ffSValentin Clement matchAndRewrite(fir::BoxTypeDescOp boxtypedesc, OpAdaptor adaptor, 508e38ef2ffSValentin Clement mlir::ConversionPatternRewriter &rewriter) const override { 509e38ef2ffSValentin Clement mlir::Value box = adaptor.getOperands()[0]; 5108a1ce2d6SjeanPerier TypePair boxTyPair = getBoxTypePair(boxtypedesc.getBox().getType()); 5118a1ce2d6SjeanPerier auto typeDescAddr = 5128a1ce2d6SjeanPerier loadTypeDescAddress(boxtypedesc.getLoc(), boxTyPair, box, rewriter); 5132e978986SValentin Clement rewriter.replaceOp(boxtypedesc, typeDescAddr); 51444e58509SEric Schweitz return mlir::success(); 515e38ef2ffSValentin Clement } 516e38ef2ffSValentin Clement }; 517e38ef2ffSValentin Clement 51849ee5634SValentin Clement /// Lower `fir.box_typecode` to a sequence of operations to extract the type 51949ee5634SValentin Clement /// code in the boxed value. 520e9639e9cSValentin Clement (バレンタイン クレメン) struct BoxTypeCodeOpConversion 521e9639e9cSValentin Clement (バレンタイン クレメン) : public fir::FIROpConversion<fir::BoxTypeCodeOp> { 52249ee5634SValentin Clement using FIROpConversion::FIROpConversion; 52349ee5634SValentin Clement 524db791b27SRamkumar Ramachandra llvm::LogicalResult 52549ee5634SValentin Clement matchAndRewrite(fir::BoxTypeCodeOp op, OpAdaptor adaptor, 52649ee5634SValentin Clement mlir::ConversionPatternRewriter &rewriter) const override { 52749ee5634SValentin Clement mlir::Value box = adaptor.getOperands()[0]; 52849ee5634SValentin Clement auto loc = box.getLoc(); 52949ee5634SValentin Clement auto ty = convertType(op.getType()); 5308a1ce2d6SjeanPerier TypePair boxTyPair = getBoxTypePair(op.getBox().getType()); 5318a1ce2d6SjeanPerier auto typeCode = 5328a1ce2d6SjeanPerier getValueFromBox(loc, boxTyPair, box, ty, rewriter, kTypePosInBox); 53349ee5634SValentin Clement rewriter.replaceOp(op, typeCode); 53449ee5634SValentin Clement return mlir::success(); 53549ee5634SValentin Clement } 53649ee5634SValentin Clement }; 53749ee5634SValentin Clement 538dc48849fSKiran Chandramohan /// Lower `fir.string_lit` to LLVM IR dialect operation. 539e9639e9cSValentin Clement (バレンタイン クレメン) struct StringLitOpConversion : public fir::FIROpConversion<fir::StringLitOp> { 540dc48849fSKiran Chandramohan using FIROpConversion::FIROpConversion; 541dc48849fSKiran Chandramohan 542db791b27SRamkumar Ramachandra llvm::LogicalResult 543dc48849fSKiran Chandramohan matchAndRewrite(fir::StringLitOp constop, OpAdaptor adaptor, 544dc48849fSKiran Chandramohan mlir::ConversionPatternRewriter &rewriter) const override { 545dc48849fSKiran Chandramohan auto ty = convertType(constop.getType()); 546dc48849fSKiran Chandramohan auto attr = constop.getValue(); 547fac349a1SChristian Sigg if (mlir::isa<mlir::StringAttr>(attr)) { 548dc48849fSKiran Chandramohan rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(constop, ty, attr); 54944e58509SEric Schweitz return mlir::success(); 550dc48849fSKiran Chandramohan } 551dc48849fSKiran Chandramohan 552fac349a1SChristian Sigg auto charTy = mlir::cast<fir::CharacterType>(constop.getType()); 553dc48849fSKiran Chandramohan unsigned bits = lowerTy().characterBitsize(charTy); 554dc48849fSKiran Chandramohan mlir::Type intTy = rewriter.getIntegerType(bits); 555e0c782bdSValentin Clement mlir::Location loc = constop.getLoc(); 556e0c782bdSValentin Clement mlir::Value cst = rewriter.create<mlir::LLVM::UndefOp>(loc, ty); 557fac349a1SChristian Sigg if (auto arr = mlir::dyn_cast<mlir::DenseElementsAttr>(attr)) { 558e0c782bdSValentin Clement cst = rewriter.create<mlir::LLVM::ConstantOp>(loc, ty, arr); 559fac349a1SChristian Sigg } else if (auto arr = mlir::dyn_cast<mlir::ArrayAttr>(attr)) { 56065923012SJeff Niu for (auto a : llvm::enumerate(arr.getValue())) { 561e0c782bdSValentin Clement // convert each character to a precise bitsize 56265923012SJeff Niu auto elemAttr = mlir::IntegerAttr::get( 56365923012SJeff Niu intTy, 564fac349a1SChristian Sigg mlir::cast<mlir::IntegerAttr>(a.value()).getValue().zextOrTrunc( 565fac349a1SChristian Sigg bits)); 56665923012SJeff Niu auto elemCst = 56765923012SJeff Niu rewriter.create<mlir::LLVM::ConstantOp>(loc, intTy, elemAttr); 5685c5af910SJeff Niu cst = rewriter.create<mlir::LLVM::InsertValueOp>(loc, cst, elemCst, 5695c5af910SJeff Niu a.index()); 570e0c782bdSValentin Clement } 571e0c782bdSValentin Clement } else { 57244e58509SEric Schweitz return mlir::failure(); 573e0c782bdSValentin Clement } 574e0c782bdSValentin Clement rewriter.replaceOp(constop, cst); 57544e58509SEric Schweitz return mlir::success(); 576dc48849fSKiran Chandramohan } 577dc48849fSKiran Chandramohan }; 578dc48849fSKiran Chandramohan 579575c9d6dSValentin Clement /// `fir.call` -> `llvm.call` 580e9639e9cSValentin Clement (バレンタイン クレメン) struct CallOpConversion : public fir::FIROpConversion<fir::CallOp> { 581ddd11b9aSAndrzej Warzynski using FIROpConversion::FIROpConversion; 582ddd11b9aSAndrzej Warzynski 583db791b27SRamkumar Ramachandra llvm::LogicalResult 584ddd11b9aSAndrzej Warzynski matchAndRewrite(fir::CallOp call, OpAdaptor adaptor, 585ddd11b9aSAndrzej Warzynski mlir::ConversionPatternRewriter &rewriter) const override { 58644e58509SEric Schweitz llvm::SmallVector<mlir::Type> resultTys; 587ddd11b9aSAndrzej Warzynski for (auto r : call.getResults()) 588ddd11b9aSAndrzej Warzynski resultTys.push_back(convertType(r.getType())); 589bc955caeSSlava Zakharin // Convert arith::FastMathFlagsAttr to LLVM::FastMathFlagsAttr. 590bc955caeSSlava Zakharin mlir::arith::AttrConvertFastMathToLLVM<fir::CallOp, mlir::LLVM::CallOp> 591bc955caeSSlava Zakharin attrConvert(call); 592ddd11b9aSAndrzej Warzynski rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>( 593fde3c16aSSirui Mu call, resultTys, adaptor.getOperands(), 594fde3c16aSSirui Mu addLLVMOpBundleAttrs(rewriter, attrConvert.getAttrs(), 595fde3c16aSSirui Mu adaptor.getOperands().size())); 59644e58509SEric Schweitz return mlir::success(); 597ddd11b9aSAndrzej Warzynski } 598ddd11b9aSAndrzej Warzynski }; 599c2acd453SAlexisPerry } // namespace 600ddd11b9aSAndrzej Warzynski 601092cee5fSValentin Clement static mlir::Type getComplexEleTy(mlir::Type complex) { 6021753de2dSjeanPerier return mlir::cast<mlir::ComplexType>(complex).getElementType(); 603092cee5fSValentin Clement } 604092cee5fSValentin Clement 605c2acd453SAlexisPerry namespace { 606f1dfc027SDiana Picus /// Compare complex values 607f1dfc027SDiana Picus /// 608f1dfc027SDiana Picus /// Per 10.1, the only comparisons available are .EQ. (oeq) and .NE. (une). 609f1dfc027SDiana Picus /// 610f1dfc027SDiana Picus /// For completeness, all other comparison are done on the real component only. 611e9639e9cSValentin Clement (バレンタイン クレメン) struct CmpcOpConversion : public fir::FIROpConversion<fir::CmpcOp> { 612f1dfc027SDiana Picus using FIROpConversion::FIROpConversion; 613f1dfc027SDiana Picus 614db791b27SRamkumar Ramachandra llvm::LogicalResult 615f1dfc027SDiana Picus matchAndRewrite(fir::CmpcOp cmp, OpAdaptor adaptor, 616f1dfc027SDiana Picus mlir::ConversionPatternRewriter &rewriter) const override { 617f1dfc027SDiana Picus mlir::ValueRange operands = adaptor.getOperands(); 618f1dfc027SDiana Picus mlir::Type resTy = convertType(cmp.getType()); 619f1dfc027SDiana Picus mlir::Location loc = cmp.getLoc(); 620fcd06d77STom Eccles mlir::LLVM::FastmathFlags fmf = 621fcd06d77STom Eccles mlir::arith::convertArithFastMathFlagsToLLVM(cmp.getFastmath()); 622fcd06d77STom Eccles mlir::LLVM::FCmpPredicate pred = 623fcd06d77STom Eccles static_cast<mlir::LLVM::FCmpPredicate>(cmp.getPredicate()); 624fcd06d77STom Eccles auto rcp = rewriter.create<mlir::LLVM::FCmpOp>( 625fcd06d77STom Eccles loc, resTy, pred, 6265c5af910SJeff Niu rewriter.create<mlir::LLVM::ExtractValueOp>(loc, operands[0], 0), 627fcd06d77STom Eccles rewriter.create<mlir::LLVM::ExtractValueOp>(loc, operands[1], 0), fmf); 628fcd06d77STom Eccles auto icp = rewriter.create<mlir::LLVM::FCmpOp>( 629fcd06d77STom Eccles loc, resTy, pred, 6305c5af910SJeff Niu rewriter.create<mlir::LLVM::ExtractValueOp>(loc, operands[0], 1), 631fcd06d77STom Eccles rewriter.create<mlir::LLVM::ExtractValueOp>(loc, operands[1], 1), fmf); 632575c9d6dSValentin Clement llvm::SmallVector<mlir::Value, 2> cp = {rcp, icp}; 633f1dfc027SDiana Picus switch (cmp.getPredicate()) { 634f1dfc027SDiana Picus case mlir::arith::CmpFPredicate::OEQ: // .EQ. 635f1dfc027SDiana Picus rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmp, resTy, cp); 636f1dfc027SDiana Picus break; 637f1dfc027SDiana Picus case mlir::arith::CmpFPredicate::UNE: // .NE. 638f1dfc027SDiana Picus rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmp, resTy, cp); 639f1dfc027SDiana Picus break; 640f1dfc027SDiana Picus default: 641f1dfc027SDiana Picus rewriter.replaceOp(cmp, rcp.getResult()); 642f1dfc027SDiana Picus break; 643f1dfc027SDiana Picus } 64444e58509SEric Schweitz return mlir::success(); 645f1dfc027SDiana Picus } 646f1dfc027SDiana Picus }; 647f1dfc027SDiana Picus 648092cee5fSValentin Clement /// convert value of from-type to value of to-type 649e9639e9cSValentin Clement (バレンタイン クレメン) struct ConvertOpConversion : public fir::FIROpConversion<fir::ConvertOp> { 650092cee5fSValentin Clement using FIROpConversion::FIROpConversion; 651092cee5fSValentin Clement 652092cee5fSValentin Clement static bool isFloatingPointTy(mlir::Type ty) { 653fac349a1SChristian Sigg return mlir::isa<mlir::FloatType>(ty); 654092cee5fSValentin Clement } 655092cee5fSValentin Clement 656db791b27SRamkumar Ramachandra llvm::LogicalResult 657092cee5fSValentin Clement matchAndRewrite(fir::ConvertOp convert, OpAdaptor adaptor, 658092cee5fSValentin Clement mlir::ConversionPatternRewriter &rewriter) const override { 6593b7ec85aSJean Perier auto fromFirTy = convert.getValue().getType(); 6603b7ec85aSJean Perier auto toFirTy = convert.getRes().getType(); 6613b7ec85aSJean Perier auto fromTy = convertType(fromFirTy); 6623b7ec85aSJean Perier auto toTy = convertType(toFirTy); 663092cee5fSValentin Clement mlir::Value op0 = adaptor.getOperands()[0]; 664f9e995b4SSlava Zakharin 665f9e995b4SSlava Zakharin if (fromFirTy == toFirTy) { 666f9e995b4SSlava Zakharin rewriter.replaceOp(convert, op0); 667f9e995b4SSlava Zakharin return mlir::success(); 668f9e995b4SSlava Zakharin } 669f9e995b4SSlava Zakharin 670f9e995b4SSlava Zakharin auto loc = convert.getLoc(); 671f9e995b4SSlava Zakharin auto i1Type = mlir::IntegerType::get(convert.getContext(), 1); 672f9e995b4SSlava Zakharin 673390943f2SLeandro Lupori if (mlir::isa<fir::RecordType>(toFirTy)) { 674390943f2SLeandro Lupori // Convert to compatible BIND(C) record type. 675390943f2SLeandro Lupori // Double check that the record types are compatible (it should have 676390943f2SLeandro Lupori // already been checked by the verifier). 677390943f2SLeandro Lupori assert(mlir::cast<fir::RecordType>(fromFirTy).getTypeList() == 678390943f2SLeandro Lupori mlir::cast<fir::RecordType>(toFirTy).getTypeList() && 679390943f2SLeandro Lupori "incompatible record types"); 680390943f2SLeandro Lupori 681390943f2SLeandro Lupori auto toStTy = mlir::cast<mlir::LLVM::LLVMStructType>(toTy); 682390943f2SLeandro Lupori mlir::Value val = rewriter.create<mlir::LLVM::UndefOp>(loc, toStTy); 683390943f2SLeandro Lupori auto indexTypeMap = toStTy.getSubelementIndexMap(); 684390943f2SLeandro Lupori assert(indexTypeMap.has_value() && "invalid record type"); 685390943f2SLeandro Lupori 686390943f2SLeandro Lupori for (auto [attr, type] : indexTypeMap.value()) { 687390943f2SLeandro Lupori int64_t index = mlir::cast<mlir::IntegerAttr>(attr).getInt(); 688390943f2SLeandro Lupori auto extVal = 689390943f2SLeandro Lupori rewriter.create<mlir::LLVM::ExtractValueOp>(loc, op0, index); 690390943f2SLeandro Lupori val = 691390943f2SLeandro Lupori rewriter.create<mlir::LLVM::InsertValueOp>(loc, val, extVal, index); 692390943f2SLeandro Lupori } 693390943f2SLeandro Lupori 694390943f2SLeandro Lupori rewriter.replaceOp(convert, val); 695390943f2SLeandro Lupori return mlir::success(); 696390943f2SLeandro Lupori } 697390943f2SLeandro Lupori 698fac349a1SChristian Sigg if (mlir::isa<fir::LogicalType>(fromFirTy) || 699fac349a1SChristian Sigg mlir::isa<fir::LogicalType>(toFirTy)) { 700f9e995b4SSlava Zakharin // By specification fir::LogicalType value may be any number, 701f9e995b4SSlava Zakharin // where non-zero value represents .true. and zero value represents 702f9e995b4SSlava Zakharin // .false. 703f9e995b4SSlava Zakharin // 704f9e995b4SSlava Zakharin // integer<->logical conversion requires value normalization. 705f9e995b4SSlava Zakharin // Conversion from wide logical to narrow logical must set the result 706f9e995b4SSlava Zakharin // to non-zero iff the input is non-zero - the easiest way to implement 707f9e995b4SSlava Zakharin // it is to compare the input agains zero and set the result to 708f9e995b4SSlava Zakharin // the canonical 0/1. 709f9e995b4SSlava Zakharin // Conversion from narrow logical to wide logical may be implemented 710f9e995b4SSlava Zakharin // as a zero or sign extension of the input, but it may use value 711f9e995b4SSlava Zakharin // normalization as well. 712fac349a1SChristian Sigg if (!mlir::isa<mlir::IntegerType>(fromTy) || 713fac349a1SChristian Sigg !mlir::isa<mlir::IntegerType>(toTy)) 714f9e995b4SSlava Zakharin return mlir::emitError(loc) 715f9e995b4SSlava Zakharin << "unsupported types for logical conversion: " << fromTy 716f9e995b4SSlava Zakharin << " -> " << toTy; 717f9e995b4SSlava Zakharin 718f9e995b4SSlava Zakharin // Do folding for constant inputs. 719a5ae54abSTom Eccles if (auto constVal = fir::getIntIfConstant(op0)) { 720f9e995b4SSlava Zakharin mlir::Value normVal = 721f9e995b4SSlava Zakharin genConstantIndex(loc, toTy, rewriter, *constVal ? 1 : 0); 722f9e995b4SSlava Zakharin rewriter.replaceOp(convert, normVal); 723f9e995b4SSlava Zakharin return mlir::success(); 724f9e995b4SSlava Zakharin } 725f9e995b4SSlava Zakharin 726f9e995b4SSlava Zakharin // If the input is i1, then we can just zero extend it, and 727f9e995b4SSlava Zakharin // the result will be normalized. 728f9e995b4SSlava Zakharin if (fromTy == i1Type) { 729f9e995b4SSlava Zakharin rewriter.replaceOpWithNewOp<mlir::LLVM::ZExtOp>(convert, toTy, op0); 730f9e995b4SSlava Zakharin return mlir::success(); 731f9e995b4SSlava Zakharin } 732f9e995b4SSlava Zakharin 733f9e995b4SSlava Zakharin // Compare the input with zero. 734f9e995b4SSlava Zakharin mlir::Value zero = genConstantIndex(loc, fromTy, rewriter, 0); 735f9e995b4SSlava Zakharin auto isTrue = rewriter.create<mlir::LLVM::ICmpOp>( 736f9e995b4SSlava Zakharin loc, mlir::LLVM::ICmpPredicate::ne, op0, zero); 737f9e995b4SSlava Zakharin 738f9e995b4SSlava Zakharin // Zero extend the i1 isTrue result to the required type (unless it is i1 739f9e995b4SSlava Zakharin // itself). 740f9e995b4SSlava Zakharin if (toTy != i1Type) 741f9e995b4SSlava Zakharin rewriter.replaceOpWithNewOp<mlir::LLVM::ZExtOp>(convert, toTy, isTrue); 742f9e995b4SSlava Zakharin else 743f9e995b4SSlava Zakharin rewriter.replaceOp(convert, isTrue.getResult()); 744f9e995b4SSlava Zakharin 745f9e995b4SSlava Zakharin return mlir::success(); 746f9e995b4SSlava Zakharin } 747f9e995b4SSlava Zakharin 748092cee5fSValentin Clement if (fromTy == toTy) { 749092cee5fSValentin Clement rewriter.replaceOp(convert, op0); 75044e58509SEric Schweitz return mlir::success(); 751092cee5fSValentin Clement } 752092cee5fSValentin Clement auto convertFpToFp = [&](mlir::Value val, unsigned fromBits, 753092cee5fSValentin Clement unsigned toBits, mlir::Type toTy) -> mlir::Value { 754092cee5fSValentin Clement if (fromBits == toBits) { 755092cee5fSValentin Clement // TODO: Converting between two floating-point representations with the 756092cee5fSValentin Clement // same bitwidth is not allowed for now. 757092cee5fSValentin Clement mlir::emitError(loc, 758092cee5fSValentin Clement "cannot implicitly convert between two floating-point " 759092cee5fSValentin Clement "representations of the same bitwidth"); 760092cee5fSValentin Clement return {}; 761092cee5fSValentin Clement } 762092cee5fSValentin Clement if (fromBits > toBits) 763092cee5fSValentin Clement return rewriter.create<mlir::LLVM::FPTruncOp>(loc, toTy, val); 764092cee5fSValentin Clement return rewriter.create<mlir::LLVM::FPExtOp>(loc, toTy, val); 765092cee5fSValentin Clement }; 766092cee5fSValentin Clement // Complex to complex conversion. 7673b7ec85aSJean Perier if (fir::isa_complex(fromFirTy) && fir::isa_complex(toFirTy)) { 768092cee5fSValentin Clement // Special case: handle the conversion of a complex such that both the 769092cee5fSValentin Clement // real and imaginary parts are converted together. 770149ad3d5SShraiysh Vaishay auto ty = convertType(getComplexEleTy(convert.getValue().getType())); 7715c5af910SJeff Niu auto rp = rewriter.create<mlir::LLVM::ExtractValueOp>(loc, op0, 0); 7725c5af910SJeff Niu auto ip = rewriter.create<mlir::LLVM::ExtractValueOp>(loc, op0, 1); 773149ad3d5SShraiysh Vaishay auto nt = convertType(getComplexEleTy(convert.getRes().getType())); 774092cee5fSValentin Clement auto fromBits = mlir::LLVM::getPrimitiveTypeSizeInBits(ty); 775092cee5fSValentin Clement auto toBits = mlir::LLVM::getPrimitiveTypeSizeInBits(nt); 776092cee5fSValentin Clement auto rc = convertFpToFp(rp, fromBits, toBits, nt); 777092cee5fSValentin Clement auto ic = convertFpToFp(ip, fromBits, toBits, nt); 778092cee5fSValentin Clement auto un = rewriter.create<mlir::LLVM::UndefOp>(loc, toTy); 7795c5af910SJeff Niu auto i1 = rewriter.create<mlir::LLVM::InsertValueOp>(loc, un, rc, 0); 7805c5af910SJeff Niu rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(convert, i1, ic, 7815c5af910SJeff Niu 1); 782092cee5fSValentin Clement return mlir::success(); 783092cee5fSValentin Clement } 7843b7ec85aSJean Perier 785092cee5fSValentin Clement // Floating point to floating point conversion. 786092cee5fSValentin Clement if (isFloatingPointTy(fromTy)) { 787092cee5fSValentin Clement if (isFloatingPointTy(toTy)) { 788092cee5fSValentin Clement auto fromBits = mlir::LLVM::getPrimitiveTypeSizeInBits(fromTy); 789092cee5fSValentin Clement auto toBits = mlir::LLVM::getPrimitiveTypeSizeInBits(toTy); 790092cee5fSValentin Clement auto v = convertFpToFp(op0, fromBits, toBits, toTy); 791092cee5fSValentin Clement rewriter.replaceOp(convert, v); 792092cee5fSValentin Clement return mlir::success(); 793092cee5fSValentin Clement } 794fac349a1SChristian Sigg if (mlir::isa<mlir::IntegerType>(toTy)) { 795fc97d2e6SPeter Klausler if (toTy.isUnsignedInteger()) 796fc97d2e6SPeter Klausler rewriter.replaceOpWithNewOp<mlir::LLVM::FPToUIOp>(convert, toTy, op0); 797fc97d2e6SPeter Klausler else 798092cee5fSValentin Clement rewriter.replaceOpWithNewOp<mlir::LLVM::FPToSIOp>(convert, toTy, op0); 799092cee5fSValentin Clement return mlir::success(); 800092cee5fSValentin Clement } 801fac349a1SChristian Sigg } else if (mlir::isa<mlir::IntegerType>(fromTy)) { 802092cee5fSValentin Clement // Integer to integer conversion. 803fac349a1SChristian Sigg if (mlir::isa<mlir::IntegerType>(toTy)) { 804092cee5fSValentin Clement auto fromBits = mlir::LLVM::getPrimitiveTypeSizeInBits(fromTy); 805092cee5fSValentin Clement auto toBits = mlir::LLVM::getPrimitiveTypeSizeInBits(toTy); 806092cee5fSValentin Clement assert(fromBits != toBits); 807092cee5fSValentin Clement if (fromBits > toBits) { 808092cee5fSValentin Clement rewriter.replaceOpWithNewOp<mlir::LLVM::TruncOp>(convert, toTy, op0); 809092cee5fSValentin Clement return mlir::success(); 810092cee5fSValentin Clement } 811fc97d2e6SPeter Klausler if (fromFirTy == i1Type || fromFirTy.isUnsignedInteger()) { 812c024fa4bSValentin Clement rewriter.replaceOpWithNewOp<mlir::LLVM::ZExtOp>(convert, toTy, op0); 813c024fa4bSValentin Clement return mlir::success(); 814c024fa4bSValentin Clement } 815092cee5fSValentin Clement rewriter.replaceOpWithNewOp<mlir::LLVM::SExtOp>(convert, toTy, op0); 816092cee5fSValentin Clement return mlir::success(); 817092cee5fSValentin Clement } 818092cee5fSValentin Clement // Integer to floating point conversion. 819092cee5fSValentin Clement if (isFloatingPointTy(toTy)) { 820fc97d2e6SPeter Klausler if (fromTy.isUnsignedInteger()) 821fc97d2e6SPeter Klausler rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(convert, toTy, op0); 822fc97d2e6SPeter Klausler else 823092cee5fSValentin Clement rewriter.replaceOpWithNewOp<mlir::LLVM::SIToFPOp>(convert, toTy, op0); 824092cee5fSValentin Clement return mlir::success(); 825092cee5fSValentin Clement } 826092cee5fSValentin Clement // Integer to pointer conversion. 827fac349a1SChristian Sigg if (mlir::isa<mlir::LLVM::LLVMPointerType>(toTy)) { 828092cee5fSValentin Clement rewriter.replaceOpWithNewOp<mlir::LLVM::IntToPtrOp>(convert, toTy, op0); 829092cee5fSValentin Clement return mlir::success(); 830092cee5fSValentin Clement } 831fac349a1SChristian Sigg } else if (mlir::isa<mlir::LLVM::LLVMPointerType>(fromTy)) { 832092cee5fSValentin Clement // Pointer to integer conversion. 833fac349a1SChristian Sigg if (mlir::isa<mlir::IntegerType>(toTy)) { 834092cee5fSValentin Clement rewriter.replaceOpWithNewOp<mlir::LLVM::PtrToIntOp>(convert, toTy, op0); 835092cee5fSValentin Clement return mlir::success(); 836092cee5fSValentin Clement } 837092cee5fSValentin Clement // Pointer to pointer conversion. 838fac349a1SChristian Sigg if (mlir::isa<mlir::LLVM::LLVMPointerType>(toTy)) { 839092cee5fSValentin Clement rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(convert, toTy, op0); 840092cee5fSValentin Clement return mlir::success(); 841092cee5fSValentin Clement } 842092cee5fSValentin Clement } 843092cee5fSValentin Clement return emitError(loc) << "cannot convert " << fromTy << " to " << toTy; 844092cee5fSValentin Clement } 845092cee5fSValentin Clement }; 846092cee5fSValentin Clement 8474ccd57ddSjeanPerier /// `fir.type_info` operation has no specific CodeGen. The operation is 8484ccd57ddSjeanPerier /// only used to carry information during FIR to FIR passes. It may be used 8494ccd57ddSjeanPerier /// in the future to generate the runtime type info data structures instead 8504ccd57ddSjeanPerier /// of generating them in lowering. 851e9639e9cSValentin Clement (バレンタイン クレメン) struct TypeInfoOpConversion : public fir::FIROpConversion<fir::TypeInfoOp> { 8529534e361SValentin Clement using FIROpConversion::FIROpConversion; 8539534e361SValentin Clement 854db791b27SRamkumar Ramachandra llvm::LogicalResult 8554ccd57ddSjeanPerier matchAndRewrite(fir::TypeInfoOp op, OpAdaptor, 8569534e361SValentin Clement mlir::ConversionPatternRewriter &rewriter) const override { 8576393d2eaSValentin Clement rewriter.eraseOp(op); 8586393d2eaSValentin Clement return mlir::success(); 8599534e361SValentin Clement } 8609534e361SValentin Clement }; 8619534e361SValentin Clement 8626393d2eaSValentin Clement /// `fir.dt_entry` operation has no specific CodeGen. The operation is only used 8636393d2eaSValentin Clement /// to carry information during FIR to FIR passes. 864e9639e9cSValentin Clement (バレンタイン クレメン) struct DTEntryOpConversion : public fir::FIROpConversion<fir::DTEntryOp> { 8659534e361SValentin Clement using FIROpConversion::FIROpConversion; 8669534e361SValentin Clement 867db791b27SRamkumar Ramachandra llvm::LogicalResult 8686393d2eaSValentin Clement matchAndRewrite(fir::DTEntryOp op, OpAdaptor, 8699534e361SValentin Clement mlir::ConversionPatternRewriter &rewriter) const override { 8706393d2eaSValentin Clement rewriter.eraseOp(op); 8716393d2eaSValentin Clement return mlir::success(); 8729534e361SValentin Clement } 8739534e361SValentin Clement }; 8749534e361SValentin Clement 875677df8c7SValentin Clement /// Lower `fir.global_len` operation. 876e9639e9cSValentin Clement (バレンタイン クレメン) struct GlobalLenOpConversion : public fir::FIROpConversion<fir::GlobalLenOp> { 877677df8c7SValentin Clement using FIROpConversion::FIROpConversion; 878677df8c7SValentin Clement 879db791b27SRamkumar Ramachandra llvm::LogicalResult 880677df8c7SValentin Clement matchAndRewrite(fir::GlobalLenOp globalLen, OpAdaptor adaptor, 881677df8c7SValentin Clement mlir::ConversionPatternRewriter &rewriter) const override { 8827ce8c6fcSKiran Chandramohan TODO(globalLen.getLoc(), "fir.global_len codegen"); 88344e58509SEric Schweitz return mlir::failure(); 884677df8c7SValentin Clement } 885677df8c7SValentin Clement }; 886677df8c7SValentin Clement 887cdc476abSDiana Picus /// Lower fir.len_param_index 888cdc476abSDiana Picus struct LenParamIndexOpConversion 889e9639e9cSValentin Clement (バレンタイン クレメン) : public fir::FIROpConversion<fir::LenParamIndexOp> { 890cdc476abSDiana Picus using FIROpConversion::FIROpConversion; 891cdc476abSDiana Picus 892cdc476abSDiana Picus // FIXME: this should be specialized by the runtime target 893db791b27SRamkumar Ramachandra llvm::LogicalResult 894cdc476abSDiana Picus matchAndRewrite(fir::LenParamIndexOp lenp, OpAdaptor, 895cdc476abSDiana Picus mlir::ConversionPatternRewriter &rewriter) const override { 8967ce8c6fcSKiran Chandramohan TODO(lenp.getLoc(), "fir.len_param_index codegen"); 897cdc476abSDiana Picus } 898cdc476abSDiana Picus }; 899cdc476abSDiana Picus 900dc48849fSKiran Chandramohan /// Convert `!fir.emboxchar<!fir.char<KIND, ?>, #n>` into a sequence of 901dc48849fSKiran Chandramohan /// instructions that generate `!llvm.struct<(ptr<ik>, i64)>`. The 1st element 902dc48849fSKiran Chandramohan /// in this struct is a pointer. Its type is determined from `KIND`. The 2nd 903dc48849fSKiran Chandramohan /// element is the length of the character buffer (`#n`). 904e9639e9cSValentin Clement (バレンタイン クレメン) struct EmboxCharOpConversion : public fir::FIROpConversion<fir::EmboxCharOp> { 90531246187SValentin Clement using FIROpConversion::FIROpConversion; 90631246187SValentin Clement 907db791b27SRamkumar Ramachandra llvm::LogicalResult 908dc48849fSKiran Chandramohan matchAndRewrite(fir::EmboxCharOp emboxChar, OpAdaptor adaptor, 90931246187SValentin Clement mlir::ConversionPatternRewriter &rewriter) const override { 910dc48849fSKiran Chandramohan mlir::ValueRange operands = adaptor.getOperands(); 911dc48849fSKiran Chandramohan 912dc48849fSKiran Chandramohan mlir::Value charBuffer = operands[0]; 913dc48849fSKiran Chandramohan mlir::Value charBufferLen = operands[1]; 914dc48849fSKiran Chandramohan 915dc48849fSKiran Chandramohan mlir::Location loc = emboxChar.getLoc(); 916dc48849fSKiran Chandramohan mlir::Type llvmStructTy = convertType(emboxChar.getType()); 917dc48849fSKiran Chandramohan auto llvmStruct = rewriter.create<mlir::LLVM::UndefOp>(loc, llvmStructTy); 918dc48849fSKiran Chandramohan 919dc48849fSKiran Chandramohan mlir::Type lenTy = 920fac349a1SChristian Sigg mlir::cast<mlir::LLVM::LLVMStructType>(llvmStructTy).getBody()[1]; 921dc48849fSKiran Chandramohan mlir::Value lenAfterCast = integerCast(loc, rewriter, lenTy, charBufferLen); 922dc48849fSKiran Chandramohan 923959de150SJean Perier mlir::Type addrTy = 924fac349a1SChristian Sigg mlir::cast<mlir::LLVM::LLVMStructType>(llvmStructTy).getBody()[0]; 925959de150SJean Perier if (addrTy != charBuffer.getType()) 926959de150SJean Perier charBuffer = 927959de150SJean Perier rewriter.create<mlir::LLVM::BitcastOp>(loc, addrTy, charBuffer); 928959de150SJean Perier 929dc48849fSKiran Chandramohan auto insertBufferOp = rewriter.create<mlir::LLVM::InsertValueOp>( 9305c5af910SJeff Niu loc, llvmStruct, charBuffer, 0); 931dc48849fSKiran Chandramohan rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>( 9325c5af910SJeff Niu emboxChar, insertBufferOp, lenAfterCast, 1); 933dc48849fSKiran Chandramohan 93444e58509SEric Schweitz return mlir::success(); 93531246187SValentin Clement } 93631246187SValentin Clement }; 937c2acd453SAlexisPerry } // namespace 938c2acd453SAlexisPerry 939e5092c30SValentin Clement (バレンタイン クレメン) template <typename ModuleOp> 9404f62a183SjeanPerier static mlir::SymbolRefAttr 941e5092c30SValentin Clement (バレンタイン クレメン) getMallocInModule(ModuleOp mod, fir::AllocMemOp op, 942e5092c30SValentin Clement (バレンタイン クレメン) mlir::ConversionPatternRewriter &rewriter) { 9434f62a183SjeanPerier static constexpr char mallocName[] = "malloc"; 944e5092c30SValentin Clement (バレンタイン クレメン) if (auto mallocFunc = 945e5092c30SValentin Clement (バレンタイン クレメン) mod.template lookupSymbol<mlir::LLVM::LLVMFuncOp>(mallocName)) 9464f62a183SjeanPerier return mlir::SymbolRefAttr::get(mallocFunc); 947e5092c30SValentin Clement (バレンタイン クレメン) if (auto userMalloc = 948e5092c30SValentin Clement (バレンタイン クレメン) mod.template lookupSymbol<mlir::func::FuncOp>(mallocName)) 9494f62a183SjeanPerier return mlir::SymbolRefAttr::get(userMalloc); 950e5092c30SValentin Clement (バレンタイン クレメン) 951e5092c30SValentin Clement (バレンタイン クレメン) mlir::OpBuilder moduleBuilder(mod.getBodyRegion()); 952c2acd453SAlexisPerry auto indexType = mlir::IntegerType::get(op.getContext(), 64); 9534f62a183SjeanPerier auto mallocDecl = moduleBuilder.create<mlir::LLVM::LLVMFuncOp>( 9544f62a183SjeanPerier op.getLoc(), mallocName, 9558a1ce2d6SjeanPerier mlir::LLVM::LLVMFunctionType::get(getLlvmPtrType(op.getContext()), 956c2acd453SAlexisPerry indexType, 957c2acd453SAlexisPerry /*isVarArg=*/false)); 9584f62a183SjeanPerier return mlir::SymbolRefAttr::get(mallocDecl); 959c2acd453SAlexisPerry } 960c2acd453SAlexisPerry 961e5092c30SValentin Clement (バレンタイン クレメン) /// Return the LLVMFuncOp corresponding to the standard malloc call. 962e5092c30SValentin Clement (バレンタイン クレメン) static mlir::SymbolRefAttr 963e5092c30SValentin Clement (バレンタイン クレメン) getMalloc(fir::AllocMemOp op, mlir::ConversionPatternRewriter &rewriter) { 964e5092c30SValentin Clement (バレンタイン クレメン) if (auto mod = op->getParentOfType<mlir::gpu::GPUModuleOp>()) 965e5092c30SValentin Clement (バレンタイン クレメン) return getMallocInModule(mod, op, rewriter); 966e5092c30SValentin Clement (バレンタイン クレメン) auto mod = op->getParentOfType<mlir::ModuleOp>(); 967e5092c30SValentin Clement (バレンタイン クレメン) return getMallocInModule(mod, op, rewriter); 968e5092c30SValentin Clement (バレンタイン クレメン) } 969e5092c30SValentin Clement (バレンタイン クレメン) 97002f3fec3SSlava Zakharin /// Helper function for generating the LLVM IR that computes the distance 97102f3fec3SSlava Zakharin /// in bytes between adjacent elements pointed to by a pointer 97202f3fec3SSlava Zakharin /// of type \p ptrTy. The result is returned as a value of \p idxTy integer 97302f3fec3SSlava Zakharin /// type. 974c2acd453SAlexisPerry static mlir::Value 9758a1ce2d6SjeanPerier computeElementDistance(mlir::Location loc, mlir::Type llvmObjectType, 9768a1ce2d6SjeanPerier mlir::Type idxTy, 977c2acd453SAlexisPerry mlir::ConversionPatternRewriter &rewriter) { 97802f3fec3SSlava Zakharin // Note that we cannot use something like 97902f3fec3SSlava Zakharin // mlir::LLVM::getPrimitiveTypeSizeInBits() for the element type here. For 98002f3fec3SSlava Zakharin // example, it returns 10 bytes for mlir::Float80Type for targets where it 98102f3fec3SSlava Zakharin // occupies 16 bytes. Proper solution is probably to use 98202f3fec3SSlava Zakharin // mlir::DataLayout::getTypeABIAlignment(), but DataLayout is not being set 98302f3fec3SSlava Zakharin // yet (see llvm-project#57230). For the time being use the '(intptr_t)((type 98402f3fec3SSlava Zakharin // *)0 + 1)' trick for all types. The generated instructions are optimized 98502f3fec3SSlava Zakharin // into constant by the first pass of InstCombine, so it should not be a 98602f3fec3SSlava Zakharin // performance issue. 9878a1ce2d6SjeanPerier auto llvmPtrTy = ::getLlvmPtrType(llvmObjectType.getContext()); 9888a1ce2d6SjeanPerier auto nullPtr = rewriter.create<mlir::LLVM::ZeroOp>(loc, llvmPtrTy); 989bd7eff1fSMarkus Böck auto gep = rewriter.create<mlir::LLVM::GEPOp>( 9908a1ce2d6SjeanPerier loc, llvmPtrTy, llvmObjectType, nullPtr, 9918a1ce2d6SjeanPerier llvm::ArrayRef<mlir::LLVM::GEPArg>{1}); 992c2acd453SAlexisPerry return rewriter.create<mlir::LLVM::PtrToIntOp>(loc, idxTy, gep); 993c2acd453SAlexisPerry } 994c2acd453SAlexisPerry 99502f3fec3SSlava Zakharin /// Return value of the stride in bytes between adjacent elements 99602f3fec3SSlava Zakharin /// of LLVM type \p llTy. The result is returned as a value of 99702f3fec3SSlava Zakharin /// \p idxTy integer type. 99802f3fec3SSlava Zakharin static mlir::Value 99902f3fec3SSlava Zakharin genTypeStrideInBytes(mlir::Location loc, mlir::Type idxTy, 100002f3fec3SSlava Zakharin mlir::ConversionPatternRewriter &rewriter, 100102f3fec3SSlava Zakharin mlir::Type llTy) { 100202f3fec3SSlava Zakharin // Create a pointer type and use computeElementDistance(). 10038a1ce2d6SjeanPerier return computeElementDistance(loc, llTy, idxTy, rewriter); 100402f3fec3SSlava Zakharin } 100502f3fec3SSlava Zakharin 1006c2acd453SAlexisPerry namespace { 1007c2acd453SAlexisPerry /// Lower a `fir.allocmem` instruction into `llvm.call @malloc` 1008e9639e9cSValentin Clement (バレンタイン クレメン) struct AllocMemOpConversion : public fir::FIROpConversion<fir::AllocMemOp> { 1009c2acd453SAlexisPerry using FIROpConversion::FIROpConversion; 1010c2acd453SAlexisPerry 1011db791b27SRamkumar Ramachandra llvm::LogicalResult 1012c2acd453SAlexisPerry matchAndRewrite(fir::AllocMemOp heap, OpAdaptor adaptor, 1013c2acd453SAlexisPerry mlir::ConversionPatternRewriter &rewriter) const override { 1014575c9d6dSValentin Clement mlir::Type heapTy = heap.getType(); 1015c2acd453SAlexisPerry mlir::Location loc = heap.getLoc(); 1016c2acd453SAlexisPerry auto ity = lowerTy().indexType(); 1017575c9d6dSValentin Clement mlir::Type dataTy = fir::unwrapRefType(heapTy); 10188a1ce2d6SjeanPerier mlir::Type llvmObjectTy = convertObjectType(dataTy); 1019c45bd4b9SEric Schweitz if (fir::isRecordWithTypeParameters(fir::unwrapSequenceType(dataTy))) 1020c45bd4b9SEric Schweitz TODO(loc, "fir.allocmem codegen of derived type with length parameters"); 10218a1ce2d6SjeanPerier mlir::Value size = genTypeSizeInBytes(loc, ity, rewriter, llvmObjectTy); 1022ac0f4c8fSPeixinQiao if (auto scaleSize = genAllocationScaleSize(heap, ity, rewriter)) 1023ac0f4c8fSPeixinQiao size = rewriter.create<mlir::LLVM::MulOp>(loc, ity, size, scaleSize); 1024c2acd453SAlexisPerry for (mlir::Value opnd : adaptor.getOperands()) 1025c2acd453SAlexisPerry size = rewriter.create<mlir::LLVM::MulOp>( 1026c2acd453SAlexisPerry loc, ity, size, integerCast(loc, rewriter, ity, opnd)); 10274f62a183SjeanPerier heap->setAttr("callee", getMalloc(heap, rewriter)); 10288a1ce2d6SjeanPerier rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>( 1029fde3c16aSSirui Mu heap, ::getLlvmPtrType(heap.getContext()), size, 1030fde3c16aSSirui Mu addLLVMOpBundleAttrs(rewriter, heap->getAttrs(), 1)); 103144e58509SEric Schweitz return mlir::success(); 1032c2acd453SAlexisPerry } 1033c2acd453SAlexisPerry 103402f3fec3SSlava Zakharin /// Compute the allocation size in bytes of the element type of 103502f3fec3SSlava Zakharin /// \p llTy pointer type. The result is returned as a value of \p idxTy 103602f3fec3SSlava Zakharin /// integer type. 1037c2acd453SAlexisPerry mlir::Value genTypeSizeInBytes(mlir::Location loc, mlir::Type idxTy, 1038c2acd453SAlexisPerry mlir::ConversionPatternRewriter &rewriter, 1039c2acd453SAlexisPerry mlir::Type llTy) const { 10408a1ce2d6SjeanPerier return computeElementDistance(loc, llTy, idxTy, rewriter); 1041c2acd453SAlexisPerry } 1042c2acd453SAlexisPerry }; 1043c2acd453SAlexisPerry } // namespace 1044c2acd453SAlexisPerry 1045c2acd453SAlexisPerry /// Return the LLVMFuncOp corresponding to the standard free call. 1046e5092c30SValentin Clement (バレンタイン クレメン) template <typename ModuleOp> 1047e5092c30SValentin Clement (バレンタイン クレメン) static mlir::SymbolRefAttr 1048e5092c30SValentin Clement (バレンタイン クレメン) getFreeInModule(ModuleOp mod, fir::FreeMemOp op, 10494f62a183SjeanPerier mlir::ConversionPatternRewriter &rewriter) { 10504f62a183SjeanPerier static constexpr char freeName[] = "free"; 10514f62a183SjeanPerier // Check if free already defined in the module. 1052e5092c30SValentin Clement (バレンタイン クレメン) if (auto freeFunc = 1053e5092c30SValentin Clement (バレンタイン クレメン) mod.template lookupSymbol<mlir::LLVM::LLVMFuncOp>(freeName)) 10544f62a183SjeanPerier return mlir::SymbolRefAttr::get(freeFunc); 10554f62a183SjeanPerier if (auto freeDefinedByUser = 1056e5092c30SValentin Clement (バレンタイン クレメン) mod.template lookupSymbol<mlir::func::FuncOp>(freeName)) 10574f62a183SjeanPerier return mlir::SymbolRefAttr::get(freeDefinedByUser); 10584f62a183SjeanPerier // Create llvm declaration for free. 1059e5092c30SValentin Clement (バレンタイン クレメン) mlir::OpBuilder moduleBuilder(mod.getBodyRegion()); 1060c2acd453SAlexisPerry auto voidType = mlir::LLVM::LLVMVoidType::get(op.getContext()); 10614f62a183SjeanPerier auto freeDecl = moduleBuilder.create<mlir::LLVM::LLVMFuncOp>( 10624f62a183SjeanPerier rewriter.getUnknownLoc(), freeName, 1063c2acd453SAlexisPerry mlir::LLVM::LLVMFunctionType::get(voidType, 10648a1ce2d6SjeanPerier getLlvmPtrType(op.getContext()), 1065c2acd453SAlexisPerry /*isVarArg=*/false)); 10664f62a183SjeanPerier return mlir::SymbolRefAttr::get(freeDecl); 1067c2acd453SAlexisPerry } 1068c2acd453SAlexisPerry 1069e5092c30SValentin Clement (バレンタイン クレメン) static mlir::SymbolRefAttr getFree(fir::FreeMemOp op, 1070e5092c30SValentin Clement (バレンタイン クレメン) mlir::ConversionPatternRewriter &rewriter) { 1071e5092c30SValentin Clement (バレンタイン クレメン) if (auto mod = op->getParentOfType<mlir::gpu::GPUModuleOp>()) 1072e5092c30SValentin Clement (バレンタイン クレメン) return getFreeInModule(mod, op, rewriter); 1073e5092c30SValentin Clement (バレンタイン クレメン) auto mod = op->getParentOfType<mlir::ModuleOp>(); 1074e5092c30SValentin Clement (バレンタイン クレメン) return getFreeInModule(mod, op, rewriter); 1075e5092c30SValentin Clement (バレンタイン クレメン) } 1076e5092c30SValentin Clement (バレンタイン クレメン) 1077b094c737SJean Perier static unsigned getDimension(mlir::LLVM::LLVMArrayType ty) { 1078b094c737SJean Perier unsigned result = 1; 1079fac349a1SChristian Sigg for (auto eleTy = 1080fac349a1SChristian Sigg mlir::dyn_cast<mlir::LLVM::LLVMArrayType>(ty.getElementType()); 1081fac349a1SChristian Sigg eleTy; eleTy = mlir::dyn_cast<mlir::LLVM::LLVMArrayType>( 1082fac349a1SChristian Sigg eleTy.getElementType())) 1083b094c737SJean Perier ++result; 1084b094c737SJean Perier return result; 1085b094c737SJean Perier } 1086b094c737SJean Perier 1087c2acd453SAlexisPerry namespace { 1088c2acd453SAlexisPerry /// Lower a `fir.freemem` instruction into `llvm.call @free` 1089e9639e9cSValentin Clement (バレンタイン クレメン) struct FreeMemOpConversion : public fir::FIROpConversion<fir::FreeMemOp> { 1090c2acd453SAlexisPerry using FIROpConversion::FIROpConversion; 1091c2acd453SAlexisPerry 1092db791b27SRamkumar Ramachandra llvm::LogicalResult 1093c2acd453SAlexisPerry matchAndRewrite(fir::FreeMemOp freemem, OpAdaptor adaptor, 1094c2acd453SAlexisPerry mlir::ConversionPatternRewriter &rewriter) const override { 1095c2acd453SAlexisPerry mlir::Location loc = freemem.getLoc(); 10964f62a183SjeanPerier freemem->setAttr("callee", getFree(freemem, rewriter)); 1097fde3c16aSSirui Mu rewriter.create<mlir::LLVM::CallOp>( 1098fde3c16aSSirui Mu loc, mlir::TypeRange{}, mlir::ValueRange{adaptor.getHeapref()}, 1099fde3c16aSSirui Mu addLLVMOpBundleAttrs(rewriter, freemem->getAttrs(), 1)); 1100c2acd453SAlexisPerry rewriter.eraseOp(freemem); 110144e58509SEric Schweitz return mlir::success(); 1102c2acd453SAlexisPerry } 1103c2acd453SAlexisPerry }; 1104c2acd453SAlexisPerry } // namespace 1105044d5b5dSValentin Clement 1106783222efSLeandro Lupori // Convert subcomponent array indices from column-major to row-major ordering. 1107783222efSLeandro Lupori static llvm::SmallVector<mlir::Value> 1108783222efSLeandro Lupori convertSubcomponentIndices(mlir::Location loc, mlir::Type eleTy, 1109783222efSLeandro Lupori mlir::ValueRange indices, 1110783222efSLeandro Lupori mlir::Type *retTy = nullptr) { 1111783222efSLeandro Lupori llvm::SmallVector<mlir::Value> result; 1112783222efSLeandro Lupori llvm::SmallVector<mlir::Value> arrayIndices; 1113783222efSLeandro Lupori 1114783222efSLeandro Lupori auto appendArrayIndices = [&] { 1115783222efSLeandro Lupori if (arrayIndices.empty()) 1116783222efSLeandro Lupori return; 1117783222efSLeandro Lupori std::reverse(arrayIndices.begin(), arrayIndices.end()); 1118783222efSLeandro Lupori result.append(arrayIndices.begin(), arrayIndices.end()); 1119783222efSLeandro Lupori arrayIndices.clear(); 1120783222efSLeandro Lupori }; 1121783222efSLeandro Lupori 1122783222efSLeandro Lupori for (mlir::Value index : indices) { 1123783222efSLeandro Lupori // Component indices can be field index to select a component, or array 1124783222efSLeandro Lupori // index, to select an element in an array component. 1125783222efSLeandro Lupori if (auto structTy = mlir::dyn_cast<mlir::LLVM::LLVMStructType>(eleTy)) { 1126783222efSLeandro Lupori std::int64_t cstIndex = getConstantIntValue(index); 1127783222efSLeandro Lupori assert(cstIndex < (int64_t)structTy.getBody().size() && 1128783222efSLeandro Lupori "out-of-bounds struct field index"); 1129783222efSLeandro Lupori eleTy = structTy.getBody()[cstIndex]; 1130783222efSLeandro Lupori appendArrayIndices(); 1131783222efSLeandro Lupori result.push_back(index); 1132783222efSLeandro Lupori } else if (auto arrayTy = 1133783222efSLeandro Lupori mlir::dyn_cast<mlir::LLVM::LLVMArrayType>(eleTy)) { 1134783222efSLeandro Lupori eleTy = arrayTy.getElementType(); 1135783222efSLeandro Lupori arrayIndices.push_back(index); 1136783222efSLeandro Lupori } else 1137783222efSLeandro Lupori fir::emitFatalError(loc, "Unexpected subcomponent type"); 1138783222efSLeandro Lupori } 1139783222efSLeandro Lupori appendArrayIndices(); 1140783222efSLeandro Lupori if (retTy) 1141783222efSLeandro Lupori *retTy = eleTy; 1142783222efSLeandro Lupori return result; 1143783222efSLeandro Lupori } 1144783222efSLeandro Lupori 11454530273dSValentin Clement (バレンタイン クレメン) static mlir::Value genSourceFile(mlir::Location loc, mlir::ModuleOp mod, 11464530273dSValentin Clement (バレンタイン クレメン) mlir::ConversionPatternRewriter &rewriter) { 11474530273dSValentin Clement (バレンタイン クレメン) auto ptrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext()); 11484530273dSValentin Clement (バレンタイン クレメン) if (auto flc = mlir::dyn_cast<mlir::FileLineColLoc>(loc)) { 11494530273dSValentin Clement (バレンタイン クレメン) auto fn = flc.getFilename().str() + '\0'; 11504530273dSValentin Clement (バレンタイン クレメン) std::string globalName = fir::factory::uniqueCGIdent("cl", fn); 11514530273dSValentin Clement (バレンタイン クレメン) 11524530273dSValentin Clement (バレンタイン クレメン) if (auto g = mod.lookupSymbol<fir::GlobalOp>(globalName)) { 11534530273dSValentin Clement (バレンタイン クレメン) return rewriter.create<mlir::LLVM::AddressOfOp>(loc, ptrTy, g.getName()); 11544530273dSValentin Clement (バレンタイン クレメン) } else if (auto g = mod.lookupSymbol<mlir::LLVM::GlobalOp>(globalName)) { 11554530273dSValentin Clement (バレンタイン クレメン) return rewriter.create<mlir::LLVM::AddressOfOp>(loc, ptrTy, g.getName()); 11564530273dSValentin Clement (バレンタイン クレメン) } 11574530273dSValentin Clement (バレンタイン クレメン) 11584530273dSValentin Clement (バレンタイン クレメン) auto crtInsPt = rewriter.saveInsertionPoint(); 11594530273dSValentin Clement (バレンタイン クレメン) rewriter.setInsertionPoint(mod.getBody(), mod.getBody()->end()); 11604530273dSValentin Clement (バレンタイン クレメン) auto arrayTy = mlir::LLVM::LLVMArrayType::get( 11614530273dSValentin Clement (バレンタイン クレメン) mlir::IntegerType::get(rewriter.getContext(), 8), fn.size()); 11624530273dSValentin Clement (バレンタイン クレメン) mlir::LLVM::GlobalOp globalOp = rewriter.create<mlir::LLVM::GlobalOp>( 11634530273dSValentin Clement (バレンタイン クレメン) loc, arrayTy, /*constant=*/true, mlir::LLVM::Linkage::Linkonce, 11644530273dSValentin Clement (バレンタイン クレメン) globalName, mlir::Attribute()); 11654530273dSValentin Clement (バレンタイン クレメン) 11664530273dSValentin Clement (バレンタイン クレメン) mlir::Region ®ion = globalOp.getInitializerRegion(); 11674530273dSValentin Clement (バレンタイン クレメン) mlir::Block *block = rewriter.createBlock(®ion); 11684530273dSValentin Clement (バレンタイン クレメン) rewriter.setInsertionPoint(block, block->begin()); 11694530273dSValentin Clement (バレンタイン クレメン) mlir::Value constValue = rewriter.create<mlir::LLVM::ConstantOp>( 11704530273dSValentin Clement (バレンタイン クレメン) loc, arrayTy, rewriter.getStringAttr(fn)); 11714530273dSValentin Clement (バレンタイン クレメン) rewriter.create<mlir::LLVM::ReturnOp>(loc, constValue); 11724530273dSValentin Clement (バレンタイン クレメン) rewriter.restoreInsertionPoint(crtInsPt); 11734530273dSValentin Clement (バレンタイン クレメン) return rewriter.create<mlir::LLVM::AddressOfOp>(loc, ptrTy, 11744530273dSValentin Clement (バレンタイン クレメン) globalOp.getName()); 11754530273dSValentin Clement (バレンタイン クレメン) } 11764530273dSValentin Clement (バレンタイン クレメン) return rewriter.create<mlir::LLVM::ZeroOp>(loc, ptrTy); 11774530273dSValentin Clement (バレンタイン クレメン) } 11784530273dSValentin Clement (バレンタイン クレメン) 11794530273dSValentin Clement (バレンタイン クレメン) static mlir::Value genSourceLine(mlir::Location loc, 11804530273dSValentin Clement (バレンタイン クレメン) mlir::ConversionPatternRewriter &rewriter) { 11814530273dSValentin Clement (バレンタイン クレメン) if (auto flc = mlir::dyn_cast<mlir::FileLineColLoc>(loc)) 11824530273dSValentin Clement (バレンタイン クレメン) return rewriter.create<mlir::LLVM::ConstantOp>(loc, rewriter.getI32Type(), 11834530273dSValentin Clement (バレンタイン クレメン) flc.getLine()); 11844530273dSValentin Clement (バレンタイン クレメン) return rewriter.create<mlir::LLVM::ConstantOp>(loc, rewriter.getI32Type(), 0); 11854530273dSValentin Clement (バレンタイン クレメン) } 11864530273dSValentin Clement (バレンタイン クレメン) 11874530273dSValentin Clement (バレンタイン クレメン) static mlir::Value 11884530273dSValentin Clement (バレンタイン クレメン) genCUFAllocDescriptor(mlir::Location loc, 11894530273dSValentin Clement (バレンタイン クレメン) mlir::ConversionPatternRewriter &rewriter, 11904530273dSValentin Clement (バレンタイン クレメン) mlir::ModuleOp mod, fir::BaseBoxType boxTy, 11914530273dSValentin Clement (バレンタイン クレメン) const fir::LLVMTypeConverter &typeConverter) { 11924530273dSValentin Clement (バレンタイン クレメン) std::optional<mlir::DataLayout> dl = 11934530273dSValentin Clement (バレンタイン クレメン) fir::support::getOrSetDataLayout(mod, /*allowDefaultLayout=*/true); 11944530273dSValentin Clement (バレンタイン クレメン) if (!dl) 11954530273dSValentin Clement (バレンタイン クレメン) mlir::emitError(mod.getLoc(), 11964530273dSValentin Clement (バレンタイン クレメン) "module operation must carry a data layout attribute " 11974530273dSValentin Clement (バレンタイン クレメン) "to generate llvm IR from FIR"); 11984530273dSValentin Clement (バレンタイン クレメン) 11994530273dSValentin Clement (バレンタイン クレメン) mlir::Value sourceFile = genSourceFile(loc, mod, rewriter); 12004530273dSValentin Clement (バレンタイン クレメン) mlir::Value sourceLine = genSourceLine(loc, rewriter); 12014530273dSValentin Clement (バレンタイン クレメン) 12024530273dSValentin Clement (バレンタイン クレメン) mlir::MLIRContext *ctx = mod.getContext(); 12034530273dSValentin Clement (バレンタイン クレメン) 12044530273dSValentin Clement (バレンタイン クレメン) mlir::LLVM::LLVMPointerType llvmPointerType = 12054530273dSValentin Clement (バレンタイン クレメン) mlir::LLVM::LLVMPointerType::get(ctx); 12064530273dSValentin Clement (バレンタイン クレメン) mlir::Type llvmInt32Type = mlir::IntegerType::get(ctx, 32); 12074530273dSValentin Clement (バレンタイン クレメン) mlir::Type llvmIntPtrType = 12084530273dSValentin Clement (バレンタイン クレメン) mlir::IntegerType::get(ctx, typeConverter.getPointerBitwidth(0)); 12094530273dSValentin Clement (バレンタイン クレメン) auto fctTy = mlir::LLVM::LLVMFunctionType::get( 12104530273dSValentin Clement (バレンタイン クレメン) llvmPointerType, {llvmIntPtrType, llvmPointerType, llvmInt32Type}); 12114530273dSValentin Clement (バレンタイン クレメン) 12124530273dSValentin Clement (バレンタイン クレメン) auto llvmFunc = mod.lookupSymbol<mlir::LLVM::LLVMFuncOp>( 1213e650ac16SValentin Clement (バレンタイン クレメン) RTNAME_STRING(CUFAllocDescriptor)); 12144530273dSValentin Clement (バレンタイン クレメン) auto funcFunc = 1215e650ac16SValentin Clement (バレンタイン クレメン) mod.lookupSymbol<mlir::func::FuncOp>(RTNAME_STRING(CUFAllocDescriptor)); 12164530273dSValentin Clement (バレンタイン クレメン) if (!llvmFunc && !funcFunc) 12174530273dSValentin Clement (バレンタイン クレメン) mlir::OpBuilder::atBlockEnd(mod.getBody()) 1218e650ac16SValentin Clement (バレンタイン クレメン) .create<mlir::LLVM::LLVMFuncOp>(loc, RTNAME_STRING(CUFAllocDescriptor), 12194530273dSValentin Clement (バレンタイン クレメン) fctTy); 12204530273dSValentin Clement (バレンタイン クレメン) 12214530273dSValentin Clement (バレンタイン クレメン) mlir::Type structTy = typeConverter.convertBoxTypeAsStruct(boxTy); 12224530273dSValentin Clement (バレンタイン クレメン) std::size_t boxSize = dl->getTypeSizeInBits(structTy) / 8; 12234530273dSValentin Clement (バレンタイン クレメン) mlir::Value sizeInBytes = 12244530273dSValentin Clement (バレンタイン クレメン) genConstantIndex(loc, llvmIntPtrType, rewriter, boxSize); 12254530273dSValentin Clement (バレンタイン クレメン) llvm::SmallVector args = {sizeInBytes, sourceFile, sourceLine}; 12264530273dSValentin Clement (バレンタイン クレメン) return rewriter 1227e650ac16SValentin Clement (バレンタイン クレメン) .create<mlir::LLVM::CallOp>(loc, fctTy, RTNAME_STRING(CUFAllocDescriptor), 12284530273dSValentin Clement (バレンタイン クレメン) args) 12294530273dSValentin Clement (バレンタイン クレメン) .getResult(); 12304530273dSValentin Clement (バレンタイン クレメン) } 12314530273dSValentin Clement (バレンタイン クレメン) 1232af6ee580SValentin Clement /// Common base class for embox to descriptor conversion. 1233af6ee580SValentin Clement template <typename OP> 1234e9639e9cSValentin Clement (バレンタイン クレメン) struct EmboxCommonConversion : public fir::FIROpConversion<OP> { 1235e9639e9cSValentin Clement (バレンタイン クレメン) using fir::FIROpConversion<OP>::FIROpConversion; 1236e9639e9cSValentin Clement (バレンタイン クレメン) using TypePair = typename fir::FIROpConversion<OP>::TypePair; 1237af6ee580SValentin Clement 12386e85b880SValentin Clement static int getCFIAttr(fir::BaseBoxType boxTy) { 1239af6ee580SValentin Clement auto eleTy = boxTy.getEleTy(); 1240fac349a1SChristian Sigg if (mlir::isa<fir::PointerType>(eleTy)) 1241af6ee580SValentin Clement return CFI_attribute_pointer; 1242fac349a1SChristian Sigg if (mlir::isa<fir::HeapType>(eleTy)) 1243af6ee580SValentin Clement return CFI_attribute_allocatable; 1244af6ee580SValentin Clement return CFI_attribute_other; 1245af6ee580SValentin Clement } 1246af6ee580SValentin Clement 1247b881fc27SJean Perier mlir::Value getCharacterByteSize(mlir::Location loc, 1248b881fc27SJean Perier mlir::ConversionPatternRewriter &rewriter, 1249b881fc27SJean Perier fir::CharacterType charTy, 1250b881fc27SJean Perier mlir::ValueRange lenParams) const { 1251b881fc27SJean Perier auto i64Ty = mlir::IntegerType::get(rewriter.getContext(), 64); 1252b881fc27SJean Perier mlir::Value size = 1253b881fc27SJean Perier genTypeStrideInBytes(loc, i64Ty, rewriter, this->convertType(charTy)); 1254b881fc27SJean Perier if (charTy.hasConstantLen()) 1255b881fc27SJean Perier return size; // Length accounted for in the genTypeStrideInBytes GEP. 1256b881fc27SJean Perier // Otherwise, multiply the single character size by the length. 1257b881fc27SJean Perier assert(!lenParams.empty()); 1258e9639e9cSValentin Clement (バレンタイン クレメン) auto len64 = fir::FIROpConversion<OP>::integerCast(loc, rewriter, i64Ty, 1259b881fc27SJean Perier lenParams.back()); 1260b881fc27SJean Perier return rewriter.create<mlir::LLVM::MulOp>(loc, i64Ty, size, len64); 1261b881fc27SJean Perier } 1262b881fc27SJean Perier 1263af6ee580SValentin Clement // Get the element size and CFI type code of the boxed value. 1264af6ee580SValentin Clement std::tuple<mlir::Value, mlir::Value> getSizeAndTypeCode( 1265af6ee580SValentin Clement mlir::Location loc, mlir::ConversionPatternRewriter &rewriter, 1266af6ee580SValentin Clement mlir::Type boxEleTy, mlir::ValueRange lenParams = {}) const { 126702f3fec3SSlava Zakharin auto i64Ty = mlir::IntegerType::get(rewriter.getContext(), 64); 1268bddd7a64SV Donaldson if (auto eleTy = fir::dyn_cast_ptrEleTy(boxEleTy)) 1269bddd7a64SV Donaldson boxEleTy = eleTy; 1270fac349a1SChristian Sigg if (auto seqTy = mlir::dyn_cast<fir::SequenceType>(boxEleTy)) 1271bddd7a64SV Donaldson return getSizeAndTypeCode(loc, rewriter, seqTy.getEleTy(), lenParams); 1272fac349a1SChristian Sigg if (mlir::isa<mlir::NoneType>( 1273fac349a1SChristian Sigg boxEleTy)) // unlimited polymorphic or assumed type 1274bddd7a64SV Donaldson return {rewriter.create<mlir::LLVM::ConstantOp>(loc, i64Ty, 0), 1275bddd7a64SV Donaldson this->genConstantOffset(loc, rewriter, CFI_type_other)}; 1276bddd7a64SV Donaldson mlir::Value typeCodeVal = this->genConstantOffset( 1277bddd7a64SV Donaldson loc, rewriter, 1278bddd7a64SV Donaldson fir::getTypeCode(boxEleTy, this->lowerTy().getKindMap())); 1279fac349a1SChristian Sigg if (fir::isa_integer(boxEleTy) || 1280fac349a1SChristian Sigg mlir::dyn_cast<fir::LogicalType>(boxEleTy) || fir::isa_real(boxEleTy) || 1281fac349a1SChristian Sigg fir::isa_complex(boxEleTy)) 1282bddd7a64SV Donaldson return {genTypeStrideInBytes(loc, i64Ty, rewriter, 1283bddd7a64SV Donaldson this->convertType(boxEleTy)), 1284bddd7a64SV Donaldson typeCodeVal}; 1285fac349a1SChristian Sigg if (auto charTy = mlir::dyn_cast<fir::CharacterType>(boxEleTy)) 1286b881fc27SJean Perier return {getCharacterByteSize(loc, rewriter, charTy, lenParams), 1287b881fc27SJean Perier typeCodeVal}; 1288af6ee580SValentin Clement if (fir::isa_ref_type(boxEleTy)) { 12898a1ce2d6SjeanPerier auto ptrTy = ::getLlvmPtrType(rewriter.getContext()); 1290bddd7a64SV Donaldson return {genTypeStrideInBytes(loc, i64Ty, rewriter, ptrTy), typeCodeVal}; 1291af6ee580SValentin Clement } 1292fac349a1SChristian Sigg if (mlir::isa<fir::RecordType>(boxEleTy)) 1293bddd7a64SV Donaldson return {genTypeStrideInBytes(loc, i64Ty, rewriter, 1294bddd7a64SV Donaldson this->convertType(boxEleTy)), 1295bddd7a64SV Donaldson typeCodeVal}; 1296af6ee580SValentin Clement fir::emitFatalError(loc, "unhandled type in fir.box code generation"); 1297af6ee580SValentin Clement } 1298af6ee580SValentin Clement 1299af6ee580SValentin Clement /// Basic pattern to write a field in the descriptor 1300af6ee580SValentin Clement mlir::Value insertField(mlir::ConversionPatternRewriter &rewriter, 1301af6ee580SValentin Clement mlir::Location loc, mlir::Value dest, 13025c5af910SJeff Niu llvm::ArrayRef<std::int64_t> fldIndexes, 130344e58509SEric Schweitz mlir::Value value, bool bitcast = false) const { 1304af6ee580SValentin Clement auto boxTy = dest.getType(); 1305af6ee580SValentin Clement auto fldTy = this->getBoxEleTy(boxTy, fldIndexes); 13068a1ce2d6SjeanPerier if (!bitcast) 1307af6ee580SValentin Clement value = this->integerCast(loc, rewriter, fldTy, value); 13088a1ce2d6SjeanPerier // bitcast are no-ops with LLVM opaque pointers. 13095c5af910SJeff Niu return rewriter.create<mlir::LLVM::InsertValueOp>(loc, dest, value, 13105c5af910SJeff Niu fldIndexes); 1311af6ee580SValentin Clement } 1312af6ee580SValentin Clement 1313af6ee580SValentin Clement inline mlir::Value 1314af6ee580SValentin Clement insertBaseAddress(mlir::ConversionPatternRewriter &rewriter, 1315af6ee580SValentin Clement mlir::Location loc, mlir::Value dest, 1316af6ee580SValentin Clement mlir::Value base) const { 13171f551032SValentin Clement return insertField(rewriter, loc, dest, {kAddrPosInBox}, base, 13181f551032SValentin Clement /*bitCast=*/true); 13191f551032SValentin Clement } 13201f551032SValentin Clement 13211f551032SValentin Clement inline mlir::Value insertLowerBound(mlir::ConversionPatternRewriter &rewriter, 13221f551032SValentin Clement mlir::Location loc, mlir::Value dest, 13231f551032SValentin Clement unsigned dim, mlir::Value lb) const { 13241f551032SValentin Clement return insertField(rewriter, loc, dest, 13251f551032SValentin Clement {kDimsPosInBox, dim, kDimLowerBoundPos}, lb); 13261f551032SValentin Clement } 13271f551032SValentin Clement 13281f551032SValentin Clement inline mlir::Value insertExtent(mlir::ConversionPatternRewriter &rewriter, 13291f551032SValentin Clement mlir::Location loc, mlir::Value dest, 13301f551032SValentin Clement unsigned dim, mlir::Value extent) const { 13311f551032SValentin Clement return insertField(rewriter, loc, dest, {kDimsPosInBox, dim, kDimExtentPos}, 13321f551032SValentin Clement extent); 13331f551032SValentin Clement } 13341f551032SValentin Clement 13351f551032SValentin Clement inline mlir::Value insertStride(mlir::ConversionPatternRewriter &rewriter, 13361f551032SValentin Clement mlir::Location loc, mlir::Value dest, 13371f551032SValentin Clement unsigned dim, mlir::Value stride) const { 13381f551032SValentin Clement return insertField(rewriter, loc, dest, {kDimsPosInBox, dim, kDimStridePos}, 13391f551032SValentin Clement stride); 1340af6ee580SValentin Clement } 1341af6ee580SValentin Clement 1342af6ee580SValentin Clement /// Get the address of the type descriptor global variable that was created by 1343af6ee580SValentin Clement /// lowering for derived type \p recType. 1344e93d2266SValentin Clement (バレンタイン クレメン) template <typename ModOpTy> 1345e93d2266SValentin Clement (バレンタイン クレメン) mlir::Value 1346e93d2266SValentin Clement (バレンタイン クレメン) getTypeDescriptor(ModOpTy mod, mlir::ConversionPatternRewriter &rewriter, 1347e93d2266SValentin Clement (バレンタイン クレメン) mlir::Location loc, fir::RecordType recType) const { 1348013160f6SJean Perier std::string name = 1349cfd4c180SSlava Zakharin this->options.typeDescriptorsRenamedForAssembly 1350cfd4c180SSlava Zakharin ? fir::NameUniquer::getTypeDescriptorAssemblyName(recType.getName()) 1351cfd4c180SSlava Zakharin : fir::NameUniquer::getTypeDescriptorName(recType.getName()); 13528a1ce2d6SjeanPerier mlir::Type llvmPtrTy = ::getLlvmPtrType(mod.getContext()); 1353c1b7e9c9SValentin Clement if (auto global = mod.template lookupSymbol<fir::GlobalOp>(name)) { 13548a1ce2d6SjeanPerier return rewriter.create<mlir::LLVM::AddressOfOp>(loc, llvmPtrTy, 1355feeee78aSJacques Pienaar global.getSymName()); 1356af6ee580SValentin Clement } 1357c1b7e9c9SValentin Clement if (auto global = mod.template lookupSymbol<mlir::LLVM::GlobalOp>(name)) { 1358af6ee580SValentin Clement // The global may have already been translated to LLVM. 13598a1ce2d6SjeanPerier return rewriter.create<mlir::LLVM::AddressOfOp>(loc, llvmPtrTy, 1360feeee78aSJacques Pienaar global.getSymName()); 1361af6ee580SValentin Clement } 13627dd7ccd2SJean Perier // Type info derived types do not have type descriptors since they are the 13637dd7ccd2SJean Perier // types defining type descriptors. 1364013160f6SJean Perier if (!this->options.ignoreMissingTypeDescriptors && 1365013160f6SJean Perier !fir::NameUniquer::belongsToModule( 1366013160f6SJean Perier name, Fortran::semantics::typeInfoBuiltinModule)) 1367013160f6SJean Perier fir::emitFatalError( 1368013160f6SJean Perier loc, "runtime derived type info descriptor was not generated"); 13698a1ce2d6SjeanPerier return rewriter.create<mlir::LLVM::ZeroOp>(loc, llvmPtrTy); 13707dd7ccd2SJean Perier } 1371af6ee580SValentin Clement 1372e93d2266SValentin Clement (バレンタイン クレメン) template <typename ModOpTy> 1373e93d2266SValentin Clement (バレンタイン クレメン) mlir::Value populateDescriptor(mlir::Location loc, ModOpTy mod, 1374c1b7e9c9SValentin Clement fir::BaseBoxType boxTy, mlir::Type inputType, 1375c1b7e9c9SValentin Clement mlir::ConversionPatternRewriter &rewriter, 1376c1b7e9c9SValentin Clement unsigned rank, mlir::Value eleSize, 13770def9a92SValentin Clement (バレンタイン クレメン) mlir::Value cfiTy, mlir::Value typeDesc, 137815e1e3b2SValentin Clement (バレンタイン クレメン) int allocatorIdx = kDefaultAllocator, 137915e1e3b2SValentin Clement (バレンタイン クレメン) mlir::Value extraField = {}) const { 13808a1ce2d6SjeanPerier auto llvmBoxTy = this->lowerTy().convertBoxTypeAsStruct(boxTy, rank); 1381c1b7e9c9SValentin Clement bool isUnlimitedPolymorphic = fir::isUnlimitedPolymorphicType(boxTy); 1382c97d3e5fSValentin Clement bool useInputType = fir::isPolymorphicType(boxTy) || isUnlimitedPolymorphic; 1383af6ee580SValentin Clement mlir::Value descriptor = 1384af6ee580SValentin Clement rewriter.create<mlir::LLVM::UndefOp>(loc, llvmBoxTy); 1385af6ee580SValentin Clement descriptor = 1386af6ee580SValentin Clement insertField(rewriter, loc, descriptor, {kElemLenPosInBox}, eleSize); 1387af6ee580SValentin Clement descriptor = insertField(rewriter, loc, descriptor, {kVersionPosInBox}, 1388af6ee580SValentin Clement this->genI32Constant(loc, rewriter, CFI_VERSION)); 1389af6ee580SValentin Clement descriptor = insertField(rewriter, loc, descriptor, {kRankPosInBox}, 1390af6ee580SValentin Clement this->genI32Constant(loc, rewriter, rank)); 1391af6ee580SValentin Clement descriptor = insertField(rewriter, loc, descriptor, {kTypePosInBox}, cfiTy); 1392af6ee580SValentin Clement descriptor = 1393af6ee580SValentin Clement insertField(rewriter, loc, descriptor, {kAttributePosInBox}, 1394af6ee580SValentin Clement this->genI32Constant(loc, rewriter, getCFIAttr(boxTy))); 13956df4e7c2SValentin Clement (バレンタイン クレメン) 13960538bfe7SRenaud-K const bool hasAddendum = fir::boxHasAddendum(boxTy); 13970def9a92SValentin Clement (バレンタイン クレメン) 139815e1e3b2SValentin Clement (バレンタイン クレメン) if (extraField) { 139915e1e3b2SValentin Clement (バレンタイン クレメン) // Make sure to set the addendum presence flag according to the 140015e1e3b2SValentin Clement (バレンタイン クレメン) // destination box. 140115e1e3b2SValentin Clement (バレンタイン クレメン) if (hasAddendum) { 140215e1e3b2SValentin Clement (バレンタイン クレメン) auto maskAttr = mlir::IntegerAttr::get( 140315e1e3b2SValentin Clement (バレンタイン クレメン) rewriter.getIntegerType(8, /*isSigned=*/false), 140415e1e3b2SValentin Clement (バレンタイン クレメン) llvm::APInt(8, (uint64_t)_CFI_ADDENDUM_FLAG, /*isSigned=*/false)); 140515e1e3b2SValentin Clement (バレンタイン クレメン) mlir::LLVM::ConstantOp mask = rewriter.create<mlir::LLVM::ConstantOp>( 140615e1e3b2SValentin Clement (バレンタイン クレメン) loc, rewriter.getI8Type(), maskAttr); 140715e1e3b2SValentin Clement (バレンタイン クレメン) extraField = rewriter.create<mlir::LLVM::OrOp>(loc, extraField, mask); 140815e1e3b2SValentin Clement (バレンタイン クレメン) } else { 140915e1e3b2SValentin Clement (バレンタイン クレメン) auto maskAttr = mlir::IntegerAttr::get( 141015e1e3b2SValentin Clement (バレンタイン クレメン) rewriter.getIntegerType(8, /*isSigned=*/false), 141167e19e5bSNikita Popov llvm::APInt(8, (uint64_t)~_CFI_ADDENDUM_FLAG, /*isSigned=*/true)); 141215e1e3b2SValentin Clement (バレンタイン クレメン) mlir::LLVM::ConstantOp mask = rewriter.create<mlir::LLVM::ConstantOp>( 141315e1e3b2SValentin Clement (バレンタイン クレメン) loc, rewriter.getI8Type(), maskAttr); 141415e1e3b2SValentin Clement (バレンタイン クレメン) extraField = rewriter.create<mlir::LLVM::AndOp>(loc, extraField, mask); 141515e1e3b2SValentin Clement (バレンタイン クレメン) } 141615e1e3b2SValentin Clement (バレンタイン クレメン) // Extra field value is provided so just use it. 141715e1e3b2SValentin Clement (バレンタイン クレメン) descriptor = 141815e1e3b2SValentin Clement (バレンタイン クレメン) insertField(rewriter, loc, descriptor, {kExtraPosInBox}, extraField); 141915e1e3b2SValentin Clement (バレンタイン クレメン) } else { 142015e1e3b2SValentin Clement (バレンタイン クレメン) // Compute the value of the extra field based on allocator_idx and 1421c91ba043SMichael Kruse // addendum present. 1422c91ba043SMichael Kruse unsigned extra = allocatorIdx << _CFI_ALLOCATOR_IDX_SHIFT; 14230def9a92SValentin Clement (バレンタイン クレメン) if (hasAddendum) 1424c91ba043SMichael Kruse extra |= _CFI_ADDENDUM_FLAG; 1425c91ba043SMichael Kruse descriptor = insertField(rewriter, loc, descriptor, {kExtraPosInBox}, 1426c91ba043SMichael Kruse this->genI32Constant(loc, rewriter, extra)); 142715e1e3b2SValentin Clement (バレンタイン クレメン) } 1428af6ee580SValentin Clement 1429af6ee580SValentin Clement if (hasAddendum) { 1430016fbc40SValentin Clement unsigned typeDescFieldId = getTypeDescFieldId(boxTy); 1431c1b7e9c9SValentin Clement if (!typeDesc) { 1432c97d3e5fSValentin Clement if (useInputType) { 1433c1b7e9c9SValentin Clement mlir::Type innerType = fir::unwrapInnerType(inputType); 1434fac349a1SChristian Sigg if (innerType && mlir::isa<fir::RecordType>(innerType)) { 1435fac349a1SChristian Sigg auto recTy = mlir::dyn_cast<fir::RecordType>(innerType); 1436c1b7e9c9SValentin Clement typeDesc = getTypeDescriptor(mod, rewriter, loc, recTy); 1437c1b7e9c9SValentin Clement } else { 1438c1b7e9c9SValentin Clement // Unlimited polymorphic type descriptor with no record type. Set 1439c1b7e9c9SValentin Clement // type descriptor address to a clean state. 144085175eddSTobias Gysi typeDesc = rewriter.create<mlir::LLVM::ZeroOp>( 14418a1ce2d6SjeanPerier loc, ::getLlvmPtrType(mod.getContext())); 1442c1b7e9c9SValentin Clement } 1443c1b7e9c9SValentin Clement } else { 14440538bfe7SRenaud-K typeDesc = getTypeDescriptor(mod, rewriter, loc, 14450538bfe7SRenaud-K fir::unwrapIfDerived(boxTy)); 1446c1b7e9c9SValentin Clement } 1447c1b7e9c9SValentin Clement } 1448c1b7e9c9SValentin Clement if (typeDesc) 1449af6ee580SValentin Clement descriptor = 1450af6ee580SValentin Clement insertField(rewriter, loc, descriptor, {typeDescFieldId}, typeDesc, 1451af6ee580SValentin Clement /*bitCast=*/true); 1452d26a6464SjeanPerier // Always initialize the length parameter field to zero to avoid issues 1453d26a6464SjeanPerier // with uninitialized values in Fortran code trying to compare physical 1454d26a6464SjeanPerier // representation of derived types with pointer/allocatable components. 1455d26a6464SjeanPerier // This has been seen in hashing algorithms using TRANSFER. 1456d26a6464SjeanPerier mlir::Value zero = 1457d26a6464SjeanPerier genConstantIndex(loc, rewriter.getI64Type(), rewriter, 0); 1458d26a6464SjeanPerier descriptor = insertField(rewriter, loc, descriptor, 1459d26a6464SjeanPerier {getLenParamFieldId(boxTy), 0}, zero); 1460af6ee580SValentin Clement } 1461c1b7e9c9SValentin Clement return descriptor; 1462c1b7e9c9SValentin Clement } 1463c1b7e9c9SValentin Clement 1464c1b7e9c9SValentin Clement // Template used for fir::EmboxOp and fir::cg::XEmboxOp 1465c1b7e9c9SValentin Clement template <typename BOX> 1466c1b7e9c9SValentin Clement std::tuple<fir::BaseBoxType, mlir::Value, mlir::Value> 1467c1b7e9c9SValentin Clement consDescriptorPrefix(BOX box, mlir::Type inputType, 1468c1b7e9c9SValentin Clement mlir::ConversionPatternRewriter &rewriter, unsigned rank, 1469a45ca5d9SSlava Zakharin [[maybe_unused]] mlir::ValueRange substrParams, 14709f1bb307SValentin Clement mlir::ValueRange lenParams, mlir::Value sourceBox = {}, 14719f1bb307SValentin Clement mlir::Type sourceBoxType = {}) const { 1472c1b7e9c9SValentin Clement auto loc = box.getLoc(); 1473fac349a1SChristian Sigg auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(box.getType()); 1474a6924c6dSValentin Clement bool useInputType = fir::isPolymorphicType(boxTy) && 1475a6924c6dSValentin Clement !fir::isUnlimitedPolymorphicType(inputType); 1476c1b7e9c9SValentin Clement llvm::SmallVector<mlir::Value> typeparams = lenParams; 1477c1b7e9c9SValentin Clement if constexpr (!std::is_same_v<BOX, fir::EmboxOp>) { 1478c1b7e9c9SValentin Clement if (!box.getSubstr().empty() && fir::hasDynamicSize(boxTy.getEleTy())) 1479a45ca5d9SSlava Zakharin typeparams.push_back(substrParams[1]); 1480c1b7e9c9SValentin Clement } 1481c1b7e9c9SValentin Clement 14820def9a92SValentin Clement (バレンタイン クレメン) int allocatorIdx = 0; 14830def9a92SValentin Clement (バレンタイン クレメン) if constexpr (std::is_same_v<BOX, fir::EmboxOp> || 14840def9a92SValentin Clement (バレンタイン クレメン) std::is_same_v<BOX, fir::cg::XEmboxOp>) { 14850def9a92SValentin Clement (バレンタイン クレメン) if (box.getAllocatorIdx()) 14860def9a92SValentin Clement (バレンタイン クレメン) allocatorIdx = *box.getAllocatorIdx(); 14870def9a92SValentin Clement (バレンタイン クレメン) } 14880def9a92SValentin Clement (バレンタイン クレメン) 1489c1b7e9c9SValentin Clement // Write each of the fields with the appropriate values. 1490a6924c6dSValentin Clement // When emboxing an element to a polymorphic descriptor, use the 1491a6924c6dSValentin Clement // input type since the destination descriptor type has not the exact 1492a6924c6dSValentin Clement // information. 1493c1b7e9c9SValentin Clement auto [eleSize, cfiTy] = getSizeAndTypeCode( 1494c1b7e9c9SValentin Clement loc, rewriter, useInputType ? inputType : boxTy.getEleTy(), typeparams); 1495747211b7SValentin Clement 14969f1bb307SValentin Clement mlir::Value typeDesc; 149715e1e3b2SValentin Clement (バレンタイン クレメン) mlir::Value extraField; 14980b19ac83SValentin Clement // When emboxing to a polymorphic box, get the type descriptor, type code 14990b19ac83SValentin Clement // and element size from the source box if any. 15000b19ac83SValentin Clement if (fir::isPolymorphicType(boxTy) && sourceBox) { 15018a1ce2d6SjeanPerier TypePair sourceBoxTyPair = this->getBoxTypePair(sourceBoxType); 15029f1bb307SValentin Clement typeDesc = 15038a1ce2d6SjeanPerier this->loadTypeDescAddress(loc, sourceBoxTyPair, sourceBox, rewriter); 1504747211b7SValentin Clement mlir::Type idxTy = this->lowerTy().indexType(); 15058a1ce2d6SjeanPerier eleSize = this->getElementSizeFromBox(loc, idxTy, sourceBoxTyPair, 15069c84d20fSSlava Zakharin sourceBox, rewriter); 15078a1ce2d6SjeanPerier cfiTy = this->getValueFromBox(loc, sourceBoxTyPair, sourceBox, 15089c84d20fSSlava Zakharin cfiTy.getType(), rewriter, kTypePosInBox); 150915e1e3b2SValentin Clement (バレンタイン クレメン) extraField = 151015e1e3b2SValentin Clement (バレンタイン クレメン) this->getExtraFromBox(loc, sourceBoxTyPair, sourceBox, rewriter); 1511747211b7SValentin Clement } 1512e93d2266SValentin Clement (バレンタイン クレメン) 1513e93d2266SValentin Clement (バレンタイン クレメン) mlir::Value descriptor; 1514e93d2266SValentin Clement (バレンタイン クレメン) if (auto gpuMod = box->template getParentOfType<mlir::gpu::GPUModuleOp>()) 1515e93d2266SValentin Clement (バレンタイン クレメン) descriptor = populateDescriptor(loc, gpuMod, boxTy, inputType, rewriter, 1516e93d2266SValentin Clement (バレンタイン クレメン) rank, eleSize, cfiTy, typeDesc, 1517e93d2266SValentin Clement (バレンタイン クレメン) allocatorIdx, extraField); 1518e93d2266SValentin Clement (バレンタイン クレメン) else if (auto mod = box->template getParentOfType<mlir::ModuleOp>()) 1519e93d2266SValentin Clement (バレンタイン クレメン) descriptor = populateDescriptor(loc, mod, boxTy, inputType, rewriter, 1520e93d2266SValentin Clement (バレンタイン クレメン) rank, eleSize, cfiTy, typeDesc, 1521e93d2266SValentin Clement (バレンタイン クレメン) allocatorIdx, extraField); 1522c1b7e9c9SValentin Clement 1523c1b7e9c9SValentin Clement return {boxTy, descriptor, eleSize}; 1524c1b7e9c9SValentin Clement } 1525c1b7e9c9SValentin Clement 1526c1b7e9c9SValentin Clement std::tuple<fir::BaseBoxType, mlir::Value, mlir::Value> 1527c1b7e9c9SValentin Clement consDescriptorPrefix(fir::cg::XReboxOp box, mlir::Value loweredBox, 1528c1b7e9c9SValentin Clement mlir::ConversionPatternRewriter &rewriter, unsigned rank, 1529a45ca5d9SSlava Zakharin mlir::ValueRange substrParams, 1530c1b7e9c9SValentin Clement mlir::ValueRange lenParams, 1531c1b7e9c9SValentin Clement mlir::Value typeDesc = {}) const { 1532c1b7e9c9SValentin Clement auto loc = box.getLoc(); 1533fac349a1SChristian Sigg auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(box.getType()); 1534fac349a1SChristian Sigg auto inputBoxTy = mlir::dyn_cast<fir::BaseBoxType>(box.getBox().getType()); 15358a1ce2d6SjeanPerier auto inputBoxTyPair = this->getBoxTypePair(inputBoxTy); 1536c1b7e9c9SValentin Clement llvm::SmallVector<mlir::Value> typeparams = lenParams; 1537c1b7e9c9SValentin Clement if (!box.getSubstr().empty() && fir::hasDynamicSize(boxTy.getEleTy())) 1538a45ca5d9SSlava Zakharin typeparams.push_back(substrParams[1]); 1539c1b7e9c9SValentin Clement 1540c1b7e9c9SValentin Clement auto [eleSize, cfiTy] = 1541c1b7e9c9SValentin Clement getSizeAndTypeCode(loc, rewriter, boxTy.getEleTy(), typeparams); 1542c1b7e9c9SValentin Clement 1543959caaaaSValentin Clement // Reboxing to a polymorphic entity. eleSize and type code need to 1544f3a94ff0SValentin Clement // be retrieved from the initial box and propagated to the new box. 1545959caaaaSValentin Clement // If the initial box has an addendum, the type desc must be propagated as 1546959caaaaSValentin Clement // well. 1547959caaaaSValentin Clement if (fir::isPolymorphicType(boxTy)) { 1548c1b7e9c9SValentin Clement mlir::Type idxTy = this->lowerTy().indexType(); 15498a1ce2d6SjeanPerier eleSize = this->getElementSizeFromBox(loc, idxTy, inputBoxTyPair, 15508a1ce2d6SjeanPerier loweredBox, rewriter); 15518a1ce2d6SjeanPerier cfiTy = this->getValueFromBox(loc, inputBoxTyPair, loweredBox, 15528a1ce2d6SjeanPerier cfiTy.getType(), rewriter, kTypePosInBox); 1553959caaaaSValentin Clement // TODO: For initial box that are unlimited polymorphic entities, this 1554959caaaaSValentin Clement // code must be made conditional because unlimited polymorphic entities 1555959caaaaSValentin Clement // with intrinsic type spec does not have addendum. 15560538bfe7SRenaud-K if (fir::boxHasAddendum(inputBoxTy)) 15578a1ce2d6SjeanPerier typeDesc = this->loadTypeDescAddress(loc, inputBoxTyPair, loweredBox, 15588a1ce2d6SjeanPerier rewriter); 1559c1b7e9c9SValentin Clement } 1560c1b7e9c9SValentin Clement 156115e1e3b2SValentin Clement (バレンタイン クレメン) mlir::Value extraField = 156215e1e3b2SValentin Clement (バレンタイン クレメン) this->getExtraFromBox(loc, inputBoxTyPair, loweredBox, rewriter); 156315e1e3b2SValentin Clement (バレンタイン クレメン) 1564e93d2266SValentin Clement (バレンタイン クレメン) mlir::Value descriptor; 1565e93d2266SValentin Clement (バレンタイン クレメン) if (auto gpuMod = box->template getParentOfType<mlir::gpu::GPUModuleOp>()) 1566e93d2266SValentin Clement (バレンタイン クレメン) descriptor = 1567e93d2266SValentin Clement (バレンタイン クレメン) populateDescriptor(loc, gpuMod, boxTy, box.getBox().getType(), 1568e93d2266SValentin Clement (バレンタイン クレメン) rewriter, rank, eleSize, cfiTy, typeDesc, 1569e93d2266SValentin Clement (バレンタイン クレメン) /*allocatorIdx=*/kDefaultAllocator, extraField); 1570e93d2266SValentin Clement (バレンタイン クレメン) else if (auto mod = box->template getParentOfType<mlir::ModuleOp>()) 1571e93d2266SValentin Clement (バレンタイン クレメン) descriptor = 1572c1b7e9c9SValentin Clement populateDescriptor(loc, mod, boxTy, box.getBox().getType(), rewriter, 157315e1e3b2SValentin Clement (バレンタイン クレメン) rank, eleSize, cfiTy, typeDesc, 157415e1e3b2SValentin Clement (バレンタイン クレメン) /*allocatorIdx=*/kDefaultAllocator, extraField); 1575af6ee580SValentin Clement 1576af6ee580SValentin Clement return {boxTy, descriptor, eleSize}; 1577af6ee580SValentin Clement } 1578af6ee580SValentin Clement 1579af40f99eSJean Perier // Compute the base address of a fir.box given the indices from the slice. 1580af40f99eSJean Perier // The indices from the "outer" dimensions (every dimension after the first 15818a1ce2d6SjeanPerier // one (included) that is not a compile time constant) must have been 1582af40f99eSJean Perier // multiplied with the related extents and added together into \p outerOffset. 1583af40f99eSJean Perier mlir::Value 1584af40f99eSJean Perier genBoxOffsetGep(mlir::ConversionPatternRewriter &rewriter, mlir::Location loc, 15858a1ce2d6SjeanPerier mlir::Value base, mlir::Type llvmBaseObjectType, 15868a1ce2d6SjeanPerier mlir::Value outerOffset, mlir::ValueRange cstInteriorIndices, 1587af40f99eSJean Perier mlir::ValueRange componentIndices, 158822426110SRamkumar Ramachandra std::optional<mlir::Value> substringOffset) const { 1589bd7eff1fSMarkus Böck llvm::SmallVector<mlir::LLVM::GEPArg> gepArgs{outerOffset}; 15908a1ce2d6SjeanPerier mlir::Type resultTy = llvmBaseObjectType; 1591af40f99eSJean Perier // Fortran is column major, llvm GEP is row major: reverse the indices here. 1592af40f99eSJean Perier for (mlir::Value interiorIndex : llvm::reverse(cstInteriorIndices)) { 1593fac349a1SChristian Sigg auto arrayTy = mlir::dyn_cast<mlir::LLVM::LLVMArrayType>(resultTy); 1594af40f99eSJean Perier if (!arrayTy) 1595af40f99eSJean Perier fir::emitFatalError( 1596af40f99eSJean Perier loc, 1597af40f99eSJean Perier "corrupted GEP generated being generated in fir.embox/fir.rebox"); 1598af40f99eSJean Perier resultTy = arrayTy.getElementType(); 1599af40f99eSJean Perier gepArgs.push_back(interiorIndex); 16006c89c531SEric Schweitz } 1601783222efSLeandro Lupori llvm::SmallVector<mlir::Value> gepIndices = 1602783222efSLeandro Lupori convertSubcomponentIndices(loc, resultTy, componentIndices, &resultTy); 1603783222efSLeandro Lupori gepArgs.append(gepIndices.begin(), gepIndices.end()); 1604af40f99eSJean Perier if (substringOffset) { 1605fac349a1SChristian Sigg if (auto arrayTy = mlir::dyn_cast<mlir::LLVM::LLVMArrayType>(resultTy)) { 1606af40f99eSJean Perier gepArgs.push_back(*substringOffset); 1607af40f99eSJean Perier resultTy = arrayTy.getElementType(); 1608af40f99eSJean Perier } else { 1609af40f99eSJean Perier // If the CHARACTER length is dynamic, the whole base type should have 1610af40f99eSJean Perier // degenerated to an llvm.ptr<i[width]>, and there should not be any 1611af40f99eSJean Perier // cstInteriorIndices/componentIndices. The substring offset can be 1612af40f99eSJean Perier // added to the outterOffset since it applies on the same LLVM type. 1613af40f99eSJean Perier if (gepArgs.size() != 1) 1614af40f99eSJean Perier fir::emitFatalError(loc, 1615af40f99eSJean Perier "corrupted substring GEP in fir.embox/fir.rebox"); 1616392651a7SKazu Hirata mlir::Type outterOffsetTy = 1617392651a7SKazu Hirata llvm::cast<mlir::Value>(gepArgs[0]).getType(); 1618af40f99eSJean Perier mlir::Value cast = 1619af40f99eSJean Perier this->integerCast(loc, rewriter, outterOffsetTy, *substringOffset); 1620af40f99eSJean Perier 1621bd7eff1fSMarkus Böck gepArgs[0] = rewriter.create<mlir::LLVM::AddOp>( 1622392651a7SKazu Hirata loc, outterOffsetTy, llvm::cast<mlir::Value>(gepArgs[0]), cast); 1623af40f99eSJean Perier } 1624af40f99eSJean Perier } 16258a1ce2d6SjeanPerier mlir::Type llvmPtrTy = ::getLlvmPtrType(resultTy.getContext()); 16268a1ce2d6SjeanPerier return rewriter.create<mlir::LLVM::GEPOp>( 16278a1ce2d6SjeanPerier loc, llvmPtrTy, llvmBaseObjectType, base, gepArgs); 1628af40f99eSJean Perier } 1629af40f99eSJean Perier 1630af40f99eSJean Perier template <typename BOX> 1631af40f99eSJean Perier void 1632af40f99eSJean Perier getSubcomponentIndices(BOX xbox, mlir::Value memref, 1633af40f99eSJean Perier mlir::ValueRange operands, 1634af40f99eSJean Perier mlir::SmallVectorImpl<mlir::Value> &indices) const { 1635af40f99eSJean Perier // For each field in the path add the offset to base via the args list. 1636af40f99eSJean Perier // In the most general case, some offsets must be computed since 1637af40f99eSJean Perier // they are not be known until runtime. 1638af40f99eSJean Perier if (fir::hasDynamicSize(fir::unwrapSequenceType( 1639af40f99eSJean Perier fir::unwrapPassByRefType(memref.getType())))) 1640af40f99eSJean Perier TODO(xbox.getLoc(), 1641af40f99eSJean Perier "fir.embox codegen dynamic size component in derived type"); 1642d8b672daSjeanPerier indices.append(operands.begin() + xbox.getSubcomponentOperandIndex(), 1643d8b672daSjeanPerier operands.begin() + xbox.getSubcomponentOperandIndex() + 1644a89b0480SValentin Clement xbox.getSubcomponent().size()); 16451f551032SValentin Clement } 16461f551032SValentin Clement 1647de2811eeSJean Perier static bool isInGlobalOp(mlir::ConversionPatternRewriter &rewriter) { 1648de2811eeSJean Perier auto *thisBlock = rewriter.getInsertionBlock(); 1649de2811eeSJean Perier return thisBlock && 1650de2811eeSJean Perier mlir::isa<mlir::LLVM::GlobalOp>(thisBlock->getParentOp()); 1651de2811eeSJean Perier } 1652de2811eeSJean Perier 1653af6ee580SValentin Clement /// If the embox is not in a globalOp body, allocate storage for the box; 1654af6ee580SValentin Clement /// store the value inside and return the generated alloca. Return the input 1655af6ee580SValentin Clement /// value otherwise. 1656af6ee580SValentin Clement mlir::Value 1657af6ee580SValentin Clement placeInMemoryIfNotGlobalInit(mlir::ConversionPatternRewriter &rewriter, 16589c84d20fSSlava Zakharin mlir::Location loc, mlir::Type boxTy, 16594530273dSValentin Clement (バレンタイン クレメン) mlir::Value boxValue, 16604530273dSValentin Clement (バレンタイン クレメン) bool needDeviceAllocation = false) const { 1661de2811eeSJean Perier if (isInGlobalOp(rewriter)) 1662af6ee580SValentin Clement return boxValue; 16638a1ce2d6SjeanPerier mlir::Type llvmBoxTy = boxValue.getType(); 16644530273dSValentin Clement (バレンタイン クレメン) mlir::Value storage; 16654530273dSValentin Clement (バレンタイン クレメン) if (needDeviceAllocation) { 16664530273dSValentin Clement (バレンタイン クレメン) auto mod = boxValue.getDefiningOp()->getParentOfType<mlir::ModuleOp>(); 16674530273dSValentin Clement (バレンタイン クレメン) auto baseBoxTy = mlir::dyn_cast<fir::BaseBoxType>(boxTy); 16684530273dSValentin Clement (バレンタイン クレメン) storage = 16694530273dSValentin Clement (バレンタイン クレメン) genCUFAllocDescriptor(loc, rewriter, mod, baseBoxTy, this->lowerTy()); 16704530273dSValentin Clement (バレンタイン クレメン) } else { 16714530273dSValentin Clement (バレンタイン クレメン) storage = this->genAllocaAndAddrCastWithType(loc, llvmBoxTy, defaultAlign, 16724530273dSValentin Clement (バレンタイン クレメン) rewriter); 16734530273dSValentin Clement (バレンタイン クレメン) } 16744530273dSValentin Clement (バレンタイン クレメン) auto storeOp = rewriter.create<mlir::LLVM::StoreOp>(loc, boxValue, storage); 16759c84d20fSSlava Zakharin this->attachTBAATag(storeOp, boxTy, boxTy, nullptr); 16764530273dSValentin Clement (バレンタイン クレメン) return storage; 1677af6ee580SValentin Clement } 1678af6ee580SValentin Clement 16791f551032SValentin Clement /// Compute the extent of a triplet slice (lb:ub:step). 1680*0b80491cSSlava Zakharin mlir::Value computeTripletExtent(mlir::ConversionPatternRewriter &rewriter, 1681*0b80491cSSlava Zakharin mlir::Location loc, mlir::Value lb, 1682*0b80491cSSlava Zakharin mlir::Value ub, mlir::Value step, 1683*0b80491cSSlava Zakharin mlir::Value zero, mlir::Type type) const { 1684*0b80491cSSlava Zakharin lb = this->integerCast(loc, rewriter, type, lb); 1685*0b80491cSSlava Zakharin ub = this->integerCast(loc, rewriter, type, ub); 1686*0b80491cSSlava Zakharin step = this->integerCast(loc, rewriter, type, step); 1687*0b80491cSSlava Zakharin zero = this->integerCast(loc, rewriter, type, zero); 16881f551032SValentin Clement mlir::Value extent = rewriter.create<mlir::LLVM::SubOp>(loc, type, ub, lb); 16891f551032SValentin Clement extent = rewriter.create<mlir::LLVM::AddOp>(loc, type, extent, step); 16901f551032SValentin Clement extent = rewriter.create<mlir::LLVM::SDivOp>(loc, type, extent, step); 16911f551032SValentin Clement // If the resulting extent is negative (`ub-lb` and `step` have different 16921f551032SValentin Clement // signs), zero must be returned instead. 16931f551032SValentin Clement auto cmp = rewriter.create<mlir::LLVM::ICmpOp>( 16941f551032SValentin Clement loc, mlir::LLVM::ICmpPredicate::sgt, extent, zero); 16951f551032SValentin Clement return rewriter.create<mlir::LLVM::SelectOp>(loc, cmp, extent, zero); 16961f551032SValentin Clement } 1697*0b80491cSSlava Zakharin }; 16981f551032SValentin Clement 1699af6ee580SValentin Clement /// Create a generic box on a memory reference. This conversions lowers the 1700af6ee580SValentin Clement /// abstract box to the appropriate, initialized descriptor. 1701af6ee580SValentin Clement struct EmboxOpConversion : public EmboxCommonConversion<fir::EmboxOp> { 1702af6ee580SValentin Clement using EmboxCommonConversion::EmboxCommonConversion; 1703af6ee580SValentin Clement 1704db791b27SRamkumar Ramachandra llvm::LogicalResult 1705af6ee580SValentin Clement matchAndRewrite(fir::EmboxOp embox, OpAdaptor adaptor, 1706af6ee580SValentin Clement mlir::ConversionPatternRewriter &rewriter) const override { 170712d26ce9SValentin Clement mlir::ValueRange operands = adaptor.getOperands(); 17089f1bb307SValentin Clement mlir::Value sourceBox; 17099f1bb307SValentin Clement mlir::Type sourceBoxType; 17109f1bb307SValentin Clement if (embox.getSourceBox()) { 1711d8b672daSjeanPerier sourceBox = operands[embox.getSourceBoxOperandIndex()]; 17129f1bb307SValentin Clement sourceBoxType = embox.getSourceBox().getType(); 17139f1bb307SValentin Clement } 1714af6ee580SValentin Clement assert(!embox.getShape() && "There should be no dims on this embox op"); 171512d26ce9SValentin Clement auto [boxTy, dest, eleSize] = consDescriptorPrefix( 1716c1b7e9c9SValentin Clement embox, fir::unwrapRefType(embox.getMemref().getType()), rewriter, 1717a45ca5d9SSlava Zakharin /*rank=*/0, /*substrParams=*/mlir::ValueRange{}, 1718a45ca5d9SSlava Zakharin adaptor.getTypeparams(), sourceBox, sourceBoxType); 171912d26ce9SValentin Clement dest = insertBaseAddress(rewriter, embox.getLoc(), dest, operands[0]); 17200538bfe7SRenaud-K if (fir::isDerivedTypeWithLenParams(boxTy)) { 17217ce8c6fcSKiran Chandramohan TODO(embox.getLoc(), 17227ce8c6fcSKiran Chandramohan "fir.embox codegen of derived with length parameters"); 172344e58509SEric Schweitz return mlir::failure(); 17247ce8c6fcSKiran Chandramohan } 17259c84d20fSSlava Zakharin auto result = 17269c84d20fSSlava Zakharin placeInMemoryIfNotGlobalInit(rewriter, embox.getLoc(), boxTy, dest); 1727af6ee580SValentin Clement rewriter.replaceOp(embox, result); 172844e58509SEric Schweitz return mlir::success(); 1729af6ee580SValentin Clement } 1730af6ee580SValentin Clement }; 1731af6ee580SValentin Clement 1732c26e1a22SValentin Clement (バレンタイン クレメン) static bool isDeviceAllocation(mlir::Value val, mlir::Value adaptorVal) { 173381831ef3SValentin Clement (バレンタイン クレメン) if (auto loadOp = mlir::dyn_cast_or_null<fir::LoadOp>(val.getDefiningOp())) 1734c26e1a22SValentin Clement (バレンタイン クレメン) return isDeviceAllocation(loadOp.getMemref(), {}); 1735d36836deSValentin Clement (バレンタイン クレメン) if (auto boxAddrOp = 1736d36836deSValentin Clement (バレンタイン クレメン) mlir::dyn_cast_or_null<fir::BoxAddrOp>(val.getDefiningOp())) 1737c26e1a22SValentin Clement (バレンタイン クレメン) return isDeviceAllocation(boxAddrOp.getVal(), {}); 17384530273dSValentin Clement (バレンタイン クレメン) if (auto convertOp = 17394530273dSValentin Clement (バレンタイン クレメン) mlir::dyn_cast_or_null<fir::ConvertOp>(val.getDefiningOp())) 1740c26e1a22SValentin Clement (バレンタイン クレメン) return isDeviceAllocation(convertOp.getValue(), {}); 1741c26e1a22SValentin Clement (バレンタイン クレメン) if (!val.getDefiningOp() && adaptorVal) { 1742c26e1a22SValentin Clement (バレンタイン クレメン) if (auto blockArg = llvm::cast<mlir::BlockArgument>(adaptorVal)) { 1743c26e1a22SValentin Clement (バレンタイン クレメン) if (blockArg.getOwner() && blockArg.getOwner()->getParentOp() && 1744c26e1a22SValentin Clement (バレンタイン クレメン) blockArg.getOwner()->isEntryBlock()) { 1745c26e1a22SValentin Clement (バレンタイン クレメン) if (auto func = mlir::dyn_cast_or_null<mlir::FunctionOpInterface>( 1746c26e1a22SValentin Clement (バレンタイン クレメン) *blockArg.getOwner()->getParentOp())) { 1747c26e1a22SValentin Clement (バレンタイン クレメン) auto argAttrs = func.getArgAttrs(blockArg.getArgNumber()); 1748c26e1a22SValentin Clement (バレンタイン クレメン) for (auto attr : argAttrs) { 1749c26e1a22SValentin Clement (バレンタイン クレメン) if (attr.getName().getValue().ends_with(cuf::getDataAttrName())) { 1750c26e1a22SValentin Clement (バレンタイン クレメン) auto dataAttr = 1751c26e1a22SValentin Clement (バレンタイン クレメン) mlir::dyn_cast<cuf::DataAttributeAttr>(attr.getValue()); 1752c26e1a22SValentin Clement (バレンタイン クレメン) if (dataAttr.getValue() != cuf::DataAttribute::Pinned && 1753c26e1a22SValentin Clement (バレンタイン クレメン) dataAttr.getValue() != cuf::DataAttribute::Unified) 1754c26e1a22SValentin Clement (バレンタイン クレメン) return true; 1755c26e1a22SValentin Clement (バレンタイン クレメン) } 1756c26e1a22SValentin Clement (バレンタイン クレメン) } 1757c26e1a22SValentin Clement (バレンタイン クレメン) } 1758c26e1a22SValentin Clement (バレンタイン クレメン) } 1759c26e1a22SValentin Clement (バレンタイン クレメン) } 1760c26e1a22SValentin Clement (バレンタイン クレメン) } 17614530273dSValentin Clement (バレンタイン クレメン) if (auto callOp = mlir::dyn_cast_or_null<fir::CallOp>(val.getDefiningOp())) 17624530273dSValentin Clement (バレンタイン クレメン) if (callOp.getCallee() && 176381831ef3SValentin Clement (バレンタイン クレメン) (callOp.getCallee().value().getRootReference().getValue().starts_with( 176481831ef3SValentin Clement (バレンタイン クレメン) RTNAME_STRING(CUFMemAlloc)) || 17654530273dSValentin Clement (バレンタイン クレメン) callOp.getCallee().value().getRootReference().getValue().starts_with( 1766e650ac16SValentin Clement (バレンタイン クレメン) RTNAME_STRING(CUFAllocDescriptor)))) 17674530273dSValentin Clement (バレンタイン クレメン) return true; 17684530273dSValentin Clement (バレンタイン クレメン) return false; 17694530273dSValentin Clement (バレンタイン クレメン) } 17704530273dSValentin Clement (バレンタイン クレメン) 17711f551032SValentin Clement /// Create a generic box on a memory reference. 17721f551032SValentin Clement struct XEmboxOpConversion : public EmboxCommonConversion<fir::cg::XEmboxOp> { 17731f551032SValentin Clement using EmboxCommonConversion::EmboxCommonConversion; 17741f551032SValentin Clement 1775db791b27SRamkumar Ramachandra llvm::LogicalResult 17761f551032SValentin Clement matchAndRewrite(fir::cg::XEmboxOp xbox, OpAdaptor adaptor, 17771f551032SValentin Clement mlir::ConversionPatternRewriter &rewriter) const override { 17781f551032SValentin Clement mlir::ValueRange operands = adaptor.getOperands(); 17799f1bb307SValentin Clement mlir::Value sourceBox; 17809f1bb307SValentin Clement mlir::Type sourceBoxType; 17819f1bb307SValentin Clement if (xbox.getSourceBox()) { 1782d8b672daSjeanPerier sourceBox = operands[xbox.getSourceBoxOperandIndex()]; 17839f1bb307SValentin Clement sourceBoxType = xbox.getSourceBox().getType(); 17849f1bb307SValentin Clement } 1785b881fc27SJean Perier auto [boxTy, dest, resultEleSize] = consDescriptorPrefix( 1786c1b7e9c9SValentin Clement xbox, fir::unwrapRefType(xbox.getMemref().getType()), rewriter, 1787a45ca5d9SSlava Zakharin xbox.getOutRank(), adaptor.getSubstr(), adaptor.getLenParams(), 17889f1bb307SValentin Clement sourceBox, sourceBoxType); 178912d26ce9SValentin Clement // Generate the triples in the dims field of the descriptor 17901f551032SValentin Clement auto i64Ty = mlir::IntegerType::get(xbox.getContext(), 64); 1791a89b0480SValentin Clement assert(!xbox.getShape().empty() && "must have a shape"); 1792d8b672daSjeanPerier unsigned shapeOffset = xbox.getShapeOperandIndex(); 1793a89b0480SValentin Clement bool hasShift = !xbox.getShift().empty(); 1794d8b672daSjeanPerier unsigned shiftOffset = xbox.getShiftOperandIndex(); 1795a89b0480SValentin Clement bool hasSlice = !xbox.getSlice().empty(); 1796d8b672daSjeanPerier unsigned sliceOffset = xbox.getSliceOperandIndex(); 17971f551032SValentin Clement mlir::Location loc = xbox.getLoc(); 17981f551032SValentin Clement mlir::Value zero = genConstantIndex(loc, i64Ty, rewriter, 0); 17991f551032SValentin Clement mlir::Value one = genConstantIndex(loc, i64Ty, rewriter, 1); 18001f551032SValentin Clement mlir::Value prevPtrOff = one; 18011f551032SValentin Clement mlir::Type eleTy = boxTy.getEleTy(); 18021f551032SValentin Clement const unsigned rank = xbox.getRank(); 1803af40f99eSJean Perier llvm::SmallVector<mlir::Value> cstInteriorIndices; 18041f551032SValentin Clement unsigned constRows = 0; 18051f551032SValentin Clement mlir::Value ptrOffset = zero; 1806a89b0480SValentin Clement mlir::Type memEleTy = fir::dyn_cast_ptrEleTy(xbox.getMemref().getType()); 1807fac349a1SChristian Sigg assert(mlir::isa<fir::SequenceType>(memEleTy)); 1808fac349a1SChristian Sigg auto seqTy = mlir::cast<fir::SequenceType>(memEleTy); 18091f551032SValentin Clement mlir::Type seqEleTy = seqTy.getEleTy(); 18101f551032SValentin Clement // Adjust the element scaling factor if the element is a dependent type. 18111f551032SValentin Clement if (fir::hasDynamicSize(seqEleTy)) { 1812fac349a1SChristian Sigg if (auto charTy = mlir::dyn_cast<fir::CharacterType>(seqEleTy)) { 1813315939fdSSlava Zakharin // The GEP pointer type decays to llvm.ptr<i[width]>. 1814315939fdSSlava Zakharin // The scaling factor is the runtime value of the length. 1815315939fdSSlava Zakharin assert(!adaptor.getLenParams().empty()); 1816315939fdSSlava Zakharin prevPtrOff = FIROpConversion::integerCast( 1817315939fdSSlava Zakharin loc, rewriter, i64Ty, adaptor.getLenParams().back()); 1818fac349a1SChristian Sigg } else if (mlir::isa<fir::RecordType>(seqEleTy)) { 18196c89c531SEric Schweitz // prevPtrOff = ; 18201f551032SValentin Clement TODO(loc, "generate call to calculate size of PDT"); 18211f551032SValentin Clement } else { 18226c89c531SEric Schweitz fir::emitFatalError(loc, "unexpected dynamic type"); 18231f551032SValentin Clement } 18241f551032SValentin Clement } else { 18251f551032SValentin Clement constRows = seqTy.getConstantRows(); 18261f551032SValentin Clement } 18271f551032SValentin Clement 1828a89b0480SValentin Clement const auto hasSubcomp = !xbox.getSubcomponent().empty(); 1829a89b0480SValentin Clement const bool hasSubstr = !xbox.getSubstr().empty(); 183002f3fec3SSlava Zakharin // Initial element stride that will be use to compute the step in 1831b881fc27SJean Perier // each dimension. Initially, this is the size of the input element. 1832b881fc27SJean Perier // Note that when there are no components/substring, the resultEleSize 1833b881fc27SJean Perier // that was previously computed matches the input element size. 1834b881fc27SJean Perier mlir::Value prevDimByteStride = resultEleSize; 18351f551032SValentin Clement if (hasSubcomp) { 18361f551032SValentin Clement // We have a subcomponent. The step value needs to be the number of 18371f551032SValentin Clement // bytes per element (which is a derived type). 183802f3fec3SSlava Zakharin prevDimByteStride = 183902f3fec3SSlava Zakharin genTypeStrideInBytes(loc, i64Ty, rewriter, convertType(seqEleTy)); 18406c89c531SEric Schweitz } else if (hasSubstr) { 18416c89c531SEric Schweitz // We have a substring. The step value needs to be the number of bytes 18426c89c531SEric Schweitz // per CHARACTER element. 1843fac349a1SChristian Sigg auto charTy = mlir::cast<fir::CharacterType>(seqEleTy); 18446c89c531SEric Schweitz if (fir::hasDynamicSize(charTy)) { 1845315939fdSSlava Zakharin prevDimByteStride = 1846315939fdSSlava Zakharin getCharacterByteSize(loc, rewriter, charTy, adaptor.getLenParams()); 18476c89c531SEric Schweitz } else { 18486c89c531SEric Schweitz prevDimByteStride = genConstantIndex( 18496c89c531SEric Schweitz loc, i64Ty, rewriter, 18506c89c531SEric Schweitz charTy.getLen() * lowerTy().characterBitsize(charTy) / 8); 18516c89c531SEric Schweitz } 18521f551032SValentin Clement } 18531f551032SValentin Clement 18541f551032SValentin Clement // Process the array subspace arguments (shape, shift, etc.), if any, 18551f551032SValentin Clement // translating everything to values in the descriptor wherever the entity 18561f551032SValentin Clement // has a dynamic array dimension. 18571f551032SValentin Clement for (unsigned di = 0, descIdx = 0; di < rank; ++di) { 1858*0b80491cSSlava Zakharin mlir::Value extent = 1859*0b80491cSSlava Zakharin integerCast(loc, rewriter, i64Ty, operands[shapeOffset]); 18601f551032SValentin Clement mlir::Value outerExtent = extent; 18611f551032SValentin Clement bool skipNext = false; 18621f551032SValentin Clement if (hasSlice) { 1863*0b80491cSSlava Zakharin mlir::Value off = 1864*0b80491cSSlava Zakharin integerCast(loc, rewriter, i64Ty, operands[sliceOffset]); 18651f551032SValentin Clement mlir::Value adj = one; 18661f551032SValentin Clement if (hasShift) 1867*0b80491cSSlava Zakharin adj = integerCast(loc, rewriter, i64Ty, operands[shiftOffset]); 18681f551032SValentin Clement auto ao = rewriter.create<mlir::LLVM::SubOp>(loc, i64Ty, off, adj); 18691f551032SValentin Clement if (constRows > 0) { 1870af40f99eSJean Perier cstInteriorIndices.push_back(ao); 18711f551032SValentin Clement } else { 18721f551032SValentin Clement auto dimOff = 18731f551032SValentin Clement rewriter.create<mlir::LLVM::MulOp>(loc, i64Ty, ao, prevPtrOff); 18741f551032SValentin Clement ptrOffset = 18751f551032SValentin Clement rewriter.create<mlir::LLVM::AddOp>(loc, i64Ty, dimOff, ptrOffset); 18761f551032SValentin Clement } 18771f551032SValentin Clement if (mlir::isa_and_nonnull<fir::UndefOp>( 1878a89b0480SValentin Clement xbox.getSlice()[3 * di + 1].getDefiningOp())) { 18791f551032SValentin Clement // This dimension contains a scalar expression in the array slice op. 18801f551032SValentin Clement // The dimension is loop invariant, will be dropped, and will not 18811f551032SValentin Clement // appear in the descriptor. 18821f551032SValentin Clement skipNext = true; 18831f551032SValentin Clement } 18841f551032SValentin Clement } 18851f551032SValentin Clement if (!skipNext) { 18866c89c531SEric Schweitz // store extent 18871f551032SValentin Clement if (hasSlice) 18881f551032SValentin Clement extent = computeTripletExtent(rewriter, loc, operands[sliceOffset], 18891f551032SValentin Clement operands[sliceOffset + 1], 18901f551032SValentin Clement operands[sliceOffset + 2], zero, i64Ty); 18916c89c531SEric Schweitz // Lower bound is normalized to 0 for BIND(C) interoperability. 1892d3bc3a04SJean Perier mlir::Value lb = zero; 1893d3bc3a04SJean Perier const bool isaPointerOrAllocatable = 1894fac349a1SChristian Sigg mlir::isa<fir::PointerType, fir::HeapType>(eleTy); 1895d3bc3a04SJean Perier // Lower bound is defaults to 1 for POINTER, ALLOCATABLE, and 1896d3bc3a04SJean Perier // denormalized descriptors. 18976c89c531SEric Schweitz if (isaPointerOrAllocatable || !normalizedLowerBound(xbox)) 1898d3bc3a04SJean Perier lb = one; 1899bb3afae9SJean Perier // If there is a shifted origin, and no fir.slice, and this is not 1900bb3afae9SJean Perier // a normalized descriptor then use the value from the shift op as 1901bb3afae9SJean Perier // the lower bound. 19026c89c531SEric Schweitz if (hasShift && !(hasSlice || hasSubcomp || hasSubstr) && 19036c89c531SEric Schweitz (isaPointerOrAllocatable || !normalizedLowerBound(xbox))) { 1904*0b80491cSSlava Zakharin lb = integerCast(loc, rewriter, i64Ty, operands[shiftOffset]); 1905d3bc3a04SJean Perier auto extentIsEmpty = rewriter.create<mlir::LLVM::ICmpOp>( 1906d3bc3a04SJean Perier loc, mlir::LLVM::ICmpPredicate::eq, extent, zero); 1907d3bc3a04SJean Perier lb = rewriter.create<mlir::LLVM::SelectOp>(loc, extentIsEmpty, one, 1908d3bc3a04SJean Perier lb); 1909d3bc3a04SJean Perier } 1910d3bc3a04SJean Perier dest = insertLowerBound(rewriter, loc, dest, descIdx, lb); 1911d3bc3a04SJean Perier 19121f551032SValentin Clement dest = insertExtent(rewriter, loc, dest, descIdx, extent); 19131f551032SValentin Clement 19141f551032SValentin Clement // store step (scaled by shaped extent) 19156c89c531SEric Schweitz mlir::Value step = prevDimByteStride; 1916*0b80491cSSlava Zakharin if (hasSlice) { 1917*0b80491cSSlava Zakharin mlir::Value sliceStep = 1918*0b80491cSSlava Zakharin integerCast(loc, rewriter, i64Ty, operands[sliceOffset + 2]); 1919*0b80491cSSlava Zakharin step = 1920*0b80491cSSlava Zakharin rewriter.create<mlir::LLVM::MulOp>(loc, i64Ty, step, sliceStep); 1921*0b80491cSSlava Zakharin } 19221f551032SValentin Clement dest = insertStride(rewriter, loc, dest, descIdx, step); 19231f551032SValentin Clement ++descIdx; 19241f551032SValentin Clement } 19251f551032SValentin Clement 19261f551032SValentin Clement // compute the stride and offset for the next natural dimension 19276c89c531SEric Schweitz prevDimByteStride = rewriter.create<mlir::LLVM::MulOp>( 19286c89c531SEric Schweitz loc, i64Ty, prevDimByteStride, outerExtent); 19291f551032SValentin Clement if (constRows == 0) 19301f551032SValentin Clement prevPtrOff = rewriter.create<mlir::LLVM::MulOp>(loc, i64Ty, prevPtrOff, 19311f551032SValentin Clement outerExtent); 19320601a0dcSJean Perier else 19330601a0dcSJean Perier --constRows; 19341f551032SValentin Clement 19351f551032SValentin Clement // increment iterators 19361f551032SValentin Clement ++shapeOffset; 19371f551032SValentin Clement if (hasShift) 19381f551032SValentin Clement ++shiftOffset; 19391f551032SValentin Clement if (hasSlice) 19401f551032SValentin Clement sliceOffset += 3; 19411f551032SValentin Clement } 19428a1ce2d6SjeanPerier mlir::Value base = adaptor.getMemref(); 19436c89c531SEric Schweitz if (hasSlice || hasSubcomp || hasSubstr) { 1944af40f99eSJean Perier // Shift the base address. 1945af40f99eSJean Perier llvm::SmallVector<mlir::Value> fieldIndices; 194622426110SRamkumar Ramachandra std::optional<mlir::Value> substringOffset; 1947af40f99eSJean Perier if (hasSubcomp) 1948a89b0480SValentin Clement getSubcomponentIndices(xbox, xbox.getMemref(), operands, fieldIndices); 19496c89c531SEric Schweitz if (hasSubstr) 1950d8b672daSjeanPerier substringOffset = operands[xbox.getSubstrOperandIndex()]; 19518a1ce2d6SjeanPerier mlir::Type llvmBaseType = 19528a1ce2d6SjeanPerier convertType(fir::unwrapRefType(xbox.getMemref().getType())); 19538a1ce2d6SjeanPerier base = genBoxOffsetGep(rewriter, loc, base, llvmBaseType, ptrOffset, 19548a1ce2d6SjeanPerier cstInteriorIndices, fieldIndices, substringOffset); 19551f551032SValentin Clement } 19561f551032SValentin Clement dest = insertBaseAddress(rewriter, loc, dest, base); 19570538bfe7SRenaud-K if (fir::isDerivedTypeWithLenParams(boxTy)) 19581f551032SValentin Clement TODO(loc, "fir.embox codegen of derived with length parameters"); 19594530273dSValentin Clement (バレンタイン クレメン) mlir::Value result = placeInMemoryIfNotGlobalInit( 1960c26e1a22SValentin Clement (バレンタイン クレメン) rewriter, loc, boxTy, dest, 1961c26e1a22SValentin Clement (バレンタイン クレメン) isDeviceAllocation(xbox.getMemref(), adaptor.getMemref())); 19621f551032SValentin Clement rewriter.replaceOp(xbox, result); 196344e58509SEric Schweitz return mlir::success(); 19641f551032SValentin Clement } 1965d3bc3a04SJean Perier 1966d3bc3a04SJean Perier /// Return true if `xbox` has a normalized lower bounds attribute. A box value 1967d3bc3a04SJean Perier /// that is neither a POINTER nor an ALLOCATABLE should be normalized to a 1968d3bc3a04SJean Perier /// zero origin lower bound for interoperability with BIND(C). 1969d3bc3a04SJean Perier inline static bool normalizedLowerBound(fir::cg::XEmboxOp xbox) { 1970d3bc3a04SJean Perier return xbox->hasAttr(fir::getNormalizedLowerBoundAttrName()); 1971d3bc3a04SJean Perier } 19721f551032SValentin Clement }; 19731f551032SValentin Clement 1974fa517555SKiran Chandramohan /// Create a new box given a box reference. 1975fa517555SKiran Chandramohan struct XReboxOpConversion : public EmboxCommonConversion<fir::cg::XReboxOp> { 1976fa517555SKiran Chandramohan using EmboxCommonConversion::EmboxCommonConversion; 1977fa517555SKiran Chandramohan 1978db791b27SRamkumar Ramachandra llvm::LogicalResult 1979fa517555SKiran Chandramohan matchAndRewrite(fir::cg::XReboxOp rebox, OpAdaptor adaptor, 1980fa517555SKiran Chandramohan mlir::ConversionPatternRewriter &rewriter) const override { 1981fa517555SKiran Chandramohan mlir::Location loc = rebox.getLoc(); 1982fa517555SKiran Chandramohan mlir::Type idxTy = lowerTy().indexType(); 1983fa517555SKiran Chandramohan mlir::Value loweredBox = adaptor.getOperands()[0]; 1984fa517555SKiran Chandramohan mlir::ValueRange operands = adaptor.getOperands(); 1985fa517555SKiran Chandramohan 1986de2811eeSJean Perier // Inside a fir.global, the input box was produced as an llvm.struct<> 1987de2811eeSJean Perier // because objects cannot be handled in memory inside a fir.global body that 1988de2811eeSJean Perier // must be constant foldable. However, the type translation are not 1989de2811eeSJean Perier // contextual, so the fir.box<T> type of the operation that produced the 1990de2811eeSJean Perier // fir.box was translated to an llvm.ptr<llvm.struct<>> and the MLIR pass 1991de2811eeSJean Perier // manager inserted a builtin.unrealized_conversion_cast that was inserted 1992de2811eeSJean Perier // and needs to be removed here. 1993de2811eeSJean Perier if (isInGlobalOp(rewriter)) 1994de2811eeSJean Perier if (auto unrealizedCast = 1995de2811eeSJean Perier loweredBox.getDefiningOp<mlir::UnrealizedConversionCastOp>()) 1996de2811eeSJean Perier loweredBox = unrealizedCast.getInputs()[0]; 1997de2811eeSJean Perier 19988a1ce2d6SjeanPerier TypePair inputBoxTyPair = getBoxTypePair(rebox.getBox().getType()); 19998a1ce2d6SjeanPerier 2000fa517555SKiran Chandramohan // Create new descriptor and fill its non-shape related data. 2001fa517555SKiran Chandramohan llvm::SmallVector<mlir::Value, 2> lenParams; 2002fa517555SKiran Chandramohan mlir::Type inputEleTy = getInputEleTy(rebox); 2003fac349a1SChristian Sigg if (auto charTy = mlir::dyn_cast<fir::CharacterType>(inputEleTy)) { 200451a34681SJean Perier if (charTy.hasConstantLen()) { 200551a34681SJean Perier mlir::Value len = 200651a34681SJean Perier genConstantIndex(loc, idxTy, rewriter, charTy.getLen()); 200751a34681SJean Perier lenParams.emplace_back(len); 200851a34681SJean Perier } else { 20098a1ce2d6SjeanPerier mlir::Value len = getElementSizeFromBox(loc, idxTy, inputBoxTyPair, 20108a1ce2d6SjeanPerier loweredBox, rewriter); 2011fa517555SKiran Chandramohan if (charTy.getFKind() != 1) { 201251a34681SJean Perier assert(!isInGlobalOp(rewriter) && 201351a34681SJean Perier "character target in global op must have constant length"); 2014fa517555SKiran Chandramohan mlir::Value width = 2015fa517555SKiran Chandramohan genConstantIndex(loc, idxTy, rewriter, charTy.getFKind()); 2016fa517555SKiran Chandramohan len = rewriter.create<mlir::LLVM::SDivOp>(loc, idxTy, len, width); 2017fa517555SKiran Chandramohan } 2018fa517555SKiran Chandramohan lenParams.emplace_back(len); 201951a34681SJean Perier } 2020fac349a1SChristian Sigg } else if (auto recTy = mlir::dyn_cast<fir::RecordType>(inputEleTy)) { 2021fa517555SKiran Chandramohan if (recTy.getNumLenParams() != 0) 2022fa517555SKiran Chandramohan TODO(loc, "reboxing descriptor of derived type with length parameters"); 2023fa517555SKiran Chandramohan } 2024016fbc40SValentin Clement 2025016fbc40SValentin Clement // Rebox on polymorphic entities needs to carry over the dynamic type. 2026016fbc40SValentin Clement mlir::Value typeDescAddr; 2027fac349a1SChristian Sigg if (mlir::isa<fir::ClassType>(inputBoxTyPair.fir) && 2028fac349a1SChristian Sigg mlir::isa<fir::ClassType>(rebox.getType())) 20298a1ce2d6SjeanPerier typeDescAddr = 20308a1ce2d6SjeanPerier loadTypeDescAddress(loc, inputBoxTyPair, loweredBox, rewriter); 2031016fbc40SValentin Clement 2032c1b7e9c9SValentin Clement auto [boxTy, dest, eleSize] = 2033c1b7e9c9SValentin Clement consDescriptorPrefix(rebox, loweredBox, rewriter, rebox.getOutRank(), 2034a45ca5d9SSlava Zakharin adaptor.getSubstr(), lenParams, typeDescAddr); 2035fa517555SKiran Chandramohan 2036fa517555SKiran Chandramohan // Read input extents, strides, and base address 2037fa517555SKiran Chandramohan llvm::SmallVector<mlir::Value> inputExtents; 2038fa517555SKiran Chandramohan llvm::SmallVector<mlir::Value> inputStrides; 2039fa517555SKiran Chandramohan const unsigned inputRank = rebox.getRank(); 2040de2811eeSJean Perier for (unsigned dim = 0; dim < inputRank; ++dim) { 204144e58509SEric Schweitz llvm::SmallVector<mlir::Value, 3> dimInfo = 20428a1ce2d6SjeanPerier getDimsFromBox(loc, {idxTy, idxTy, idxTy}, inputBoxTyPair, loweredBox, 20438a1ce2d6SjeanPerier dim, rewriter); 2044fa517555SKiran Chandramohan inputExtents.emplace_back(dimInfo[1]); 2045fa517555SKiran Chandramohan inputStrides.emplace_back(dimInfo[2]); 2046fa517555SKiran Chandramohan } 2047fa517555SKiran Chandramohan 20488a1ce2d6SjeanPerier mlir::Value baseAddr = 20498a1ce2d6SjeanPerier getBaseAddrFromBox(loc, inputBoxTyPair, loweredBox, rewriter); 2050fa517555SKiran Chandramohan 2051a89b0480SValentin Clement if (!rebox.getSlice().empty() || !rebox.getSubcomponent().empty()) 20529f83c4edSValentin Clement (バレンタイン クレメン) return sliceBox(rebox, adaptor, boxTy, dest, baseAddr, inputExtents, 20539f83c4edSValentin Clement (バレンタイン クレメン) inputStrides, operands, rewriter); 20549f83c4edSValentin Clement (バレンタイン クレメン) return reshapeBox(rebox, adaptor, boxTy, dest, baseAddr, inputExtents, 20559f83c4edSValentin Clement (バレンタイン クレメン) inputStrides, operands, rewriter); 2056fa517555SKiran Chandramohan } 2057fa517555SKiran Chandramohan 2058fa517555SKiran Chandramohan private: 2059fa517555SKiran Chandramohan /// Write resulting shape and base address in descriptor, and replace rebox 2060fa517555SKiran Chandramohan /// op. 2061db791b27SRamkumar Ramachandra llvm::LogicalResult 20629f83c4edSValentin Clement (バレンタイン クレメン) finalizeRebox(fir::cg::XReboxOp rebox, OpAdaptor adaptor, 20639f83c4edSValentin Clement (バレンタイン クレメン) mlir::Type destBoxTy, mlir::Value dest, mlir::Value base, 20649f83c4edSValentin Clement (バレンタイン クレメン) mlir::ValueRange lbounds, mlir::ValueRange extents, 20659f83c4edSValentin Clement (バレンタイン クレメン) mlir::ValueRange strides, 2066fa517555SKiran Chandramohan mlir::ConversionPatternRewriter &rewriter) const { 2067fa517555SKiran Chandramohan mlir::Location loc = rebox.getLoc(); 2068d3bc3a04SJean Perier mlir::Value zero = 2069d3bc3a04SJean Perier genConstantIndex(loc, lowerTy().indexType(), rewriter, 0); 2070fa517555SKiran Chandramohan mlir::Value one = genConstantIndex(loc, lowerTy().indexType(), rewriter, 1); 2071fa517555SKiran Chandramohan for (auto iter : llvm::enumerate(llvm::zip(extents, strides))) { 2072d3bc3a04SJean Perier mlir::Value extent = std::get<0>(iter.value()); 2073fa517555SKiran Chandramohan unsigned dim = iter.index(); 2074d3bc3a04SJean Perier mlir::Value lb = one; 2075d3bc3a04SJean Perier if (!lbounds.empty()) { 2076d3bc3a04SJean Perier lb = lbounds[dim]; 2077d3bc3a04SJean Perier auto extentIsEmpty = rewriter.create<mlir::LLVM::ICmpOp>( 2078d3bc3a04SJean Perier loc, mlir::LLVM::ICmpPredicate::eq, extent, zero); 2079d3bc3a04SJean Perier lb = rewriter.create<mlir::LLVM::SelectOp>(loc, extentIsEmpty, one, lb); 2080d3bc3a04SJean Perier }; 2081fa517555SKiran Chandramohan dest = insertLowerBound(rewriter, loc, dest, dim, lb); 2082d3bc3a04SJean Perier dest = insertExtent(rewriter, loc, dest, dim, extent); 2083fa517555SKiran Chandramohan dest = insertStride(rewriter, loc, dest, dim, std::get<1>(iter.value())); 2084fa517555SKiran Chandramohan } 2085fa517555SKiran Chandramohan dest = insertBaseAddress(rewriter, loc, dest, base); 2086c26e1a22SValentin Clement (バレンタイン クレメン) mlir::Value result = placeInMemoryIfNotGlobalInit( 2087c26e1a22SValentin Clement (バレンタイン クレメン) rewriter, rebox.getLoc(), destBoxTy, dest, 20889f83c4edSValentin Clement (バレンタイン クレメン) isDeviceAllocation(rebox.getBox(), adaptor.getBox())); 2089fa517555SKiran Chandramohan rewriter.replaceOp(rebox, result); 209044e58509SEric Schweitz return mlir::success(); 2091fa517555SKiran Chandramohan } 2092fa517555SKiran Chandramohan 2093fa517555SKiran Chandramohan // Apply slice given the base address, extents and strides of the input box. 2094db791b27SRamkumar Ramachandra llvm::LogicalResult 20959f83c4edSValentin Clement (バレンタイン クレメン) sliceBox(fir::cg::XReboxOp rebox, OpAdaptor adaptor, mlir::Type destBoxTy, 20969f83c4edSValentin Clement (バレンタイン クレメン) mlir::Value dest, mlir::Value base, mlir::ValueRange inputExtents, 20979c84d20fSSlava Zakharin mlir::ValueRange inputStrides, mlir::ValueRange operands, 2098fa517555SKiran Chandramohan mlir::ConversionPatternRewriter &rewriter) const { 2099fa517555SKiran Chandramohan mlir::Location loc = rebox.getLoc(); 21008a1ce2d6SjeanPerier mlir::Type byteTy = ::getI8Type(rebox.getContext()); 2101fa517555SKiran Chandramohan mlir::Type idxTy = lowerTy().indexType(); 2102fa517555SKiran Chandramohan mlir::Value zero = genConstantIndex(loc, idxTy, rewriter, 0); 2103fa517555SKiran Chandramohan // Apply subcomponent and substring shift on base address. 2104a89b0480SValentin Clement if (!rebox.getSubcomponent().empty() || !rebox.getSubstr().empty()) { 2105fa517555SKiran Chandramohan // Cast to inputEleTy* so that a GEP can be used. 2106fa517555SKiran Chandramohan mlir::Type inputEleTy = getInputEleTy(rebox); 21078a1ce2d6SjeanPerier mlir::Type llvmBaseObjectType = convertType(inputEleTy); 2108af40f99eSJean Perier llvm::SmallVector<mlir::Value> fieldIndices; 210922426110SRamkumar Ramachandra std::optional<mlir::Value> substringOffset; 2110a89b0480SValentin Clement if (!rebox.getSubcomponent().empty()) 2111a89b0480SValentin Clement getSubcomponentIndices(rebox, rebox.getBox(), operands, fieldIndices); 2112a89b0480SValentin Clement if (!rebox.getSubstr().empty()) 2113d8b672daSjeanPerier substringOffset = operands[rebox.getSubstrOperandIndex()]; 21148a1ce2d6SjeanPerier base = genBoxOffsetGep(rewriter, loc, base, llvmBaseObjectType, zero, 21159a417395SKazu Hirata /*cstInteriorIndices=*/std::nullopt, fieldIndices, 2116af40f99eSJean Perier substringOffset); 2117fa517555SKiran Chandramohan } 2118fa517555SKiran Chandramohan 2119a89b0480SValentin Clement if (rebox.getSlice().empty()) 2120fa517555SKiran Chandramohan // The array section is of the form array[%component][substring], keep 2121fa517555SKiran Chandramohan // the input array extents and strides. 21229f83c4edSValentin Clement (バレンタイン クレメン) return finalizeRebox(rebox, adaptor, destBoxTy, dest, base, 21239c84d20fSSlava Zakharin /*lbounds*/ std::nullopt, inputExtents, inputStrides, 21249c84d20fSSlava Zakharin rewriter); 2125fa517555SKiran Chandramohan 2126fa517555SKiran Chandramohan // The slice is of the form array(i:j:k)[%component]. Compute new extents 2127fa517555SKiran Chandramohan // and strides. 2128fa517555SKiran Chandramohan llvm::SmallVector<mlir::Value> slicedExtents; 2129fa517555SKiran Chandramohan llvm::SmallVector<mlir::Value> slicedStrides; 2130fa517555SKiran Chandramohan mlir::Value one = genConstantIndex(loc, idxTy, rewriter, 1); 2131a89b0480SValentin Clement const bool sliceHasOrigins = !rebox.getShift().empty(); 2132d8b672daSjeanPerier unsigned sliceOps = rebox.getSliceOperandIndex(); 2133d8b672daSjeanPerier unsigned shiftOps = rebox.getShiftOperandIndex(); 2134fa517555SKiran Chandramohan auto strideOps = inputStrides.begin(); 2135fa517555SKiran Chandramohan const unsigned inputRank = inputStrides.size(); 2136fa517555SKiran Chandramohan for (unsigned i = 0; i < inputRank; 2137fa517555SKiran Chandramohan ++i, ++strideOps, ++shiftOps, sliceOps += 3) { 2138fa517555SKiran Chandramohan mlir::Value sliceLb = 2139fa517555SKiran Chandramohan integerCast(loc, rewriter, idxTy, operands[sliceOps]); 2140fa517555SKiran Chandramohan mlir::Value inputStride = *strideOps; // already idxTy 2141fa517555SKiran Chandramohan // Apply origin shift: base += (lb-shift)*input_stride 2142fa517555SKiran Chandramohan mlir::Value sliceOrigin = 2143fa517555SKiran Chandramohan sliceHasOrigins 2144fa517555SKiran Chandramohan ? integerCast(loc, rewriter, idxTy, operands[shiftOps]) 2145fa517555SKiran Chandramohan : one; 2146fa517555SKiran Chandramohan mlir::Value diff = 2147fa517555SKiran Chandramohan rewriter.create<mlir::LLVM::SubOp>(loc, idxTy, sliceLb, sliceOrigin); 2148fa517555SKiran Chandramohan mlir::Value offset = 2149fa517555SKiran Chandramohan rewriter.create<mlir::LLVM::MulOp>(loc, idxTy, diff, inputStride); 21508a1ce2d6SjeanPerier // Strides from the fir.box are in bytes. 21518a1ce2d6SjeanPerier base = genGEP(loc, byteTy, rewriter, base, offset); 2152fa517555SKiran Chandramohan // Apply upper bound and step if this is a triplet. Otherwise, the 2153fa517555SKiran Chandramohan // dimension is dropped and no extents/strides are computed. 2154fa517555SKiran Chandramohan mlir::Value upper = operands[sliceOps + 1]; 2155fa517555SKiran Chandramohan const bool isTripletSlice = 2156fa517555SKiran Chandramohan !mlir::isa_and_nonnull<mlir::LLVM::UndefOp>(upper.getDefiningOp()); 2157fa517555SKiran Chandramohan if (isTripletSlice) { 2158fa517555SKiran Chandramohan mlir::Value step = 2159fa517555SKiran Chandramohan integerCast(loc, rewriter, idxTy, operands[sliceOps + 2]); 2160fa517555SKiran Chandramohan // extent = ub-lb+step/step 2161fa517555SKiran Chandramohan mlir::Value sliceUb = integerCast(loc, rewriter, idxTy, upper); 2162fa517555SKiran Chandramohan mlir::Value extent = computeTripletExtent(rewriter, loc, sliceLb, 2163fa517555SKiran Chandramohan sliceUb, step, zero, idxTy); 2164fa517555SKiran Chandramohan slicedExtents.emplace_back(extent); 2165fa517555SKiran Chandramohan // stride = step*input_stride 2166fa517555SKiran Chandramohan mlir::Value stride = 2167fa517555SKiran Chandramohan rewriter.create<mlir::LLVM::MulOp>(loc, idxTy, step, inputStride); 2168fa517555SKiran Chandramohan slicedStrides.emplace_back(stride); 2169fa517555SKiran Chandramohan } 2170fa517555SKiran Chandramohan } 21719f83c4edSValentin Clement (バレンタイン クレメン) return finalizeRebox(rebox, adaptor, destBoxTy, dest, base, 21729f83c4edSValentin Clement (バレンタイン クレメン) /*lbounds*/ std::nullopt, slicedExtents, slicedStrides, 21739f83c4edSValentin Clement (バレンタイン クレメン) rewriter); 2174fa517555SKiran Chandramohan } 2175fa517555SKiran Chandramohan 2176fa517555SKiran Chandramohan /// Apply a new shape to the data described by a box given the base address, 2177fa517555SKiran Chandramohan /// extents and strides of the box. 2178db791b27SRamkumar Ramachandra llvm::LogicalResult 21799f83c4edSValentin Clement (バレンタイン クレメン) reshapeBox(fir::cg::XReboxOp rebox, OpAdaptor adaptor, mlir::Type destBoxTy, 21809f83c4edSValentin Clement (バレンタイン クレメン) mlir::Value dest, mlir::Value base, mlir::ValueRange inputExtents, 21819c84d20fSSlava Zakharin mlir::ValueRange inputStrides, mlir::ValueRange operands, 2182fa517555SKiran Chandramohan mlir::ConversionPatternRewriter &rewriter) const { 2183d8b672daSjeanPerier mlir::ValueRange reboxShifts{ 2184d8b672daSjeanPerier operands.begin() + rebox.getShiftOperandIndex(), 2185d8b672daSjeanPerier operands.begin() + rebox.getShiftOperandIndex() + 2186a89b0480SValentin Clement rebox.getShift().size()}; 2187a89b0480SValentin Clement if (rebox.getShape().empty()) { 2188fa517555SKiran Chandramohan // Only setting new lower bounds. 21899f83c4edSValentin Clement (バレンタイン クレメン) return finalizeRebox(rebox, adaptor, destBoxTy, dest, base, reboxShifts, 21909c84d20fSSlava Zakharin inputExtents, inputStrides, rewriter); 2191fa517555SKiran Chandramohan } 2192fa517555SKiran Chandramohan 2193fa517555SKiran Chandramohan mlir::Location loc = rebox.getLoc(); 2194fa517555SKiran Chandramohan 2195fa517555SKiran Chandramohan llvm::SmallVector<mlir::Value> newStrides; 2196fa517555SKiran Chandramohan llvm::SmallVector<mlir::Value> newExtents; 2197fa517555SKiran Chandramohan mlir::Type idxTy = lowerTy().indexType(); 2198fa517555SKiran Chandramohan // First stride from input box is kept. The rest is assumed contiguous 2199fa517555SKiran Chandramohan // (it is not possible to reshape otherwise). If the input is scalar, 2200fa517555SKiran Chandramohan // which may be OK if all new extents are ones, the stride does not 2201fa517555SKiran Chandramohan // matter, use one. 2202fa517555SKiran Chandramohan mlir::Value stride = inputStrides.empty() 2203fa517555SKiran Chandramohan ? genConstantIndex(loc, idxTy, rewriter, 1) 2204fa517555SKiran Chandramohan : inputStrides[0]; 2205a89b0480SValentin Clement for (unsigned i = 0; i < rebox.getShape().size(); ++i) { 2206d8b672daSjeanPerier mlir::Value rawExtent = operands[rebox.getShapeOperandIndex() + i]; 2207fa517555SKiran Chandramohan mlir::Value extent = integerCast(loc, rewriter, idxTy, rawExtent); 2208fa517555SKiran Chandramohan newExtents.emplace_back(extent); 2209fa517555SKiran Chandramohan newStrides.emplace_back(stride); 2210fa517555SKiran Chandramohan // nextStride = extent * stride; 2211fa517555SKiran Chandramohan stride = rewriter.create<mlir::LLVM::MulOp>(loc, idxTy, extent, stride); 2212fa517555SKiran Chandramohan } 22139f83c4edSValentin Clement (バレンタイン クレメン) return finalizeRebox(rebox, adaptor, destBoxTy, dest, base, reboxShifts, 22149f83c4edSValentin Clement (バレンタイン クレメン) newExtents, newStrides, rewriter); 2215fa517555SKiran Chandramohan } 2216fa517555SKiran Chandramohan 2217fa517555SKiran Chandramohan /// Return scalar element type of the input box. 2218fa517555SKiran Chandramohan static mlir::Type getInputEleTy(fir::cg::XReboxOp rebox) { 2219a89b0480SValentin Clement auto ty = fir::dyn_cast_ptrOrBoxEleTy(rebox.getBox().getType()); 2220fac349a1SChristian Sigg if (auto seqTy = mlir::dyn_cast<fir::SequenceType>(ty)) 2221fa517555SKiran Chandramohan return seqTy.getEleTy(); 2222fa517555SKiran Chandramohan return ty; 2223fa517555SKiran Chandramohan } 2224fa517555SKiran Chandramohan }; 2225fa517555SKiran Chandramohan 2226dc48849fSKiran Chandramohan /// Lower `fir.emboxproc` operation. Creates a procedure box. 2227dc48849fSKiran Chandramohan /// TODO: Part of supporting Fortran 2003 procedure pointers. 2228e9639e9cSValentin Clement (バレンタイン クレメン) struct EmboxProcOpConversion : public fir::FIROpConversion<fir::EmboxProcOp> { 2229dc48849fSKiran Chandramohan using FIROpConversion::FIROpConversion; 2230dc48849fSKiran Chandramohan 2231db791b27SRamkumar Ramachandra llvm::LogicalResult 2232dc48849fSKiran Chandramohan matchAndRewrite(fir::EmboxProcOp emboxproc, OpAdaptor adaptor, 2233dc48849fSKiran Chandramohan mlir::ConversionPatternRewriter &rewriter) const override { 2234dc48849fSKiran Chandramohan TODO(emboxproc.getLoc(), "fir.emboxproc codegen"); 223544e58509SEric Schweitz return mlir::failure(); 2236dc48849fSKiran Chandramohan } 2237dc48849fSKiran Chandramohan }; 2238dc48849fSKiran Chandramohan 223954c56347SValentin Clement // Code shared between insert_value and extract_value Ops. 224054c56347SValentin Clement struct ValueOpCommon { 224154c56347SValentin Clement // Translate the arguments pertaining to any multidimensional array to 224254c56347SValentin Clement // row-major order for LLVM-IR. 22435c5af910SJeff Niu static void toRowMajor(llvm::SmallVectorImpl<int64_t> &indices, 224454c56347SValentin Clement mlir::Type ty) { 224554c56347SValentin Clement assert(ty && "type is null"); 22465c5af910SJeff Niu const auto end = indices.size(); 224754c56347SValentin Clement for (std::remove_const_t<decltype(end)> i = 0; i < end; ++i) { 2248fac349a1SChristian Sigg if (auto seq = mlir::dyn_cast<mlir::LLVM::LLVMArrayType>(ty)) { 224954c56347SValentin Clement const auto dim = getDimension(seq); 225054c56347SValentin Clement if (dim > 1) { 225154c56347SValentin Clement auto ub = std::min(i + dim, end); 22525c5af910SJeff Niu std::reverse(indices.begin() + i, indices.begin() + ub); 225354c56347SValentin Clement i += dim - 1; 225454c56347SValentin Clement } 225554c56347SValentin Clement ty = getArrayElementType(seq); 2256fac349a1SChristian Sigg } else if (auto st = mlir::dyn_cast<mlir::LLVM::LLVMStructType>(ty)) { 22575c5af910SJeff Niu ty = st.getBody()[indices[i]]; 225854c56347SValentin Clement } else { 225954c56347SValentin Clement llvm_unreachable("index into invalid type"); 226054c56347SValentin Clement } 226154c56347SValentin Clement } 226254c56347SValentin Clement } 226354c56347SValentin Clement 22645c5af910SJeff Niu static llvm::SmallVector<int64_t> 226554c56347SValentin Clement collectIndices(mlir::ConversionPatternRewriter &rewriter, 226654c56347SValentin Clement mlir::ArrayAttr arrAttr) { 22675c5af910SJeff Niu llvm::SmallVector<int64_t> indices; 226854c56347SValentin Clement for (auto i = arrAttr.begin(), e = arrAttr.end(); i != e; ++i) { 2269bd9fdce6SChristian Sigg if (auto intAttr = mlir::dyn_cast<mlir::IntegerAttr>(*i)) { 22705c5af910SJeff Niu indices.push_back(intAttr.getInt()); 227154c56347SValentin Clement } else { 2272bd9fdce6SChristian Sigg auto fieldName = mlir::cast<mlir::StringAttr>(*i).getValue(); 227354c56347SValentin Clement ++i; 2274bd9fdce6SChristian Sigg auto ty = mlir::cast<mlir::TypeAttr>(*i).getValue(); 2275fac349a1SChristian Sigg auto index = mlir::cast<fir::RecordType>(ty).getFieldIndex(fieldName); 22765c5af910SJeff Niu indices.push_back(index); 227754c56347SValentin Clement } 227854c56347SValentin Clement } 22795c5af910SJeff Niu return indices; 228054c56347SValentin Clement } 228154c56347SValentin Clement 228254c56347SValentin Clement private: 228354c56347SValentin Clement static mlir::Type getArrayElementType(mlir::LLVM::LLVMArrayType ty) { 228454c56347SValentin Clement auto eleTy = ty.getElementType(); 2285fac349a1SChristian Sigg while (auto arrTy = mlir::dyn_cast<mlir::LLVM::LLVMArrayType>(eleTy)) 228654c56347SValentin Clement eleTy = arrTy.getElementType(); 228754c56347SValentin Clement return eleTy; 228854c56347SValentin Clement } 228954c56347SValentin Clement }; 229054c56347SValentin Clement 2291c2acd453SAlexisPerry namespace { 229254c56347SValentin Clement /// Extract a subobject value from an ssa-value of aggregate type 229354c56347SValentin Clement struct ExtractValueOpConversion 2294e9639e9cSValentin Clement (バレンタイン クレメン) : public fir::FIROpAndTypeConversion<fir::ExtractValueOp>, 229554c56347SValentin Clement public ValueOpCommon { 229654c56347SValentin Clement using FIROpAndTypeConversion::FIROpAndTypeConversion; 229754c56347SValentin Clement 2298db791b27SRamkumar Ramachandra llvm::LogicalResult 229954c56347SValentin Clement doRewrite(fir::ExtractValueOp extractVal, mlir::Type ty, OpAdaptor adaptor, 230054c56347SValentin Clement mlir::ConversionPatternRewriter &rewriter) const override { 230112d26ce9SValentin Clement mlir::ValueRange operands = adaptor.getOperands(); 23025c5af910SJeff Niu auto indices = collectIndices(rewriter, extractVal.getCoor()); 23035c5af910SJeff Niu toRowMajor(indices, operands[0].getType()); 230454c56347SValentin Clement rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractValueOp>( 23055c5af910SJeff Niu extractVal, operands[0], indices); 230644e58509SEric Schweitz return mlir::success(); 230754c56347SValentin Clement } 230854c56347SValentin Clement }; 230954c56347SValentin Clement 231054c56347SValentin Clement /// InsertValue is the generalized instruction for the composition of new 231154c56347SValentin Clement /// aggregate type values. 231254c56347SValentin Clement struct InsertValueOpConversion 2313e73cf2f0SMatthias Springer : public mlir::OpConversionPattern<fir::InsertValueOp>, 231454c56347SValentin Clement public ValueOpCommon { 2315e73cf2f0SMatthias Springer using OpConversionPattern::OpConversionPattern; 231654c56347SValentin Clement 2317db791b27SRamkumar Ramachandra llvm::LogicalResult 2318e73cf2f0SMatthias Springer matchAndRewrite(fir::InsertValueOp insertVal, OpAdaptor adaptor, 231954c56347SValentin Clement mlir::ConversionPatternRewriter &rewriter) const override { 232012d26ce9SValentin Clement mlir::ValueRange operands = adaptor.getOperands(); 23215c5af910SJeff Niu auto indices = collectIndices(rewriter, insertVal.getCoor()); 23225c5af910SJeff Niu toRowMajor(indices, operands[0].getType()); 232354c56347SValentin Clement rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>( 23245c5af910SJeff Niu insertVal, operands[0], operands[1], indices); 232544e58509SEric Schweitz return mlir::success(); 232654c56347SValentin Clement } 232754c56347SValentin Clement }; 232854c56347SValentin Clement 23293ae8e442SValentin Clement /// InsertOnRange inserts a value into a sequence over a range of offsets. 23303ae8e442SValentin Clement struct InsertOnRangeOpConversion 2331e9639e9cSValentin Clement (バレンタイン クレメン) : public fir::FIROpAndTypeConversion<fir::InsertOnRangeOp> { 23323ae8e442SValentin Clement using FIROpAndTypeConversion::FIROpAndTypeConversion; 23333ae8e442SValentin Clement 23343ae8e442SValentin Clement // Increments an array of subscripts in a row major fasion. 23355c5af910SJeff Niu void incrementSubscripts(llvm::ArrayRef<int64_t> dims, 23365c5af910SJeff Niu llvm::SmallVectorImpl<int64_t> &subscripts) const { 23373ae8e442SValentin Clement for (size_t i = dims.size(); i > 0; --i) { 23383ae8e442SValentin Clement if (++subscripts[i - 1] < dims[i - 1]) { 23393ae8e442SValentin Clement return; 23403ae8e442SValentin Clement } 23413ae8e442SValentin Clement subscripts[i - 1] = 0; 23423ae8e442SValentin Clement } 23433ae8e442SValentin Clement } 23443ae8e442SValentin Clement 2345db791b27SRamkumar Ramachandra llvm::LogicalResult 23463ae8e442SValentin Clement doRewrite(fir::InsertOnRangeOp range, mlir::Type ty, OpAdaptor adaptor, 23473ae8e442SValentin Clement mlir::ConversionPatternRewriter &rewriter) const override { 23483ae8e442SValentin Clement 23495c5af910SJeff Niu llvm::SmallVector<std::int64_t> dims; 23503ae8e442SValentin Clement auto type = adaptor.getOperands()[0].getType(); 23513ae8e442SValentin Clement 23523ae8e442SValentin Clement // Iteratively extract the array dimensions from the type. 2353fac349a1SChristian Sigg while (auto t = mlir::dyn_cast<mlir::LLVM::LLVMArrayType>(type)) { 23543ae8e442SValentin Clement dims.push_back(t.getNumElements()); 23553ae8e442SValentin Clement type = t.getElementType(); 23563ae8e442SValentin Clement } 23573ae8e442SValentin Clement 23585c5af910SJeff Niu llvm::SmallVector<std::int64_t> lBounds; 23595c5af910SJeff Niu llvm::SmallVector<std::int64_t> uBounds; 23603ae8e442SValentin Clement 23613ae8e442SValentin Clement // Unzip the upper and lower bound and convert to a row major format. 2362149ad3d5SShraiysh Vaishay mlir::DenseIntElementsAttr coor = range.getCoor(); 23638ec0f221SMehdi Amini auto reversedCoor = llvm::reverse(coor.getValues<int64_t>()); 23648ec0f221SMehdi Amini for (auto i = reversedCoor.begin(), e = reversedCoor.end(); i != e; ++i) { 23653ae8e442SValentin Clement uBounds.push_back(*i++); 23663ae8e442SValentin Clement lBounds.push_back(*i); 23673ae8e442SValentin Clement } 23683ae8e442SValentin Clement 23693ae8e442SValentin Clement auto &subscripts = lBounds; 23703ae8e442SValentin Clement auto loc = range.getLoc(); 23713ae8e442SValentin Clement mlir::Value lastOp = adaptor.getOperands()[0]; 23723ae8e442SValentin Clement mlir::Value insertVal = adaptor.getOperands()[1]; 23733ae8e442SValentin Clement 23743ae8e442SValentin Clement while (subscripts != uBounds) { 23753ae8e442SValentin Clement lastOp = rewriter.create<mlir::LLVM::InsertValueOp>( 23765c5af910SJeff Niu loc, lastOp, insertVal, subscripts); 23773ae8e442SValentin Clement 23783ae8e442SValentin Clement incrementSubscripts(dims, subscripts); 23793ae8e442SValentin Clement } 23803ae8e442SValentin Clement 23813ae8e442SValentin Clement rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>( 23825c5af910SJeff Niu range, lastOp, insertVal, subscripts); 23833ae8e442SValentin Clement 238444e58509SEric Schweitz return mlir::success(); 23853ae8e442SValentin Clement } 23863ae8e442SValentin Clement }; 2387c2acd453SAlexisPerry } // namespace 23887b5132daSValentin Clement 2389dc48849fSKiran Chandramohan namespace { 23905d27abe6SValentin Clement /// XArrayCoor is the address arithmetic on a dynamically shaped, sliced, 23915d27abe6SValentin Clement /// shifted etc. array. 23925d27abe6SValentin Clement /// (See the static restriction on coordinate_of.) array_coor determines the 23935d27abe6SValentin Clement /// coordinate (location) of a specific element. 23945d27abe6SValentin Clement struct XArrayCoorOpConversion 2395e9639e9cSValentin Clement (バレンタイン クレメン) : public fir::FIROpAndTypeConversion<fir::cg::XArrayCoorOp> { 23965d27abe6SValentin Clement using FIROpAndTypeConversion::FIROpAndTypeConversion; 23975d27abe6SValentin Clement 2398db791b27SRamkumar Ramachandra llvm::LogicalResult 23998a1ce2d6SjeanPerier doRewrite(fir::cg::XArrayCoorOp coor, mlir::Type llvmPtrTy, OpAdaptor adaptor, 24005d27abe6SValentin Clement mlir::ConversionPatternRewriter &rewriter) const override { 24015d27abe6SValentin Clement auto loc = coor.getLoc(); 24025d27abe6SValentin Clement mlir::ValueRange operands = adaptor.getOperands(); 24035d27abe6SValentin Clement unsigned rank = coor.getRank(); 2404a89b0480SValentin Clement assert(coor.getIndices().size() == rank); 2405a89b0480SValentin Clement assert(coor.getShape().empty() || coor.getShape().size() == rank); 2406a89b0480SValentin Clement assert(coor.getShift().empty() || coor.getShift().size() == rank); 2407a89b0480SValentin Clement assert(coor.getSlice().empty() || coor.getSlice().size() == 3 * rank); 24085d27abe6SValentin Clement mlir::Type idxTy = lowerTy().indexType(); 2409d8b672daSjeanPerier unsigned indexOffset = coor.getIndicesOperandIndex(); 2410d8b672daSjeanPerier unsigned shapeOffset = coor.getShapeOperandIndex(); 2411d8b672daSjeanPerier unsigned shiftOffset = coor.getShiftOperandIndex(); 2412d8b672daSjeanPerier unsigned sliceOffset = coor.getSliceOperandIndex(); 2413a89b0480SValentin Clement auto sliceOps = coor.getSlice().begin(); 24145d27abe6SValentin Clement mlir::Value one = genConstantIndex(loc, idxTy, rewriter, 1); 24155d27abe6SValentin Clement mlir::Value prevExt = one; 2416bd7eff1fSMarkus Böck mlir::Value offset = genConstantIndex(loc, idxTy, rewriter, 0); 2417a89b0480SValentin Clement const bool isShifted = !coor.getShift().empty(); 2418a89b0480SValentin Clement const bool isSliced = !coor.getSlice().empty(); 2419fac349a1SChristian Sigg const bool baseIsBoxed = 2420fac349a1SChristian Sigg mlir::isa<fir::BaseBoxType>(coor.getMemref().getType()); 24218a1ce2d6SjeanPerier TypePair baseBoxTyPair = 24228a1ce2d6SjeanPerier baseIsBoxed ? getBoxTypePair(coor.getMemref().getType()) : TypePair{}; 2423e553ac4dSJeff Niu mlir::LLVM::IntegerOverflowFlags nsw = 2424e553ac4dSJeff Niu mlir::LLVM::IntegerOverflowFlags::nsw; 24255d27abe6SValentin Clement 24265d27abe6SValentin Clement // For each dimension of the array, generate the offset calculation. 2427914b9eecSKiran Chandramohan for (unsigned i = 0; i < rank; ++i, ++indexOffset, ++shapeOffset, 2428914b9eecSKiran Chandramohan ++shiftOffset, sliceOffset += 3, sliceOps += 3) { 24295d27abe6SValentin Clement mlir::Value index = 2430914b9eecSKiran Chandramohan integerCast(loc, rewriter, idxTy, operands[indexOffset]); 2431914b9eecSKiran Chandramohan mlir::Value lb = 2432914b9eecSKiran Chandramohan isShifted ? integerCast(loc, rewriter, idxTy, operands[shiftOffset]) 24335d27abe6SValentin Clement : one; 24345d27abe6SValentin Clement mlir::Value step = one; 24355d27abe6SValentin Clement bool normalSlice = isSliced; 24365d27abe6SValentin Clement // Compute zero based index in dimension i of the element, applying 24375d27abe6SValentin Clement // potential triplets and lower bounds. 24385d27abe6SValentin Clement if (isSliced) { 2439914b9eecSKiran Chandramohan mlir::Value originalUb = *(sliceOps + 1); 2440914b9eecSKiran Chandramohan normalSlice = 2441914b9eecSKiran Chandramohan !mlir::isa_and_nonnull<fir::UndefOp>(originalUb.getDefiningOp()); 24425d27abe6SValentin Clement if (normalSlice) 2443914b9eecSKiran Chandramohan step = integerCast(loc, rewriter, idxTy, operands[sliceOffset + 2]); 24445d27abe6SValentin Clement } 2445bdacd56fSTom Eccles auto idx = rewriter.create<mlir::LLVM::SubOp>(loc, idxTy, index, lb, nsw); 24465d27abe6SValentin Clement mlir::Value diff = 2447bdacd56fSTom Eccles rewriter.create<mlir::LLVM::MulOp>(loc, idxTy, idx, step, nsw); 24485d27abe6SValentin Clement if (normalSlice) { 24495d27abe6SValentin Clement mlir::Value sliceLb = 2450914b9eecSKiran Chandramohan integerCast(loc, rewriter, idxTy, operands[sliceOffset]); 2451bdacd56fSTom Eccles auto adj = 2452bdacd56fSTom Eccles rewriter.create<mlir::LLVM::SubOp>(loc, idxTy, sliceLb, lb, nsw); 2453bdacd56fSTom Eccles diff = rewriter.create<mlir::LLVM::AddOp>(loc, idxTy, diff, adj, nsw); 24545d27abe6SValentin Clement } 24555d27abe6SValentin Clement // Update the offset given the stride and the zero based index `diff` 24565d27abe6SValentin Clement // that was just computed. 24575d27abe6SValentin Clement if (baseIsBoxed) { 24585d27abe6SValentin Clement // Use stride in bytes from the descriptor. 24598a1ce2d6SjeanPerier mlir::Value stride = 24608a1ce2d6SjeanPerier getStrideFromBox(loc, baseBoxTyPair, operands[0], i, rewriter); 2461bdacd56fSTom Eccles auto sc = 2462bdacd56fSTom Eccles rewriter.create<mlir::LLVM::MulOp>(loc, idxTy, diff, stride, nsw); 2463bdacd56fSTom Eccles offset = 2464bdacd56fSTom Eccles rewriter.create<mlir::LLVM::AddOp>(loc, idxTy, sc, offset, nsw); 24655d27abe6SValentin Clement } else { 24665d27abe6SValentin Clement // Use stride computed at last iteration. 2467bdacd56fSTom Eccles auto sc = 2468bdacd56fSTom Eccles rewriter.create<mlir::LLVM::MulOp>(loc, idxTy, diff, prevExt, nsw); 2469bdacd56fSTom Eccles offset = 2470bdacd56fSTom Eccles rewriter.create<mlir::LLVM::AddOp>(loc, idxTy, sc, offset, nsw); 24715d27abe6SValentin Clement // Compute next stride assuming contiguity of the base array 24725d27abe6SValentin Clement // (in element number). 2473914b9eecSKiran Chandramohan auto nextExt = integerCast(loc, rewriter, idxTy, operands[shapeOffset]); 2474bdacd56fSTom Eccles prevExt = rewriter.create<mlir::LLVM::MulOp>(loc, idxTy, prevExt, 2475bdacd56fSTom Eccles nextExt, nsw); 24765d27abe6SValentin Clement } 24775d27abe6SValentin Clement } 24785d27abe6SValentin Clement 24795d27abe6SValentin Clement // Add computed offset to the base address. 24805d27abe6SValentin Clement if (baseIsBoxed) { 24815d27abe6SValentin Clement // Working with byte offsets. The base address is read from the fir.box. 24828a1ce2d6SjeanPerier // and used in i8* GEP to do the pointer arithmetic. 24838a1ce2d6SjeanPerier mlir::Type byteTy = ::getI8Type(coor.getContext()); 24848a1ce2d6SjeanPerier mlir::Value base = 24858a1ce2d6SjeanPerier getBaseAddrFromBox(loc, baseBoxTyPair, operands[0], rewriter); 2486bd7eff1fSMarkus Böck llvm::SmallVector<mlir::LLVM::GEPArg> args{offset}; 24878a1ce2d6SjeanPerier auto addr = rewriter.create<mlir::LLVM::GEPOp>(loc, llvmPtrTy, byteTy, 24888a1ce2d6SjeanPerier base, args); 2489a89b0480SValentin Clement if (coor.getSubcomponent().empty()) { 24908a1ce2d6SjeanPerier rewriter.replaceOp(coor, addr); 249144e58509SEric Schweitz return mlir::success(); 24925d27abe6SValentin Clement } 24933ce7e4b2SJean Perier // Cast the element address from void* to the derived type so that the 24943ce7e4b2SJean Perier // derived type members can be addresses via a GEP using the index of 24953ce7e4b2SJean Perier // components. 24963ce7e4b2SJean Perier mlir::Type elementType = 24978a1ce2d6SjeanPerier getLlvmObjectTypeFromBoxType(coor.getMemref().getType()); 2498fac349a1SChristian Sigg while (auto arrayTy = 2499fac349a1SChristian Sigg mlir::dyn_cast<mlir::LLVM::LLVMArrayType>(elementType)) 25003ce7e4b2SJean Perier elementType = arrayTy.getElementType(); 25015d27abe6SValentin Clement args.clear(); 2502bd7eff1fSMarkus Böck args.push_back(0); 2503a89b0480SValentin Clement if (!coor.getLenParams().empty()) { 25045d27abe6SValentin Clement // If type parameters are present, then we don't want to use a GEPOp 25055d27abe6SValentin Clement // as below, as the LLVM struct type cannot be statically defined. 25065d27abe6SValentin Clement TODO(loc, "derived type with type parameters"); 25075d27abe6SValentin Clement } 2508783222efSLeandro Lupori llvm::SmallVector<mlir::Value> indices = convertSubcomponentIndices( 2509783222efSLeandro Lupori loc, elementType, 2510d8b672daSjeanPerier operands.slice(coor.getSubcomponentOperandIndex(), 2511783222efSLeandro Lupori coor.getSubcomponent().size())); 2512783222efSLeandro Lupori args.append(indices.begin(), indices.end()); 25138a1ce2d6SjeanPerier rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(coor, llvmPtrTy, 25148a1ce2d6SjeanPerier elementType, addr, args); 251544e58509SEric Schweitz return mlir::success(); 25165d27abe6SValentin Clement } 25175d27abe6SValentin Clement 25185d27abe6SValentin Clement // The array was not boxed, so it must be contiguous. offset is therefore an 25195d27abe6SValentin Clement // element offset and the base type is kept in the GEP unless the element 25205d27abe6SValentin Clement // type size is itself dynamic. 25218a1ce2d6SjeanPerier mlir::Type objectTy = fir::unwrapRefType(coor.getMemref().getType()); 25228a1ce2d6SjeanPerier mlir::Type eleType = fir::unwrapSequenceType(objectTy); 25238a1ce2d6SjeanPerier mlir::Type gepObjectType = convertType(eleType); 25248a1ce2d6SjeanPerier llvm::SmallVector<mlir::LLVM::GEPArg> args; 2525a89b0480SValentin Clement if (coor.getSubcomponent().empty()) { 25265d27abe6SValentin Clement // No subcomponent. 2527a89b0480SValentin Clement if (!coor.getLenParams().empty()) { 25285d27abe6SValentin Clement // Type parameters. Adjust element size explicitly. 25295d27abe6SValentin Clement auto eleTy = fir::dyn_cast_ptrEleTy(coor.getType()); 25305d27abe6SValentin Clement assert(eleTy && "result must be a reference-like type"); 25315d27abe6SValentin Clement if (fir::characterWithDynamicLen(eleTy)) { 2532a89b0480SValentin Clement assert(coor.getLenParams().size() == 1); 2533649439e7SValentin Clement auto length = integerCast(loc, rewriter, idxTy, 2534d8b672daSjeanPerier operands[coor.getLenParamsOperandIndex()]); 2535bdacd56fSTom Eccles offset = rewriter.create<mlir::LLVM::MulOp>(loc, idxTy, offset, 2536bdacd56fSTom Eccles length, nsw); 25375d27abe6SValentin Clement } else { 25385d27abe6SValentin Clement TODO(loc, "compute size of derived type with type parameters"); 25395d27abe6SValentin Clement } 25405d27abe6SValentin Clement } 25418a1ce2d6SjeanPerier args.push_back(offset); 25428a1ce2d6SjeanPerier } else { 25438a1ce2d6SjeanPerier // There are subcomponents. 25448a1ce2d6SjeanPerier args.push_back(offset); 2545783222efSLeandro Lupori llvm::SmallVector<mlir::Value> indices = convertSubcomponentIndices( 25468a1ce2d6SjeanPerier loc, gepObjectType, 2547d8b672daSjeanPerier operands.slice(coor.getSubcomponentOperandIndex(), 2548783222efSLeandro Lupori coor.getSubcomponent().size())); 2549783222efSLeandro Lupori args.append(indices.begin(), indices.end()); 25505d27abe6SValentin Clement } 25518a1ce2d6SjeanPerier rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>( 25528a1ce2d6SjeanPerier coor, llvmPtrTy, gepObjectType, adaptor.getMemref(), args); 255344e58509SEric Schweitz return mlir::success(); 25545d27abe6SValentin Clement } 25555d27abe6SValentin Clement }; 2556dc48849fSKiran Chandramohan } // namespace 2557dc48849fSKiran Chandramohan 2558dc48849fSKiran Chandramohan /// Convert to (memory) reference to a reference to a subobject. 2559dc48849fSKiran Chandramohan /// The coordinate_of op is a Swiss army knife operation that can be used on 2560dc48849fSKiran Chandramohan /// (memory) references to records, arrays, complex, etc. as well as boxes. 2561dc48849fSKiran Chandramohan /// With unboxed arrays, there is the restriction that the array have a static 2562dc48849fSKiran Chandramohan /// shape in all but the last column. 2563dc48849fSKiran Chandramohan struct CoordinateOpConversion 2564e9639e9cSValentin Clement (バレンタイン クレメン) : public fir::FIROpAndTypeConversion<fir::CoordinateOp> { 2565dc48849fSKiran Chandramohan using FIROpAndTypeConversion::FIROpAndTypeConversion; 2566dc48849fSKiran Chandramohan 2567db791b27SRamkumar Ramachandra llvm::LogicalResult 2568dc48849fSKiran Chandramohan doRewrite(fir::CoordinateOp coor, mlir::Type ty, OpAdaptor adaptor, 2569dc48849fSKiran Chandramohan mlir::ConversionPatternRewriter &rewriter) const override { 2570dc48849fSKiran Chandramohan mlir::ValueRange operands = adaptor.getOperands(); 2571dc48849fSKiran Chandramohan 2572dc48849fSKiran Chandramohan mlir::Location loc = coor.getLoc(); 2573dc48849fSKiran Chandramohan mlir::Value base = operands[0]; 2574dc48849fSKiran Chandramohan mlir::Type baseObjectTy = coor.getBaseType(); 2575dc48849fSKiran Chandramohan mlir::Type objectTy = fir::dyn_cast_ptrOrBoxEleTy(baseObjectTy); 2576dc48849fSKiran Chandramohan assert(objectTy && "fir.coordinate_of expects a reference type"); 25778a1ce2d6SjeanPerier mlir::Type llvmObjectTy = convertType(objectTy); 2578dc48849fSKiran Chandramohan 2579dc48849fSKiran Chandramohan // Complex type - basically, extract the real or imaginary part 25808a1ce2d6SjeanPerier // FIXME: double check why this is done before the fir.box case below. 2581dc48849fSKiran Chandramohan if (fir::isa_complex(objectTy)) { 25828a1ce2d6SjeanPerier mlir::Value gep = 25838a1ce2d6SjeanPerier genGEP(loc, llvmObjectTy, rewriter, base, 0, operands[1]); 2584dc48849fSKiran Chandramohan rewriter.replaceOp(coor, gep); 258544e58509SEric Schweitz return mlir::success(); 2586dc48849fSKiran Chandramohan } 2587dc48849fSKiran Chandramohan 2588dc48849fSKiran Chandramohan // Boxed type - get the base pointer from the box 2589fac349a1SChristian Sigg if (mlir::dyn_cast<fir::BaseBoxType>(baseObjectTy)) 25908a1ce2d6SjeanPerier return doRewriteBox(coor, operands, loc, rewriter); 2591dc48849fSKiran Chandramohan 259203efa5a3SAndrzej Warzynski // Reference, pointer or a heap type 2593fac349a1SChristian Sigg if (mlir::isa<fir::ReferenceType, fir::PointerType, fir::HeapType>( 2594fac349a1SChristian Sigg baseObjectTy)) 25958a1ce2d6SjeanPerier return doRewriteRefOrPtr(coor, llvmObjectTy, operands, loc, rewriter); 2596dc48849fSKiran Chandramohan 2597dc48849fSKiran Chandramohan return rewriter.notifyMatchFailure( 2598dc48849fSKiran Chandramohan coor, "fir.coordinate_of base operand has unsupported type"); 2599dc48849fSKiran Chandramohan } 2600dc48849fSKiran Chandramohan 260103efa5a3SAndrzej Warzynski static unsigned getFieldNumber(fir::RecordType ty, mlir::Value op) { 2602dc48849fSKiran Chandramohan return fir::hasDynamicSize(ty) 2603dc48849fSKiran Chandramohan ? op.getDefiningOp() 2604dc48849fSKiran Chandramohan ->getAttrOfType<mlir::IntegerAttr>("field") 2605dc48849fSKiran Chandramohan .getInt() 2606af40f99eSJean Perier : getConstantIntValue(op); 2607dc48849fSKiran Chandramohan } 2608dc48849fSKiran Chandramohan 260903efa5a3SAndrzej Warzynski static bool hasSubDimensions(mlir::Type type) { 2610fac349a1SChristian Sigg return mlir::isa<fir::SequenceType, fir::RecordType, mlir::TupleType>(type); 2611dc48849fSKiran Chandramohan } 2612dc48849fSKiran Chandramohan 2613dc48849fSKiran Chandramohan /// Check whether this form of `!fir.coordinate_of` is supported. These 2614dc48849fSKiran Chandramohan /// additional checks are required, because we are not yet able to convert 2615dc48849fSKiran Chandramohan /// all valid forms of `!fir.coordinate_of`. 2616dc48849fSKiran Chandramohan /// TODO: Either implement the unsupported cases or extend the verifier 2617dc48849fSKiran Chandramohan /// in FIROps.cpp instead. 261803efa5a3SAndrzej Warzynski static bool supportedCoordinate(mlir::Type type, mlir::ValueRange coors) { 2619dc48849fSKiran Chandramohan const std::size_t numOfCoors = coors.size(); 2620dc48849fSKiran Chandramohan std::size_t i = 0; 2621dc48849fSKiran Chandramohan bool subEle = false; 2622dc48849fSKiran Chandramohan bool ptrEle = false; 2623dc48849fSKiran Chandramohan for (; i < numOfCoors; ++i) { 2624dc48849fSKiran Chandramohan mlir::Value nxtOpnd = coors[i]; 2625fac349a1SChristian Sigg if (auto arrTy = mlir::dyn_cast<fir::SequenceType>(type)) { 2626dc48849fSKiran Chandramohan subEle = true; 2627dc48849fSKiran Chandramohan i += arrTy.getDimension() - 1; 2628dc48849fSKiran Chandramohan type = arrTy.getEleTy(); 2629fac349a1SChristian Sigg } else if (auto recTy = mlir::dyn_cast<fir::RecordType>(type)) { 2630dc48849fSKiran Chandramohan subEle = true; 2631dc48849fSKiran Chandramohan type = recTy.getType(getFieldNumber(recTy, nxtOpnd)); 2632fac349a1SChristian Sigg } else if (auto tupTy = mlir::dyn_cast<mlir::TupleType>(type)) { 2633dc48849fSKiran Chandramohan subEle = true; 2634af40f99eSJean Perier type = tupTy.getType(getConstantIntValue(nxtOpnd)); 2635dc48849fSKiran Chandramohan } else { 2636dc48849fSKiran Chandramohan ptrEle = true; 2637dc48849fSKiran Chandramohan } 2638dc48849fSKiran Chandramohan } 2639dc48849fSKiran Chandramohan if (ptrEle) 2640dc48849fSKiran Chandramohan return (!subEle) && (numOfCoors == 1); 2641dc48849fSKiran Chandramohan return subEle && (i >= numOfCoors); 2642dc48849fSKiran Chandramohan } 2643dc48849fSKiran Chandramohan 2644dc48849fSKiran Chandramohan /// Walk the abstract memory layout and determine if the path traverses any 2645dc48849fSKiran Chandramohan /// array types with unknown shape. Return true iff all the array types have a 2646dc48849fSKiran Chandramohan /// constant shape along the path. 264703efa5a3SAndrzej Warzynski static bool arraysHaveKnownShape(mlir::Type type, mlir::ValueRange coors) { 264803efa5a3SAndrzej Warzynski for (std::size_t i = 0, sz = coors.size(); i < sz; ++i) { 2649dc48849fSKiran Chandramohan mlir::Value nxtOpnd = coors[i]; 2650fac349a1SChristian Sigg if (auto arrTy = mlir::dyn_cast<fir::SequenceType>(type)) { 2651dc48849fSKiran Chandramohan if (fir::sequenceWithNonConstantShape(arrTy)) 2652dc48849fSKiran Chandramohan return false; 2653dc48849fSKiran Chandramohan i += arrTy.getDimension() - 1; 2654dc48849fSKiran Chandramohan type = arrTy.getEleTy(); 2655fac349a1SChristian Sigg } else if (auto strTy = mlir::dyn_cast<fir::RecordType>(type)) { 2656dc48849fSKiran Chandramohan type = strTy.getType(getFieldNumber(strTy, nxtOpnd)); 2657fac349a1SChristian Sigg } else if (auto strTy = mlir::dyn_cast<mlir::TupleType>(type)) { 2658af40f99eSJean Perier type = strTy.getType(getConstantIntValue(nxtOpnd)); 2659dc48849fSKiran Chandramohan } else { 2660dc48849fSKiran Chandramohan return true; 2661dc48849fSKiran Chandramohan } 2662dc48849fSKiran Chandramohan } 2663dc48849fSKiran Chandramohan return true; 2664dc48849fSKiran Chandramohan } 2665dc48849fSKiran Chandramohan 2666dc48849fSKiran Chandramohan private: 2667db791b27SRamkumar Ramachandra llvm::LogicalResult 26688a1ce2d6SjeanPerier doRewriteBox(fir::CoordinateOp coor, mlir::ValueRange operands, 2669dc48849fSKiran Chandramohan mlir::Location loc, 2670dc48849fSKiran Chandramohan mlir::ConversionPatternRewriter &rewriter) const { 2671dc48849fSKiran Chandramohan mlir::Type boxObjTy = coor.getBaseType(); 2672fac349a1SChristian Sigg assert(mlir::dyn_cast<fir::BaseBoxType>(boxObjTy) && 2673fac349a1SChristian Sigg "This is not a `fir.box`"); 26748a1ce2d6SjeanPerier TypePair boxTyPair = getBoxTypePair(boxObjTy); 2675dc48849fSKiran Chandramohan 2676dc48849fSKiran Chandramohan mlir::Value boxBaseAddr = operands[0]; 2677dc48849fSKiran Chandramohan 2678dc48849fSKiran Chandramohan // 1. SPECIAL CASE (uses `fir.len_param_index`): 2679dc48849fSKiran Chandramohan // %box = ... : !fir.box<!fir.type<derived{len1:i32}>> 2680dc48849fSKiran Chandramohan // %lenp = fir.len_param_index len1, !fir.type<derived{len1:i32}> 2681dc48849fSKiran Chandramohan // %addr = coordinate_of %box, %lenp 2682dc48849fSKiran Chandramohan if (coor.getNumOperands() == 2) { 2683dc48849fSKiran Chandramohan mlir::Operation *coordinateDef = 2684dc48849fSKiran Chandramohan (*coor.getCoor().begin()).getDefiningOp(); 268544e58509SEric Schweitz if (mlir::isa_and_nonnull<fir::LenParamIndexOp>(coordinateDef)) 2686dc48849fSKiran Chandramohan TODO(loc, 2687dc48849fSKiran Chandramohan "fir.coordinate_of - fir.len_param_index is not supported yet"); 2688dc48849fSKiran Chandramohan } 2689dc48849fSKiran Chandramohan 2690dc48849fSKiran Chandramohan // 2. GENERAL CASE: 2691dc48849fSKiran Chandramohan // 2.1. (`fir.array`) 2692dc48849fSKiran Chandramohan // %box = ... : !fix.box<!fir.array<?xU>> 2693dc48849fSKiran Chandramohan // %idx = ... : index 2694dc48849fSKiran Chandramohan // %resultAddr = coordinate_of %box, %idx : !fir.ref<U> 2695dc48849fSKiran Chandramohan // 2.2 (`fir.derived`) 2696dc48849fSKiran Chandramohan // %box = ... : !fix.box<!fir.type<derived_type{field_1:i32}>> 2697dc48849fSKiran Chandramohan // %idx = ... : i32 2698dc48849fSKiran Chandramohan // %resultAddr = coordinate_of %box, %idx : !fir.ref<i32> 2699dc48849fSKiran Chandramohan // 2.3 (`fir.derived` inside `fir.array`) 2700dc48849fSKiran Chandramohan // %box = ... : !fir.box<!fir.array<10 x !fir.type<derived_1{field_1:f32, 2701dc48849fSKiran Chandramohan // field_2:f32}>>> %idx1 = ... : index %idx2 = ... : i32 %resultAddr = 2702dc48849fSKiran Chandramohan // coordinate_of %box, %idx1, %idx2 : !fir.ref<f32> 2703dc48849fSKiran Chandramohan // 2.4. TODO: Either document or disable any other case that the following 2704dc48849fSKiran Chandramohan // implementation might convert. 2705dc48849fSKiran Chandramohan mlir::Value resultAddr = 27068a1ce2d6SjeanPerier getBaseAddrFromBox(loc, boxTyPair, boxBaseAddr, rewriter); 270703efa5a3SAndrzej Warzynski // Component Type 270803efa5a3SAndrzej Warzynski auto cpnTy = fir::dyn_cast_ptrOrBoxEleTy(boxObjTy); 27098a1ce2d6SjeanPerier mlir::Type llvmPtrTy = ::getLlvmPtrType(coor.getContext()); 27108a1ce2d6SjeanPerier mlir::Type byteTy = ::getI8Type(coor.getContext()); 2711e553ac4dSJeff Niu mlir::LLVM::IntegerOverflowFlags nsw = 2712e553ac4dSJeff Niu mlir::LLVM::IntegerOverflowFlags::nsw; 2713dc48849fSKiran Chandramohan 2714dc48849fSKiran Chandramohan for (unsigned i = 1, last = operands.size(); i < last; ++i) { 2715fac349a1SChristian Sigg if (auto arrTy = mlir::dyn_cast<fir::SequenceType>(cpnTy)) { 2716dc48849fSKiran Chandramohan if (i != 1) 2717dc48849fSKiran Chandramohan TODO(loc, "fir.array nested inside other array and/or derived type"); 2718dc48849fSKiran Chandramohan // Applies byte strides from the box. Ignore lower bound from box 2719dc48849fSKiran Chandramohan // since fir.coordinate_of indexes are zero based. Lowering takes care 2720dc48849fSKiran Chandramohan // of lower bound aspects. This both accounts for dynamically sized 2721dc48849fSKiran Chandramohan // types and non contiguous arrays. 2722dc48849fSKiran Chandramohan auto idxTy = lowerTy().indexType(); 2723dc48849fSKiran Chandramohan mlir::Value off = genConstantIndex(loc, idxTy, rewriter, 0); 2724dc48849fSKiran Chandramohan for (unsigned index = i, lastIndex = i + arrTy.getDimension(); 2725dc48849fSKiran Chandramohan index < lastIndex; ++index) { 27268a1ce2d6SjeanPerier mlir::Value stride = getStrideFromBox(loc, boxTyPair, operands[0], 27278a1ce2d6SjeanPerier index - i, rewriter); 2728bdacd56fSTom Eccles auto sc = rewriter.create<mlir::LLVM::MulOp>( 2729bdacd56fSTom Eccles loc, idxTy, operands[index], stride, nsw); 2730bdacd56fSTom Eccles off = rewriter.create<mlir::LLVM::AddOp>(loc, idxTy, sc, off, nsw); 2731dc48849fSKiran Chandramohan } 2732bd7eff1fSMarkus Böck resultAddr = rewriter.create<mlir::LLVM::GEPOp>( 27338a1ce2d6SjeanPerier loc, llvmPtrTy, byteTy, resultAddr, 2734bd7eff1fSMarkus Böck llvm::ArrayRef<mlir::LLVM::GEPArg>{off}); 2735dc48849fSKiran Chandramohan i += arrTy.getDimension() - 1; 273603efa5a3SAndrzej Warzynski cpnTy = arrTy.getEleTy(); 2737fac349a1SChristian Sigg } else if (auto recTy = mlir::dyn_cast<fir::RecordType>(cpnTy)) { 2738dc48849fSKiran Chandramohan mlir::Value nxtOpnd = operands[i]; 273903efa5a3SAndrzej Warzynski cpnTy = recTy.getType(getFieldNumber(recTy, nxtOpnd)); 27408a1ce2d6SjeanPerier auto llvmRecTy = lowerTy().convertType(recTy); 27418a1ce2d6SjeanPerier resultAddr = rewriter.create<mlir::LLVM::GEPOp>( 27428a1ce2d6SjeanPerier loc, llvmPtrTy, llvmRecTy, resultAddr, 2743bd7eff1fSMarkus Böck llvm::ArrayRef<mlir::LLVM::GEPArg>{0, nxtOpnd}); 2744dc48849fSKiran Chandramohan } else { 2745dc48849fSKiran Chandramohan fir::emitFatalError(loc, "unexpected type in coordinate_of"); 2746dc48849fSKiran Chandramohan } 2747dc48849fSKiran Chandramohan } 2748dc48849fSKiran Chandramohan 27498a1ce2d6SjeanPerier rewriter.replaceOp(coor, resultAddr); 275044e58509SEric Schweitz return mlir::success(); 2751dc48849fSKiran Chandramohan } 2752dc48849fSKiran Chandramohan 2753db791b27SRamkumar Ramachandra llvm::LogicalResult 27548a1ce2d6SjeanPerier doRewriteRefOrPtr(fir::CoordinateOp coor, mlir::Type llvmObjectTy, 2755dc48849fSKiran Chandramohan mlir::ValueRange operands, mlir::Location loc, 2756dc48849fSKiran Chandramohan mlir::ConversionPatternRewriter &rewriter) const { 2757dc48849fSKiran Chandramohan mlir::Type baseObjectTy = coor.getBaseType(); 2758dc48849fSKiran Chandramohan 275903efa5a3SAndrzej Warzynski // Component Type 276003efa5a3SAndrzej Warzynski mlir::Type cpnTy = fir::dyn_cast_ptrOrBoxEleTy(baseObjectTy); 276103efa5a3SAndrzej Warzynski bool hasSubdimension = hasSubDimensions(cpnTy); 2762dc48849fSKiran Chandramohan bool columnIsDeferred = !hasSubdimension; 2763dc48849fSKiran Chandramohan 276403efa5a3SAndrzej Warzynski if (!supportedCoordinate(cpnTy, operands.drop_front(1))) 2765dc48849fSKiran Chandramohan TODO(loc, "unsupported combination of coordinate operands"); 2766dc48849fSKiran Chandramohan 2767dc48849fSKiran Chandramohan const bool hasKnownShape = 276803efa5a3SAndrzej Warzynski arraysHaveKnownShape(cpnTy, operands.drop_front(1)); 2769dc48849fSKiran Chandramohan 2770dc48849fSKiran Chandramohan // If only the column is `?`, then we can simply place the column value in 2771dc48849fSKiran Chandramohan // the 0-th GEP position. 2772fac349a1SChristian Sigg if (auto arrTy = mlir::dyn_cast<fir::SequenceType>(cpnTy)) { 2773dc48849fSKiran Chandramohan if (!hasKnownShape) { 2774dc48849fSKiran Chandramohan const unsigned sz = arrTy.getDimension(); 2775dc48849fSKiran Chandramohan if (arraysHaveKnownShape(arrTy.getEleTy(), 2776dc48849fSKiran Chandramohan operands.drop_front(1 + sz))) { 277703efa5a3SAndrzej Warzynski fir::SequenceType::ShapeRef shape = arrTy.getShape(); 2778dc48849fSKiran Chandramohan bool allConst = true; 2779dc48849fSKiran Chandramohan for (unsigned i = 0; i < sz - 1; ++i) { 2780dc48849fSKiran Chandramohan if (shape[i] < 0) { 2781dc48849fSKiran Chandramohan allConst = false; 2782dc48849fSKiran Chandramohan break; 2783dc48849fSKiran Chandramohan } 2784dc48849fSKiran Chandramohan } 2785dc48849fSKiran Chandramohan if (allConst) 2786dc48849fSKiran Chandramohan columnIsDeferred = true; 2787dc48849fSKiran Chandramohan } 2788dc48849fSKiran Chandramohan } 2789dc48849fSKiran Chandramohan } 2790dc48849fSKiran Chandramohan 279103efa5a3SAndrzej Warzynski if (fir::hasDynamicSize(fir::unwrapSequenceType(cpnTy))) 279203efa5a3SAndrzej Warzynski return mlir::emitError( 2793dc48849fSKiran Chandramohan loc, "fir.coordinate_of with a dynamic element size is unsupported"); 2794dc48849fSKiran Chandramohan 2795dc48849fSKiran Chandramohan if (hasKnownShape || columnIsDeferred) { 2796bd7eff1fSMarkus Böck llvm::SmallVector<mlir::LLVM::GEPArg> offs; 2797dc48849fSKiran Chandramohan if (hasKnownShape && hasSubdimension) { 2798bd7eff1fSMarkus Böck offs.push_back(0); 2799dc48849fSKiran Chandramohan } 280022426110SRamkumar Ramachandra std::optional<int> dims; 280144e58509SEric Schweitz llvm::SmallVector<mlir::Value> arrIdx; 280203efa5a3SAndrzej Warzynski for (std::size_t i = 1, sz = operands.size(); i < sz; ++i) { 2803dc48849fSKiran Chandramohan mlir::Value nxtOpnd = operands[i]; 2804dc48849fSKiran Chandramohan 280503efa5a3SAndrzej Warzynski if (!cpnTy) 280603efa5a3SAndrzej Warzynski return mlir::emitError(loc, "invalid coordinate/check failed"); 2807dc48849fSKiran Chandramohan 2808dc48849fSKiran Chandramohan // check if the i-th coordinate relates to an array 28095413bf1bSKazu Hirata if (dims) { 2810dc48849fSKiran Chandramohan arrIdx.push_back(nxtOpnd); 2811dc48849fSKiran Chandramohan int dimsLeft = *dims; 2812dc48849fSKiran Chandramohan if (dimsLeft > 1) { 2813dc48849fSKiran Chandramohan dims = dimsLeft - 1; 2814dc48849fSKiran Chandramohan continue; 2815dc48849fSKiran Chandramohan } 2816e6a4346bSScott Manley cpnTy = mlir::cast<fir::SequenceType>(cpnTy).getElementType(); 2817dc48849fSKiran Chandramohan // append array range in reverse (FIR arrays are column-major) 2818dc48849fSKiran Chandramohan offs.append(arrIdx.rbegin(), arrIdx.rend()); 2819dc48849fSKiran Chandramohan arrIdx.clear(); 2820dc48849fSKiran Chandramohan dims.reset(); 2821dc48849fSKiran Chandramohan continue; 2822dc48849fSKiran Chandramohan } 2823fac349a1SChristian Sigg if (auto arrTy = mlir::dyn_cast<fir::SequenceType>(cpnTy)) { 2824dc48849fSKiran Chandramohan int d = arrTy.getDimension() - 1; 2825dc48849fSKiran Chandramohan if (d > 0) { 2826dc48849fSKiran Chandramohan dims = d; 2827dc48849fSKiran Chandramohan arrIdx.push_back(nxtOpnd); 2828dc48849fSKiran Chandramohan continue; 2829dc48849fSKiran Chandramohan } 2830e6a4346bSScott Manley cpnTy = mlir::cast<fir::SequenceType>(cpnTy).getElementType(); 2831dc48849fSKiran Chandramohan offs.push_back(nxtOpnd); 2832dc48849fSKiran Chandramohan continue; 2833dc48849fSKiran Chandramohan } 2834dc48849fSKiran Chandramohan 2835dc48849fSKiran Chandramohan // check if the i-th coordinate relates to a field 2836fac349a1SChristian Sigg if (auto recTy = mlir::dyn_cast<fir::RecordType>(cpnTy)) 283703efa5a3SAndrzej Warzynski cpnTy = recTy.getType(getFieldNumber(recTy, nxtOpnd)); 2838fac349a1SChristian Sigg else if (auto tupTy = mlir::dyn_cast<mlir::TupleType>(cpnTy)) 2839af40f99eSJean Perier cpnTy = tupTy.getType(getConstantIntValue(nxtOpnd)); 2840dc48849fSKiran Chandramohan else 284103efa5a3SAndrzej Warzynski cpnTy = nullptr; 2842dc48849fSKiran Chandramohan 2843dc48849fSKiran Chandramohan offs.push_back(nxtOpnd); 2844dc48849fSKiran Chandramohan } 28455413bf1bSKazu Hirata if (dims) 2846dc48849fSKiran Chandramohan offs.append(arrIdx.rbegin(), arrIdx.rend()); 2847dc48849fSKiran Chandramohan mlir::Value base = operands[0]; 28488a1ce2d6SjeanPerier mlir::Value retval = genGEP(loc, llvmObjectTy, rewriter, base, offs); 2849dc48849fSKiran Chandramohan rewriter.replaceOp(coor, retval); 285044e58509SEric Schweitz return mlir::success(); 2851dc48849fSKiran Chandramohan } 2852dc48849fSKiran Chandramohan 285303efa5a3SAndrzej Warzynski return mlir::emitError( 285403efa5a3SAndrzej Warzynski loc, "fir.coordinate_of base operand has unsupported type"); 2855dc48849fSKiran Chandramohan } 2856dc48849fSKiran Chandramohan }; 2857dc48849fSKiran Chandramohan 2858dc48849fSKiran Chandramohan /// Convert `fir.field_index`. The conversion depends on whether the size of 2859dc48849fSKiran Chandramohan /// the record is static or dynamic. 2860e9639e9cSValentin Clement (バレンタイン クレメン) struct FieldIndexOpConversion : public fir::FIROpConversion<fir::FieldIndexOp> { 2861dc48849fSKiran Chandramohan using FIROpConversion::FIROpConversion; 2862dc48849fSKiran Chandramohan 2863dc48849fSKiran Chandramohan // NB: most field references should be resolved by this point 2864db791b27SRamkumar Ramachandra llvm::LogicalResult 2865dc48849fSKiran Chandramohan matchAndRewrite(fir::FieldIndexOp field, OpAdaptor adaptor, 2866dc48849fSKiran Chandramohan mlir::ConversionPatternRewriter &rewriter) const override { 2867fac349a1SChristian Sigg auto recTy = mlir::cast<fir::RecordType>(field.getOnType()); 2868dc48849fSKiran Chandramohan unsigned index = recTy.getFieldIndex(field.getFieldId()); 2869dc48849fSKiran Chandramohan 2870dc48849fSKiran Chandramohan if (!fir::hasDynamicSize(recTy)) { 2871dc48849fSKiran Chandramohan // Derived type has compile-time constant layout. Return index of the 2872dc48849fSKiran Chandramohan // component type in the parent type (to be used in GEP). 2873dc48849fSKiran Chandramohan rewriter.replaceOp(field, mlir::ValueRange{genConstantOffset( 2874dc48849fSKiran Chandramohan field.getLoc(), rewriter, index)}); 287544e58509SEric Schweitz return mlir::success(); 2876dc48849fSKiran Chandramohan } 2877dc48849fSKiran Chandramohan 2878dc48849fSKiran Chandramohan // Derived type has compile-time constant layout. Call the compiler 2879dc48849fSKiran Chandramohan // generated function to determine the byte offset of the field at runtime. 2880dc48849fSKiran Chandramohan // This returns a non-constant. 288144e58509SEric Schweitz mlir::FlatSymbolRefAttr symAttr = mlir::SymbolRefAttr::get( 2882dc48849fSKiran Chandramohan field.getContext(), getOffsetMethodName(recTy, field.getFieldId())); 288344e58509SEric Schweitz mlir::NamedAttribute callAttr = rewriter.getNamedAttr("callee", symAttr); 288444e58509SEric Schweitz mlir::NamedAttribute fieldAttr = rewriter.getNamedAttr( 2885dc48849fSKiran Chandramohan "field", mlir::IntegerAttr::get(lowerTy().indexType(), index)); 2886dc48849fSKiran Chandramohan rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>( 2887dc48849fSKiran Chandramohan field, lowerTy().offsetType(), adaptor.getOperands(), 2888fde3c16aSSirui Mu addLLVMOpBundleAttrs(rewriter, {callAttr, fieldAttr}, 2889fde3c16aSSirui Mu adaptor.getOperands().size())); 289044e58509SEric Schweitz return mlir::success(); 2891dc48849fSKiran Chandramohan } 2892dc48849fSKiran Chandramohan 2893dc48849fSKiran Chandramohan // Re-Construct the name of the compiler generated method that calculates the 2894dc48849fSKiran Chandramohan // offset 2895dc48849fSKiran Chandramohan inline static std::string getOffsetMethodName(fir::RecordType recTy, 2896dc48849fSKiran Chandramohan llvm::StringRef field) { 2897dc48849fSKiran Chandramohan return recTy.getName().str() + "P." + field.str() + ".offset"; 2898dc48849fSKiran Chandramohan } 2899dc48849fSKiran Chandramohan }; 2900dc48849fSKiran Chandramohan 2901dc48849fSKiran Chandramohan /// Convert `fir.end` 2902e9639e9cSValentin Clement (バレンタイン クレメン) struct FirEndOpConversion : public fir::FIROpConversion<fir::FirEndOp> { 2903dc48849fSKiran Chandramohan using FIROpConversion::FIROpConversion; 2904dc48849fSKiran Chandramohan 2905db791b27SRamkumar Ramachandra llvm::LogicalResult 2906dc48849fSKiran Chandramohan matchAndRewrite(fir::FirEndOp firEnd, OpAdaptor, 2907dc48849fSKiran Chandramohan mlir::ConversionPatternRewriter &rewriter) const override { 2908dc48849fSKiran Chandramohan TODO(firEnd.getLoc(), "fir.end codegen"); 290944e58509SEric Schweitz return mlir::failure(); 2910dc48849fSKiran Chandramohan } 2911dc48849fSKiran Chandramohan }; 2912dc48849fSKiran Chandramohan 291316bd0fe5SValentin Clement /// Lower `fir.type_desc` to a global addr. 2914e9639e9cSValentin Clement (バレンタイン クレメン) struct TypeDescOpConversion : public fir::FIROpConversion<fir::TypeDescOp> { 2915dc48849fSKiran Chandramohan using FIROpConversion::FIROpConversion; 2916dc48849fSKiran Chandramohan 2917db791b27SRamkumar Ramachandra llvm::LogicalResult 291816bd0fe5SValentin Clement matchAndRewrite(fir::TypeDescOp typeDescOp, OpAdaptor adaptor, 2919dc48849fSKiran Chandramohan mlir::ConversionPatternRewriter &rewriter) const override { 292016bd0fe5SValentin Clement mlir::Type inTy = typeDescOp.getInType(); 2921fac349a1SChristian Sigg assert(mlir::isa<fir::RecordType>(inTy) && "expecting fir.type"); 2922fac349a1SChristian Sigg auto recordType = mlir::dyn_cast<fir::RecordType>(inTy); 292316bd0fe5SValentin Clement auto module = typeDescOp.getOperation()->getParentOfType<mlir::ModuleOp>(); 292416bd0fe5SValentin Clement std::string typeDescName = 2925cfd4c180SSlava Zakharin this->options.typeDescriptorsRenamedForAssembly 2926cfd4c180SSlava Zakharin ? fir::NameUniquer::getTypeDescriptorAssemblyName( 2927cfd4c180SSlava Zakharin recordType.getName()) 2928cfd4c180SSlava Zakharin : fir::NameUniquer::getTypeDescriptorName(recordType.getName()); 29298a1ce2d6SjeanPerier auto llvmPtrTy = ::getLlvmPtrType(typeDescOp.getContext()); 293016bd0fe5SValentin Clement if (auto global = module.lookupSymbol<mlir::LLVM::GlobalOp>(typeDescName)) { 29318a1ce2d6SjeanPerier rewriter.replaceOpWithNewOp<mlir::LLVM::AddressOfOp>( 29328a1ce2d6SjeanPerier typeDescOp, llvmPtrTy, global.getSymName()); 293316bd0fe5SValentin Clement return mlir::success(); 293416bd0fe5SValentin Clement } else if (auto global = module.lookupSymbol<fir::GlobalOp>(typeDescName)) { 29358a1ce2d6SjeanPerier rewriter.replaceOpWithNewOp<mlir::LLVM::AddressOfOp>( 29368a1ce2d6SjeanPerier typeDescOp, llvmPtrTy, global.getSymName()); 293716bd0fe5SValentin Clement return mlir::success(); 293816bd0fe5SValentin Clement } 293944e58509SEric Schweitz return mlir::failure(); 2940dc48849fSKiran Chandramohan } 2941dc48849fSKiran Chandramohan }; 2942dc48849fSKiran Chandramohan 2943dc48849fSKiran Chandramohan /// Lower `fir.has_value` operation to `llvm.return` operation. 2944e73cf2f0SMatthias Springer struct HasValueOpConversion 2945e73cf2f0SMatthias Springer : public mlir::OpConversionPattern<fir::HasValueOp> { 2946e73cf2f0SMatthias Springer using OpConversionPattern::OpConversionPattern; 2947dc48849fSKiran Chandramohan 2948db791b27SRamkumar Ramachandra llvm::LogicalResult 2949dc48849fSKiran Chandramohan matchAndRewrite(fir::HasValueOp op, OpAdaptor adaptor, 2950dc48849fSKiran Chandramohan mlir::ConversionPatternRewriter &rewriter) const override { 295144e58509SEric Schweitz rewriter.replaceOpWithNewOp<mlir::LLVM::ReturnOp>(op, 295244e58509SEric Schweitz adaptor.getOperands()); 295344e58509SEric Schweitz return mlir::success(); 2954dc48849fSKiran Chandramohan } 2955dc48849fSKiran Chandramohan }; 2956dc48849fSKiran Chandramohan 2957910b9372SJie Fu #ifndef NDEBUG 2958c8517f17SLeandro Lupori // Check if attr's type is compatible with ty. 2959c8517f17SLeandro Lupori // 2960c8517f17SLeandro Lupori // This is done by comparing attr's element type, converted to LLVM type, 2961c8517f17SLeandro Lupori // with ty's element type. 2962c8517f17SLeandro Lupori // 2963c8517f17SLeandro Lupori // Only integer and floating point (including complex) attributes are 2964c8517f17SLeandro Lupori // supported. Also, attr is expected to have a TensorType and ty is expected 2965c8517f17SLeandro Lupori // to be of LLVMArrayType. If any of the previous conditions is false, then 2966c8517f17SLeandro Lupori // the specified attr and ty are not supported by this function and are 2967c8517f17SLeandro Lupori // assumed to be compatible. 2968c8517f17SLeandro Lupori static inline bool attributeTypeIsCompatible(mlir::MLIRContext *ctx, 2969c8517f17SLeandro Lupori mlir::Attribute attr, 2970c8517f17SLeandro Lupori mlir::Type ty) { 2971c8517f17SLeandro Lupori // Get attr's LLVM element type. 2972c8517f17SLeandro Lupori if (!attr) 2973c8517f17SLeandro Lupori return true; 2974c8517f17SLeandro Lupori auto intOrFpEleAttr = mlir::dyn_cast<mlir::DenseIntOrFPElementsAttr>(attr); 2975c8517f17SLeandro Lupori if (!intOrFpEleAttr) 2976c8517f17SLeandro Lupori return true; 2977c8517f17SLeandro Lupori auto tensorTy = mlir::dyn_cast<mlir::TensorType>(intOrFpEleAttr.getType()); 2978c8517f17SLeandro Lupori if (!tensorTy) 2979c8517f17SLeandro Lupori return true; 2980c8517f17SLeandro Lupori mlir::Type attrEleTy = 2981c8517f17SLeandro Lupori mlir::LLVMTypeConverter(ctx).convertType(tensorTy.getElementType()); 2982c8517f17SLeandro Lupori 2983c8517f17SLeandro Lupori // Get ty's element type. 2984c8517f17SLeandro Lupori auto arrTy = mlir::dyn_cast<mlir::LLVM::LLVMArrayType>(ty); 2985c8517f17SLeandro Lupori if (!arrTy) 2986c8517f17SLeandro Lupori return true; 2987c8517f17SLeandro Lupori mlir::Type eleTy = arrTy.getElementType(); 2988c8517f17SLeandro Lupori while ((arrTy = mlir::dyn_cast<mlir::LLVM::LLVMArrayType>(eleTy))) 2989c8517f17SLeandro Lupori eleTy = arrTy.getElementType(); 2990c8517f17SLeandro Lupori 2991c8517f17SLeandro Lupori return attrEleTy == eleTy; 2992c8517f17SLeandro Lupori } 2993910b9372SJie Fu #endif 2994c8517f17SLeandro Lupori 2995dc48849fSKiran Chandramohan /// Lower `fir.global` operation to `llvm.global` operation. 2996dc48849fSKiran Chandramohan /// `fir.insert_on_range` operations are replaced with constant dense attribute 2997dc48849fSKiran Chandramohan /// if they are applied on the full range. 2998e9639e9cSValentin Clement (バレンタイン クレメン) struct GlobalOpConversion : public fir::FIROpConversion<fir::GlobalOp> { 2999dc48849fSKiran Chandramohan using FIROpConversion::FIROpConversion; 3000dc48849fSKiran Chandramohan 3001db791b27SRamkumar Ramachandra llvm::LogicalResult 3002dc48849fSKiran Chandramohan matchAndRewrite(fir::GlobalOp global, OpAdaptor adaptor, 3003dc48849fSKiran Chandramohan mlir::ConversionPatternRewriter &rewriter) const override { 3004f156b9ceSAbid Qadeer 3005cd12ffb6SAbid Qadeer llvm::SmallVector<mlir::Attribute> dbgExprs; 3006f156b9ceSAbid Qadeer 3007f156b9ceSAbid Qadeer if (auto fusedLoc = mlir::dyn_cast<mlir::FusedLoc>(global.getLoc())) { 3008afa4681cSAbid Qadeer if (auto gvExprAttr = mlir::dyn_cast_if_present<mlir::ArrayAttr>( 3009f156b9ceSAbid Qadeer fusedLoc.getMetadata())) { 3010afa4681cSAbid Qadeer for (auto attr : gvExprAttr.getAsRange<mlir::Attribute>()) 3011afa4681cSAbid Qadeer if (auto dbgAttr = 3012afa4681cSAbid Qadeer mlir::dyn_cast<mlir::LLVM::DIGlobalVariableExpressionAttr>( 3013afa4681cSAbid Qadeer attr)) 3014afa4681cSAbid Qadeer dbgExprs.push_back(dbgAttr); 3015f156b9ceSAbid Qadeer } 3016f156b9ceSAbid Qadeer } 3017f156b9ceSAbid Qadeer 3018dc48849fSKiran Chandramohan auto tyAttr = convertType(global.getType()); 30198a1ce2d6SjeanPerier if (auto boxType = mlir::dyn_cast<fir::BaseBoxType>(global.getType())) 30208a1ce2d6SjeanPerier tyAttr = this->lowerTy().convertBoxTypeAsStruct(boxType); 3021dc48849fSKiran Chandramohan auto loc = global.getLoc(); 3022c715e2ffSKazu Hirata mlir::Attribute initAttr = global.getInitVal().value_or(mlir::Attribute()); 3023c8517f17SLeandro Lupori assert(attributeTypeIsCompatible(global.getContext(), initAttr, tyAttr)); 3024dc48849fSKiran Chandramohan auto linkage = convertLinkage(global.getLinkName()); 3025c82fb16fSKazu Hirata auto isConst = global.getConstant().has_value(); 3026f156b9ceSAbid Qadeer mlir::SymbolRefAttr comdat; 3027f156b9ceSAbid Qadeer llvm::ArrayRef<mlir::NamedAttribute> attrs; 3028dc48849fSKiran Chandramohan auto g = rewriter.create<mlir::LLVM::GlobalOp>( 3029f156b9ceSAbid Qadeer loc, tyAttr, isConst, linkage, global.getSymName(), initAttr, 0, 0, 3030cd12ffb6SAbid Qadeer false, false, comdat, attrs, dbgExprs); 30316b44274dSAndrew Gozillon 3032c1654c38SValentin Clement (バレンタイン クレメン) if (global.getAlignment() && *global.getAlignment() > 0) 3033c1654c38SValentin Clement (バレンタイン クレメン) g.setAlignment(*global.getAlignment()); 3034c1654c38SValentin Clement (バレンタイン クレメン) 30358cb0c3bbSDavid Truby auto module = global->getParentOfType<mlir::ModuleOp>(); 30363e13acfbSValentin Clement (バレンタイン クレメン) auto gpuMod = global->getParentOfType<mlir::gpu::GPUModuleOp>(); 30378cb0c3bbSDavid Truby // Add comdat if necessary 30388cb0c3bbSDavid Truby if (fir::getTargetTriple(module).supportsCOMDAT() && 30398cb0c3bbSDavid Truby (linkage == mlir::LLVM::Linkage::Linkonce || 30403e13acfbSValentin Clement (バレンタイン クレメン) linkage == mlir::LLVM::Linkage::LinkonceODR) && 30413e13acfbSValentin Clement (バレンタイン クレメン) !gpuMod) { 30428cb0c3bbSDavid Truby addComdat(g, rewriter, module); 30438cb0c3bbSDavid Truby } 30448cb0c3bbSDavid Truby 30456b44274dSAndrew Gozillon // Apply all non-Fir::GlobalOp attributes to the LLVM::GlobalOp, preserving 30466b44274dSAndrew Gozillon // them; whilst taking care not to apply attributes that are lowered in 30476b44274dSAndrew Gozillon // other ways. 30486b44274dSAndrew Gozillon llvm::SmallDenseSet<llvm::StringRef> elidedAttrsSet( 30496b44274dSAndrew Gozillon global.getAttributeNames().begin(), global.getAttributeNames().end()); 30506b44274dSAndrew Gozillon for (auto &attr : global->getAttrs()) 30516b44274dSAndrew Gozillon if (!elidedAttrsSet.contains(attr.getName().strref())) 30526b44274dSAndrew Gozillon g->setAttr(attr.getName(), attr.getValue()); 30536b44274dSAndrew Gozillon 3054dc48849fSKiran Chandramohan auto &gr = g.getInitializerRegion(); 3055dc48849fSKiran Chandramohan rewriter.inlineRegionBefore(global.getRegion(), gr, gr.end()); 3056dc48849fSKiran Chandramohan if (!gr.empty()) { 3057dc48849fSKiran Chandramohan // Replace insert_on_range with a constant dense attribute if the 3058dc48849fSKiran Chandramohan // initialization is on the full range. 3059dc48849fSKiran Chandramohan auto insertOnRangeOps = gr.front().getOps<fir::InsertOnRangeOp>(); 3060dc48849fSKiran Chandramohan for (auto insertOp : insertOnRangeOps) { 3061dc48849fSKiran Chandramohan if (isFullRange(insertOp.getCoor(), insertOp.getType())) { 3062dc48849fSKiran Chandramohan auto seqTyAttr = convertType(insertOp.getType()); 3063dc48849fSKiran Chandramohan auto *op = insertOp.getVal().getDefiningOp(); 3064dc48849fSKiran Chandramohan auto constant = mlir::dyn_cast<mlir::arith::ConstantOp>(op); 3065dc48849fSKiran Chandramohan if (!constant) { 3066dc48849fSKiran Chandramohan auto convertOp = mlir::dyn_cast<fir::ConvertOp>(op); 3067dc48849fSKiran Chandramohan if (!convertOp) 3068dc48849fSKiran Chandramohan continue; 306944e58509SEric Schweitz constant = mlir::cast<mlir::arith::ConstantOp>( 3070dc48849fSKiran Chandramohan convertOp.getValue().getDefiningOp()); 3071dc48849fSKiran Chandramohan } 3072dc48849fSKiran Chandramohan mlir::Type vecType = mlir::VectorType::get( 3073dc48849fSKiran Chandramohan insertOp.getType().getShape(), constant.getType()); 3074dc48849fSKiran Chandramohan auto denseAttr = mlir::DenseElementsAttr::get( 3075fac349a1SChristian Sigg mlir::cast<mlir::ShapedType>(vecType), constant.getValue()); 3076dc48849fSKiran Chandramohan rewriter.setInsertionPointAfter(insertOp); 3077dc48849fSKiran Chandramohan rewriter.replaceOpWithNewOp<mlir::arith::ConstantOp>( 3078dc48849fSKiran Chandramohan insertOp, seqTyAttr, denseAttr); 3079dc48849fSKiran Chandramohan } 3080dc48849fSKiran Chandramohan } 3081dc48849fSKiran Chandramohan } 3082dc48849fSKiran Chandramohan rewriter.eraseOp(global); 308344e58509SEric Schweitz return mlir::success(); 3084dc48849fSKiran Chandramohan } 3085dc48849fSKiran Chandramohan 3086dc48849fSKiran Chandramohan bool isFullRange(mlir::DenseIntElementsAttr indexes, 3087dc48849fSKiran Chandramohan fir::SequenceType seqTy) const { 3088dc48849fSKiran Chandramohan auto extents = seqTy.getShape(); 3089dc48849fSKiran Chandramohan if (indexes.size() / 2 != static_cast<int64_t>(extents.size())) 3090dc48849fSKiran Chandramohan return false; 3091dc48849fSKiran Chandramohan auto cur_index = indexes.value_begin<int64_t>(); 3092dc48849fSKiran Chandramohan for (unsigned i = 0; i < indexes.size(); i += 2) { 3093dc48849fSKiran Chandramohan if (*(cur_index++) != 0) 3094dc48849fSKiran Chandramohan return false; 3095dc48849fSKiran Chandramohan if (*(cur_index++) != extents[i / 2] - 1) 3096dc48849fSKiran Chandramohan return false; 3097dc48849fSKiran Chandramohan } 3098dc48849fSKiran Chandramohan return true; 3099dc48849fSKiran Chandramohan } 3100dc48849fSKiran Chandramohan 3101dc48849fSKiran Chandramohan // TODO: String comparaison should be avoided. Replace linkName with an 3102dc48849fSKiran Chandramohan // enumeration. 310344e58509SEric Schweitz mlir::LLVM::Linkage 310422426110SRamkumar Ramachandra convertLinkage(std::optional<llvm::StringRef> optLinkage) const { 310586b8c1d9SKazu Hirata if (optLinkage) { 3106009ab172SKazu Hirata auto name = *optLinkage; 3107dc48849fSKiran Chandramohan if (name == "internal") 3108dc48849fSKiran Chandramohan return mlir::LLVM::Linkage::Internal; 3109dc48849fSKiran Chandramohan if (name == "linkonce") 3110dc48849fSKiran Chandramohan return mlir::LLVM::Linkage::Linkonce; 311130a0fbf5SJean Perier if (name == "linkonce_odr") 311230a0fbf5SJean Perier return mlir::LLVM::Linkage::LinkonceODR; 3113dc48849fSKiran Chandramohan if (name == "common") 3114dc48849fSKiran Chandramohan return mlir::LLVM::Linkage::Common; 3115dc48849fSKiran Chandramohan if (name == "weak") 3116dc48849fSKiran Chandramohan return mlir::LLVM::Linkage::Weak; 3117dc48849fSKiran Chandramohan } 3118dc48849fSKiran Chandramohan return mlir::LLVM::Linkage::External; 3119dc48849fSKiran Chandramohan } 31208cb0c3bbSDavid Truby 31218cb0c3bbSDavid Truby private: 31228cb0c3bbSDavid Truby static void addComdat(mlir::LLVM::GlobalOp &global, 31238cb0c3bbSDavid Truby mlir::ConversionPatternRewriter &rewriter, 3124c870632eSMatthias Springer mlir::ModuleOp module) { 31258cb0c3bbSDavid Truby const char *comdatName = "__llvm_comdat"; 31268cb0c3bbSDavid Truby mlir::LLVM::ComdatOp comdatOp = 31278cb0c3bbSDavid Truby module.lookupSymbol<mlir::LLVM::ComdatOp>(comdatName); 31288cb0c3bbSDavid Truby if (!comdatOp) { 31298cb0c3bbSDavid Truby comdatOp = 31308cb0c3bbSDavid Truby rewriter.create<mlir::LLVM::ComdatOp>(module.getLoc(), comdatName); 31318cb0c3bbSDavid Truby } 3132466b58baSValentin Clement (バレンタイン クレメン) if (auto select = comdatOp.lookupSymbol<mlir::LLVM::ComdatSelectorOp>( 3133466b58baSValentin Clement (バレンタイン クレメン) global.getSymName())) 3134466b58baSValentin Clement (バレンタイン クレメン) return; 31358cb0c3bbSDavid Truby mlir::OpBuilder::InsertionGuard guard(rewriter); 31368cb0c3bbSDavid Truby rewriter.setInsertionPointToEnd(&comdatOp.getBody().back()); 31378cb0c3bbSDavid Truby auto selectorOp = rewriter.create<mlir::LLVM::ComdatSelectorOp>( 31388cb0c3bbSDavid Truby comdatOp.getLoc(), global.getSymName(), 31398cb0c3bbSDavid Truby mlir::LLVM::comdat::Comdat::Any); 31408cb0c3bbSDavid Truby global.setComdatAttr(mlir::SymbolRefAttr::get( 31418cb0c3bbSDavid Truby rewriter.getContext(), comdatName, 31428cb0c3bbSDavid Truby mlir::FlatSymbolRefAttr::get(selectorOp.getSymNameAttr()))); 31438cb0c3bbSDavid Truby } 3144dc48849fSKiran Chandramohan }; 3145dc48849fSKiran Chandramohan 3146dc48849fSKiran Chandramohan /// `fir.load` --> `llvm.load` 3147e9639e9cSValentin Clement (バレンタイン クレメン) struct LoadOpConversion : public fir::FIROpConversion<fir::LoadOp> { 3148dc48849fSKiran Chandramohan using FIROpConversion::FIROpConversion; 3149dc48849fSKiran Chandramohan 3150db791b27SRamkumar Ramachandra llvm::LogicalResult 3151dc48849fSKiran Chandramohan matchAndRewrite(fir::LoadOp load, OpAdaptor adaptor, 3152dc48849fSKiran Chandramohan mlir::ConversionPatternRewriter &rewriter) const override { 31530c9a0235SAsher Mancinelli 31548a1ce2d6SjeanPerier mlir::Type llvmLoadTy = convertObjectType(load.getType()); 3155fac349a1SChristian Sigg if (auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(load.getType())) { 31560c9a0235SAsher Mancinelli // fir.box is a special case because it is considered an ssa value in 31579e1395efSJean Perier // fir, but it is lowered as a pointer to a descriptor. So 31589e1395efSJean Perier // fir.ref<fir.box> and fir.box end up being the same llvm types and 31599e1395efSJean Perier // loading a fir.ref<fir.box> is implemented as taking a snapshot of the 31609e1395efSJean Perier // descriptor value into a new descriptor temp. 31619e1395efSJean Perier auto inputBoxStorage = adaptor.getOperands()[0]; 31625e1f87e8SValentin Clement (バレンタイン クレメン) mlir::Value newBoxStorage; 31639e1395efSJean Perier mlir::Location loc = load.getLoc(); 31645e1f87e8SValentin Clement (バレンタイン クレメン) if (auto callOp = mlir::dyn_cast_or_null<mlir::LLVM::CallOp>( 31655e1f87e8SValentin Clement (バレンタイン クレメン) inputBoxStorage.getDefiningOp())) { 31665e1f87e8SValentin Clement (バレンタイン クレメン) if (callOp.getCallee() && 31675e1f87e8SValentin Clement (バレンタイン クレメン) (*callOp.getCallee()) 3168e650ac16SValentin Clement (バレンタイン クレメン) .starts_with(RTNAME_STRING(CUFAllocDescriptor))) { 31695e1f87e8SValentin Clement (バレンタイン クレメン) // CUDA Fortran local descriptor are allocated in managed memory. So 31705e1f87e8SValentin Clement (バレンタイン クレメン) // new storage must be allocated the same way. 31715e1f87e8SValentin Clement (バレンタイン クレメン) auto mod = load->getParentOfType<mlir::ModuleOp>(); 31725e1f87e8SValentin Clement (バレンタイン クレメン) newBoxStorage = 31735e1f87e8SValentin Clement (バレンタイン クレメン) genCUFAllocDescriptor(loc, rewriter, mod, boxTy, lowerTy()); 31745e1f87e8SValentin Clement (バレンタイン クレメン) } 31755e1f87e8SValentin Clement (バレンタイン クレメン) } 31765e1f87e8SValentin Clement (バレンタイン クレメン) if (!newBoxStorage) 31775e1f87e8SValentin Clement (バレンタイン クレメン) newBoxStorage = genAllocaAndAddrCastWithType(loc, llvmLoadTy, 31785e1f87e8SValentin Clement (バレンタイン クレメン) defaultAlign, rewriter); 3179e398383fSjeanPerier 3180e398383fSjeanPerier TypePair boxTypePair{boxTy, llvmLoadTy}; 3181e398383fSjeanPerier mlir::Value boxSize = 3182e398383fSjeanPerier computeBoxSize(loc, boxTypePair, inputBoxStorage, rewriter); 3183e398383fSjeanPerier auto memcpy = rewriter.create<mlir::LLVM::MemcpyOp>( 3184e398383fSjeanPerier loc, newBoxStorage, inputBoxStorage, boxSize, /*isVolatile=*/false); 31850c9a0235SAsher Mancinelli 3186e398383fSjeanPerier if (std::optional<mlir::ArrayAttr> optionalTag = load.getTbaa()) 3187e398383fSjeanPerier memcpy.setTBAATags(*optionalTag); 3188e398383fSjeanPerier else 3189e398383fSjeanPerier attachTBAATag(memcpy, boxTy, boxTy, nullptr); 3190abeb6c9fSagozillon rewriter.replaceOp(load, newBoxStorage); 3191dc48849fSKiran Chandramohan } else { 31929c84d20fSSlava Zakharin auto loadOp = rewriter.create<mlir::LLVM::LoadOp>( 31938a1ce2d6SjeanPerier load.getLoc(), llvmLoadTy, adaptor.getOperands(), load->getAttrs()); 31948301e485STom Eccles if (std::optional<mlir::ArrayAttr> optionalTag = load.getTbaa()) 31958301e485STom Eccles loadOp.setTBAATags(*optionalTag); 31968301e485STom Eccles else 31979c84d20fSSlava Zakharin attachTBAATag(loadOp, load.getType(), load.getType(), nullptr); 31989c84d20fSSlava Zakharin rewriter.replaceOp(load, loadOp.getResult()); 3199dc48849fSKiran Chandramohan } 320044e58509SEric Schweitz return mlir::success(); 3201dc48849fSKiran Chandramohan } 3202dc48849fSKiran Chandramohan }; 3203dc48849fSKiran Chandramohan 3204dc48849fSKiran Chandramohan /// Lower `fir.no_reassoc` to LLVM IR dialect. 3205dc48849fSKiran Chandramohan /// TODO: how do we want to enforce this in LLVM-IR? Can we manipulate the fast 3206dc48849fSKiran Chandramohan /// math flags? 3207e9639e9cSValentin Clement (バレンタイン クレメン) struct NoReassocOpConversion : public fir::FIROpConversion<fir::NoReassocOp> { 3208dc48849fSKiran Chandramohan using FIROpConversion::FIROpConversion; 3209dc48849fSKiran Chandramohan 3210db791b27SRamkumar Ramachandra llvm::LogicalResult 3211dc48849fSKiran Chandramohan matchAndRewrite(fir::NoReassocOp noreassoc, OpAdaptor adaptor, 3212dc48849fSKiran Chandramohan mlir::ConversionPatternRewriter &rewriter) const override { 3213dc48849fSKiran Chandramohan rewriter.replaceOp(noreassoc, adaptor.getOperands()[0]); 321444e58509SEric Schweitz return mlir::success(); 3215dc48849fSKiran Chandramohan } 3216dc48849fSKiran Chandramohan }; 3217dc48849fSKiran Chandramohan 3218dc48849fSKiran Chandramohan static void genCondBrOp(mlir::Location loc, mlir::Value cmp, mlir::Block *dest, 321922426110SRamkumar Ramachandra std::optional<mlir::ValueRange> destOps, 3220dc48849fSKiran Chandramohan mlir::ConversionPatternRewriter &rewriter, 3221dc48849fSKiran Chandramohan mlir::Block *newBlock) { 322286b8c1d9SKazu Hirata if (destOps) 3223009ab172SKazu Hirata rewriter.create<mlir::LLVM::CondBrOp>(loc, cmp, dest, *destOps, newBlock, 3224009ab172SKazu Hirata mlir::ValueRange()); 3225dc48849fSKiran Chandramohan else 3226dc48849fSKiran Chandramohan rewriter.create<mlir::LLVM::CondBrOp>(loc, cmp, dest, newBlock); 3227dc48849fSKiran Chandramohan } 3228dc48849fSKiran Chandramohan 3229dc48849fSKiran Chandramohan template <typename A, typename B> 323022426110SRamkumar Ramachandra static void genBrOp(A caseOp, mlir::Block *dest, std::optional<B> destOps, 3231dc48849fSKiran Chandramohan mlir::ConversionPatternRewriter &rewriter) { 323286b8c1d9SKazu Hirata if (destOps) 3233009ab172SKazu Hirata rewriter.replaceOpWithNewOp<mlir::LLVM::BrOp>(caseOp, *destOps, dest); 3234dc48849fSKiran Chandramohan else 32359a417395SKazu Hirata rewriter.replaceOpWithNewOp<mlir::LLVM::BrOp>(caseOp, std::nullopt, dest); 3236dc48849fSKiran Chandramohan } 3237dc48849fSKiran Chandramohan 3238dc48849fSKiran Chandramohan static void genCaseLadderStep(mlir::Location loc, mlir::Value cmp, 3239dc48849fSKiran Chandramohan mlir::Block *dest, 324022426110SRamkumar Ramachandra std::optional<mlir::ValueRange> destOps, 3241dc48849fSKiran Chandramohan mlir::ConversionPatternRewriter &rewriter) { 3242dc48849fSKiran Chandramohan auto *thisBlock = rewriter.getInsertionBlock(); 3243dc48849fSKiran Chandramohan auto *newBlock = createBlock(rewriter, dest); 3244dc48849fSKiran Chandramohan rewriter.setInsertionPointToEnd(thisBlock); 3245dc48849fSKiran Chandramohan genCondBrOp(loc, cmp, dest, destOps, rewriter, newBlock); 3246dc48849fSKiran Chandramohan rewriter.setInsertionPointToEnd(newBlock); 3247dc48849fSKiran Chandramohan } 3248dc48849fSKiran Chandramohan 3249dc48849fSKiran Chandramohan /// Conversion of `fir.select_case` 3250dc48849fSKiran Chandramohan /// 3251dc48849fSKiran Chandramohan /// The `fir.select_case` operation is converted to a if-then-else ladder. 3252dc48849fSKiran Chandramohan /// Depending on the case condition type, one or several comparison and 3253dc48849fSKiran Chandramohan /// conditional branching can be generated. 3254dc48849fSKiran Chandramohan /// 3255fc04472aSFangrui Song /// A point value case such as `case(4)`, a lower bound case such as 3256dc48849fSKiran Chandramohan /// `case(5:)` or an upper bound case such as `case(:3)` are converted to a 3257dc48849fSKiran Chandramohan /// simple comparison between the selector value and the constant value in the 3258dc48849fSKiran Chandramohan /// case. The block associated with the case condition is then executed if 3259dc48849fSKiran Chandramohan /// the comparison succeed otherwise it branch to the next block with the 3260fc04472aSFangrui Song /// comparison for the next case conditon. 3261dc48849fSKiran Chandramohan /// 3262dc48849fSKiran Chandramohan /// A closed interval case condition such as `case(7:10)` is converted with a 3263dc48849fSKiran Chandramohan /// first comparison and conditional branching for the lower bound. If 3264dc48849fSKiran Chandramohan /// successful, it branch to a second block with the comparison for the 3265dc48849fSKiran Chandramohan /// upper bound in the same case condition. 3266dc48849fSKiran Chandramohan /// 3267dc48849fSKiran Chandramohan /// TODO: lowering of CHARACTER type cases is not handled yet. 3268e9639e9cSValentin Clement (バレンタイン クレメン) struct SelectCaseOpConversion : public fir::FIROpConversion<fir::SelectCaseOp> { 3269dc48849fSKiran Chandramohan using FIROpConversion::FIROpConversion; 3270dc48849fSKiran Chandramohan 3271db791b27SRamkumar Ramachandra llvm::LogicalResult 3272dc48849fSKiran Chandramohan matchAndRewrite(fir::SelectCaseOp caseOp, OpAdaptor adaptor, 3273dc48849fSKiran Chandramohan mlir::ConversionPatternRewriter &rewriter) const override { 3274dc48849fSKiran Chandramohan unsigned conds = caseOp.getNumConditions(); 3275dc48849fSKiran Chandramohan llvm::ArrayRef<mlir::Attribute> cases = caseOp.getCases().getValue(); 3276dc48849fSKiran Chandramohan // Type can be CHARACTER, INTEGER, or LOGICAL (C1145) 3277dc48849fSKiran Chandramohan auto ty = caseOp.getSelector().getType(); 3278fac349a1SChristian Sigg if (mlir::isa<fir::CharacterType>(ty)) { 3279dc48849fSKiran Chandramohan TODO(caseOp.getLoc(), "fir.select_case codegen with character type"); 328044e58509SEric Schweitz return mlir::failure(); 3281dc48849fSKiran Chandramohan } 3282dc48849fSKiran Chandramohan mlir::Value selector = caseOp.getSelector(adaptor.getOperands()); 3283dc48849fSKiran Chandramohan auto loc = caseOp.getLoc(); 3284dc48849fSKiran Chandramohan for (unsigned t = 0; t != conds; ++t) { 3285dc48849fSKiran Chandramohan mlir::Block *dest = caseOp.getSuccessor(t); 328622426110SRamkumar Ramachandra std::optional<mlir::ValueRange> destOps = 3287dc48849fSKiran Chandramohan caseOp.getSuccessorOperands(adaptor.getOperands(), t); 328822426110SRamkumar Ramachandra std::optional<mlir::ValueRange> cmpOps = 3289dc48849fSKiran Chandramohan *caseOp.getCompareOperands(adaptor.getOperands(), t); 3290dc48849fSKiran Chandramohan mlir::Attribute attr = cases[t]; 3291101f977fSKrzysztof Parzyszek assert(mlir::isa<mlir::UnitAttr>(attr) || cmpOps.has_value()); 3292fac349a1SChristian Sigg if (mlir::isa<fir::PointIntervalAttr>(attr)) { 3293dc48849fSKiran Chandramohan auto cmp = rewriter.create<mlir::LLVM::ICmpOp>( 3294101f977fSKrzysztof Parzyszek loc, mlir::LLVM::ICmpPredicate::eq, selector, cmpOps->front()); 3295dc48849fSKiran Chandramohan genCaseLadderStep(loc, cmp, dest, destOps, rewriter); 3296dc48849fSKiran Chandramohan continue; 3297dc48849fSKiran Chandramohan } 3298fac349a1SChristian Sigg if (mlir::isa<fir::LowerBoundAttr>(attr)) { 3299dc48849fSKiran Chandramohan auto cmp = rewriter.create<mlir::LLVM::ICmpOp>( 3300101f977fSKrzysztof Parzyszek loc, mlir::LLVM::ICmpPredicate::sle, cmpOps->front(), selector); 3301dc48849fSKiran Chandramohan genCaseLadderStep(loc, cmp, dest, destOps, rewriter); 3302dc48849fSKiran Chandramohan continue; 3303dc48849fSKiran Chandramohan } 3304fac349a1SChristian Sigg if (mlir::isa<fir::UpperBoundAttr>(attr)) { 3305dc48849fSKiran Chandramohan auto cmp = rewriter.create<mlir::LLVM::ICmpOp>( 3306101f977fSKrzysztof Parzyszek loc, mlir::LLVM::ICmpPredicate::sle, selector, cmpOps->front()); 3307dc48849fSKiran Chandramohan genCaseLadderStep(loc, cmp, dest, destOps, rewriter); 3308dc48849fSKiran Chandramohan continue; 3309dc48849fSKiran Chandramohan } 3310fac349a1SChristian Sigg if (mlir::isa<fir::ClosedIntervalAttr>(attr)) { 3311101f977fSKrzysztof Parzyszek mlir::Value caseArg0 = *cmpOps->begin(); 3312101f977fSKrzysztof Parzyszek auto cmp0 = rewriter.create<mlir::LLVM::ICmpOp>( 3313101f977fSKrzysztof Parzyszek loc, mlir::LLVM::ICmpPredicate::sle, caseArg0, selector); 3314dc48849fSKiran Chandramohan auto *thisBlock = rewriter.getInsertionBlock(); 3315dc48849fSKiran Chandramohan auto *newBlock1 = createBlock(rewriter, dest); 3316dc48849fSKiran Chandramohan auto *newBlock2 = createBlock(rewriter, dest); 3317dc48849fSKiran Chandramohan rewriter.setInsertionPointToEnd(thisBlock); 3318101f977fSKrzysztof Parzyszek rewriter.create<mlir::LLVM::CondBrOp>(loc, cmp0, newBlock1, newBlock2); 3319dc48849fSKiran Chandramohan rewriter.setInsertionPointToEnd(newBlock1); 3320101f977fSKrzysztof Parzyszek mlir::Value caseArg1 = *(cmpOps->begin() + 1); 3321101f977fSKrzysztof Parzyszek auto cmp1 = rewriter.create<mlir::LLVM::ICmpOp>( 3322101f977fSKrzysztof Parzyszek loc, mlir::LLVM::ICmpPredicate::sle, selector, caseArg1); 3323101f977fSKrzysztof Parzyszek genCondBrOp(loc, cmp1, dest, destOps, rewriter, newBlock2); 3324dc48849fSKiran Chandramohan rewriter.setInsertionPointToEnd(newBlock2); 3325dc48849fSKiran Chandramohan continue; 3326dc48849fSKiran Chandramohan } 3327fac349a1SChristian Sigg assert(mlir::isa<mlir::UnitAttr>(attr)); 3328dc48849fSKiran Chandramohan assert((t + 1 == conds) && "unit must be last"); 3329dc48849fSKiran Chandramohan genBrOp(caseOp, dest, destOps, rewriter); 3330dc48849fSKiran Chandramohan } 333144e58509SEric Schweitz return mlir::success(); 3332dc48849fSKiran Chandramohan } 3333dc48849fSKiran Chandramohan }; 3334dc48849fSKiran Chandramohan 3335eb6c4197SMatthias Springer /// Helper function for converting select ops. This function converts the 3336eb6c4197SMatthias Springer /// signature of the given block. If the new block signature is different from 3337eb6c4197SMatthias Springer /// `expectedTypes`, returns "failure". 3338eb6c4197SMatthias Springer static llvm::FailureOr<mlir::Block *> 3339eb6c4197SMatthias Springer getConvertedBlock(mlir::ConversionPatternRewriter &rewriter, 3340eb6c4197SMatthias Springer const mlir::TypeConverter *converter, 3341eb6c4197SMatthias Springer mlir::Operation *branchOp, mlir::Block *block, 3342eb6c4197SMatthias Springer mlir::TypeRange expectedTypes) { 3343eb6c4197SMatthias Springer assert(converter && "expected non-null type converter"); 3344eb6c4197SMatthias Springer assert(!block->isEntryBlock() && "entry blocks have no predecessors"); 3345eb6c4197SMatthias Springer 3346eb6c4197SMatthias Springer // There is nothing to do if the types already match. 3347eb6c4197SMatthias Springer if (block->getArgumentTypes() == expectedTypes) 3348eb6c4197SMatthias Springer return block; 3349eb6c4197SMatthias Springer 3350eb6c4197SMatthias Springer // Compute the new block argument types and convert the block. 3351eb6c4197SMatthias Springer std::optional<mlir::TypeConverter::SignatureConversion> conversion = 3352eb6c4197SMatthias Springer converter->convertBlockSignature(block); 3353eb6c4197SMatthias Springer if (!conversion) 3354eb6c4197SMatthias Springer return rewriter.notifyMatchFailure(branchOp, 3355eb6c4197SMatthias Springer "could not compute block signature"); 3356eb6c4197SMatthias Springer if (expectedTypes != conversion->getConvertedTypes()) 3357eb6c4197SMatthias Springer return rewriter.notifyMatchFailure( 3358eb6c4197SMatthias Springer branchOp, 3359eb6c4197SMatthias Springer "mismatch between adaptor operand types and computed block signature"); 3360eb6c4197SMatthias Springer return rewriter.applySignatureConversion(block, *conversion, converter); 3361eb6c4197SMatthias Springer } 3362eb6c4197SMatthias Springer 3363dc48849fSKiran Chandramohan template <typename OP> 3364eb6c4197SMatthias Springer static llvm::LogicalResult 3365eb6c4197SMatthias Springer selectMatchAndRewrite(const fir::LLVMTypeConverter &lowering, OP select, 3366eb6c4197SMatthias Springer typename OP::Adaptor adaptor, 3367eb6c4197SMatthias Springer mlir::ConversionPatternRewriter &rewriter, 3368eb6c4197SMatthias Springer const mlir::TypeConverter *converter) { 3369dc48849fSKiran Chandramohan unsigned conds = select.getNumConditions(); 3370dc48849fSKiran Chandramohan auto cases = select.getCases().getValue(); 3371dc48849fSKiran Chandramohan mlir::Value selector = adaptor.getSelector(); 3372dc48849fSKiran Chandramohan auto loc = select.getLoc(); 3373dc48849fSKiran Chandramohan assert(conds > 0 && "select must have cases"); 3374dc48849fSKiran Chandramohan 3375dc48849fSKiran Chandramohan llvm::SmallVector<mlir::Block *> destinations; 3376dc48849fSKiran Chandramohan llvm::SmallVector<mlir::ValueRange> destinationsOperands; 3377dc48849fSKiran Chandramohan mlir::Block *defaultDestination; 3378dc48849fSKiran Chandramohan mlir::ValueRange defaultOperands; 3379dc48849fSKiran Chandramohan llvm::SmallVector<int32_t> caseValues; 3380dc48849fSKiran Chandramohan 3381dc48849fSKiran Chandramohan for (unsigned t = 0; t != conds; ++t) { 3382dc48849fSKiran Chandramohan mlir::Block *dest = select.getSuccessor(t); 3383dc48849fSKiran Chandramohan auto destOps = select.getSuccessorOperands(adaptor.getOperands(), t); 3384dc48849fSKiran Chandramohan const mlir::Attribute &attr = cases[t]; 3385fac349a1SChristian Sigg if (auto intAttr = mlir::dyn_cast<mlir::IntegerAttr>(attr)) { 338686b8c1d9SKazu Hirata destinationsOperands.push_back(destOps ? *destOps : mlir::ValueRange{}); 3387eb6c4197SMatthias Springer auto convertedBlock = 3388eb6c4197SMatthias Springer getConvertedBlock(rewriter, converter, select, dest, 3389eb6c4197SMatthias Springer mlir::TypeRange(destinationsOperands.back())); 3390eb6c4197SMatthias Springer if (mlir::failed(convertedBlock)) 3391eb6c4197SMatthias Springer return mlir::failure(); 3392eb6c4197SMatthias Springer destinations.push_back(*convertedBlock); 3393dc48849fSKiran Chandramohan caseValues.push_back(intAttr.getInt()); 3394dc48849fSKiran Chandramohan continue; 3395dc48849fSKiran Chandramohan } 3396bd9fdce6SChristian Sigg assert(mlir::dyn_cast_or_null<mlir::UnitAttr>(attr)); 3397dc48849fSKiran Chandramohan assert((t + 1 == conds) && "unit must be last"); 339886b8c1d9SKazu Hirata defaultOperands = destOps ? *destOps : mlir::ValueRange{}; 3399eb6c4197SMatthias Springer auto convertedBlock = getConvertedBlock(rewriter, converter, select, dest, 3400eb6c4197SMatthias Springer mlir::TypeRange(defaultOperands)); 3401eb6c4197SMatthias Springer if (mlir::failed(convertedBlock)) 3402eb6c4197SMatthias Springer return mlir::failure(); 3403eb6c4197SMatthias Springer defaultDestination = *convertedBlock; 3404dc48849fSKiran Chandramohan } 3405dc48849fSKiran Chandramohan 3406dc48849fSKiran Chandramohan // LLVM::SwitchOp takes a i32 type for the selector. 3407dc48849fSKiran Chandramohan if (select.getSelector().getType() != rewriter.getI32Type()) 340844e58509SEric Schweitz selector = rewriter.create<mlir::LLVM::TruncOp>(loc, rewriter.getI32Type(), 340944e58509SEric Schweitz selector); 3410dc48849fSKiran Chandramohan 3411dc48849fSKiran Chandramohan rewriter.replaceOpWithNewOp<mlir::LLVM::SwitchOp>( 3412dc48849fSKiran Chandramohan select, selector, 3413dc48849fSKiran Chandramohan /*defaultDestination=*/defaultDestination, 3414dc48849fSKiran Chandramohan /*defaultOperands=*/defaultOperands, 3415dc48849fSKiran Chandramohan /*caseValues=*/caseValues, 3416dc48849fSKiran Chandramohan /*caseDestinations=*/destinations, 3417dc48849fSKiran Chandramohan /*caseOperands=*/destinationsOperands, 341844e58509SEric Schweitz /*branchWeights=*/llvm::ArrayRef<std::int32_t>()); 3419eb6c4197SMatthias Springer return mlir::success(); 3420dc48849fSKiran Chandramohan } 3421dc48849fSKiran Chandramohan 3422dc48849fSKiran Chandramohan /// conversion of fir::SelectOp to an if-then-else ladder 3423e9639e9cSValentin Clement (バレンタイン クレメン) struct SelectOpConversion : public fir::FIROpConversion<fir::SelectOp> { 3424dc48849fSKiran Chandramohan using FIROpConversion::FIROpConversion; 3425dc48849fSKiran Chandramohan 3426db791b27SRamkumar Ramachandra llvm::LogicalResult 3427dc48849fSKiran Chandramohan matchAndRewrite(fir::SelectOp op, OpAdaptor adaptor, 3428dc48849fSKiran Chandramohan mlir::ConversionPatternRewriter &rewriter) const override { 3429eb6c4197SMatthias Springer return selectMatchAndRewrite<fir::SelectOp>(lowerTy(), op, adaptor, 3430eb6c4197SMatthias Springer rewriter, getTypeConverter()); 3431dc48849fSKiran Chandramohan } 3432dc48849fSKiran Chandramohan }; 3433dc48849fSKiran Chandramohan 3434dc48849fSKiran Chandramohan /// conversion of fir::SelectRankOp to an if-then-else ladder 3435e9639e9cSValentin Clement (バレンタイン クレメン) struct SelectRankOpConversion : public fir::FIROpConversion<fir::SelectRankOp> { 3436dc48849fSKiran Chandramohan using FIROpConversion::FIROpConversion; 3437dc48849fSKiran Chandramohan 3438db791b27SRamkumar Ramachandra llvm::LogicalResult 3439dc48849fSKiran Chandramohan matchAndRewrite(fir::SelectRankOp op, OpAdaptor adaptor, 3440dc48849fSKiran Chandramohan mlir::ConversionPatternRewriter &rewriter) const override { 3441eb6c4197SMatthias Springer return selectMatchAndRewrite<fir::SelectRankOp>( 3442eb6c4197SMatthias Springer lowerTy(), op, adaptor, rewriter, getTypeConverter()); 3443dc48849fSKiran Chandramohan } 3444dc48849fSKiran Chandramohan }; 3445dc48849fSKiran Chandramohan 3446dc48849fSKiran Chandramohan /// Lower `fir.select_type` to LLVM IR dialect. 3447e9639e9cSValentin Clement (バレンタイン クレメン) struct SelectTypeOpConversion : public fir::FIROpConversion<fir::SelectTypeOp> { 3448dc48849fSKiran Chandramohan using FIROpConversion::FIROpConversion; 3449dc48849fSKiran Chandramohan 3450db791b27SRamkumar Ramachandra llvm::LogicalResult 3451dc48849fSKiran Chandramohan matchAndRewrite(fir::SelectTypeOp select, OpAdaptor adaptor, 3452dc48849fSKiran Chandramohan mlir::ConversionPatternRewriter &rewriter) const override { 3453dc48849fSKiran Chandramohan mlir::emitError(select.getLoc(), 3454dc48849fSKiran Chandramohan "fir.select_type should have already been converted"); 345544e58509SEric Schweitz return mlir::failure(); 3456dc48849fSKiran Chandramohan } 3457dc48849fSKiran Chandramohan }; 3458dc48849fSKiran Chandramohan 3459dc48849fSKiran Chandramohan /// `fir.store` --> `llvm.store` 3460e9639e9cSValentin Clement (バレンタイン クレメン) struct StoreOpConversion : public fir::FIROpConversion<fir::StoreOp> { 3461dc48849fSKiran Chandramohan using FIROpConversion::FIROpConversion; 3462dc48849fSKiran Chandramohan 3463db791b27SRamkumar Ramachandra llvm::LogicalResult 3464dc48849fSKiran Chandramohan matchAndRewrite(fir::StoreOp store, OpAdaptor adaptor, 3465dc48849fSKiran Chandramohan mlir::ConversionPatternRewriter &rewriter) const override { 3466dc48849fSKiran Chandramohan mlir::Location loc = store.getLoc(); 34679c84d20fSSlava Zakharin mlir::Type storeTy = store.getValue().getType(); 3468a7869192SjeanPerier mlir::Value llvmValue = adaptor.getValue(); 3469a7869192SjeanPerier mlir::Value llvmMemref = adaptor.getMemref(); 3470a7869192SjeanPerier mlir::LLVM::AliasAnalysisOpInterface newOp; 3471fac349a1SChristian Sigg if (auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(storeTy)) { 34728a1ce2d6SjeanPerier mlir::Type llvmBoxTy = lowerTy().convertBoxTypeAsStruct(boxTy); 34730c9a0235SAsher Mancinelli // Always use memcpy because LLVM is not as effective at optimizing 34740c9a0235SAsher Mancinelli // aggregate loads/stores as it is optimizing memcpy. 3475a7869192SjeanPerier TypePair boxTypePair{boxTy, llvmBoxTy}; 3476a7869192SjeanPerier mlir::Value boxSize = 3477a7869192SjeanPerier computeBoxSize(loc, boxTypePair, llvmValue, rewriter); 3478a7869192SjeanPerier newOp = rewriter.create<mlir::LLVM::MemcpyOp>( 3479a7869192SjeanPerier loc, llvmMemref, llvmValue, boxSize, /*isVolatile=*/false); 3480dc48849fSKiran Chandramohan } else { 3481a7869192SjeanPerier newOp = rewriter.create<mlir::LLVM::StoreOp>(loc, llvmValue, llvmMemref); 3482dc48849fSKiran Chandramohan } 34838301e485STom Eccles if (std::optional<mlir::ArrayAttr> optionalTag = store.getTbaa()) 3484a7869192SjeanPerier newOp.setTBAATags(*optionalTag); 34858301e485STom Eccles else 3486a7869192SjeanPerier attachTBAATag(newOp, storeTy, storeTy, nullptr); 34879c84d20fSSlava Zakharin rewriter.eraseOp(store); 348844e58509SEric Schweitz return mlir::success(); 3489dc48849fSKiran Chandramohan } 3490dc48849fSKiran Chandramohan }; 3491dc48849fSKiran Chandramohan 3492dc48849fSKiran Chandramohan namespace { 3493dc48849fSKiran Chandramohan 3494dc48849fSKiran Chandramohan /// Convert `fir.unboxchar` into two `llvm.extractvalue` instructions. One for 3495dc48849fSKiran Chandramohan /// the character buffer and one for the buffer length. 3496e9639e9cSValentin Clement (バレンタイン クレメン) struct UnboxCharOpConversion : public fir::FIROpConversion<fir::UnboxCharOp> { 3497dc48849fSKiran Chandramohan using FIROpConversion::FIROpConversion; 3498dc48849fSKiran Chandramohan 3499db791b27SRamkumar Ramachandra llvm::LogicalResult 3500dc48849fSKiran Chandramohan matchAndRewrite(fir::UnboxCharOp unboxchar, OpAdaptor adaptor, 3501dc48849fSKiran Chandramohan mlir::ConversionPatternRewriter &rewriter) const override { 3502dc48849fSKiran Chandramohan mlir::Type lenTy = convertType(unboxchar.getType(1)); 3503dc48849fSKiran Chandramohan mlir::Value tuple = adaptor.getOperands()[0]; 3504dc48849fSKiran Chandramohan 3505dc48849fSKiran Chandramohan mlir::Location loc = unboxchar.getLoc(); 3506dc48849fSKiran Chandramohan mlir::Value ptrToBuffer = 35075c5af910SJeff Niu rewriter.create<mlir::LLVM::ExtractValueOp>(loc, tuple, 0); 3508dc48849fSKiran Chandramohan 35095c5af910SJeff Niu auto len = rewriter.create<mlir::LLVM::ExtractValueOp>(loc, tuple, 1); 3510dc48849fSKiran Chandramohan mlir::Value lenAfterCast = integerCast(loc, rewriter, lenTy, len); 3511dc48849fSKiran Chandramohan 3512dc48849fSKiran Chandramohan rewriter.replaceOp(unboxchar, 351344e58509SEric Schweitz llvm::ArrayRef<mlir::Value>{ptrToBuffer, lenAfterCast}); 351444e58509SEric Schweitz return mlir::success(); 3515dc48849fSKiran Chandramohan } 3516dc48849fSKiran Chandramohan }; 3517dc48849fSKiran Chandramohan 3518dc48849fSKiran Chandramohan /// Lower `fir.unboxproc` operation. Unbox a procedure box value, yielding its 3519dc48849fSKiran Chandramohan /// components. 3520dc48849fSKiran Chandramohan /// TODO: Part of supporting Fortran 2003 procedure pointers. 3521e9639e9cSValentin Clement (バレンタイン クレメン) struct UnboxProcOpConversion : public fir::FIROpConversion<fir::UnboxProcOp> { 3522dc48849fSKiran Chandramohan using FIROpConversion::FIROpConversion; 3523dc48849fSKiran Chandramohan 3524db791b27SRamkumar Ramachandra llvm::LogicalResult 3525dc48849fSKiran Chandramohan matchAndRewrite(fir::UnboxProcOp unboxproc, OpAdaptor adaptor, 3526dc48849fSKiran Chandramohan mlir::ConversionPatternRewriter &rewriter) const override { 3527dc48849fSKiran Chandramohan TODO(unboxproc.getLoc(), "fir.unboxproc codegen"); 352844e58509SEric Schweitz return mlir::failure(); 3529dc48849fSKiran Chandramohan } 3530dc48849fSKiran Chandramohan }; 3531dc48849fSKiran Chandramohan 3532dc48849fSKiran Chandramohan /// convert to LLVM IR dialect `undef` 3533e9639e9cSValentin Clement (バレンタイン クレメン) struct UndefOpConversion : public fir::FIROpConversion<fir::UndefOp> { 3534dc48849fSKiran Chandramohan using FIROpConversion::FIROpConversion; 3535dc48849fSKiran Chandramohan 3536db791b27SRamkumar Ramachandra llvm::LogicalResult 3537dc48849fSKiran Chandramohan matchAndRewrite(fir::UndefOp undef, OpAdaptor, 3538dc48849fSKiran Chandramohan mlir::ConversionPatternRewriter &rewriter) const override { 3539dc48849fSKiran Chandramohan rewriter.replaceOpWithNewOp<mlir::LLVM::UndefOp>( 3540dc48849fSKiran Chandramohan undef, convertType(undef.getType())); 354144e58509SEric Schweitz return mlir::success(); 3542dc48849fSKiran Chandramohan } 3543dc48849fSKiran Chandramohan }; 3544dc48849fSKiran Chandramohan 3545e9639e9cSValentin Clement (バレンタイン クレメン) struct ZeroOpConversion : public fir::FIROpConversion<fir::ZeroOp> { 3546dc48849fSKiran Chandramohan using FIROpConversion::FIROpConversion; 3547dc48849fSKiran Chandramohan 3548db791b27SRamkumar Ramachandra llvm::LogicalResult 3549dc48849fSKiran Chandramohan matchAndRewrite(fir::ZeroOp zero, OpAdaptor, 3550dc48849fSKiran Chandramohan mlir::ConversionPatternRewriter &rewriter) const override { 3551dc48849fSKiran Chandramohan mlir::Type ty = convertType(zero.getType()); 355285175eddSTobias Gysi rewriter.replaceOpWithNewOp<mlir::LLVM::ZeroOp>(zero, ty); 355344e58509SEric Schweitz return mlir::success(); 3554dc48849fSKiran Chandramohan } 3555dc48849fSKiran Chandramohan }; 3556dc48849fSKiran Chandramohan 3557dc48849fSKiran Chandramohan /// `fir.unreachable` --> `llvm.unreachable` 3558e9639e9cSValentin Clement (バレンタイン クレメン) struct UnreachableOpConversion 3559e9639e9cSValentin Clement (バレンタイン クレメン) : public fir::FIROpConversion<fir::UnreachableOp> { 3560dc48849fSKiran Chandramohan using FIROpConversion::FIROpConversion; 3561dc48849fSKiran Chandramohan 3562db791b27SRamkumar Ramachandra llvm::LogicalResult 3563dc48849fSKiran Chandramohan matchAndRewrite(fir::UnreachableOp unreach, OpAdaptor adaptor, 3564dc48849fSKiran Chandramohan mlir::ConversionPatternRewriter &rewriter) const override { 3565dc48849fSKiran Chandramohan rewriter.replaceOpWithNewOp<mlir::LLVM::UnreachableOp>(unreach); 356644e58509SEric Schweitz return mlir::success(); 3567dc48849fSKiran Chandramohan } 3568dc48849fSKiran Chandramohan }; 3569dc48849fSKiran Chandramohan 3570dc48849fSKiran Chandramohan /// `fir.is_present` --> 3571dc48849fSKiran Chandramohan /// ``` 3572dc48849fSKiran Chandramohan /// %0 = llvm.mlir.constant(0 : i64) 3573dc48849fSKiran Chandramohan /// %1 = llvm.ptrtoint %0 3574dc48849fSKiran Chandramohan /// %2 = llvm.icmp "ne" %1, %0 : i64 3575dc48849fSKiran Chandramohan /// ``` 3576e9639e9cSValentin Clement (バレンタイン クレメン) struct IsPresentOpConversion : public fir::FIROpConversion<fir::IsPresentOp> { 3577dc48849fSKiran Chandramohan using FIROpConversion::FIROpConversion; 3578dc48849fSKiran Chandramohan 3579db791b27SRamkumar Ramachandra llvm::LogicalResult 3580dc48849fSKiran Chandramohan matchAndRewrite(fir::IsPresentOp isPresent, OpAdaptor adaptor, 3581dc48849fSKiran Chandramohan mlir::ConversionPatternRewriter &rewriter) const override { 3582dc48849fSKiran Chandramohan mlir::Type idxTy = lowerTy().indexType(); 3583dc48849fSKiran Chandramohan mlir::Location loc = isPresent.getLoc(); 3584dc48849fSKiran Chandramohan auto ptr = adaptor.getOperands()[0]; 3585dc48849fSKiran Chandramohan 3586fac349a1SChristian Sigg if (mlir::isa<fir::BoxCharType>(isPresent.getVal().getType())) { 358767d0d7acSMichele Scuttari [[maybe_unused]] auto structTy = 3588fac349a1SChristian Sigg mlir::cast<mlir::LLVM::LLVMStructType>(ptr.getType()); 3589dc48849fSKiran Chandramohan assert(!structTy.isOpaque() && !structTy.getBody().empty()); 3590dc48849fSKiran Chandramohan 35915c5af910SJeff Niu ptr = rewriter.create<mlir::LLVM::ExtractValueOp>(loc, ptr, 0); 3592dc48849fSKiran Chandramohan } 3593dc48849fSKiran Chandramohan mlir::LLVM::ConstantOp c0 = 3594dc48849fSKiran Chandramohan genConstantIndex(isPresent.getLoc(), idxTy, rewriter, 0); 3595dc48849fSKiran Chandramohan auto addr = rewriter.create<mlir::LLVM::PtrToIntOp>(loc, idxTy, ptr); 3596dc48849fSKiran Chandramohan rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>( 3597dc48849fSKiran Chandramohan isPresent, mlir::LLVM::ICmpPredicate::ne, addr, c0); 3598dc48849fSKiran Chandramohan 359944e58509SEric Schweitz return mlir::success(); 3600dc48849fSKiran Chandramohan } 3601dc48849fSKiran Chandramohan }; 3602dc48849fSKiran Chandramohan 3603dc48849fSKiran Chandramohan /// Create value signaling an absent optional argument in a call, e.g. 360485175eddSTobias Gysi /// `fir.absent !fir.ref<i64>` --> `llvm.mlir.zero : !llvm.ptr<i64>` 3605e9639e9cSValentin Clement (バレンタイン クレメン) struct AbsentOpConversion : public fir::FIROpConversion<fir::AbsentOp> { 3606dc48849fSKiran Chandramohan using FIROpConversion::FIROpConversion; 3607dc48849fSKiran Chandramohan 3608db791b27SRamkumar Ramachandra llvm::LogicalResult 3609dc48849fSKiran Chandramohan matchAndRewrite(fir::AbsentOp absent, OpAdaptor, 3610dc48849fSKiran Chandramohan mlir::ConversionPatternRewriter &rewriter) const override { 3611dc48849fSKiran Chandramohan mlir::Type ty = convertType(absent.getType()); 361285175eddSTobias Gysi rewriter.replaceOpWithNewOp<mlir::LLVM::ZeroOp>(absent, ty); 361344e58509SEric Schweitz return mlir::success(); 3614dc48849fSKiran Chandramohan } 3615dc48849fSKiran Chandramohan }; 36165d27abe6SValentin Clement 36177b5132daSValentin Clement // 36187b5132daSValentin Clement // Primitive operations on Complex types 36197b5132daSValentin Clement // 36207b5132daSValentin Clement 36216be0e979STom Eccles template <typename OPTY> 36226be0e979STom Eccles static inline mlir::LLVM::FastmathFlagsAttr getLLVMFMFAttr(OPTY op) { 36236be0e979STom Eccles return mlir::LLVM::FastmathFlagsAttr::get( 36246be0e979STom Eccles op.getContext(), 36256be0e979STom Eccles mlir::arith::convertArithFastMathFlagsToLLVM(op.getFastmath())); 36266be0e979STom Eccles } 36276be0e979STom Eccles 36287b5132daSValentin Clement /// Generate inline code for complex addition/subtraction 36297b5132daSValentin Clement template <typename LLVMOP, typename OPTY> 3630c2acd453SAlexisPerry static mlir::LLVM::InsertValueOp 3631c2acd453SAlexisPerry complexSum(OPTY sumop, mlir::ValueRange opnds, 36327b5132daSValentin Clement mlir::ConversionPatternRewriter &rewriter, 3633ce254598SMatthias Springer const fir::LLVMTypeConverter &lowering) { 36346be0e979STom Eccles mlir::LLVM::FastmathFlagsAttr fmf = getLLVMFMFAttr(sumop); 36357b5132daSValentin Clement mlir::Value a = opnds[0]; 36367b5132daSValentin Clement mlir::Value b = opnds[1]; 36377b5132daSValentin Clement auto loc = sumop.getLoc(); 36387b5132daSValentin Clement mlir::Type eleTy = lowering.convertType(getComplexEleTy(sumop.getType())); 36397b5132daSValentin Clement mlir::Type ty = lowering.convertType(sumop.getType()); 36405c5af910SJeff Niu auto x0 = rewriter.create<mlir::LLVM::ExtractValueOp>(loc, a, 0); 36415c5af910SJeff Niu auto y0 = rewriter.create<mlir::LLVM::ExtractValueOp>(loc, a, 1); 36425c5af910SJeff Niu auto x1 = rewriter.create<mlir::LLVM::ExtractValueOp>(loc, b, 0); 36435c5af910SJeff Niu auto y1 = rewriter.create<mlir::LLVM::ExtractValueOp>(loc, b, 1); 36446be0e979STom Eccles auto rx = rewriter.create<LLVMOP>(loc, eleTy, x0, x1, fmf); 36456be0e979STom Eccles auto ry = rewriter.create<LLVMOP>(loc, eleTy, y0, y1, fmf); 36467b5132daSValentin Clement auto r0 = rewriter.create<mlir::LLVM::UndefOp>(loc, ty); 36475c5af910SJeff Niu auto r1 = rewriter.create<mlir::LLVM::InsertValueOp>(loc, r0, rx, 0); 36485c5af910SJeff Niu return rewriter.create<mlir::LLVM::InsertValueOp>(loc, r1, ry, 1); 36497b5132daSValentin Clement } 3650dc48849fSKiran Chandramohan } // namespace 36517b5132daSValentin Clement 3652c2acd453SAlexisPerry namespace { 3653e9639e9cSValentin Clement (バレンタイン クレメン) struct AddcOpConversion : public fir::FIROpConversion<fir::AddcOp> { 36547b5132daSValentin Clement using FIROpConversion::FIROpConversion; 36557b5132daSValentin Clement 3656db791b27SRamkumar Ramachandra llvm::LogicalResult 36577b5132daSValentin Clement matchAndRewrite(fir::AddcOp addc, OpAdaptor adaptor, 36587b5132daSValentin Clement mlir::ConversionPatternRewriter &rewriter) const override { 36597b5132daSValentin Clement // given: (x + iy) + (x' + iy') 36607b5132daSValentin Clement // result: (x + x') + i(y + y') 36617b5132daSValentin Clement auto r = complexSum<mlir::LLVM::FAddOp>(addc, adaptor.getOperands(), 36627b5132daSValentin Clement rewriter, lowerTy()); 36637b5132daSValentin Clement rewriter.replaceOp(addc, r.getResult()); 366444e58509SEric Schweitz return mlir::success(); 36657b5132daSValentin Clement } 36667b5132daSValentin Clement }; 36677b5132daSValentin Clement 3668e9639e9cSValentin Clement (バレンタイン クレメン) struct SubcOpConversion : public fir::FIROpConversion<fir::SubcOp> { 36697b5132daSValentin Clement using FIROpConversion::FIROpConversion; 36707b5132daSValentin Clement 3671db791b27SRamkumar Ramachandra llvm::LogicalResult 36727b5132daSValentin Clement matchAndRewrite(fir::SubcOp subc, OpAdaptor adaptor, 36737b5132daSValentin Clement mlir::ConversionPatternRewriter &rewriter) const override { 36747b5132daSValentin Clement // given: (x + iy) - (x' + iy') 36757b5132daSValentin Clement // result: (x - x') + i(y - y') 36767b5132daSValentin Clement auto r = complexSum<mlir::LLVM::FSubOp>(subc, adaptor.getOperands(), 36777b5132daSValentin Clement rewriter, lowerTy()); 36787b5132daSValentin Clement rewriter.replaceOp(subc, r.getResult()); 367944e58509SEric Schweitz return mlir::success(); 36807b5132daSValentin Clement } 36817b5132daSValentin Clement }; 36827b5132daSValentin Clement 36837b5132daSValentin Clement /// Inlined complex multiply 3684e9639e9cSValentin Clement (バレンタイン クレメン) struct MulcOpConversion : public fir::FIROpConversion<fir::MulcOp> { 36857b5132daSValentin Clement using FIROpConversion::FIROpConversion; 36867b5132daSValentin Clement 3687db791b27SRamkumar Ramachandra llvm::LogicalResult 36887b5132daSValentin Clement matchAndRewrite(fir::MulcOp mulc, OpAdaptor adaptor, 36897b5132daSValentin Clement mlir::ConversionPatternRewriter &rewriter) const override { 36907b5132daSValentin Clement // TODO: Can we use a call to __muldc3 ? 36917b5132daSValentin Clement // given: (x + iy) * (x' + iy') 36927b5132daSValentin Clement // result: (xx'-yy')+i(xy'+yx') 36936be0e979STom Eccles mlir::LLVM::FastmathFlagsAttr fmf = getLLVMFMFAttr(mulc); 36947b5132daSValentin Clement mlir::Value a = adaptor.getOperands()[0]; 36957b5132daSValentin Clement mlir::Value b = adaptor.getOperands()[1]; 36967b5132daSValentin Clement auto loc = mulc.getLoc(); 36977b5132daSValentin Clement mlir::Type eleTy = convertType(getComplexEleTy(mulc.getType())); 36987b5132daSValentin Clement mlir::Type ty = convertType(mulc.getType()); 36995c5af910SJeff Niu auto x0 = rewriter.create<mlir::LLVM::ExtractValueOp>(loc, a, 0); 37005c5af910SJeff Niu auto y0 = rewriter.create<mlir::LLVM::ExtractValueOp>(loc, a, 1); 37015c5af910SJeff Niu auto x1 = rewriter.create<mlir::LLVM::ExtractValueOp>(loc, b, 0); 37025c5af910SJeff Niu auto y1 = rewriter.create<mlir::LLVM::ExtractValueOp>(loc, b, 1); 37036be0e979STom Eccles auto xx = rewriter.create<mlir::LLVM::FMulOp>(loc, eleTy, x0, x1, fmf); 37046be0e979STom Eccles auto yx = rewriter.create<mlir::LLVM::FMulOp>(loc, eleTy, y0, x1, fmf); 37056be0e979STom Eccles auto xy = rewriter.create<mlir::LLVM::FMulOp>(loc, eleTy, x0, y1, fmf); 37066be0e979STom Eccles auto ri = rewriter.create<mlir::LLVM::FAddOp>(loc, eleTy, xy, yx, fmf); 37076be0e979STom Eccles auto yy = rewriter.create<mlir::LLVM::FMulOp>(loc, eleTy, y0, y1, fmf); 37086be0e979STom Eccles auto rr = rewriter.create<mlir::LLVM::FSubOp>(loc, eleTy, xx, yy, fmf); 37097b5132daSValentin Clement auto ra = rewriter.create<mlir::LLVM::UndefOp>(loc, ty); 37105c5af910SJeff Niu auto r1 = rewriter.create<mlir::LLVM::InsertValueOp>(loc, ra, rr, 0); 37115c5af910SJeff Niu auto r0 = rewriter.create<mlir::LLVM::InsertValueOp>(loc, r1, ri, 1); 37127b5132daSValentin Clement rewriter.replaceOp(mulc, r0.getResult()); 371344e58509SEric Schweitz return mlir::success(); 37147b5132daSValentin Clement } 37157b5132daSValentin Clement }; 37167b5132daSValentin Clement 371796e1d2b5SKiran Chandramohan /// Inlined complex division 3718e9639e9cSValentin Clement (バレンタイン クレメン) struct DivcOpConversion : public fir::FIROpConversion<fir::DivcOp> { 37197b5132daSValentin Clement using FIROpConversion::FIROpConversion; 37207b5132daSValentin Clement 3721db791b27SRamkumar Ramachandra llvm::LogicalResult 37227b5132daSValentin Clement matchAndRewrite(fir::DivcOp divc, OpAdaptor adaptor, 37237b5132daSValentin Clement mlir::ConversionPatternRewriter &rewriter) const override { 372496e1d2b5SKiran Chandramohan // TODO: Can we use a call to __divdc3 instead? 372596e1d2b5SKiran Chandramohan // Just generate inline code for now. 37267b5132daSValentin Clement // given: (x + iy) / (x' + iy') 37277b5132daSValentin Clement // result: ((xx'+yy')/d) + i((yx'-xy')/d) where d = x'x' + y'y' 37286be0e979STom Eccles mlir::LLVM::FastmathFlagsAttr fmf = getLLVMFMFAttr(divc); 37297b5132daSValentin Clement mlir::Value a = adaptor.getOperands()[0]; 37307b5132daSValentin Clement mlir::Value b = adaptor.getOperands()[1]; 37317b5132daSValentin Clement auto loc = divc.getLoc(); 37327b5132daSValentin Clement mlir::Type eleTy = convertType(getComplexEleTy(divc.getType())); 373396e1d2b5SKiran Chandramohan mlir::Type ty = convertType(divc.getType()); 37345c5af910SJeff Niu auto x0 = rewriter.create<mlir::LLVM::ExtractValueOp>(loc, a, 0); 37355c5af910SJeff Niu auto y0 = rewriter.create<mlir::LLVM::ExtractValueOp>(loc, a, 1); 37365c5af910SJeff Niu auto x1 = rewriter.create<mlir::LLVM::ExtractValueOp>(loc, b, 0); 37375c5af910SJeff Niu auto y1 = rewriter.create<mlir::LLVM::ExtractValueOp>(loc, b, 1); 37386be0e979STom Eccles auto xx = rewriter.create<mlir::LLVM::FMulOp>(loc, eleTy, x0, x1, fmf); 37396be0e979STom Eccles auto x1x1 = rewriter.create<mlir::LLVM::FMulOp>(loc, eleTy, x1, x1, fmf); 37406be0e979STom Eccles auto yx = rewriter.create<mlir::LLVM::FMulOp>(loc, eleTy, y0, x1, fmf); 37416be0e979STom Eccles auto xy = rewriter.create<mlir::LLVM::FMulOp>(loc, eleTy, x0, y1, fmf); 37426be0e979STom Eccles auto yy = rewriter.create<mlir::LLVM::FMulOp>(loc, eleTy, y0, y1, fmf); 37436be0e979STom Eccles auto y1y1 = rewriter.create<mlir::LLVM::FMulOp>(loc, eleTy, y1, y1, fmf); 37446be0e979STom Eccles auto d = rewriter.create<mlir::LLVM::FAddOp>(loc, eleTy, x1x1, y1y1, fmf); 37456be0e979STom Eccles auto rrn = rewriter.create<mlir::LLVM::FAddOp>(loc, eleTy, xx, yy, fmf); 37466be0e979STom Eccles auto rin = rewriter.create<mlir::LLVM::FSubOp>(loc, eleTy, yx, xy, fmf); 37476be0e979STom Eccles auto rr = rewriter.create<mlir::LLVM::FDivOp>(loc, eleTy, rrn, d, fmf); 37486be0e979STom Eccles auto ri = rewriter.create<mlir::LLVM::FDivOp>(loc, eleTy, rin, d, fmf); 37497b5132daSValentin Clement auto ra = rewriter.create<mlir::LLVM::UndefOp>(loc, ty); 37505c5af910SJeff Niu auto r1 = rewriter.create<mlir::LLVM::InsertValueOp>(loc, ra, rr, 0); 37515c5af910SJeff Niu auto r0 = rewriter.create<mlir::LLVM::InsertValueOp>(loc, r1, ri, 1); 37527b5132daSValentin Clement rewriter.replaceOp(divc, r0.getResult()); 375344e58509SEric Schweitz return mlir::success(); 37547b5132daSValentin Clement } 37557b5132daSValentin Clement }; 37567b5132daSValentin Clement 37577b5132daSValentin Clement /// Inlined complex negation 3758e9639e9cSValentin Clement (バレンタイン クレメン) struct NegcOpConversion : public fir::FIROpConversion<fir::NegcOp> { 37597b5132daSValentin Clement using FIROpConversion::FIROpConversion; 37607b5132daSValentin Clement 3761db791b27SRamkumar Ramachandra llvm::LogicalResult 37627b5132daSValentin Clement matchAndRewrite(fir::NegcOp neg, OpAdaptor adaptor, 37637b5132daSValentin Clement mlir::ConversionPatternRewriter &rewriter) const override { 37647b5132daSValentin Clement // given: -(x + iy) 37657b5132daSValentin Clement // result: -x - iy 37667b5132daSValentin Clement auto eleTy = convertType(getComplexEleTy(neg.getType())); 37677b5132daSValentin Clement auto loc = neg.getLoc(); 37687b5132daSValentin Clement mlir::Value o0 = adaptor.getOperands()[0]; 37695c5af910SJeff Niu auto rp = rewriter.create<mlir::LLVM::ExtractValueOp>(loc, o0, 0); 37705c5af910SJeff Niu auto ip = rewriter.create<mlir::LLVM::ExtractValueOp>(loc, o0, 1); 37717b5132daSValentin Clement auto nrp = rewriter.create<mlir::LLVM::FNegOp>(loc, eleTy, rp); 37727b5132daSValentin Clement auto nip = rewriter.create<mlir::LLVM::FNegOp>(loc, eleTy, ip); 37735c5af910SJeff Niu auto r = rewriter.create<mlir::LLVM::InsertValueOp>(loc, o0, nrp, 0); 37745c5af910SJeff Niu rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(neg, r, nip, 1); 377544e58509SEric Schweitz return mlir::success(); 37767b5132daSValentin Clement } 37777b5132daSValentin Clement }; 37787b5132daSValentin Clement 3779e9639e9cSValentin Clement (バレンタイン クレメン) struct BoxOffsetOpConversion : public fir::FIROpConversion<fir::BoxOffsetOp> { 378091e1b4a6SjeanPerier using FIROpConversion::FIROpConversion; 378191e1b4a6SjeanPerier 3782db791b27SRamkumar Ramachandra llvm::LogicalResult 378391e1b4a6SjeanPerier matchAndRewrite(fir::BoxOffsetOp boxOffset, OpAdaptor adaptor, 378491e1b4a6SjeanPerier mlir::ConversionPatternRewriter &rewriter) const override { 378591e1b4a6SjeanPerier 378691e1b4a6SjeanPerier mlir::Type pty = ::getLlvmPtrType(boxOffset.getContext()); 378791e1b4a6SjeanPerier mlir::Type boxType = fir::unwrapRefType(boxOffset.getBoxRef().getType()); 378891e1b4a6SjeanPerier mlir::Type llvmBoxTy = 378991e1b4a6SjeanPerier lowerTy().convertBoxTypeAsStruct(mlir::cast<fir::BaseBoxType>(boxType)); 3790740f14edSjeanPerier int fieldId = boxOffset.getField() == fir::BoxFieldAttr::derived_type 379191e1b4a6SjeanPerier ? getTypeDescFieldId(boxType) 379291e1b4a6SjeanPerier : kAddrPosInBox; 379391e1b4a6SjeanPerier rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>( 379491e1b4a6SjeanPerier boxOffset, pty, llvmBoxTy, adaptor.getBoxRef(), 379591e1b4a6SjeanPerier llvm::ArrayRef<mlir::LLVM::GEPArg>{0, fieldId}); 379691e1b4a6SjeanPerier return mlir::success(); 379791e1b4a6SjeanPerier } 379891e1b4a6SjeanPerier }; 379991e1b4a6SjeanPerier 38001ed5a90fSValentin Clement /// Conversion pattern for operation that must be dead. The information in these 38011ed5a90fSValentin Clement /// operations is used by other operation. At this point they should not have 38021ed5a90fSValentin Clement /// anymore uses. 38031ed5a90fSValentin Clement /// These operations are normally dead after the pre-codegen pass. 38041ed5a90fSValentin Clement template <typename FromOp> 3805e9639e9cSValentin Clement (バレンタイン クレメン) struct MustBeDeadConversion : public fir::FIROpConversion<FromOp> { 3806ce254598SMatthias Springer explicit MustBeDeadConversion(const fir::LLVMTypeConverter &lowering, 38074c5dee77SRenaud-K const fir::FIRToLLVMPassOptions &options) 3808e9639e9cSValentin Clement (バレンタイン クレメン) : fir::FIROpConversion<FromOp>(lowering, options) {} 38091ed5a90fSValentin Clement using OpAdaptor = typename FromOp::Adaptor; 38101ed5a90fSValentin Clement 3811db791b27SRamkumar Ramachandra llvm::LogicalResult 38121ed5a90fSValentin Clement matchAndRewrite(FromOp op, OpAdaptor adaptor, 38131ed5a90fSValentin Clement mlir::ConversionPatternRewriter &rewriter) const final { 38141ed5a90fSValentin Clement if (!op->getUses().empty()) 38151ed5a90fSValentin Clement return rewriter.notifyMatchFailure(op, "op must be dead"); 38161ed5a90fSValentin Clement rewriter.eraseOp(op); 381744e58509SEric Schweitz return mlir::success(); 38181ed5a90fSValentin Clement } 38191ed5a90fSValentin Clement }; 38201ed5a90fSValentin Clement 38211ed5a90fSValentin Clement struct ShapeOpConversion : public MustBeDeadConversion<fir::ShapeOp> { 38221ed5a90fSValentin Clement using MustBeDeadConversion::MustBeDeadConversion; 38231ed5a90fSValentin Clement }; 38241ed5a90fSValentin Clement 38251ed5a90fSValentin Clement struct ShapeShiftOpConversion : public MustBeDeadConversion<fir::ShapeShiftOp> { 38261ed5a90fSValentin Clement using MustBeDeadConversion::MustBeDeadConversion; 38271ed5a90fSValentin Clement }; 38281ed5a90fSValentin Clement 38291ed5a90fSValentin Clement struct ShiftOpConversion : public MustBeDeadConversion<fir::ShiftOp> { 38301ed5a90fSValentin Clement using MustBeDeadConversion::MustBeDeadConversion; 38311ed5a90fSValentin Clement }; 38321ed5a90fSValentin Clement 38331ed5a90fSValentin Clement struct SliceOpConversion : public MustBeDeadConversion<fir::SliceOp> { 38341ed5a90fSValentin Clement using MustBeDeadConversion::MustBeDeadConversion; 38351ed5a90fSValentin Clement }; 38361ed5a90fSValentin Clement 3837044d5b5dSValentin Clement } // namespace 3838044d5b5dSValentin Clement 3839044d5b5dSValentin Clement namespace { 384036799dfdSDiana Picus class RenameMSVCLibmCallees 384136799dfdSDiana Picus : public mlir::OpRewritePattern<mlir::LLVM::CallOp> { 384236799dfdSDiana Picus public: 384336799dfdSDiana Picus using OpRewritePattern::OpRewritePattern; 384436799dfdSDiana Picus 3845db791b27SRamkumar Ramachandra llvm::LogicalResult 384636799dfdSDiana Picus matchAndRewrite(mlir::LLVM::CallOp op, 384736799dfdSDiana Picus mlir::PatternRewriter &rewriter) const override { 38485fcf907bSMatthias Springer rewriter.startOpModification(op); 384936799dfdSDiana Picus auto callee = op.getCallee(); 385036799dfdSDiana Picus if (callee) 3851f841ca0cSKazu Hirata if (*callee == "hypotf") 385236799dfdSDiana Picus op.setCalleeAttr(mlir::SymbolRefAttr::get(op.getContext(), "_hypotf")); 385336799dfdSDiana Picus 38545fcf907bSMatthias Springer rewriter.finalizeOpModification(op); 385536799dfdSDiana Picus return mlir::success(); 385636799dfdSDiana Picus } 385736799dfdSDiana Picus }; 385836799dfdSDiana Picus 385936799dfdSDiana Picus class RenameMSVCLibmFuncs 386036799dfdSDiana Picus : public mlir::OpRewritePattern<mlir::LLVM::LLVMFuncOp> { 386136799dfdSDiana Picus public: 386236799dfdSDiana Picus using OpRewritePattern::OpRewritePattern; 386336799dfdSDiana Picus 3864db791b27SRamkumar Ramachandra llvm::LogicalResult 386536799dfdSDiana Picus matchAndRewrite(mlir::LLVM::LLVMFuncOp op, 386636799dfdSDiana Picus mlir::PatternRewriter &rewriter) const override { 38675fcf907bSMatthias Springer rewriter.startOpModification(op); 3868f841ca0cSKazu Hirata if (op.getSymName() == "hypotf") 386936799dfdSDiana Picus op.setSymNameAttr(rewriter.getStringAttr("_hypotf")); 38705fcf907bSMatthias Springer rewriter.finalizeOpModification(op); 387136799dfdSDiana Picus return mlir::success(); 387236799dfdSDiana Picus } 387336799dfdSDiana Picus }; 387436799dfdSDiana Picus } // namespace 387536799dfdSDiana Picus 387636799dfdSDiana Picus namespace { 3877044d5b5dSValentin Clement /// Convert FIR dialect to LLVM dialect 3878044d5b5dSValentin Clement /// 3879044d5b5dSValentin Clement /// This pass lowers all FIR dialect operations to LLVM IR dialect. An 3880044d5b5dSValentin Clement /// MLIR pass is used to lower residual Std dialect to LLVM IR dialect. 388167d0d7acSMichele Scuttari class FIRToLLVMLowering 388267d0d7acSMichele Scuttari : public fir::impl::FIRToLLVMLoweringBase<FIRToLLVMLowering> { 3883044d5b5dSValentin Clement public: 3884013160f6SJean Perier FIRToLLVMLowering() = default; 3885013160f6SJean Perier FIRToLLVMLowering(fir::FIRToLLVMPassOptions options) : options{options} {} 3886044d5b5dSValentin Clement mlir::ModuleOp getModule() { return getOperation(); } 3887044d5b5dSValentin Clement 3888044d5b5dSValentin Clement void runOnOperation() override final { 38897b5132daSValentin Clement auto mod = getModule(); 389044e58509SEric Schweitz if (!forcedTargetTriple.empty()) 38917b5132daSValentin Clement fir::setTargetTriple(mod, forcedTargetTriple); 38927b5132daSValentin Clement 3893abeb6c9fSagozillon if (!forcedDataLayout.empty()) { 3894abeb6c9fSagozillon llvm::DataLayout dl(forcedDataLayout); 3895abeb6c9fSagozillon fir::support::setMLIRDataLayout(mod, dl); 3896abeb6c9fSagozillon } 3897abeb6c9fSagozillon 3898837bff11SSergio Afonso if (!forcedTargetCPU.empty()) 3899837bff11SSergio Afonso fir::setTargetCPU(mod, forcedTargetCPU); 3900837bff11SSergio Afonso 3901f1d3fe7aSAlexis Perry-Holby if (!forcedTuneCPU.empty()) 3902f1d3fe7aSAlexis Perry-Holby fir::setTuneCPU(mod, forcedTuneCPU); 3903f1d3fe7aSAlexis Perry-Holby 3904837bff11SSergio Afonso if (!forcedTargetFeatures.empty()) 3905837bff11SSergio Afonso fir::setTargetFeatures(mod, forcedTargetFeatures); 3906837bff11SSergio Afonso 3907cfd4c180SSlava Zakharin if (typeDescriptorsRenamedForAssembly) 3908cfd4c180SSlava Zakharin options.typeDescriptorsRenamedForAssembly = 3909cfd4c180SSlava Zakharin typeDescriptorsRenamedForAssembly; 3910cfd4c180SSlava Zakharin 3911bac3aedaSSlava Zakharin // Run dynamic pass pipeline for converting Math dialect 3912bac3aedaSSlava Zakharin // operations into other dialects (llvm, func, etc.). 3913bac3aedaSSlava Zakharin // Some conversions of Math operations cannot be done 3914bac3aedaSSlava Zakharin // by just using conversion patterns. This is true for 3915bac3aedaSSlava Zakharin // conversions that affect the ModuleOp, e.g. create new 3916bac3aedaSSlava Zakharin // function operations in it. We have to run such conversions 3917bac3aedaSSlava Zakharin // as passes here. 3918bac3aedaSSlava Zakharin mlir::OpPassManager mathConvertionPM("builtin.module"); 39199e8f6772SSlava Zakharin 39204290e34eSJan Leyonberg bool isAMDGCN = fir::getTargetTriple(mod).isAMDGCN(); 39214290e34eSJan Leyonberg // If compiling for AMD target some math operations must be lowered to AMD 39224290e34eSJan Leyonberg // GPU library calls, the rest can be converted to LLVM intrinsics, which 39234290e34eSJan Leyonberg // is handled in the mathToLLVM conversion. The lowering to libm calls is 39244290e34eSJan Leyonberg // not needed since all math operations are handled this way. 39254290e34eSJan Leyonberg if (isAMDGCN) 39264290e34eSJan Leyonberg mathConvertionPM.addPass(mlir::createConvertMathToROCDL()); 39274290e34eSJan Leyonberg 39289e8f6772SSlava Zakharin // Convert math::FPowI operations to inline implementation 39299e8f6772SSlava Zakharin // only if the exponent's width is greater than 32, otherwise, 39309e8f6772SSlava Zakharin // it will be lowered to LLVM intrinsic operation by a later conversion. 39319e8f6772SSlava Zakharin mlir::ConvertMathToFuncsOptions mathToFuncsOptions{}; 39329e8f6772SSlava Zakharin mathToFuncsOptions.minWidthOfFPowIExponent = 33; 39339e8f6772SSlava Zakharin mathConvertionPM.addPass( 39349e8f6772SSlava Zakharin mlir::createConvertMathToFuncs(mathToFuncsOptions)); 3935000de666SDavid Truby mathConvertionPM.addPass(mlir::createConvertComplexToStandardPass()); 3936cf550e61SSlava Zakharin // Convert Math dialect operations into LLVM dialect operations. 3937cf550e61SSlava Zakharin // There is no way to prefer MathToLLVM patterns over MathToLibm 3938cf550e61SSlava Zakharin // patterns (applied below), so we have to run MathToLLVM conversion here. 3939cf550e61SSlava Zakharin mathConvertionPM.addNestedPass<mlir::func::FuncOp>( 3940cf550e61SSlava Zakharin mlir::createConvertMathToLLVMPass()); 3941bac3aedaSSlava Zakharin if (mlir::failed(runPipeline(mathConvertionPM, mod))) 3942bac3aedaSSlava Zakharin return signalPassFailure(); 3943bac3aedaSSlava Zakharin 394427d9a479SjeanPerier std::optional<mlir::DataLayout> dl = 394527d9a479SjeanPerier fir::support::getOrSetDataLayout(mod, /*allowDefaultLayout=*/true); 394627d9a479SjeanPerier if (!dl) { 394727d9a479SjeanPerier mlir::emitError(mod.getLoc(), 394827d9a479SjeanPerier "module operation must carry a data layout attribute " 394927d9a479SjeanPerier "to generate llvm IR from FIR"); 395027d9a479SjeanPerier signalPassFailure(); 395127d9a479SjeanPerier return; 395227d9a479SjeanPerier } 395327d9a479SjeanPerier 3954044d5b5dSValentin Clement auto *context = getModule().getContext(); 39559c84d20fSSlava Zakharin fir::LLVMTypeConverter typeConverter{getModule(), 3956ac0015feSTom Eccles options.applyTBAA || applyTBAA, 395727d9a479SjeanPerier options.forceUnifiedTBAATree, *dl}; 39589f85c198SRiver Riddle mlir::RewritePatternSet pattern(context); 3959408d4e13SValentin Clement (バレンタイン クレメン) fir::populateFIRToLLVMConversionPatterns(typeConverter, pattern, options); 39605a7b9194SRiver Riddle mlir::populateFuncToLLVMConversionPatterns(typeConverter, pattern); 3961c6ac9370SKiran Chandramohan mlir::populateOpenMPToLLVMConversionPatterns(typeConverter, pattern); 39626c8d8d10SJakub Kuderski mlir::arith::populateArithToLLVMConversionPatterns(typeConverter, pattern); 3963ace01605SRiver Riddle mlir::cf::populateControlFlowToLLVMConversionPatterns(typeConverter, 3964ace01605SRiver Riddle pattern); 3965599c7399SMatthias Springer mlir::cf::populateAssertToLLVMConversionPattern(typeConverter, pattern); 3966cf550e61SSlava Zakharin // Math operations that have not been converted yet must be converted 3967cf550e61SSlava Zakharin // to Libm. 39684290e34eSJan Leyonberg if (!isAMDGCN) 3969d61a3d3aSAlexander Belyaev mlir::populateMathToLibmConversionPatterns(pattern); 3970000de666SDavid Truby mlir::populateComplexToLLVMConversionPatterns(typeConverter, pattern); 3971a9e1d2e7SKelvin Li mlir::populateVectorToLLVMConversionPatterns(typeConverter, pattern); 397295fe47caSagozillon 397395fe47caSagozillon // Flang specific overloads for OpenMP operations, to allow for special 397495fe47caSagozillon // handling of things like Box types. 397595fe47caSagozillon fir::populateOpenMPFIRToLLVMConversionPatterns(typeConverter, pattern); 397695fe47caSagozillon 3977044d5b5dSValentin Clement mlir::ConversionTarget target{*context}; 3978044d5b5dSValentin Clement target.addLegalDialect<mlir::LLVM::LLVMDialect>(); 3979c6ac9370SKiran Chandramohan // The OpenMP dialect is legal for Operations without regions, for those 3980c6ac9370SKiran Chandramohan // which contains regions it is legal if the region contains only the 398100c511b3SNimish Mishra // LLVM dialect. Add OpenMP dialect as a legal dialect for conversion and 398200c511b3SNimish Mishra // legalize conversion of OpenMP operations without regions. 398300c511b3SNimish Mishra mlir::configureOpenMPToLLVMConversionLegality(target, typeConverter); 3984c6ac9370SKiran Chandramohan target.addLegalDialect<mlir::omp::OpenMPDialect>(); 3985cd9cdc68SValentin Clement target.addLegalDialect<mlir::acc::OpenACCDialect>(); 3986e5092c30SValentin Clement (バレンタイン クレメン) target.addLegalDialect<mlir::gpu::GPUDialect>(); 3987044d5b5dSValentin Clement 3988044d5b5dSValentin Clement // required NOPs for applying a full conversion 3989044d5b5dSValentin Clement target.addLegalOp<mlir::ModuleOp>(); 3990044d5b5dSValentin Clement 399136799dfdSDiana Picus // If we're on Windows, we might need to rename some libm calls. 399236799dfdSDiana Picus bool isMSVC = fir::getTargetTriple(mod).isOSMSVCRT(); 399336799dfdSDiana Picus if (isMSVC) { 399436799dfdSDiana Picus pattern.insert<RenameMSVCLibmCallees, RenameMSVCLibmFuncs>(context); 399536799dfdSDiana Picus 399636799dfdSDiana Picus target.addDynamicallyLegalOp<mlir::LLVM::CallOp>( 399736799dfdSDiana Picus [](mlir::LLVM::CallOp op) { 399836799dfdSDiana Picus auto callee = op.getCallee(); 399936799dfdSDiana Picus if (!callee) 400036799dfdSDiana Picus return true; 4001f841ca0cSKazu Hirata return *callee != "hypotf"; 400236799dfdSDiana Picus }); 400336799dfdSDiana Picus target.addDynamicallyLegalOp<mlir::LLVM::LLVMFuncOp>( 400436799dfdSDiana Picus [](mlir::LLVM::LLVMFuncOp op) { 4005f841ca0cSKazu Hirata return op.getSymName() != "hypotf"; 400636799dfdSDiana Picus }); 400736799dfdSDiana Picus } 400836799dfdSDiana Picus 4009044d5b5dSValentin Clement // apply the patterns 4010044d5b5dSValentin Clement if (mlir::failed(mlir::applyFullConversion(getModule(), target, 4011044d5b5dSValentin Clement std::move(pattern)))) { 4012044d5b5dSValentin Clement signalPassFailure(); 4013044d5b5dSValentin Clement } 40145f476b80SDavid Truby 4015e73cf2f0SMatthias Springer // Run pass to add comdats to functions that have weak linkage on relevant 4016e73cf2f0SMatthias Springer // platforms 40175f476b80SDavid Truby if (fir::getTargetTriple(mod).supportsCOMDAT()) { 40185f476b80SDavid Truby mlir::OpPassManager comdatPM("builtin.module"); 40195f476b80SDavid Truby comdatPM.addPass(mlir::LLVM::createLLVMAddComdats()); 40205f476b80SDavid Truby if (mlir::failed(runPipeline(comdatPM, mod))) 40215f476b80SDavid Truby return signalPassFailure(); 40225f476b80SDavid Truby } 4023044d5b5dSValentin Clement } 4024013160f6SJean Perier 4025013160f6SJean Perier private: 4026013160f6SJean Perier fir::FIRToLLVMPassOptions options; 4027044d5b5dSValentin Clement }; 4028853e79d8SValentin Clement 4029853e79d8SValentin Clement /// Lower from LLVM IR dialect to proper LLVM-IR and dump the module 4030853e79d8SValentin Clement struct LLVMIRLoweringPass 4031853e79d8SValentin Clement : public mlir::PassWrapper<LLVMIRLoweringPass, 4032853e79d8SValentin Clement mlir::OperationPass<mlir::ModuleOp>> { 40335e50dd04SRiver Riddle MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(LLVMIRLoweringPass) 40345e50dd04SRiver Riddle 403544e58509SEric Schweitz LLVMIRLoweringPass(llvm::raw_ostream &output, fir::LLVMIRLoweringPrinter p) 4036853e79d8SValentin Clement : output{output}, printer{p} {} 4037853e79d8SValentin Clement 4038853e79d8SValentin Clement mlir::ModuleOp getModule() { return getOperation(); } 4039853e79d8SValentin Clement 4040853e79d8SValentin Clement void runOnOperation() override final { 4041853e79d8SValentin Clement auto *ctx = getModule().getContext(); 4042853e79d8SValentin Clement auto optName = getModule().getName(); 4043853e79d8SValentin Clement llvm::LLVMContext llvmCtx; 4044853e79d8SValentin Clement if (auto llvmModule = mlir::translateModuleToLLVMIR( 4045853e79d8SValentin Clement getModule(), llvmCtx, optName ? *optName : "FIRModule")) { 4046853e79d8SValentin Clement printer(*llvmModule, output); 4047853e79d8SValentin Clement return; 4048853e79d8SValentin Clement } 4049853e79d8SValentin Clement 4050853e79d8SValentin Clement mlir::emitError(mlir::UnknownLoc::get(ctx), "could not emit LLVM-IR\n"); 4051853e79d8SValentin Clement signalPassFailure(); 4052853e79d8SValentin Clement } 4053853e79d8SValentin Clement 4054853e79d8SValentin Clement private: 405544e58509SEric Schweitz llvm::raw_ostream &output; 405644e58509SEric Schweitz fir::LLVMIRLoweringPrinter printer; 4057853e79d8SValentin Clement }; 4058853e79d8SValentin Clement 4059044d5b5dSValentin Clement } // namespace 4060044d5b5dSValentin Clement 4061044d5b5dSValentin Clement std::unique_ptr<mlir::Pass> fir::createFIRToLLVMPass() { 4062044d5b5dSValentin Clement return std::make_unique<FIRToLLVMLowering>(); 4063044d5b5dSValentin Clement } 4064853e79d8SValentin Clement 4065853e79d8SValentin Clement std::unique_ptr<mlir::Pass> 406644e58509SEric Schweitz fir::createFIRToLLVMPass(fir::FIRToLLVMPassOptions options) { 4067013160f6SJean Perier return std::make_unique<FIRToLLVMLowering>(options); 4068013160f6SJean Perier } 4069013160f6SJean Perier 4070013160f6SJean Perier std::unique_ptr<mlir::Pass> 407144e58509SEric Schweitz fir::createLLVMDialectToLLVMPass(llvm::raw_ostream &output, 4072853e79d8SValentin Clement fir::LLVMIRLoweringPrinter printer) { 4073853e79d8SValentin Clement return std::make_unique<LLVMIRLoweringPass>(output, printer); 4074853e79d8SValentin Clement } 4075408d4e13SValentin Clement (バレンタイン クレメン) 4076408d4e13SValentin Clement (バレンタイン クレメン) void fir::populateFIRToLLVMConversionPatterns( 4077206fad0eSMatthias Springer const fir::LLVMTypeConverter &converter, mlir::RewritePatternSet &patterns, 4078408d4e13SValentin Clement (バレンタイン クレメン) fir::FIRToLLVMPassOptions &options) { 4079408d4e13SValentin Clement (バレンタイン クレメン) patterns.insert< 4080408d4e13SValentin Clement (バレンタイン クレメン) AbsentOpConversion, AddcOpConversion, AddrOfOpConversion, 4081408d4e13SValentin Clement (バレンタイン クレメン) AllocaOpConversion, AllocMemOpConversion, BoxAddrOpConversion, 4082408d4e13SValentin Clement (バレンタイン クレメン) BoxCharLenOpConversion, BoxDimsOpConversion, BoxEleSizeOpConversion, 4083408d4e13SValentin Clement (バレンタイン クレメン) BoxIsAllocOpConversion, BoxIsArrayOpConversion, BoxIsPtrOpConversion, 4084408d4e13SValentin Clement (バレンタイン クレメン) BoxOffsetOpConversion, BoxProcHostOpConversion, BoxRankOpConversion, 4085408d4e13SValentin Clement (バレンタイン クレメン) BoxTypeCodeOpConversion, BoxTypeDescOpConversion, CallOpConversion, 4086c2601f17SjeanPerier CmpcOpConversion, ConvertOpConversion, CoordinateOpConversion, 4087c2601f17SjeanPerier DTEntryOpConversion, DeclareOpConversion, DivcOpConversion, 4088c2601f17SjeanPerier EmboxOpConversion, EmboxCharOpConversion, EmboxProcOpConversion, 4089c2601f17SjeanPerier ExtractValueOpConversion, FieldIndexOpConversion, FirEndOpConversion, 4090c2601f17SjeanPerier FreeMemOpConversion, GlobalLenOpConversion, GlobalOpConversion, 4091c2601f17SjeanPerier InsertOnRangeOpConversion, IsPresentOpConversion, 4092e73cf2f0SMatthias Springer LenParamIndexOpConversion, LoadOpConversion, MulcOpConversion, 4093e73cf2f0SMatthias Springer NegcOpConversion, NoReassocOpConversion, SelectCaseOpConversion, 4094e73cf2f0SMatthias Springer SelectOpConversion, SelectRankOpConversion, SelectTypeOpConversion, 4095e73cf2f0SMatthias Springer ShapeOpConversion, ShapeShiftOpConversion, ShiftOpConversion, 4096e73cf2f0SMatthias Springer SliceOpConversion, StoreOpConversion, StringLitOpConversion, 4097e73cf2f0SMatthias Springer SubcOpConversion, TypeDescOpConversion, TypeInfoOpConversion, 4098e73cf2f0SMatthias Springer UnboxCharOpConversion, UnboxProcOpConversion, UndefOpConversion, 4099e73cf2f0SMatthias Springer UnreachableOpConversion, XArrayCoorOpConversion, XEmboxOpConversion, 4100e73cf2f0SMatthias Springer XReboxOpConversion, ZeroOpConversion>(converter, options); 4101e73cf2f0SMatthias Springer 4102e73cf2f0SMatthias Springer // Patterns that are populated without a type converter do not trigger 4103e73cf2f0SMatthias Springer // target materializations for the operands of the root op. 4104e73cf2f0SMatthias Springer patterns.insert<HasValueOpConversion, InsertValueOpConversion>( 4105e73cf2f0SMatthias Springer patterns.getContext()); 4106408d4e13SValentin Clement (バレンタイン クレメン) } 4107