1fe252f8eSValentin Clement //===-- BoxedProcedure.cpp ------------------------------------------------===// 2fe252f8eSValentin Clement // 3fe252f8eSValentin Clement // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4fe252f8eSValentin Clement // See https://llvm.org/LICENSE.txt for license information. 5fe252f8eSValentin Clement // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6fe252f8eSValentin Clement // 7fe252f8eSValentin Clement //===----------------------------------------------------------------------===// 8fe252f8eSValentin Clement 967d0d7acSMichele Scuttari #include "flang/Optimizer/CodeGen/CodeGen.h" 1067d0d7acSMichele Scuttari 11fe252f8eSValentin Clement #include "flang/Optimizer/Builder/FIRBuilder.h" 12fe252f8eSValentin Clement #include "flang/Optimizer/Builder/LowLevelIntrinsics.h" 13fe252f8eSValentin Clement #include "flang/Optimizer/Dialect/FIRDialect.h" 14fe252f8eSValentin Clement #include "flang/Optimizer/Dialect/FIROps.h" 15fe252f8eSValentin Clement #include "flang/Optimizer/Dialect/FIRType.h" 16b07ef9e7SRenaud-K #include "flang/Optimizer/Dialect/Support/FIRContext.h" 17fe252f8eSValentin Clement #include "flang/Optimizer/Support/FatalError.h" 187de3c03eSPeixin Qiao #include "flang/Optimizer/Support/InternalNames.h" 19fe252f8eSValentin Clement #include "mlir/IR/PatternMatch.h" 20fe252f8eSValentin Clement #include "mlir/Pass/Pass.h" 21fe252f8eSValentin Clement #include "mlir/Transforms/DialectConversion.h" 22df3f0eeeSjeanPerier #include "llvm/ADT/DenseMap.h" 23fe252f8eSValentin Clement 2467d0d7acSMichele Scuttari namespace fir { 2567d0d7acSMichele Scuttari #define GEN_PASS_DEF_BOXEDPROCEDUREPASS 2667d0d7acSMichele Scuttari #include "flang/Optimizer/CodeGen/CGPasses.h.inc" 2767d0d7acSMichele Scuttari } // namespace fir 2867d0d7acSMichele Scuttari 29fe252f8eSValentin Clement #define DEBUG_TYPE "flang-procedure-pointer" 30fe252f8eSValentin Clement 31fe252f8eSValentin Clement using namespace fir; 32fe252f8eSValentin Clement 33fe252f8eSValentin Clement namespace { 34fe252f8eSValentin Clement /// Options to the procedure pointer pass. 35fe252f8eSValentin Clement struct BoxedProcedureOptions { 36fe252f8eSValentin Clement // Lower the boxproc abstraction to function pointers and thunks where 37fe252f8eSValentin Clement // required. 38fe252f8eSValentin Clement bool useThunks = true; 39fe252f8eSValentin Clement }; 40fe252f8eSValentin Clement 41fe252f8eSValentin Clement /// This type converter rewrites all `!fir.boxproc<Func>` types to `Func` types. 42fe252f8eSValentin Clement class BoxprocTypeRewriter : public mlir::TypeConverter { 43fe252f8eSValentin Clement public: 44fe252f8eSValentin Clement using mlir::TypeConverter::convertType; 45fe252f8eSValentin Clement 46fe252f8eSValentin Clement /// Does the type \p ty need to be converted? 47fe252f8eSValentin Clement /// Any type that is a `!fir.boxproc` in whole or in part will need to be 48fe252f8eSValentin Clement /// converted to a function type to lower the IR to function pointer form in 49fe252f8eSValentin Clement /// the default implementation performed in this pass. Other implementations 50fe252f8eSValentin Clement /// are possible, so those may convert `!fir.boxproc` to some other type or 51fe252f8eSValentin Clement /// not at all depending on the implementation target's characteristics and 52fe252f8eSValentin Clement /// preference. 53fe252f8eSValentin Clement bool needsConversion(mlir::Type ty) { 54fac349a1SChristian Sigg if (mlir::isa<BoxProcType>(ty)) 55fe252f8eSValentin Clement return true; 56fac349a1SChristian Sigg if (auto funcTy = mlir::dyn_cast<mlir::FunctionType>(ty)) { 57fe252f8eSValentin Clement for (auto t : funcTy.getInputs()) 58fe252f8eSValentin Clement if (needsConversion(t)) 59fe252f8eSValentin Clement return true; 60fe252f8eSValentin Clement for (auto t : funcTy.getResults()) 61fe252f8eSValentin Clement if (needsConversion(t)) 62fe252f8eSValentin Clement return true; 63fe252f8eSValentin Clement return false; 64fe252f8eSValentin Clement } 65fac349a1SChristian Sigg if (auto tupleTy = mlir::dyn_cast<mlir::TupleType>(ty)) { 66fe252f8eSValentin Clement for (auto t : tupleTy.getTypes()) 67fe252f8eSValentin Clement if (needsConversion(t)) 68fe252f8eSValentin Clement return true; 69fe252f8eSValentin Clement return false; 70fe252f8eSValentin Clement } 71fac349a1SChristian Sigg if (auto recTy = mlir::dyn_cast<RecordType>(ty)) { 72df3bc54eSKazu Hirata auto [visited, inserted] = visitedTypes.try_emplace(ty, false); 73df3bc54eSKazu Hirata if (!inserted) 74a0e9a8daSjeanPerier return visited->second; 75a0e9a8daSjeanPerier bool wasAlreadyVisitingRecordType = needConversionIsVisitingRecordType; 76a0e9a8daSjeanPerier needConversionIsVisitingRecordType = true; 77fe252f8eSValentin Clement bool result = false; 78fe252f8eSValentin Clement for (auto t : recTy.getTypeList()) { 79fe252f8eSValentin Clement if (needsConversion(t.second)) { 80fe252f8eSValentin Clement result = true; 81fe252f8eSValentin Clement break; 82fe252f8eSValentin Clement } 83fe252f8eSValentin Clement } 84a0e9a8daSjeanPerier // Only keep the result cached if the fir.type visited was a "top-level 85a0e9a8daSjeanPerier // type". Nested types with a recursive reference to the "top-level type" 86a0e9a8daSjeanPerier // may incorrectly have been resolved as not needed conversions because it 87a0e9a8daSjeanPerier // had not been determined yet if the "top-level type" needed conversion. 88a0e9a8daSjeanPerier // This is not an issue to determine the "top-level type" need of 89a0e9a8daSjeanPerier // conversion, but the result should not be kept and later used in other 90a0e9a8daSjeanPerier // contexts. 91a0e9a8daSjeanPerier needConversionIsVisitingRecordType = wasAlreadyVisitingRecordType; 92a0e9a8daSjeanPerier if (needConversionIsVisitingRecordType) 93a0e9a8daSjeanPerier visitedTypes.erase(ty); 94a0e9a8daSjeanPerier else 95a0e9a8daSjeanPerier visitedTypes.find(ty)->second = result; 96fe252f8eSValentin Clement return result; 97fe252f8eSValentin Clement } 98fac349a1SChristian Sigg if (auto boxTy = mlir::dyn_cast<BaseBoxType>(ty)) 99fe252f8eSValentin Clement return needsConversion(boxTy.getEleTy()); 100fe252f8eSValentin Clement if (isa_ref_type(ty)) 101fe252f8eSValentin Clement return needsConversion(unwrapRefType(ty)); 102fac349a1SChristian Sigg if (auto t = mlir::dyn_cast<SequenceType>(ty)) 103fe252f8eSValentin Clement return needsConversion(unwrapSequenceType(ty)); 1044e59721cSKiran Chandramohan if (auto t = mlir::dyn_cast<TypeDescType>(ty)) 1054e59721cSKiran Chandramohan return needsConversion(t.getOfTy()); 106fe252f8eSValentin Clement return false; 107fe252f8eSValentin Clement } 108fe252f8eSValentin Clement 109a370a4ffSjeanPerier BoxprocTypeRewriter(mlir::Location location) : loc{location} { 110fe252f8eSValentin Clement addConversion([](mlir::Type ty) { return ty; }); 111a370a4ffSjeanPerier addConversion( 112a370a4ffSjeanPerier [&](BoxProcType boxproc) { return convertType(boxproc.getEleTy()); }); 113fe252f8eSValentin Clement addConversion([&](mlir::TupleType tupTy) { 114fe252f8eSValentin Clement llvm::SmallVector<mlir::Type> memTys; 115fe252f8eSValentin Clement for (auto ty : tupTy.getTypes()) 116fe252f8eSValentin Clement memTys.push_back(convertType(ty)); 117fe252f8eSValentin Clement return mlir::TupleType::get(tupTy.getContext(), memTys); 118fe252f8eSValentin Clement }); 119fe252f8eSValentin Clement addConversion([&](mlir::FunctionType funcTy) { 120fe252f8eSValentin Clement llvm::SmallVector<mlir::Type> inTys; 121fe252f8eSValentin Clement llvm::SmallVector<mlir::Type> resTys; 122fe252f8eSValentin Clement for (auto ty : funcTy.getInputs()) 123fe252f8eSValentin Clement inTys.push_back(convertType(ty)); 124fe252f8eSValentin Clement for (auto ty : funcTy.getResults()) 125fe252f8eSValentin Clement resTys.push_back(convertType(ty)); 126fe252f8eSValentin Clement return mlir::FunctionType::get(funcTy.getContext(), inTys, resTys); 127fe252f8eSValentin Clement }); 128fe252f8eSValentin Clement addConversion([&](ReferenceType ty) { 129fe252f8eSValentin Clement return ReferenceType::get(convertType(ty.getEleTy())); 130fe252f8eSValentin Clement }); 131fe252f8eSValentin Clement addConversion([&](PointerType ty) { 132fe252f8eSValentin Clement return PointerType::get(convertType(ty.getEleTy())); 133fe252f8eSValentin Clement }); 134fe252f8eSValentin Clement addConversion( 135fe252f8eSValentin Clement [&](HeapType ty) { return HeapType::get(convertType(ty.getEleTy())); }); 136c373f581SjeanPerier addConversion([&](fir::LLVMPointerType ty) { 137c373f581SjeanPerier return fir::LLVMPointerType::get(convertType(ty.getEleTy())); 138c373f581SjeanPerier }); 139fe252f8eSValentin Clement addConversion( 140fe252f8eSValentin Clement [&](BoxType ty) { return BoxType::get(convertType(ty.getEleTy())); }); 141c373f581SjeanPerier addConversion([&](ClassType ty) { 142c373f581SjeanPerier return ClassType::get(convertType(ty.getEleTy())); 143c373f581SjeanPerier }); 144fe252f8eSValentin Clement addConversion([&](SequenceType ty) { 145fe252f8eSValentin Clement // TODO: add ty.getLayoutMap() as needed. 146fe252f8eSValentin Clement return SequenceType::get(ty.getShape(), convertType(ty.getEleTy())); 147fe252f8eSValentin Clement }); 148a370a4ffSjeanPerier addConversion([&](RecordType ty) -> mlir::Type { 149a370a4ffSjeanPerier if (!needsConversion(ty)) 150a370a4ffSjeanPerier return ty; 151df3f0eeeSjeanPerier if (auto converted = convertedTypes.lookup(ty)) 152c373f581SjeanPerier return converted; 1537de3c03eSPeixin Qiao auto rec = RecordType::get(ty.getContext(), 1547de3c03eSPeixin Qiao ty.getName().str() + boxprocSuffix.str()); 1557de3c03eSPeixin Qiao if (rec.isFinalized()) 1567de3c03eSPeixin Qiao return rec; 157b3316647SJie Fu [[maybe_unused]] auto it = convertedTypes.try_emplace(ty, rec); 158a0e9a8daSjeanPerier assert(it.second && "expected ty to not be in the map"); 1597de3c03eSPeixin Qiao std::vector<RecordType::TypePair> ps = ty.getLenParamList(); 1607de3c03eSPeixin Qiao std::vector<RecordType::TypePair> cs; 1617de3c03eSPeixin Qiao for (auto t : ty.getTypeList()) { 1627de3c03eSPeixin Qiao if (needsConversion(t.second)) 1637de3c03eSPeixin Qiao cs.emplace_back(t.first, convertType(t.second)); 1647de3c03eSPeixin Qiao else 1657de3c03eSPeixin Qiao cs.emplace_back(t.first, t.second); 1667de3c03eSPeixin Qiao } 1677de3c03eSPeixin Qiao rec.finalize(ps, cs); 16879e788d0SKelvin Li rec.pack(ty.isPacked()); 1697de3c03eSPeixin Qiao return rec; 170fe252f8eSValentin Clement }); 1714e59721cSKiran Chandramohan addConversion([&](TypeDescType ty) { 1724e59721cSKiran Chandramohan return TypeDescType::get(convertType(ty.getOfTy())); 1734e59721cSKiran Chandramohan }); 174fe252f8eSValentin Clement addSourceMaterialization(materializeProcedure); 175fe252f8eSValentin Clement addTargetMaterialization(materializeProcedure); 176fe252f8eSValentin Clement } 177fe252f8eSValentin Clement 178fe252f8eSValentin Clement static mlir::Value materializeProcedure(mlir::OpBuilder &builder, 179fe252f8eSValentin Clement BoxProcType type, 180fe252f8eSValentin Clement mlir::ValueRange inputs, 181fe252f8eSValentin Clement mlir::Location loc) { 182fe252f8eSValentin Clement assert(inputs.size() == 1); 183fe252f8eSValentin Clement return builder.create<ConvertOp>(loc, unwrapRefType(type.getEleTy()), 184fe252f8eSValentin Clement inputs[0]); 185fe252f8eSValentin Clement } 186fe252f8eSValentin Clement 187a370a4ffSjeanPerier void setLocation(mlir::Location location) { loc = location; } 188a370a4ffSjeanPerier 189fe252f8eSValentin Clement private: 190a0e9a8daSjeanPerier // Maps to deal with recursive derived types (avoid infinite loops). 191df3f0eeeSjeanPerier // Caching is also beneficial for apps with big types (dozens of 192df3f0eeeSjeanPerier // components and or parent types), so the lifetime of the cache 193df3f0eeeSjeanPerier // is the whole pass. 194a0e9a8daSjeanPerier llvm::DenseMap<mlir::Type, bool> visitedTypes; 195a0e9a8daSjeanPerier bool needConversionIsVisitingRecordType = false; 196df3f0eeeSjeanPerier llvm::DenseMap<mlir::Type, mlir::Type> convertedTypes; 197a370a4ffSjeanPerier mlir::Location loc; 198fe252f8eSValentin Clement }; 199fe252f8eSValentin Clement 200fe252f8eSValentin Clement /// A `boxproc` is an abstraction for a Fortran procedure reference. Typically, 201fe252f8eSValentin Clement /// Fortran procedures can be referenced directly through a function pointer. 202fe252f8eSValentin Clement /// However, Fortran has one-level dynamic scoping between a host procedure and 203fe252f8eSValentin Clement /// its internal procedures. This allows internal procedures to directly access 204fe252f8eSValentin Clement /// and modify the state of the host procedure's variables. 205fe252f8eSValentin Clement /// 206fe252f8eSValentin Clement /// There are any number of possible implementations possible. 207fe252f8eSValentin Clement /// 208fe252f8eSValentin Clement /// The implementation used here is to convert `boxproc` values to function 209fe252f8eSValentin Clement /// pointers everywhere. If a `boxproc` value includes a frame pointer to the 210fe252f8eSValentin Clement /// host procedure's data, then a thunk will be created at runtime to capture 211fe252f8eSValentin Clement /// the frame pointer during execution. In LLVM IR, the frame pointer is 212fe252f8eSValentin Clement /// designated with the `nest` attribute. The thunk's address will then be used 213fe252f8eSValentin Clement /// as the call target instead of the original function's address directly. 21467d0d7acSMichele Scuttari class BoxedProcedurePass 21567d0d7acSMichele Scuttari : public fir::impl::BoxedProcedurePassBase<BoxedProcedurePass> { 216fe252f8eSValentin Clement public: 217c0e6dd1eSTom Eccles using BoxedProcedurePassBase<BoxedProcedurePass>::BoxedProcedurePassBase; 218fe252f8eSValentin Clement 219fe252f8eSValentin Clement inline mlir::ModuleOp getModule() { return getOperation(); } 220fe252f8eSValentin Clement 221fe252f8eSValentin Clement void runOnOperation() override final { 222fe252f8eSValentin Clement if (options.useThunks) { 223fe252f8eSValentin Clement auto *context = &getContext(); 224fe252f8eSValentin Clement mlir::IRRewriter rewriter(context); 225a370a4ffSjeanPerier BoxprocTypeRewriter typeConverter(mlir::UnknownLoc::get(context)); 226fe252f8eSValentin Clement getModule().walk([&](mlir::Operation *op) { 227546f32dfSKrzysztof Parzyszek bool opIsValid = true; 228a370a4ffSjeanPerier typeConverter.setLocation(op->getLoc()); 229fe252f8eSValentin Clement if (auto addr = mlir::dyn_cast<BoxAddrOp>(op)) { 230c373f581SjeanPerier mlir::Type ty = addr.getVal().getType(); 231c373f581SjeanPerier mlir::Type resTy = addr.getResult().getType(); 232a15ebe02SjeanPerier if (llvm::isa<mlir::FunctionType>(ty) || 233a15ebe02SjeanPerier llvm::isa<fir::BoxProcType>(ty)) { 234fe252f8eSValentin Clement // Rewrite all `fir.box_addr` ops on values of type `!fir.boxproc` 235fe252f8eSValentin Clement // or function type to be `fir.convert` ops. 236fe252f8eSValentin Clement rewriter.setInsertionPoint(addr); 237fe252f8eSValentin Clement rewriter.replaceOpWithNewOp<ConvertOp>( 238fe252f8eSValentin Clement addr, typeConverter.convertType(addr.getType()), addr.getVal()); 239546f32dfSKrzysztof Parzyszek opIsValid = false; 240c373f581SjeanPerier } else if (typeConverter.needsConversion(resTy)) { 2415fcf907bSMatthias Springer rewriter.startOpModification(op); 242c373f581SjeanPerier op->getResult(0).setType(typeConverter.convertType(resTy)); 2435fcf907bSMatthias Springer rewriter.finalizeOpModification(op); 244fe252f8eSValentin Clement } 24558ceae95SRiver Riddle } else if (auto func = mlir::dyn_cast<mlir::func::FuncOp>(op)) { 246fe252f8eSValentin Clement mlir::FunctionType ty = func.getFunctionType(); 247fe252f8eSValentin Clement if (typeConverter.needsConversion(ty)) { 2485fcf907bSMatthias Springer rewriter.startOpModification(func); 249fe252f8eSValentin Clement auto toTy = 250fac349a1SChristian Sigg mlir::cast<mlir::FunctionType>(typeConverter.convertType(ty)); 251fe252f8eSValentin Clement if (!func.empty()) 252fe252f8eSValentin Clement for (auto e : llvm::enumerate(toTy.getInputs())) { 253fe252f8eSValentin Clement unsigned i = e.index(); 254fe252f8eSValentin Clement auto &block = func.front(); 255fe252f8eSValentin Clement block.insertArgument(i, e.value(), func.getLoc()); 256fe252f8eSValentin Clement block.getArgument(i + 1).replaceAllUsesWith( 257fe252f8eSValentin Clement block.getArgument(i)); 258fe252f8eSValentin Clement block.eraseArgument(i + 1); 259fe252f8eSValentin Clement } 260fe252f8eSValentin Clement func.setType(toTy); 2615fcf907bSMatthias Springer rewriter.finalizeOpModification(func); 262fe252f8eSValentin Clement } 263fe252f8eSValentin Clement } else if (auto embox = mlir::dyn_cast<EmboxProcOp>(op)) { 264fe252f8eSValentin Clement // Rewrite all `fir.emboxproc` ops to either `fir.convert` or a thunk 265fe252f8eSValentin Clement // as required. 266c373f581SjeanPerier mlir::Type toTy = typeConverter.convertType( 267fac349a1SChristian Sigg mlir::cast<BoxProcType>(embox.getType()).getEleTy()); 268fe252f8eSValentin Clement rewriter.setInsertionPoint(embox); 269fe252f8eSValentin Clement if (embox.getHost()) { 270fe252f8eSValentin Clement // Create the thunk. 271fe252f8eSValentin Clement auto module = embox->getParentOfType<mlir::ModuleOp>(); 27253cc33b0STom Eccles FirOpBuilder builder(rewriter, module); 273*16e9601eSssijaric-nv const auto triple{fir::getTargetTriple(module)}; 274fe252f8eSValentin Clement auto loc = embox.getLoc(); 275fe252f8eSValentin Clement mlir::Type i8Ty = builder.getI8Type(); 276fe252f8eSValentin Clement mlir::Type i8Ptr = builder.getRefType(i8Ty); 277*16e9601eSssijaric-nv // For AArch64, PPC32 and PPC64, the thunk is populated by a call to 278*16e9601eSssijaric-nv // __trampoline_setup, which is defined in 279*16e9601eSssijaric-nv // compiler-rt/lib/builtins/trampoline_setup.c and requires the 280*16e9601eSssijaric-nv // thunk size greater than 32 bytes. For RISCV and x86_64, the 281*16e9601eSssijaric-nv // thunk setup doesn't go through __trampoline_setup and fits in 32 282*16e9601eSssijaric-nv // bytes. 283*16e9601eSssijaric-nv fir::SequenceType::Extent thunkSize = triple.getTrampolineSize(); 284*16e9601eSssijaric-nv mlir::Type buffTy = SequenceType::get({thunkSize}, i8Ty); 285fe252f8eSValentin Clement auto buffer = builder.create<AllocaOp>(loc, buffTy); 286fe252f8eSValentin Clement mlir::Value closure = 287fe252f8eSValentin Clement builder.createConvert(loc, i8Ptr, embox.getHost()); 288fe252f8eSValentin Clement mlir::Value tramp = builder.createConvert(loc, i8Ptr, buffer); 289fe252f8eSValentin Clement mlir::Value func = 290fe252f8eSValentin Clement builder.createConvert(loc, i8Ptr, embox.getFunc()); 291fe252f8eSValentin Clement builder.create<fir::CallOp>( 292fe252f8eSValentin Clement loc, factory::getLlvmInitTrampoline(builder), 293fe252f8eSValentin Clement llvm::ArrayRef<mlir::Value>{tramp, func, closure}); 294fe252f8eSValentin Clement auto adjustCall = builder.create<fir::CallOp>( 295fe252f8eSValentin Clement loc, factory::getLlvmAdjustTrampoline(builder), 296fe252f8eSValentin Clement llvm::ArrayRef<mlir::Value>{tramp}); 297fe252f8eSValentin Clement rewriter.replaceOpWithNewOp<ConvertOp>(embox, toTy, 298fe252f8eSValentin Clement adjustCall.getResult(0)); 299546f32dfSKrzysztof Parzyszek opIsValid = false; 300fe252f8eSValentin Clement } else { 301fe252f8eSValentin Clement // Just forward the function as a pointer. 302fe252f8eSValentin Clement rewriter.replaceOpWithNewOp<ConvertOp>(embox, toTy, 303fe252f8eSValentin Clement embox.getFunc()); 304546f32dfSKrzysztof Parzyszek opIsValid = false; 305fe252f8eSValentin Clement } 306feb9d33aSPeixin Qiao } else if (auto global = mlir::dyn_cast<GlobalOp>(op)) { 307feb9d33aSPeixin Qiao auto ty = global.getType(); 308feb9d33aSPeixin Qiao if (typeConverter.needsConversion(ty)) { 3095fcf907bSMatthias Springer rewriter.startOpModification(global); 310feb9d33aSPeixin Qiao auto toTy = typeConverter.convertType(ty); 311feb9d33aSPeixin Qiao global.setType(toTy); 3125fcf907bSMatthias Springer rewriter.finalizeOpModification(global); 313feb9d33aSPeixin Qiao } 314fe252f8eSValentin Clement } else if (auto mem = mlir::dyn_cast<AllocaOp>(op)) { 315fe252f8eSValentin Clement auto ty = mem.getType(); 316fe252f8eSValentin Clement if (typeConverter.needsConversion(ty)) { 317fe252f8eSValentin Clement rewriter.setInsertionPoint(mem); 318fe252f8eSValentin Clement auto toTy = typeConverter.convertType(unwrapRefType(ty)); 319fe252f8eSValentin Clement bool isPinned = mem.getPinned(); 320c715e2ffSKazu Hirata llvm::StringRef uniqName = 321c715e2ffSKazu Hirata mem.getUniqName().value_or(llvm::StringRef()); 322c715e2ffSKazu Hirata llvm::StringRef bindcName = 323c715e2ffSKazu Hirata mem.getBindcName().value_or(llvm::StringRef()); 324fe252f8eSValentin Clement rewriter.replaceOpWithNewOp<AllocaOp>( 325fe252f8eSValentin Clement mem, toTy, uniqName, bindcName, isPinned, mem.getTypeparams(), 326fe252f8eSValentin Clement mem.getShape()); 327546f32dfSKrzysztof Parzyszek opIsValid = false; 328fe252f8eSValentin Clement } 329fe252f8eSValentin Clement } else if (auto mem = mlir::dyn_cast<AllocMemOp>(op)) { 330fe252f8eSValentin Clement auto ty = mem.getType(); 331fe252f8eSValentin Clement if (typeConverter.needsConversion(ty)) { 332fe252f8eSValentin Clement rewriter.setInsertionPoint(mem); 333fe252f8eSValentin Clement auto toTy = typeConverter.convertType(unwrapRefType(ty)); 334c715e2ffSKazu Hirata llvm::StringRef uniqName = 335c715e2ffSKazu Hirata mem.getUniqName().value_or(llvm::StringRef()); 336c715e2ffSKazu Hirata llvm::StringRef bindcName = 337c715e2ffSKazu Hirata mem.getBindcName().value_or(llvm::StringRef()); 338fe252f8eSValentin Clement rewriter.replaceOpWithNewOp<AllocMemOp>( 339fe252f8eSValentin Clement mem, toTy, uniqName, bindcName, mem.getTypeparams(), 340fe252f8eSValentin Clement mem.getShape()); 341546f32dfSKrzysztof Parzyszek opIsValid = false; 342fe252f8eSValentin Clement } 343fe252f8eSValentin Clement } else if (auto coor = mlir::dyn_cast<CoordinateOp>(op)) { 344fe252f8eSValentin Clement auto ty = coor.getType(); 345fe252f8eSValentin Clement mlir::Type baseTy = coor.getBaseType(); 346fe252f8eSValentin Clement if (typeConverter.needsConversion(ty) || 347fe252f8eSValentin Clement typeConverter.needsConversion(baseTy)) { 348fe252f8eSValentin Clement rewriter.setInsertionPoint(coor); 349fe252f8eSValentin Clement auto toTy = typeConverter.convertType(ty); 350fe252f8eSValentin Clement auto toBaseTy = typeConverter.convertType(baseTy); 351fe252f8eSValentin Clement rewriter.replaceOpWithNewOp<CoordinateOp>(coor, toTy, coor.getRef(), 352fe252f8eSValentin Clement coor.getCoor(), toBaseTy); 353546f32dfSKrzysztof Parzyszek opIsValid = false; 354fe252f8eSValentin Clement } 355fe252f8eSValentin Clement } else if (auto index = mlir::dyn_cast<FieldIndexOp>(op)) { 356fe252f8eSValentin Clement auto ty = index.getType(); 357fe252f8eSValentin Clement mlir::Type onTy = index.getOnType(); 358fe252f8eSValentin Clement if (typeConverter.needsConversion(ty) || 359fe252f8eSValentin Clement typeConverter.needsConversion(onTy)) { 360fe252f8eSValentin Clement rewriter.setInsertionPoint(index); 361fe252f8eSValentin Clement auto toTy = typeConverter.convertType(ty); 362fe252f8eSValentin Clement auto toOnTy = typeConverter.convertType(onTy); 363fe252f8eSValentin Clement rewriter.replaceOpWithNewOp<FieldIndexOp>( 364fe252f8eSValentin Clement index, toTy, index.getFieldId(), toOnTy, index.getTypeparams()); 365546f32dfSKrzysztof Parzyszek opIsValid = false; 366fe252f8eSValentin Clement } 367fe252f8eSValentin Clement } else if (auto index = mlir::dyn_cast<LenParamIndexOp>(op)) { 368fe252f8eSValentin Clement auto ty = index.getType(); 369fe252f8eSValentin Clement mlir::Type onTy = index.getOnType(); 370fe252f8eSValentin Clement if (typeConverter.needsConversion(ty) || 371fe252f8eSValentin Clement typeConverter.needsConversion(onTy)) { 372fe252f8eSValentin Clement rewriter.setInsertionPoint(index); 373fe252f8eSValentin Clement auto toTy = typeConverter.convertType(ty); 374fe252f8eSValentin Clement auto toOnTy = typeConverter.convertType(onTy); 375fe252f8eSValentin Clement rewriter.replaceOpWithNewOp<LenParamIndexOp>( 37665524fcbSKrzysztof Parzyszek index, toTy, index.getFieldId(), toOnTy, index.getTypeparams()); 377546f32dfSKrzysztof Parzyszek opIsValid = false; 378fe252f8eSValentin Clement } 3794e59721cSKiran Chandramohan } else { 3805fcf907bSMatthias Springer rewriter.startOpModification(op); 3814e59721cSKiran Chandramohan // Convert the operands if needed 382fe252f8eSValentin Clement for (auto i : llvm::enumerate(op->getResultTypes())) 383fe252f8eSValentin Clement if (typeConverter.needsConversion(i.value())) { 384fe252f8eSValentin Clement auto toTy = typeConverter.convertType(i.value()); 385fe252f8eSValentin Clement op->getResult(i.index()).setType(toTy); 386fe252f8eSValentin Clement } 3874e59721cSKiran Chandramohan 3884e59721cSKiran Chandramohan // Convert the type attributes if needed 3894e59721cSKiran Chandramohan for (const mlir::NamedAttribute &attr : op->getAttrDictionary()) 3904e59721cSKiran Chandramohan if (auto tyAttr = llvm::dyn_cast<mlir::TypeAttr>(attr.getValue())) 3914e59721cSKiran Chandramohan if (typeConverter.needsConversion(tyAttr.getValue())) { 3924e59721cSKiran Chandramohan auto toTy = typeConverter.convertType(tyAttr.getValue()); 3934e59721cSKiran Chandramohan op->setAttr(attr.getName(), mlir::TypeAttr::get(toTy)); 3944e59721cSKiran Chandramohan } 3955fcf907bSMatthias Springer rewriter.finalizeOpModification(op); 396fe252f8eSValentin Clement } 39708e4386aSjeanPerier // Ensure block arguments are updated if needed. 398546f32dfSKrzysztof Parzyszek if (opIsValid && op->getNumRegions() != 0) { 3995fcf907bSMatthias Springer rewriter.startOpModification(op); 40008e4386aSjeanPerier for (mlir::Region ®ion : op->getRegions()) 40108e4386aSjeanPerier for (mlir::Block &block : region.getBlocks()) 40208e4386aSjeanPerier for (mlir::BlockArgument blockArg : block.getArguments()) 40308e4386aSjeanPerier if (typeConverter.needsConversion(blockArg.getType())) { 40408e4386aSjeanPerier mlir::Type toTy = 40508e4386aSjeanPerier typeConverter.convertType(blockArg.getType()); 40608e4386aSjeanPerier blockArg.setType(toTy); 40708e4386aSjeanPerier } 4085fcf907bSMatthias Springer rewriter.finalizeOpModification(op); 40908e4386aSjeanPerier } 410fe252f8eSValentin Clement }); 411fe252f8eSValentin Clement } 412fe252f8eSValentin Clement } 413fe252f8eSValentin Clement 414fe252f8eSValentin Clement private: 415fe252f8eSValentin Clement BoxedProcedureOptions options; 416fe252f8eSValentin Clement }; 417fe252f8eSValentin Clement } // namespace 418