xref: /llvm-project/flang/lib/Optimizer/CodeGen/BoxedProcedure.cpp (revision 16e9601e193e026d7f3f27e87f0adb81acf5969b)
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 &region : 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