xref: /llvm-project/mlir/test/lib/Dialect/Test/TestDialectInterfaces.cpp (revision 46e41c8631bd6c1a6c91d6cc4a5e4f1671078ccd)
18a7a7137SAlex Zinenko //===- TestDialectInterfaces.cpp - Test dialect interface definitions -----===//
28a7a7137SAlex Zinenko //
38a7a7137SAlex Zinenko // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
48a7a7137SAlex Zinenko // See https://llvm.org/LICENSE.txt for license information.
58a7a7137SAlex Zinenko // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
68a7a7137SAlex Zinenko //
78a7a7137SAlex Zinenko //===----------------------------------------------------------------------===//
88a7a7137SAlex Zinenko 
98a7a7137SAlex Zinenko #include "TestDialect.h"
10e95e94adSJeff Niu #include "TestOps.h"
118a7a7137SAlex Zinenko #include "mlir/Interfaces/FoldInterfaces.h"
128a7a7137SAlex Zinenko #include "mlir/Reducer/ReductionPatternInterface.h"
138a7a7137SAlex Zinenko #include "mlir/Transforms/InliningUtils.h"
148a7a7137SAlex Zinenko 
158a7a7137SAlex Zinenko using namespace mlir;
168a7a7137SAlex Zinenko using namespace test;
178a7a7137SAlex Zinenko 
188a7a7137SAlex Zinenko //===----------------------------------------------------------------------===//
198a7a7137SAlex Zinenko // TestDialect Interfaces
208a7a7137SAlex Zinenko //===----------------------------------------------------------------------===//
218a7a7137SAlex Zinenko 
228a7a7137SAlex Zinenko namespace {
238a7a7137SAlex Zinenko 
248a7a7137SAlex Zinenko /// Testing the correctness of some traits.
258a7a7137SAlex Zinenko static_assert(
268a7a7137SAlex Zinenko     llvm::is_detected<OpTrait::has_implicit_terminator_t,
278a7a7137SAlex Zinenko                       SingleBlockImplicitTerminatorOp>::value,
288a7a7137SAlex Zinenko     "has_implicit_terminator_t does not match SingleBlockImplicitTerminatorOp");
298a7a7137SAlex Zinenko static_assert(OpTrait::hasSingleBlockImplicitTerminator<
308a7a7137SAlex Zinenko                   SingleBlockImplicitTerminatorOp>::value,
318a7a7137SAlex Zinenko               "hasSingleBlockImplicitTerminator does not match "
328a7a7137SAlex Zinenko               "SingleBlockImplicitTerminatorOp");
338a7a7137SAlex Zinenko 
348a7a7137SAlex Zinenko struct TestResourceBlobManagerInterface
358a7a7137SAlex Zinenko     : public ResourceBlobManagerDialectInterfaceBase<
368a7a7137SAlex Zinenko           TestDialectResourceBlobHandle> {
378a7a7137SAlex Zinenko   using ResourceBlobManagerDialectInterfaceBase<
388a7a7137SAlex Zinenko       TestDialectResourceBlobHandle>::ResourceBlobManagerDialectInterfaceBase;
398a7a7137SAlex Zinenko };
408a7a7137SAlex Zinenko 
418a7a7137SAlex Zinenko namespace {
42bff6a429SMatteo Franciolini enum test_encoding { k_attr_params = 0, k_test_i32 = 99 };
43a6df3472SMehdi Amini } // namespace
448a7a7137SAlex Zinenko 
458a7a7137SAlex Zinenko // Test support for interacting with the Bytecode reader/writer.
468a7a7137SAlex Zinenko struct TestBytecodeDialectInterface : public BytecodeDialectInterface {
478a7a7137SAlex Zinenko   using BytecodeDialectInterface::BytecodeDialectInterface;
TestBytecodeDialectInterface__anon2bddc4b90111::TestBytecodeDialectInterface488a7a7137SAlex Zinenko   TestBytecodeDialectInterface(Dialect *dialect)
498a7a7137SAlex Zinenko       : BytecodeDialectInterface(dialect) {}
508a7a7137SAlex Zinenko 
writeType__anon2bddc4b90111::TestBytecodeDialectInterface51bff6a429SMatteo Franciolini   LogicalResult writeType(Type type,
52bff6a429SMatteo Franciolini                           DialectBytecodeWriter &writer) const final {
53bff6a429SMatteo Franciolini     if (auto concreteType = llvm::dyn_cast<TestI32Type>(type)) {
54bff6a429SMatteo Franciolini       writer.writeVarInt(test_encoding::k_test_i32);
55bff6a429SMatteo Franciolini       return success();
56bff6a429SMatteo Franciolini     }
57bff6a429SMatteo Franciolini     return failure();
58bff6a429SMatteo Franciolini   }
59bff6a429SMatteo Franciolini 
readType__anon2bddc4b90111::TestBytecodeDialectInterface60bff6a429SMatteo Franciolini   Type readType(DialectBytecodeReader &reader) const final {
61bff6a429SMatteo Franciolini     uint64_t encoding;
62bff6a429SMatteo Franciolini     if (failed(reader.readVarInt(encoding)))
63bff6a429SMatteo Franciolini       return Type();
64bff6a429SMatteo Franciolini     if (encoding == test_encoding::k_test_i32)
65bff6a429SMatteo Franciolini       return TestI32Type::get(getContext());
66bff6a429SMatteo Franciolini     return Type();
67bff6a429SMatteo Franciolini   }
68bff6a429SMatteo Franciolini 
writeAttribute__anon2bddc4b90111::TestBytecodeDialectInterface698a7a7137SAlex Zinenko   LogicalResult writeAttribute(Attribute attr,
708a7a7137SAlex Zinenko                                DialectBytecodeWriter &writer) const final {
718a7a7137SAlex Zinenko     if (auto concreteAttr = llvm::dyn_cast<TestAttrParamsAttr>(attr)) {
728a7a7137SAlex Zinenko       writer.writeVarInt(test_encoding::k_attr_params);
738a7a7137SAlex Zinenko       writer.writeVarInt(concreteAttr.getV0());
748a7a7137SAlex Zinenko       writer.writeVarInt(concreteAttr.getV1());
758a7a7137SAlex Zinenko       return success();
768a7a7137SAlex Zinenko     }
778a7a7137SAlex Zinenko     return failure();
788a7a7137SAlex Zinenko   }
798a7a7137SAlex Zinenko 
readAttribute__anon2bddc4b90111::TestBytecodeDialectInterface80bff6a429SMatteo Franciolini   Attribute readAttribute(DialectBytecodeReader &reader) const final {
817ad9e9dcSMatteo Franciolini     auto versionOr = reader.getDialectVersion<test::TestDialect>();
82bff6a429SMatteo Franciolini     // Assume current version if not available through the reader.
83bff6a429SMatteo Franciolini     const auto version =
84bff6a429SMatteo Franciolini         (succeeded(versionOr))
85bff6a429SMatteo Franciolini             ? *reinterpret_cast<const TestDialectVersion *>(*versionOr)
86bff6a429SMatteo Franciolini             : TestDialectVersion();
87896aada3SRoger Ferrer Ibanez     if (version.major_ < 2)
888a7a7137SAlex Zinenko       return readAttrOldEncoding(reader);
89896aada3SRoger Ferrer Ibanez     if (version.major_ == 2 && version.minor_ == 0)
908a7a7137SAlex Zinenko       return readAttrNewEncoding(reader);
918a7a7137SAlex Zinenko     // Forbid reading future versions by returning nullptr.
928a7a7137SAlex Zinenko     return Attribute();
938a7a7137SAlex Zinenko   }
948a7a7137SAlex Zinenko 
958a7a7137SAlex Zinenko   // Emit a specific version of the dialect.
writeVersion__anon2bddc4b90111::TestBytecodeDialectInterface968a7a7137SAlex Zinenko   void writeVersion(DialectBytecodeWriter &writer) const final {
977ad9e9dcSMatteo Franciolini     // Construct the current dialect version.
987ad9e9dcSMatteo Franciolini     test::TestDialectVersion versionToEmit;
997ad9e9dcSMatteo Franciolini 
1007ad9e9dcSMatteo Franciolini     // Check if a target version to emit was specified on the writer configs.
1017ad9e9dcSMatteo Franciolini     auto versionOr = writer.getDialectVersion<test::TestDialect>();
1027ad9e9dcSMatteo Franciolini     if (succeeded(versionOr))
1037ad9e9dcSMatteo Franciolini       versionToEmit =
1047ad9e9dcSMatteo Franciolini           *reinterpret_cast<const test::TestDialectVersion *>(*versionOr);
1057ad9e9dcSMatteo Franciolini     writer.writeVarInt(versionToEmit.major_); // major
1067ad9e9dcSMatteo Franciolini     writer.writeVarInt(versionToEmit.minor_); // minor
1078a7a7137SAlex Zinenko   }
1088a7a7137SAlex Zinenko 
1098a7a7137SAlex Zinenko   std::unique_ptr<DialectVersion>
readVersion__anon2bddc4b90111::TestBytecodeDialectInterface1108a7a7137SAlex Zinenko   readVersion(DialectBytecodeReader &reader) const final {
111896aada3SRoger Ferrer Ibanez     uint64_t major_, minor_;
112896aada3SRoger Ferrer Ibanez     if (failed(reader.readVarInt(major_)) || failed(reader.readVarInt(minor_)))
1138a7a7137SAlex Zinenko       return nullptr;
1148a7a7137SAlex Zinenko     auto version = std::make_unique<TestDialectVersion>();
115896aada3SRoger Ferrer Ibanez     version->major_ = major_;
116896aada3SRoger Ferrer Ibanez     version->minor_ = minor_;
1178a7a7137SAlex Zinenko     return version;
1188a7a7137SAlex Zinenko   }
1198a7a7137SAlex Zinenko 
upgradeFromVersion__anon2bddc4b90111::TestBytecodeDialectInterface1208a7a7137SAlex Zinenko   LogicalResult upgradeFromVersion(Operation *topLevelOp,
1218a7a7137SAlex Zinenko                                    const DialectVersion &version_) const final {
1228a7a7137SAlex Zinenko     const auto &version = static_cast<const TestDialectVersion &>(version_);
123896aada3SRoger Ferrer Ibanez     if ((version.major_ == 2) && (version.minor_ == 0))
1248a7a7137SAlex Zinenko       return success();
125896aada3SRoger Ferrer Ibanez     if (version.major_ > 2 || (version.major_ == 2 && version.minor_ > 0)) {
1268a7a7137SAlex Zinenko       return topLevelOp->emitError()
1278a7a7137SAlex Zinenko              << "current test dialect version is 2.0, can't parse version: "
128896aada3SRoger Ferrer Ibanez              << version.major_ << "." << version.minor_;
1298a7a7137SAlex Zinenko     }
1308a7a7137SAlex Zinenko     // Prior version 2.0, the old op supported only a single attribute called
1318a7a7137SAlex Zinenko     // "dimensions". We can perform the upgrade.
1328a7a7137SAlex Zinenko     topLevelOp->walk([](TestVersionedOpA op) {
133cf0e8dcaSMatteo Franciolini       // Prior version 2.0, `readProperties` did not process the modifier
134cf0e8dcaSMatteo Franciolini       // attribute. Handle that according to the version here.
135cf0e8dcaSMatteo Franciolini       auto &prop = op.getProperties();
136cf0e8dcaSMatteo Franciolini       prop.modifier = BoolAttr::get(op->getContext(), false);
1378a7a7137SAlex Zinenko     });
1388a7a7137SAlex Zinenko     return success();
1398a7a7137SAlex Zinenko   }
1408a7a7137SAlex Zinenko 
1418a7a7137SAlex Zinenko private:
readAttrNewEncoding__anon2bddc4b90111::TestBytecodeDialectInterface1428a7a7137SAlex Zinenko   Attribute readAttrNewEncoding(DialectBytecodeReader &reader) const {
1438a7a7137SAlex Zinenko     uint64_t encoding;
1448a7a7137SAlex Zinenko     if (failed(reader.readVarInt(encoding)) ||
1458a7a7137SAlex Zinenko         encoding != test_encoding::k_attr_params)
1468a7a7137SAlex Zinenko       return Attribute();
1478a7a7137SAlex Zinenko     // The new encoding has v0 first, v1 second.
1488a7a7137SAlex Zinenko     uint64_t v0, v1;
1498a7a7137SAlex Zinenko     if (failed(reader.readVarInt(v0)) || failed(reader.readVarInt(v1)))
1508a7a7137SAlex Zinenko       return Attribute();
1518a7a7137SAlex Zinenko     return TestAttrParamsAttr::get(getContext(), static_cast<int>(v0),
1528a7a7137SAlex Zinenko                                    static_cast<int>(v1));
1538a7a7137SAlex Zinenko   }
1548a7a7137SAlex Zinenko 
readAttrOldEncoding__anon2bddc4b90111::TestBytecodeDialectInterface1558a7a7137SAlex Zinenko   Attribute readAttrOldEncoding(DialectBytecodeReader &reader) const {
1568a7a7137SAlex Zinenko     uint64_t encoding;
1578a7a7137SAlex Zinenko     if (failed(reader.readVarInt(encoding)) ||
1588a7a7137SAlex Zinenko         encoding != test_encoding::k_attr_params)
1598a7a7137SAlex Zinenko       return Attribute();
1608a7a7137SAlex Zinenko     // The old encoding has v1 first, v0 second.
1618a7a7137SAlex Zinenko     uint64_t v0, v1;
1628a7a7137SAlex Zinenko     if (failed(reader.readVarInt(v1)) || failed(reader.readVarInt(v0)))
1638a7a7137SAlex Zinenko       return Attribute();
1648a7a7137SAlex Zinenko     return TestAttrParamsAttr::get(getContext(), static_cast<int>(v0),
1658a7a7137SAlex Zinenko                                    static_cast<int>(v1));
1668a7a7137SAlex Zinenko   }
1678a7a7137SAlex Zinenko };
1688a7a7137SAlex Zinenko 
1698a7a7137SAlex Zinenko // Test support for interacting with the AsmPrinter.
1708a7a7137SAlex Zinenko struct TestOpAsmInterface : public OpAsmDialectInterface {
1718a7a7137SAlex Zinenko   using OpAsmDialectInterface::OpAsmDialectInterface;
TestOpAsmInterface__anon2bddc4b90111::TestOpAsmInterface1728a7a7137SAlex Zinenko   TestOpAsmInterface(Dialect *dialect, TestResourceBlobManagerInterface &mgr)
1738a7a7137SAlex Zinenko       : OpAsmDialectInterface(dialect), blobManager(mgr) {}
1748a7a7137SAlex Zinenko 
1758a7a7137SAlex Zinenko   //===------------------------------------------------------------------===//
1768a7a7137SAlex Zinenko   // Aliases
1778a7a7137SAlex Zinenko   //===------------------------------------------------------------------===//
1788a7a7137SAlex Zinenko 
getAlias__anon2bddc4b90111::TestOpAsmInterface1798a7a7137SAlex Zinenko   AliasResult getAlias(Attribute attr, raw_ostream &os) const final {
1808a7a7137SAlex Zinenko     StringAttr strAttr = dyn_cast<StringAttr>(attr);
1818a7a7137SAlex Zinenko     if (!strAttr)
1828a7a7137SAlex Zinenko       return AliasResult::NoAlias;
1838a7a7137SAlex Zinenko 
1848a7a7137SAlex Zinenko     // Check the contents of the string attribute to see what the test alias
1858a7a7137SAlex Zinenko     // should be named.
1868a7a7137SAlex Zinenko     std::optional<StringRef> aliasName =
1878a7a7137SAlex Zinenko         StringSwitch<std::optional<StringRef>>(strAttr.getValue())
1888a7a7137SAlex Zinenko             .Case("alias_test:dot_in_name", StringRef("test.alias"))
1898a7a7137SAlex Zinenko             .Case("alias_test:trailing_digit", StringRef("test_alias0"))
1908a7a7137SAlex Zinenko             .Case("alias_test:prefixed_digit", StringRef("0_test_alias"))
191*46e41c86SWill Dietz             .Case("alias_test:prefixed_symbol", StringRef("%test"))
1928a7a7137SAlex Zinenko             .Case("alias_test:sanitize_conflict_a",
1938a7a7137SAlex Zinenko                   StringRef("test_alias_conflict0"))
1948a7a7137SAlex Zinenko             .Case("alias_test:sanitize_conflict_b",
1958a7a7137SAlex Zinenko                   StringRef("test_alias_conflict0_"))
1968a7a7137SAlex Zinenko             .Case("alias_test:tensor_encoding", StringRef("test_encoding"))
1978a7a7137SAlex Zinenko             .Default(std::nullopt);
1988a7a7137SAlex Zinenko     if (!aliasName)
1998a7a7137SAlex Zinenko       return AliasResult::NoAlias;
2008a7a7137SAlex Zinenko 
2018a7a7137SAlex Zinenko     os << *aliasName;
2028a7a7137SAlex Zinenko     return AliasResult::FinalAlias;
2038a7a7137SAlex Zinenko   }
2048a7a7137SAlex Zinenko 
getAlias__anon2bddc4b90111::TestOpAsmInterface2058a7a7137SAlex Zinenko   AliasResult getAlias(Type type, raw_ostream &os) const final {
2068a7a7137SAlex Zinenko     if (auto tupleType = dyn_cast<TupleType>(type)) {
2078a7a7137SAlex Zinenko       if (tupleType.size() > 0 &&
2088a7a7137SAlex Zinenko           llvm::all_of(tupleType.getTypes(), [](Type elemType) {
2098a7a7137SAlex Zinenko             return isa<SimpleAType>(elemType);
2108a7a7137SAlex Zinenko           })) {
2118a7a7137SAlex Zinenko         os << "test_tuple";
2128a7a7137SAlex Zinenko         return AliasResult::FinalAlias;
2138a7a7137SAlex Zinenko       }
2148a7a7137SAlex Zinenko     }
2158a7a7137SAlex Zinenko     if (auto intType = dyn_cast<TestIntegerType>(type)) {
2168a7a7137SAlex Zinenko       if (intType.getSignedness() ==
2178a7a7137SAlex Zinenko               TestIntegerType::SignednessSemantics::Unsigned &&
2188a7a7137SAlex Zinenko           intType.getWidth() == 8) {
2198a7a7137SAlex Zinenko         os << "test_ui8";
2208a7a7137SAlex Zinenko         return AliasResult::FinalAlias;
2218a7a7137SAlex Zinenko       }
2228a7a7137SAlex Zinenko     }
2238a7a7137SAlex Zinenko     if (auto recType = dyn_cast<TestRecursiveType>(type)) {
2248a7a7137SAlex Zinenko       if (recType.getName() == "type_to_alias") {
2258a7a7137SAlex Zinenko         // We only make alias for a specific recursive type.
2268a7a7137SAlex Zinenko         os << "testrec";
2278a7a7137SAlex Zinenko         return AliasResult::FinalAlias;
2288a7a7137SAlex Zinenko       }
2298a7a7137SAlex Zinenko     }
230de3f7e2fSMarkus Böck     if (auto recAliasType = dyn_cast<TestRecursiveAliasType>(type)) {
231de3f7e2fSMarkus Böck       os << recAliasType.getName();
232de3f7e2fSMarkus Böck       return AliasResult::FinalAlias;
233de3f7e2fSMarkus Böck     }
2348a7a7137SAlex Zinenko     return AliasResult::NoAlias;
2358a7a7137SAlex Zinenko   }
2368a7a7137SAlex Zinenko 
2378a7a7137SAlex Zinenko   //===------------------------------------------------------------------===//
2388a7a7137SAlex Zinenko   // Resources
2398a7a7137SAlex Zinenko   //===------------------------------------------------------------------===//
2408a7a7137SAlex Zinenko 
2418a7a7137SAlex Zinenko   std::string
getResourceKey__anon2bddc4b90111::TestOpAsmInterface2428a7a7137SAlex Zinenko   getResourceKey(const AsmDialectResourceHandle &handle) const override {
2438a7a7137SAlex Zinenko     return cast<TestDialectResourceBlobHandle>(handle).getKey().str();
2448a7a7137SAlex Zinenko   }
2458a7a7137SAlex Zinenko 
2468a7a7137SAlex Zinenko   FailureOr<AsmDialectResourceHandle>
declareResource__anon2bddc4b90111::TestOpAsmInterface2478a7a7137SAlex Zinenko   declareResource(StringRef key) const final {
2488a7a7137SAlex Zinenko     return blobManager.insert(key);
2498a7a7137SAlex Zinenko   }
2508a7a7137SAlex Zinenko 
parseResource__anon2bddc4b90111::TestOpAsmInterface2518a7a7137SAlex Zinenko   LogicalResult parseResource(AsmParsedResourceEntry &entry) const final {
2528a7a7137SAlex Zinenko     FailureOr<AsmResourceBlob> blob = entry.parseAsBlob();
2538a7a7137SAlex Zinenko     if (failed(blob))
2548a7a7137SAlex Zinenko       return failure();
2558a7a7137SAlex Zinenko 
2568a7a7137SAlex Zinenko     // Update the blob for this entry.
2578a7a7137SAlex Zinenko     blobManager.update(entry.getKey(), std::move(*blob));
2588a7a7137SAlex Zinenko     return success();
2598a7a7137SAlex Zinenko   }
2608a7a7137SAlex Zinenko 
2618a7a7137SAlex Zinenko   void
buildResources__anon2bddc4b90111::TestOpAsmInterface2628a7a7137SAlex Zinenko   buildResources(Operation *op,
2638a7a7137SAlex Zinenko                  const SetVector<AsmDialectResourceHandle> &referencedResources,
2648a7a7137SAlex Zinenko                  AsmResourceBuilder &provider) const final {
2658a7a7137SAlex Zinenko     blobManager.buildResources(provider, referencedResources.getArrayRef());
2668a7a7137SAlex Zinenko   }
2678a7a7137SAlex Zinenko 
2688a7a7137SAlex Zinenko private:
2698a7a7137SAlex Zinenko   /// The blob manager for the dialect.
2708a7a7137SAlex Zinenko   TestResourceBlobManagerInterface &blobManager;
2718a7a7137SAlex Zinenko };
2728a7a7137SAlex Zinenko 
2738a7a7137SAlex Zinenko struct TestDialectFoldInterface : public DialectFoldInterface {
2748a7a7137SAlex Zinenko   using DialectFoldInterface::DialectFoldInterface;
2758a7a7137SAlex Zinenko 
2768a7a7137SAlex Zinenko   /// Registered hook to check if the given region, which is attached to an
2778a7a7137SAlex Zinenko   /// operation that is *not* isolated from above, should be used when
2788a7a7137SAlex Zinenko   /// materializing constants.
shouldMaterializeInto__anon2bddc4b90111::TestDialectFoldInterface2798a7a7137SAlex Zinenko   bool shouldMaterializeInto(Region *region) const final {
2808a7a7137SAlex Zinenko     // If this is a one region operation, then insert into it.
2818a7a7137SAlex Zinenko     return isa<OneRegionOp>(region->getParentOp());
2828a7a7137SAlex Zinenko   }
2838a7a7137SAlex Zinenko };
2848a7a7137SAlex Zinenko 
2858a7a7137SAlex Zinenko /// This class defines the interface for handling inlining with standard
2868a7a7137SAlex Zinenko /// operations.
2878a7a7137SAlex Zinenko struct TestInlinerInterface : public DialectInlinerInterface {
2888a7a7137SAlex Zinenko   using DialectInlinerInterface::DialectInlinerInterface;
2898a7a7137SAlex Zinenko 
2908a7a7137SAlex Zinenko   //===--------------------------------------------------------------------===//
2918a7a7137SAlex Zinenko   // Analysis Hooks
2928a7a7137SAlex Zinenko   //===--------------------------------------------------------------------===//
2938a7a7137SAlex Zinenko 
isLegalToInline__anon2bddc4b90111::TestInlinerInterface2948a7a7137SAlex Zinenko   bool isLegalToInline(Operation *call, Operation *callable,
2958a7a7137SAlex Zinenko                        bool wouldBeCloned) const final {
2968a7a7137SAlex Zinenko     // Don't allow inlining calls that are marked `noinline`.
2978a7a7137SAlex Zinenko     return !call->hasAttr("noinline");
2988a7a7137SAlex Zinenko   }
isLegalToInline__anon2bddc4b90111::TestInlinerInterface2998a7a7137SAlex Zinenko   bool isLegalToInline(Region *, Region *, bool, IRMapping &) const final {
3008a7a7137SAlex Zinenko     // Inlining into test dialect regions is legal.
3018a7a7137SAlex Zinenko     return true;
3028a7a7137SAlex Zinenko   }
isLegalToInline__anon2bddc4b90111::TestInlinerInterface3038a7a7137SAlex Zinenko   bool isLegalToInline(Operation *, Region *, bool, IRMapping &) const final {
3048a7a7137SAlex Zinenko     return true;
3058a7a7137SAlex Zinenko   }
3068a7a7137SAlex Zinenko 
shouldAnalyzeRecursively__anon2bddc4b90111::TestInlinerInterface3078a7a7137SAlex Zinenko   bool shouldAnalyzeRecursively(Operation *op) const final {
3088a7a7137SAlex Zinenko     // Analyze recursively if this is not a functional region operation, it
3098a7a7137SAlex Zinenko     // froms a separate functional scope.
3108a7a7137SAlex Zinenko     return !isa<FunctionalRegionOp>(op);
3118a7a7137SAlex Zinenko   }
3128a7a7137SAlex Zinenko 
3138a7a7137SAlex Zinenko   //===--------------------------------------------------------------------===//
3148a7a7137SAlex Zinenko   // Transformation Hooks
3158a7a7137SAlex Zinenko   //===--------------------------------------------------------------------===//
3168a7a7137SAlex Zinenko 
3178a7a7137SAlex Zinenko   /// Handle the given inlined terminator by replacing it with a new operation
3188a7a7137SAlex Zinenko   /// as necessary.
handleTerminator__anon2bddc4b90111::TestInlinerInterface31926a0b277SMehdi Amini   void handleTerminator(Operation *op, ValueRange valuesToRepl) const final {
3208a7a7137SAlex Zinenko     // Only handle "test.return" here.
3218a7a7137SAlex Zinenko     auto returnOp = dyn_cast<TestReturnOp>(op);
3228a7a7137SAlex Zinenko     if (!returnOp)
3238a7a7137SAlex Zinenko       return;
3248a7a7137SAlex Zinenko 
3258a7a7137SAlex Zinenko     // Replace the values directly with the return operands.
3268a7a7137SAlex Zinenko     assert(returnOp.getNumOperands() == valuesToRepl.size());
3278a7a7137SAlex Zinenko     for (const auto &it : llvm::enumerate(returnOp.getOperands()))
3288a7a7137SAlex Zinenko       valuesToRepl[it.index()].replaceAllUsesWith(it.value());
3298a7a7137SAlex Zinenko   }
3308a7a7137SAlex Zinenko 
3318a7a7137SAlex Zinenko   /// Attempt to materialize a conversion for a type mismatch between a call
3328a7a7137SAlex Zinenko   /// from this dialect, and a callable region. This method should generate an
3338a7a7137SAlex Zinenko   /// operation that takes 'input' as the only operand, and produces a single
3348a7a7137SAlex Zinenko   /// result of 'resultType'. If a conversion can not be generated, nullptr
3358a7a7137SAlex Zinenko   /// should be returned.
materializeCallConversion__anon2bddc4b90111::TestInlinerInterface3368a7a7137SAlex Zinenko   Operation *materializeCallConversion(OpBuilder &builder, Value input,
3378a7a7137SAlex Zinenko                                        Type resultType,
3388a7a7137SAlex Zinenko                                        Location conversionLoc) const final {
3398a7a7137SAlex Zinenko     // Only allow conversion for i16/i32 types.
3408a7a7137SAlex Zinenko     if (!(resultType.isSignlessInteger(16) ||
3418a7a7137SAlex Zinenko           resultType.isSignlessInteger(32)) ||
3428a7a7137SAlex Zinenko         !(input.getType().isSignlessInteger(16) ||
3438a7a7137SAlex Zinenko           input.getType().isSignlessInteger(32)))
3448a7a7137SAlex Zinenko       return nullptr;
3458a7a7137SAlex Zinenko     return builder.create<TestCastOp>(conversionLoc, resultType, input);
3468a7a7137SAlex Zinenko   }
3478a7a7137SAlex Zinenko 
handleArgument__anon2bddc4b90111::TestInlinerInterface3488a7a7137SAlex Zinenko   Value handleArgument(OpBuilder &builder, Operation *call, Operation *callable,
3498a7a7137SAlex Zinenko                        Value argument,
3508a7a7137SAlex Zinenko                        DictionaryAttr argumentAttrs) const final {
3518a7a7137SAlex Zinenko     if (!argumentAttrs.contains("test.handle_argument"))
3528a7a7137SAlex Zinenko       return argument;
3538a7a7137SAlex Zinenko     return builder.create<TestTypeChangerOp>(call->getLoc(), argument.getType(),
3548a7a7137SAlex Zinenko                                              argument);
3558a7a7137SAlex Zinenko   }
3568a7a7137SAlex Zinenko 
handleResult__anon2bddc4b90111::TestInlinerInterface3578a7a7137SAlex Zinenko   Value handleResult(OpBuilder &builder, Operation *call, Operation *callable,
3588a7a7137SAlex Zinenko                      Value result, DictionaryAttr resultAttrs) const final {
3598a7a7137SAlex Zinenko     if (!resultAttrs.contains("test.handle_result"))
3608a7a7137SAlex Zinenko       return result;
3618a7a7137SAlex Zinenko     return builder.create<TestTypeChangerOp>(call->getLoc(), result.getType(),
3628a7a7137SAlex Zinenko                                              result);
3638a7a7137SAlex Zinenko   }
3648a7a7137SAlex Zinenko 
processInlinedCallBlocks__anon2bddc4b90111::TestInlinerInterface3658a7a7137SAlex Zinenko   void processInlinedCallBlocks(
3668a7a7137SAlex Zinenko       Operation *call,
3678a7a7137SAlex Zinenko       iterator_range<Region::iterator> inlinedBlocks) const final {
3688a7a7137SAlex Zinenko     if (!isa<ConversionCallOp>(call))
3698a7a7137SAlex Zinenko       return;
3708a7a7137SAlex Zinenko 
3718a7a7137SAlex Zinenko     // Set attributed on all ops in the inlined blocks.
3728a7a7137SAlex Zinenko     for (Block &block : inlinedBlocks) {
3738a7a7137SAlex Zinenko       block.walk([&](Operation *op) {
3748a7a7137SAlex Zinenko         op->setAttr("inlined_conversion", UnitAttr::get(call->getContext()));
3758a7a7137SAlex Zinenko       });
3768a7a7137SAlex Zinenko     }
3778a7a7137SAlex Zinenko   }
3788a7a7137SAlex Zinenko };
3798a7a7137SAlex Zinenko 
3808a7a7137SAlex Zinenko struct TestReductionPatternInterface : public DialectReductionPatternInterface {
3818a7a7137SAlex Zinenko public:
TestReductionPatternInterface__anon2bddc4b90111::TestReductionPatternInterface3828a7a7137SAlex Zinenko   TestReductionPatternInterface(Dialect *dialect)
3838a7a7137SAlex Zinenko       : DialectReductionPatternInterface(dialect) {}
3848a7a7137SAlex Zinenko 
populateReductionPatterns__anon2bddc4b90111::TestReductionPatternInterface3858a7a7137SAlex Zinenko   void populateReductionPatterns(RewritePatternSet &patterns) const final {
3868a7a7137SAlex Zinenko     populateTestReductionPatterns(patterns);
3878a7a7137SAlex Zinenko   }
3888a7a7137SAlex Zinenko };
3898a7a7137SAlex Zinenko 
3908a7a7137SAlex Zinenko } // namespace
3918a7a7137SAlex Zinenko 
registerInterfaces()3928a7a7137SAlex Zinenko void TestDialect::registerInterfaces() {
3938a7a7137SAlex Zinenko   auto &blobInterface = addInterface<TestResourceBlobManagerInterface>();
3948a7a7137SAlex Zinenko   addInterface<TestOpAsmInterface>(blobInterface);
3958a7a7137SAlex Zinenko 
3968a7a7137SAlex Zinenko   addInterfaces<TestDialectFoldInterface, TestInlinerInterface,
3978a7a7137SAlex Zinenko                 TestReductionPatternInterface, TestBytecodeDialectInterface>();
3988a7a7137SAlex Zinenko }
399