1fec6c5acSUday Bondhugula //===- TestDialect.cpp - MLIR Dialect for Testing -------------------------===//
2fec6c5acSUday Bondhugula //
3fec6c5acSUday Bondhugula // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4fec6c5acSUday Bondhugula // See https://llvm.org/LICENSE.txt for license information.
5fec6c5acSUday Bondhugula // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fec6c5acSUday Bondhugula //
7fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===//
8fec6c5acSUday Bondhugula 
9fec6c5acSUday Bondhugula #include "TestDialect.h"
1083ef862fSRiver Riddle #include "TestAttributes.h"
11c484c7ddSChia-hung Duan #include "TestInterfaces.h"
122e2cdd0aSRiver Riddle #include "TestTypes.h"
13a54f4eaeSMogball #include "mlir/Dialect/Arithmetic/IR/Arithmetic.h"
143ba14fa0SAlex Zinenko #include "mlir/Dialect/DLTI/DLTI.h"
1523aa5a74SRiver Riddle #include "mlir/Dialect/Func/IR/FuncOps.h"
163ed3e438SMaheshRavishankar #include "mlir/Dialect/Tensor/IR/Tensor.h"
17ea488bd6SRiver Riddle #include "mlir/IR/AsmState.h"
1895aff23eSKrzysztof Drewniak #include "mlir/IR/BuiltinAttributes.h"
1965fcddffSRiver Riddle #include "mlir/IR/BuiltinOps.h"
2095aff23eSKrzysztof Drewniak #include "mlir/IR/Diagnostics.h"
212e2cdd0aSRiver Riddle #include "mlir/IR/DialectImplementation.h"
229e0b5533SMathieu Fehr #include "mlir/IR/ExtensibleDialect.h"
2395aff23eSKrzysztof Drewniak #include "mlir/IR/MLIRContext.h"
2495aff23eSKrzysztof Drewniak #include "mlir/IR/OperationSupport.h"
25fec6c5acSUday Bondhugula #include "mlir/IR/PatternMatch.h"
26fec6c5acSUday Bondhugula #include "mlir/IR/TypeUtilities.h"
275232c5c5SChia-hung Duan #include "mlir/IR/Verifier.h"
2895aff23eSKrzysztof Drewniak #include "mlir/Interfaces/InferIntRangeInterface.h"
29c484c7ddSChia-hung Duan #include "mlir/Reducer/ReductionPatternInterface.h"
30fec6c5acSUday Bondhugula #include "mlir/Transforms/FoldUtils.h"
31fec6c5acSUday Bondhugula #include "mlir/Transforms/InliningUtils.h"
3295aff23eSKrzysztof Drewniak #include "llvm/ADT/SmallString.h"
33a266a210SJeremy Furtek #include "llvm/ADT/StringExtras.h"
34fec6c5acSUday Bondhugula #include "llvm/ADT/StringSwitch.h"
35fec6c5acSUday Bondhugula 
367776b19eSStephen Neuendorffer // Include this before the using namespace lines below to
377776b19eSStephen Neuendorffer // test that we don't have namespace dependencies.
38485cc55eSStella Laurenzo #include "TestOpsDialect.cpp.inc"
39485cc55eSStella Laurenzo 
407776b19eSStephen Neuendorffer using namespace mlir;
417776b19eSStephen Neuendorffer using namespace test;
427776b19eSStephen Neuendorffer 
registerTestDialect(DialectRegistry & registry)437776b19eSStephen Neuendorffer void test::registerTestDialect(DialectRegistry &registry) {
44f9dc2b70SMehdi Amini   registry.insert<TestDialect>();
45f9dc2b70SMehdi Amini }
46f9dc2b70SMehdi Amini 
47fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===//
48ea488bd6SRiver Riddle // External Elements Data
49ea488bd6SRiver Riddle //===----------------------------------------------------------------------===//
50ea488bd6SRiver Riddle 
getData() const51ea488bd6SRiver Riddle ArrayRef<uint64_t> TestExternalElementsData::getData() const {
52ea488bd6SRiver Riddle   ArrayRef<char> data = AsmResourceBlob::getData();
53ea488bd6SRiver Riddle   return ArrayRef<uint64_t>((const uint64_t *)data.data(),
54ea488bd6SRiver Riddle                             data.size() / sizeof(uint64_t));
55ea488bd6SRiver Riddle }
56ea488bd6SRiver Riddle 
57ea488bd6SRiver Riddle TestExternalElementsData
allocate(size_t numElements)58ea488bd6SRiver Riddle TestExternalElementsData::allocate(size_t numElements) {
59ea488bd6SRiver Riddle   return TestExternalElementsData(
60ea488bd6SRiver Riddle       llvm::ArrayRef<uint64_t>(new uint64_t[numElements], numElements),
61ea488bd6SRiver Riddle       [](const uint64_t *data, size_t) { delete[] data; },
62ea488bd6SRiver Riddle       /*dataIsMutable=*/true);
63ea488bd6SRiver Riddle }
64ea488bd6SRiver Riddle 
65ea488bd6SRiver Riddle const TestExternalElementsData *
getData(StringRef name) const66ea488bd6SRiver Riddle TestExternalElementsDataManager::getData(StringRef name) const {
67ea488bd6SRiver Riddle   auto it = dataMap.find(name);
68ea488bd6SRiver Riddle   return it != dataMap.end() ? &*it->second : nullptr;
69ea488bd6SRiver Riddle }
70ea488bd6SRiver Riddle 
71ea488bd6SRiver Riddle std::pair<TestExternalElementsDataManager::DataMap::iterator, bool>
insert(StringRef name)72ea488bd6SRiver Riddle TestExternalElementsDataManager::insert(StringRef name) {
73ea488bd6SRiver Riddle   auto it = dataMap.try_emplace(name, nullptr);
74ea488bd6SRiver Riddle   if (it.second)
75ea488bd6SRiver Riddle     return it;
76ea488bd6SRiver Riddle 
77ea488bd6SRiver Riddle   llvm::SmallString<32> nameStorage(name);
78ea488bd6SRiver Riddle   nameStorage.push_back('_');
79ea488bd6SRiver Riddle   size_t nameCounter = 1;
80ea488bd6SRiver Riddle   do {
81ea488bd6SRiver Riddle     nameStorage += std::to_string(nameCounter++);
82ea488bd6SRiver Riddle     auto it = dataMap.try_emplace(nameStorage, nullptr);
83ea488bd6SRiver Riddle     if (it.second)
84ea488bd6SRiver Riddle       return it;
85ea488bd6SRiver Riddle     nameStorage.resize(name.size() + 1);
86ea488bd6SRiver Riddle   } while (true);
87ea488bd6SRiver Riddle }
88ea488bd6SRiver Riddle 
setData(StringRef name,TestExternalElementsData && data)89ea488bd6SRiver Riddle void TestExternalElementsDataManager::setData(StringRef name,
90ea488bd6SRiver Riddle                                               TestExternalElementsData &&data) {
91ea488bd6SRiver Riddle   auto it = dataMap.find(name);
92ea488bd6SRiver Riddle   assert(it != dataMap.end() && "data not registered");
93ea488bd6SRiver Riddle   it->second = std::make_unique<TestExternalElementsData>(std::move(data));
94ea488bd6SRiver Riddle }
95ea488bd6SRiver Riddle 
96ea488bd6SRiver Riddle //===----------------------------------------------------------------------===//
97fec6c5acSUday Bondhugula // TestDialect Interfaces
98fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===//
99fec6c5acSUday Bondhugula 
100fec6c5acSUday Bondhugula namespace {
101fec6c5acSUday Bondhugula 
102973ddb7dSMehdi Amini /// Testing the correctness of some traits.
103973ddb7dSMehdi Amini static_assert(
104973ddb7dSMehdi Amini     llvm::is_detected<OpTrait::has_implicit_terminator_t,
105973ddb7dSMehdi Amini                       SingleBlockImplicitTerminatorOp>::value,
106973ddb7dSMehdi Amini     "has_implicit_terminator_t does not match SingleBlockImplicitTerminatorOp");
107973ddb7dSMehdi Amini static_assert(OpTrait::hasSingleBlockImplicitTerminator<
108973ddb7dSMehdi Amini                   SingleBlockImplicitTerminatorOp>::value,
109973ddb7dSMehdi Amini               "hasSingleBlockImplicitTerminator does not match "
110973ddb7dSMehdi Amini               "SingleBlockImplicitTerminatorOp");
111973ddb7dSMehdi Amini 
112fec6c5acSUday Bondhugula // Test support for interacting with the AsmPrinter.
113fec6c5acSUday Bondhugula struct TestOpAsmInterface : public OpAsmDialectInterface {
114fec6c5acSUday Bondhugula   using OpAsmDialectInterface::OpAsmDialectInterface;
115fec6c5acSUday Bondhugula 
116ea488bd6SRiver Riddle   //===------------------------------------------------------------------===//
117ea488bd6SRiver Riddle   // Aliases
118ea488bd6SRiver Riddle   //===------------------------------------------------------------------===//
119ea488bd6SRiver Riddle 
getAlias__anonf77d94720211::TestOpAsmInterface12059f59d1cSVladislav Vinogradov   AliasResult getAlias(Attribute attr, raw_ostream &os) const final {
121a463ea50SRiver Riddle     StringAttr strAttr = attr.dyn_cast<StringAttr>();
122a463ea50SRiver Riddle     if (!strAttr)
12359f59d1cSVladislav Vinogradov       return AliasResult::NoAlias;
124a463ea50SRiver Riddle 
125a463ea50SRiver Riddle     // Check the contents of the string attribute to see what the test alias
126a463ea50SRiver Riddle     // should be named.
127a463ea50SRiver Riddle     Optional<StringRef> aliasName =
128a463ea50SRiver Riddle         StringSwitch<Optional<StringRef>>(strAttr.getValue())
129a463ea50SRiver Riddle             .Case("alias_test:dot_in_name", StringRef("test.alias"))
130a463ea50SRiver Riddle             .Case("alias_test:trailing_digit", StringRef("test_alias0"))
131a463ea50SRiver Riddle             .Case("alias_test:prefixed_digit", StringRef("0_test_alias"))
132a463ea50SRiver Riddle             .Case("alias_test:sanitize_conflict_a",
133a463ea50SRiver Riddle                   StringRef("test_alias_conflict0"))
134a463ea50SRiver Riddle             .Case("alias_test:sanitize_conflict_b",
135a463ea50SRiver Riddle                   StringRef("test_alias_conflict0_"))
136eb6c63cbSVladislav Vinogradov             .Case("alias_test:tensor_encoding", StringRef("test_encoding"))
137a463ea50SRiver Riddle             .Default(llvm::None);
138a463ea50SRiver Riddle     if (!aliasName)
13959f59d1cSVladislav Vinogradov       return AliasResult::NoAlias;
140a463ea50SRiver Riddle 
141a463ea50SRiver Riddle     os << *aliasName;
14259f59d1cSVladislav Vinogradov     return AliasResult::FinalAlias;
14359f59d1cSVladislav Vinogradov   }
14459f59d1cSVladislav Vinogradov 
getAlias__anonf77d94720211::TestOpAsmInterface14559f59d1cSVladislav Vinogradov   AliasResult getAlias(Type type, raw_ostream &os) const final {
14659f59d1cSVladislav Vinogradov     if (auto tupleType = type.dyn_cast<TupleType>()) {
14759f59d1cSVladislav Vinogradov       if (tupleType.size() > 0 &&
14859f59d1cSVladislav Vinogradov           llvm::all_of(tupleType.getTypes(), [](Type elemType) {
14959f59d1cSVladislav Vinogradov             return elemType.isa<SimpleAType>();
15059f59d1cSVladislav Vinogradov           })) {
15159f59d1cSVladislav Vinogradov         os << "test_tuple";
15259f59d1cSVladislav Vinogradov         return AliasResult::FinalAlias;
15359f59d1cSVladislav Vinogradov       }
15459f59d1cSVladislav Vinogradov     }
155c6390f19SVladislav Vinogradov     if (auto intType = type.dyn_cast<TestIntegerType>()) {
156c6390f19SVladislav Vinogradov       if (intType.getSignedness() ==
157c6390f19SVladislav Vinogradov               TestIntegerType::SignednessSemantics::Unsigned &&
158c6390f19SVladislav Vinogradov           intType.getWidth() == 8) {
159c6390f19SVladislav Vinogradov         os << "test_ui8";
160c6390f19SVladislav Vinogradov         return AliasResult::FinalAlias;
161c6390f19SVladislav Vinogradov       }
162c6390f19SVladislav Vinogradov     }
163d4102861SMin-Yih Hsu     if (auto recType = type.dyn_cast<TestRecursiveType>()) {
164d4102861SMin-Yih Hsu       if (recType.getName() == "type_to_alias") {
165d4102861SMin-Yih Hsu         // We only make alias for a specific recursive type.
166d4102861SMin-Yih Hsu         os << "testrec";
167d4102861SMin-Yih Hsu         return AliasResult::FinalAlias;
168d4102861SMin-Yih Hsu       }
169d4102861SMin-Yih Hsu     }
17059f59d1cSVladislav Vinogradov     return AliasResult::NoAlias;
171a463ea50SRiver Riddle   }
172ea488bd6SRiver Riddle 
173ea488bd6SRiver Riddle   //===------------------------------------------------------------------===//
174ea488bd6SRiver Riddle   // Resources
175ea488bd6SRiver Riddle   //===------------------------------------------------------------------===//
176ea488bd6SRiver Riddle 
177ea488bd6SRiver Riddle   std::string
getResourceKey__anonf77d94720211::TestOpAsmInterface178ea488bd6SRiver Riddle   getResourceKey(const AsmDialectResourceHandle &handle) const override {
179ea488bd6SRiver Riddle     return cast<TestExternalElementsDataHandle>(handle).getKey().str();
180ea488bd6SRiver Riddle   }
181ea488bd6SRiver Riddle 
182ea488bd6SRiver Riddle   FailureOr<AsmDialectResourceHandle>
declareResource__anonf77d94720211::TestOpAsmInterface183ea488bd6SRiver Riddle   declareResource(StringRef key) const final {
184ea488bd6SRiver Riddle     TestDialect *dialect = cast<TestDialect>(getDialect());
185ea488bd6SRiver Riddle     TestExternalElementsDataManager &mgr = dialect->getExternalDataManager();
186ea488bd6SRiver Riddle 
187ea488bd6SRiver Riddle     // Resolve the reference by inserting a new entry into the manager.
188ea488bd6SRiver Riddle     auto it = mgr.insert(key).first;
189ea488bd6SRiver Riddle     return TestExternalElementsDataHandle(&*it, dialect);
190ea488bd6SRiver Riddle   }
191ea488bd6SRiver Riddle 
parseResource__anonf77d94720211::TestOpAsmInterface192ea488bd6SRiver Riddle   LogicalResult parseResource(AsmParsedResourceEntry &entry) const final {
193ea488bd6SRiver Riddle     TestDialect *dialect = cast<TestDialect>(getDialect());
194ea488bd6SRiver Riddle     TestExternalElementsDataManager &mgr = dialect->getExternalDataManager();
195ea488bd6SRiver Riddle 
196ea488bd6SRiver Riddle     // The resource entries are external constant data.
197ea488bd6SRiver Riddle     auto blobAllocFn = [](unsigned size, unsigned align) {
198ea488bd6SRiver Riddle       assert(align == alignof(uint64_t) && "unexpected data alignment");
199ea488bd6SRiver Riddle       return TestExternalElementsData::allocate(size / sizeof(uint64_t));
200ea488bd6SRiver Riddle     };
201ea488bd6SRiver Riddle     FailureOr<AsmResourceBlob> blob = entry.parseAsBlob(blobAllocFn);
202ea488bd6SRiver Riddle     if (failed(blob))
203ea488bd6SRiver Riddle       return failure();
204ea488bd6SRiver Riddle 
205ea488bd6SRiver Riddle     mgr.setData(entry.getKey(), std::move(*blob));
206ea488bd6SRiver Riddle     return success();
207ea488bd6SRiver Riddle   }
208ea488bd6SRiver Riddle 
209ea488bd6SRiver Riddle   void
buildResources__anonf77d94720211::TestOpAsmInterface210ea488bd6SRiver Riddle   buildResources(Operation *op,
211ea488bd6SRiver Riddle                  const SetVector<AsmDialectResourceHandle> &referencedResources,
212ea488bd6SRiver Riddle                  AsmResourceBuilder &provider) const final {
213ea488bd6SRiver Riddle     for (const AsmDialectResourceHandle &handle : referencedResources) {
214ea488bd6SRiver Riddle       const auto &testHandle = cast<TestExternalElementsDataHandle>(handle);
215ea488bd6SRiver Riddle       provider.buildBlob(testHandle.getKey(), testHandle.getData()->getData());
216ea488bd6SRiver Riddle     }
217ea488bd6SRiver Riddle   }
218fec6c5acSUday Bondhugula };
219fec6c5acSUday Bondhugula 
220b28e3db8SMehdi Amini struct TestDialectFoldInterface : public DialectFoldInterface {
221b28e3db8SMehdi Amini   using DialectFoldInterface::DialectFoldInterface;
222fec6c5acSUday Bondhugula 
223fec6c5acSUday Bondhugula   /// Registered hook to check if the given region, which is attached to an
224fec6c5acSUday Bondhugula   /// operation that is *not* isolated from above, should be used when
225fec6c5acSUday Bondhugula   /// materializing constants.
shouldMaterializeInto__anonf77d94720211::TestDialectFoldInterface226fec6c5acSUday Bondhugula   bool shouldMaterializeInto(Region *region) const final {
227fec6c5acSUday Bondhugula     // If this is a one region operation, then insert into it.
228fec6c5acSUday Bondhugula     return isa<OneRegionOp>(region->getParentOp());
229fec6c5acSUday Bondhugula   }
230fec6c5acSUday Bondhugula };
231fec6c5acSUday Bondhugula 
232fec6c5acSUday Bondhugula /// This class defines the interface for handling inlining with standard
233fec6c5acSUday Bondhugula /// operations.
234fec6c5acSUday Bondhugula struct TestInlinerInterface : public DialectInlinerInterface {
235fec6c5acSUday Bondhugula   using DialectInlinerInterface::DialectInlinerInterface;
236fec6c5acSUday Bondhugula 
237fec6c5acSUday Bondhugula   //===--------------------------------------------------------------------===//
238fec6c5acSUday Bondhugula   // Analysis Hooks
239fec6c5acSUday Bondhugula   //===--------------------------------------------------------------------===//
240fec6c5acSUday Bondhugula 
isLegalToInline__anonf77d94720211::TestInlinerInterface241fa417479SRiver Riddle   bool isLegalToInline(Operation *call, Operation *callable,
242fa417479SRiver Riddle                        bool wouldBeCloned) const final {
243501fda01SRiver Riddle     // Don't allow inlining calls that are marked `noinline`.
244501fda01SRiver Riddle     return !call->hasAttr("noinline");
245501fda01SRiver Riddle   }
isLegalToInline__anonf77d94720211::TestInlinerInterface246fa417479SRiver Riddle   bool isLegalToInline(Region *, Region *, bool,
247fa417479SRiver Riddle                        BlockAndValueMapping &) const final {
248fec6c5acSUday Bondhugula     // Inlining into test dialect regions is legal.
249fec6c5acSUday Bondhugula     return true;
250fec6c5acSUday Bondhugula   }
isLegalToInline__anonf77d94720211::TestInlinerInterface251fa417479SRiver Riddle   bool isLegalToInline(Operation *, Region *, bool,
252fec6c5acSUday Bondhugula                        BlockAndValueMapping &) const final {
253fec6c5acSUday Bondhugula     return true;
254fec6c5acSUday Bondhugula   }
255fec6c5acSUday Bondhugula 
shouldAnalyzeRecursively__anonf77d94720211::TestInlinerInterface256fec6c5acSUday Bondhugula   bool shouldAnalyzeRecursively(Operation *op) const final {
257fec6c5acSUday Bondhugula     // Analyze recursively if this is not a functional region operation, it
258fec6c5acSUday Bondhugula     // froms a separate functional scope.
259fec6c5acSUday Bondhugula     return !isa<FunctionalRegionOp>(op);
260fec6c5acSUday Bondhugula   }
261fec6c5acSUday Bondhugula 
262fec6c5acSUday Bondhugula   //===--------------------------------------------------------------------===//
263fec6c5acSUday Bondhugula   // Transformation Hooks
264fec6c5acSUday Bondhugula   //===--------------------------------------------------------------------===//
265fec6c5acSUday Bondhugula 
266fec6c5acSUday Bondhugula   /// Handle the given inlined terminator by replacing it with a new operation
267fec6c5acSUday Bondhugula   /// as necessary.
handleTerminator__anonf77d94720211::TestInlinerInterface268fec6c5acSUday Bondhugula   void handleTerminator(Operation *op,
269fec6c5acSUday Bondhugula                         ArrayRef<Value> valuesToRepl) const final {
270fec6c5acSUday Bondhugula     // Only handle "test.return" here.
271fec6c5acSUday Bondhugula     auto returnOp = dyn_cast<TestReturnOp>(op);
272fec6c5acSUday Bondhugula     if (!returnOp)
273fec6c5acSUday Bondhugula       return;
274fec6c5acSUday Bondhugula 
275fec6c5acSUday Bondhugula     // Replace the values directly with the return operands.
276fec6c5acSUday Bondhugula     assert(returnOp.getNumOperands() == valuesToRepl.size());
277fec6c5acSUday Bondhugula     for (const auto &it : llvm::enumerate(returnOp.getOperands()))
278fec6c5acSUday Bondhugula       valuesToRepl[it.index()].replaceAllUsesWith(it.value());
279fec6c5acSUday Bondhugula   }
280fec6c5acSUday Bondhugula 
281fec6c5acSUday Bondhugula   /// Attempt to materialize a conversion for a type mismatch between a call
282fec6c5acSUday Bondhugula   /// from this dialect, and a callable region. This method should generate an
283fec6c5acSUday Bondhugula   /// operation that takes 'input' as the only operand, and produces a single
284fec6c5acSUday Bondhugula   /// result of 'resultType'. If a conversion can not be generated, nullptr
285fec6c5acSUday Bondhugula   /// should be returned.
materializeCallConversion__anonf77d94720211::TestInlinerInterface286fec6c5acSUday Bondhugula   Operation *materializeCallConversion(OpBuilder &builder, Value input,
287fec6c5acSUday Bondhugula                                        Type resultType,
288fec6c5acSUday Bondhugula                                        Location conversionLoc) const final {
289fec6c5acSUday Bondhugula     // Only allow conversion for i16/i32 types.
290fec6c5acSUday Bondhugula     if (!(resultType.isSignlessInteger(16) ||
291fec6c5acSUday Bondhugula           resultType.isSignlessInteger(32)) ||
292fec6c5acSUday Bondhugula         !(input.getType().isSignlessInteger(16) ||
293fec6c5acSUday Bondhugula           input.getType().isSignlessInteger(32)))
294fec6c5acSUday Bondhugula       return nullptr;
295fec6c5acSUday Bondhugula     return builder.create<TestCastOp>(conversionLoc, resultType, input);
296fec6c5acSUday Bondhugula   }
2970e760a08SJacques Pienaar 
processInlinedCallBlocks__anonf77d94720211::TestInlinerInterface2980e760a08SJacques Pienaar   void processInlinedCallBlocks(
2990e760a08SJacques Pienaar       Operation *call,
3000e760a08SJacques Pienaar       iterator_range<Region::iterator> inlinedBlocks) const final {
3010e760a08SJacques Pienaar     if (!isa<ConversionCallOp>(call))
3020e760a08SJacques Pienaar       return;
3030e760a08SJacques Pienaar 
3040e760a08SJacques Pienaar     // Set attributed on all ops in the inlined blocks.
3050e760a08SJacques Pienaar     for (Block &block : inlinedBlocks) {
3060e760a08SJacques Pienaar       block.walk([&](Operation *op) {
3070e760a08SJacques Pienaar         op->setAttr("inlined_conversion", UnitAttr::get(call->getContext()));
3080e760a08SJacques Pienaar       });
3090e760a08SJacques Pienaar     }
3100e760a08SJacques Pienaar   }
311fec6c5acSUday Bondhugula };
312c484c7ddSChia-hung Duan 
313c484c7ddSChia-hung Duan struct TestReductionPatternInterface : public DialectReductionPatternInterface {
314c484c7ddSChia-hung Duan public:
TestReductionPatternInterface__anonf77d94720211::TestReductionPatternInterface315c484c7ddSChia-hung Duan   TestReductionPatternInterface(Dialect *dialect)
316c484c7ddSChia-hung Duan       : DialectReductionPatternInterface(dialect) {}
317c484c7ddSChia-hung Duan 
populateReductionPatterns__anonf77d94720211::TestReductionPatternInterface318b3891f28SMehdi Amini   void populateReductionPatterns(RewritePatternSet &patterns) const final {
319c484c7ddSChia-hung Duan     populateTestReductionPatterns(patterns);
320c484c7ddSChia-hung Duan   }
321c484c7ddSChia-hung Duan };
322c484c7ddSChia-hung Duan 
323be0a7e9fSMehdi Amini } // namespace
324fec6c5acSUday Bondhugula 
325fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===//
3269e0b5533SMathieu Fehr // Dynamic operations
3279e0b5533SMathieu Fehr //===----------------------------------------------------------------------===//
3289e0b5533SMathieu Fehr 
getDynamicGenericOp(TestDialect * dialect)3299e0b5533SMathieu Fehr std::unique_ptr<DynamicOpDefinition> getDynamicGenericOp(TestDialect *dialect) {
3309e0b5533SMathieu Fehr   return DynamicOpDefinition::get(
3319e0b5533SMathieu Fehr       "dynamic_generic", dialect, [](Operation *op) { return success(); },
3329e0b5533SMathieu Fehr       [](Operation *op) { return success(); });
3339e0b5533SMathieu Fehr }
3349e0b5533SMathieu Fehr 
3359e0b5533SMathieu Fehr std::unique_ptr<DynamicOpDefinition>
getDynamicOneOperandTwoResultsOp(TestDialect * dialect)3369e0b5533SMathieu Fehr getDynamicOneOperandTwoResultsOp(TestDialect *dialect) {
3379e0b5533SMathieu Fehr   return DynamicOpDefinition::get(
3389e0b5533SMathieu Fehr       "dynamic_one_operand_two_results", dialect,
3399e0b5533SMathieu Fehr       [](Operation *op) {
3409e0b5533SMathieu Fehr         if (op->getNumOperands() != 1) {
3419e0b5533SMathieu Fehr           op->emitOpError()
3429e0b5533SMathieu Fehr               << "expected 1 operand, but had " << op->getNumOperands();
3439e0b5533SMathieu Fehr           return failure();
3449e0b5533SMathieu Fehr         }
3459e0b5533SMathieu Fehr         if (op->getNumResults() != 2) {
3469e0b5533SMathieu Fehr           op->emitOpError()
3479e0b5533SMathieu Fehr               << "expected 2 results, but had " << op->getNumResults();
3489e0b5533SMathieu Fehr           return failure();
3499e0b5533SMathieu Fehr         }
3509e0b5533SMathieu Fehr         return success();
3519e0b5533SMathieu Fehr       },
3529e0b5533SMathieu Fehr       [](Operation *op) { return success(); });
3539e0b5533SMathieu Fehr }
3549e0b5533SMathieu Fehr 
3559e0b5533SMathieu Fehr std::unique_ptr<DynamicOpDefinition>
getDynamicCustomParserPrinterOp(TestDialect * dialect)3569e0b5533SMathieu Fehr getDynamicCustomParserPrinterOp(TestDialect *dialect) {
3579e0b5533SMathieu Fehr   auto verifier = [](Operation *op) {
3589e0b5533SMathieu Fehr     if (op->getNumOperands() == 0 && op->getNumResults() == 0)
3599e0b5533SMathieu Fehr       return success();
3609e0b5533SMathieu Fehr     op->emitError() << "operation should have no operands and no results";
3619e0b5533SMathieu Fehr     return failure();
3629e0b5533SMathieu Fehr   };
3639e0b5533SMathieu Fehr   auto regionVerifier = [](Operation *op) { return success(); };
3649e0b5533SMathieu Fehr 
3659e0b5533SMathieu Fehr   auto parser = [](OpAsmParser &parser, OperationState &state) {
3669e0b5533SMathieu Fehr     return parser.parseKeyword("custom_keyword");
3679e0b5533SMathieu Fehr   };
3689e0b5533SMathieu Fehr 
3699e0b5533SMathieu Fehr   auto printer = [](Operation *op, OpAsmPrinter &printer, llvm::StringRef) {
3709e0b5533SMathieu Fehr     printer << op->getName() << " custom_keyword";
3719e0b5533SMathieu Fehr   };
3729e0b5533SMathieu Fehr 
3739e0b5533SMathieu Fehr   return DynamicOpDefinition::get("dynamic_custom_parser_printer", dialect,
3749e0b5533SMathieu Fehr                                   verifier, regionVerifier, parser, printer);
3759e0b5533SMathieu Fehr }
3769e0b5533SMathieu Fehr 
3779e0b5533SMathieu Fehr //===----------------------------------------------------------------------===//
378fec6c5acSUday Bondhugula // TestDialect
379fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===//
380fec6c5acSUday Bondhugula 
381d905c103SMehdi Amini static void testSideEffectOpGetEffect(
382d905c103SMehdi Amini     Operation *op,
383d905c103SMehdi Amini     SmallVectorImpl<SideEffects::EffectInstance<TestEffects::Effect>> &effects);
384d905c103SMehdi Amini 
385d905c103SMehdi Amini // This is the implementation of a dialect fallback for `TestEffectOpInterface`.
386d905c103SMehdi Amini struct TestOpEffectInterfaceFallback
387d905c103SMehdi Amini     : public TestEffectOpInterface::FallbackModel<
388d905c103SMehdi Amini           TestOpEffectInterfaceFallback> {
classofTestOpEffectInterfaceFallback389d905c103SMehdi Amini   static bool classof(Operation *op) {
390d905c103SMehdi Amini     bool isSupportedOp =
391d905c103SMehdi Amini         op->getName().getStringRef() == "test.unregistered_side_effect_op";
392d905c103SMehdi Amini     assert(isSupportedOp && "Unexpected dispatch");
393d905c103SMehdi Amini     return isSupportedOp;
394d905c103SMehdi Amini   }
395d905c103SMehdi Amini 
396d905c103SMehdi Amini   void
getEffectsTestOpEffectInterfaceFallback397d905c103SMehdi Amini   getEffects(Operation *op,
398d905c103SMehdi Amini              SmallVectorImpl<SideEffects::EffectInstance<TestEffects::Effect>>
399d905c103SMehdi Amini                  &effects) const {
400d905c103SMehdi Amini     testSideEffectOpGetEffect(op, effects);
401d905c103SMehdi Amini   }
402d905c103SMehdi Amini };
403d905c103SMehdi Amini 
initialize()404575b22b5SMehdi Amini void TestDialect::initialize() {
40531bb8efdSRiver Riddle   registerAttributes();
40631bb8efdSRiver Riddle   registerTypes();
407fec6c5acSUday Bondhugula   addOperations<
408fec6c5acSUday Bondhugula #define GET_OP_LIST
409fec6c5acSUday Bondhugula #include "TestOps.cpp.inc"
410fec6c5acSUday Bondhugula       >();
4119e0b5533SMathieu Fehr   registerDynamicOp(getDynamicGenericOp(this));
4129e0b5533SMathieu Fehr   registerDynamicOp(getDynamicOneOperandTwoResultsOp(this));
4139e0b5533SMathieu Fehr   registerDynamicOp(getDynamicCustomParserPrinterOp(this));
4149e0b5533SMathieu Fehr 
415b28e3db8SMehdi Amini   addInterfaces<TestOpAsmInterface, TestDialectFoldInterface,
416c484c7ddSChia-hung Duan                 TestInlinerInterface, TestReductionPatternInterface>();
417fec6c5acSUday Bondhugula   allowUnknownOperations();
418d905c103SMehdi Amini 
419d905c103SMehdi Amini   // Instantiate our fallback op interface that we'll use on specific
420d905c103SMehdi Amini   // unregistered op.
421d905c103SMehdi Amini   fallbackEffectOpInterfaces = new TestOpEffectInterfaceFallback;
422d905c103SMehdi Amini }
~TestDialect()423d905c103SMehdi Amini TestDialect::~TestDialect() {
424d905c103SMehdi Amini   delete static_cast<TestOpEffectInterfaceFallback *>(
425d905c103SMehdi Amini       fallbackEffectOpInterfaces);
426fec6c5acSUday Bondhugula }
427fec6c5acSUday Bondhugula 
materializeConstant(OpBuilder & builder,Attribute value,Type type,Location loc)428186c1549SRiver Riddle Operation *TestDialect::materializeConstant(OpBuilder &builder, Attribute value,
429186c1549SRiver Riddle                                             Type type, Location loc) {
430186c1549SRiver Riddle   return builder.create<TestOpConstant>(loc, type, value);
431186c1549SRiver Riddle }
432186c1549SRiver Riddle 
inferReturnTypes(::mlir::MLIRContext * context,::llvm::Optional<::mlir::Location> location,::mlir::ValueRange operands,::mlir::DictionaryAttr attributes,::mlir::RegionRange regions,::llvm::SmallVectorImpl<::mlir::Type> & inferredReturnTypes)43305594de2SJacques Pienaar ::mlir::LogicalResult FormatInferType2Op::inferReturnTypes(
43405594de2SJacques Pienaar     ::mlir::MLIRContext *context, ::llvm::Optional<::mlir::Location> location,
43505594de2SJacques Pienaar     ::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes,
43605594de2SJacques Pienaar     ::mlir::RegionRange regions,
43705594de2SJacques Pienaar     ::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes) {
43805594de2SJacques Pienaar   inferredReturnTypes.assign({::mlir::IntegerType::get(context, 16)});
43905594de2SJacques Pienaar   return ::mlir::success();
44005594de2SJacques Pienaar }
44105594de2SJacques Pienaar 
getRegisteredInterfaceForOp(TypeID typeID,OperationName opName)442d905c103SMehdi Amini void *TestDialect::getRegisteredInterfaceForOp(TypeID typeID,
443d905c103SMehdi Amini                                                OperationName opName) {
444d905c103SMehdi Amini   if (opName.getIdentifier() == "test.unregistered_side_effect_op" &&
445d905c103SMehdi Amini       typeID == TypeID::get<TestEffectOpInterface>())
446d905c103SMehdi Amini     return fallbackEffectOpInterfaces;
447d905c103SMehdi Amini   return nullptr;
448d905c103SMehdi Amini }
449d905c103SMehdi Amini 
verifyOperationAttribute(Operation * op,NamedAttribute namedAttr)450fec6c5acSUday Bondhugula LogicalResult TestDialect::verifyOperationAttribute(Operation *op,
451fec6c5acSUday Bondhugula                                                     NamedAttribute namedAttr) {
4520c7890c8SRiver Riddle   if (namedAttr.getName() == "test.invalid_attr")
453fec6c5acSUday Bondhugula     return op->emitError() << "invalid to use 'test.invalid_attr'";
454fec6c5acSUday Bondhugula   return success();
455fec6c5acSUday Bondhugula }
456fec6c5acSUday Bondhugula 
verifyRegionArgAttribute(Operation * op,unsigned regionIndex,unsigned argIndex,NamedAttribute namedAttr)457fec6c5acSUday Bondhugula LogicalResult TestDialect::verifyRegionArgAttribute(Operation *op,
458fec6c5acSUday Bondhugula                                                     unsigned regionIndex,
459fec6c5acSUday Bondhugula                                                     unsigned argIndex,
460fec6c5acSUday Bondhugula                                                     NamedAttribute namedAttr) {
4610c7890c8SRiver Riddle   if (namedAttr.getName() == "test.invalid_attr")
462fec6c5acSUday Bondhugula     return op->emitError() << "invalid to use 'test.invalid_attr'";
463fec6c5acSUday Bondhugula   return success();
464fec6c5acSUday Bondhugula }
465fec6c5acSUday Bondhugula 
466fec6c5acSUday Bondhugula LogicalResult
verifyRegionResultAttribute(Operation * op,unsigned regionIndex,unsigned resultIndex,NamedAttribute namedAttr)467fec6c5acSUday Bondhugula TestDialect::verifyRegionResultAttribute(Operation *op, unsigned regionIndex,
468fec6c5acSUday Bondhugula                                          unsigned resultIndex,
469fec6c5acSUday Bondhugula                                          NamedAttribute namedAttr) {
4700c7890c8SRiver Riddle   if (namedAttr.getName() == "test.invalid_attr")
471fec6c5acSUday Bondhugula     return op->emitError() << "invalid to use 'test.invalid_attr'";
472fec6c5acSUday Bondhugula   return success();
473fec6c5acSUday Bondhugula }
474fec6c5acSUday Bondhugula 
475a0c776fcSMehdi Amini Optional<Dialect::ParseOpHook>
getParseOperationHook(StringRef opName) const476a0c776fcSMehdi Amini TestDialect::getParseOperationHook(StringRef opName) const {
477a0c776fcSMehdi Amini   if (opName == "test.dialect_custom_printer") {
478a0c776fcSMehdi Amini     return ParseOpHook{[](OpAsmParser &parser, OperationState &state) {
479a0c776fcSMehdi Amini       return parser.parseKeyword("custom_format");
480a0c776fcSMehdi Amini     }};
481a0c776fcSMehdi Amini   }
4820845635eSMogball   if (opName == "test.dialect_custom_format_fallback") {
4830845635eSMogball     return ParseOpHook{[](OpAsmParser &parser, OperationState &state) {
4840845635eSMogball       return parser.parseKeyword("custom_format_fallback");
4850845635eSMogball     }};
4860845635eSMogball   }
487122e6858SAlex Zinenko   if (opName == "test.dialect_custom_printer.with.dot") {
488122e6858SAlex Zinenko     return ParseOpHook{[](OpAsmParser &parser, OperationState &state) {
489122e6858SAlex Zinenko       return ParseResult::success();
490122e6858SAlex Zinenko     }};
491122e6858SAlex Zinenko   }
492a0c776fcSMehdi Amini   return None;
493a0c776fcSMehdi Amini }
494a0c776fcSMehdi Amini 
495fd87963eSMehdi Amini llvm::unique_function<void(Operation *, OpAsmPrinter &)>
getOperationPrinter(Operation * op) const496fd87963eSMehdi Amini TestDialect::getOperationPrinter(Operation *op) const {
497a0c776fcSMehdi Amini   StringRef opName = op->getName().getStringRef();
498a0c776fcSMehdi Amini   if (opName == "test.dialect_custom_printer") {
499fd87963eSMehdi Amini     return [](Operation *op, OpAsmPrinter &printer) {
500c41b16c2SMehdi Amini       printer.getStream() << " custom_format";
501fd87963eSMehdi Amini     };
502a0c776fcSMehdi Amini   }
5030845635eSMogball   if (opName == "test.dialect_custom_format_fallback") {
5040845635eSMogball     return [](Operation *op, OpAsmPrinter &printer) {
5050845635eSMogball       printer.getStream() << " custom_format_fallback";
5060845635eSMogball     };
5070845635eSMogball   }
508fd87963eSMehdi Amini   return {};
509a0c776fcSMehdi Amini }
510a0c776fcSMehdi Amini 
511fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===//
512fec6c5acSUday Bondhugula // TestBranchOp
513fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===//
514fec6c5acSUday Bondhugula 
getSuccessorOperands(unsigned index)5150c789db5SMarkus Böck SuccessorOperands TestBranchOp::getSuccessorOperands(unsigned index) {
516fec6c5acSUday Bondhugula   assert(index == 0 && "invalid successor index");
5170c789db5SMarkus Böck   return SuccessorOperands(getTargetOperandsMutable());
518fec6c5acSUday Bondhugula }
519fec6c5acSUday Bondhugula 
520fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===//
521c14ba3c4SMarkus Böck // TestProducingBranchOp
522c14ba3c4SMarkus Böck //===----------------------------------------------------------------------===//
523c14ba3c4SMarkus Böck 
getSuccessorOperands(unsigned index)5240c789db5SMarkus Böck SuccessorOperands TestProducingBranchOp::getSuccessorOperands(unsigned index) {
525c14ba3c4SMarkus Böck   assert(index <= 1 && "invalid successor index");
526a7865228SMarkus Böck   if (index == 1)
5270c789db5SMarkus Böck     return SuccessorOperands(getFirstOperandsMutable());
5280c789db5SMarkus Böck   return SuccessorOperands(getSecondOperandsMutable());
5290c789db5SMarkus Böck }
5300c789db5SMarkus Böck 
5310c789db5SMarkus Böck //===----------------------------------------------------------------------===//
5320c789db5SMarkus Böck // TestProducingBranchOp
5330c789db5SMarkus Böck //===----------------------------------------------------------------------===//
5340c789db5SMarkus Böck 
getSuccessorOperands(unsigned index)5350c789db5SMarkus Böck SuccessorOperands TestInternalBranchOp::getSuccessorOperands(unsigned index) {
5360c789db5SMarkus Böck   assert(index <= 1 && "invalid successor index");
5370c789db5SMarkus Böck   if (index == 0)
5380c789db5SMarkus Böck     return SuccessorOperands(0, getSuccessOperandsMutable());
5390c789db5SMarkus Böck   return SuccessorOperands(1, getErrorOperandsMutable());
540c14ba3c4SMarkus Böck }
541c14ba3c4SMarkus Böck 
542c14ba3c4SMarkus Böck //===----------------------------------------------------------------------===//
543108ca7a7SMatthias Springer // TestDialectCanonicalizerOp
544108ca7a7SMatthias Springer //===----------------------------------------------------------------------===//
545108ca7a7SMatthias Springer 
546108ca7a7SMatthias Springer static LogicalResult
dialectCanonicalizationPattern(TestDialectCanonicalizerOp op,PatternRewriter & rewriter)547108ca7a7SMatthias Springer dialectCanonicalizationPattern(TestDialectCanonicalizerOp op,
548108ca7a7SMatthias Springer                                PatternRewriter &rewriter) {
549a54f4eaeSMogball   rewriter.replaceOpWithNewOp<arith::ConstantOp>(
550a54f4eaeSMogball       op, rewriter.getI32IntegerAttr(42));
551108ca7a7SMatthias Springer   return success();
552108ca7a7SMatthias Springer }
553108ca7a7SMatthias Springer 
getCanonicalizationPatterns(RewritePatternSet & results) const554108ca7a7SMatthias Springer void TestDialect::getCanonicalizationPatterns(
555108ca7a7SMatthias Springer     RewritePatternSet &results) const {
556108ca7a7SMatthias Springer   results.add(&dialectCanonicalizationPattern);
557108ca7a7SMatthias Springer }
558108ca7a7SMatthias Springer 
559108ca7a7SMatthias Springer //===----------------------------------------------------------------------===//
56050f82e68SRiver Riddle // TestCallOp
56150f82e68SRiver Riddle //===----------------------------------------------------------------------===//
56250f82e68SRiver Riddle 
verifySymbolUses(SymbolTableCollection & symbolTable)56350f82e68SRiver Riddle LogicalResult TestCallOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
56450f82e68SRiver Riddle   // Check that the callee attribute was specified.
56550f82e68SRiver Riddle   auto fnAttr = (*this)->getAttrOfType<FlatSymbolRefAttr>("callee");
56650f82e68SRiver Riddle   if (!fnAttr)
56750f82e68SRiver Riddle     return emitOpError("requires a 'callee' symbol reference attribute");
56850f82e68SRiver Riddle   if (!symbolTable.lookupNearestSymbolFrom<FunctionOpInterface>(*this, fnAttr))
56950f82e68SRiver Riddle     return emitOpError() << "'" << fnAttr.getValue()
57050f82e68SRiver Riddle                          << "' does not reference a valid function";
57150f82e68SRiver Riddle   return success();
57250f82e68SRiver Riddle }
57350f82e68SRiver Riddle 
57450f82e68SRiver Riddle //===----------------------------------------------------------------------===//
575f4ef77cbSRiver Riddle // TestFoldToCallOp
576f4ef77cbSRiver Riddle //===----------------------------------------------------------------------===//
577f4ef77cbSRiver Riddle 
578f4ef77cbSRiver Riddle namespace {
579f4ef77cbSRiver Riddle struct FoldToCallOpPattern : public OpRewritePattern<FoldToCallOp> {
580f4ef77cbSRiver Riddle   using OpRewritePattern<FoldToCallOp>::OpRewritePattern;
581f4ef77cbSRiver Riddle 
matchAndRewrite__anonf77d94721311::FoldToCallOpPattern582f4ef77cbSRiver Riddle   LogicalResult matchAndRewrite(FoldToCallOp op,
583f4ef77cbSRiver Riddle                                 PatternRewriter &rewriter) const override {
58423aa5a74SRiver Riddle     rewriter.replaceOpWithNewOp<func::CallOp>(op, TypeRange(),
58523aa5a74SRiver Riddle                                               op.getCalleeAttr(), ValueRange());
586f4ef77cbSRiver Riddle     return success();
587f4ef77cbSRiver Riddle   }
588f4ef77cbSRiver Riddle };
589be0a7e9fSMehdi Amini } // namespace
590f4ef77cbSRiver Riddle 
getCanonicalizationPatterns(RewritePatternSet & results,MLIRContext * context)591dc4e913bSChris Lattner void FoldToCallOp::getCanonicalizationPatterns(RewritePatternSet &results,
592dc4e913bSChris Lattner                                                MLIRContext *context) {
593dc4e913bSChris Lattner   results.add<FoldToCallOpPattern>(context);
594f4ef77cbSRiver Riddle }
595f4ef77cbSRiver Riddle 
596f4ef77cbSRiver Riddle //===----------------------------------------------------------------------===//
59788c6e25eSRiver Riddle // Test Format* operations
59888c6e25eSRiver Riddle //===----------------------------------------------------------------------===//
59988c6e25eSRiver Riddle 
60088c6e25eSRiver Riddle //===----------------------------------------------------------------------===//
60188c6e25eSRiver Riddle // Parsing
60288c6e25eSRiver Riddle 
parseCustomOptionalOperand(OpAsmParser & parser,Optional<OpAsmParser::UnresolvedOperand> & optOperand)603e13d23bcSMarkus Böck static ParseResult parseCustomOptionalOperand(
604e13d23bcSMarkus Böck     OpAsmParser &parser, Optional<OpAsmParser::UnresolvedOperand> &optOperand) {
6055bec1ea7SShraiysh Vaishay   if (succeeded(parser.parseOptionalLParen())) {
6065bec1ea7SShraiysh Vaishay     optOperand.emplace();
6075bec1ea7SShraiysh Vaishay     if (parser.parseOperand(*optOperand) || parser.parseRParen())
6085bec1ea7SShraiysh Vaishay       return failure();
6095bec1ea7SShraiysh Vaishay   }
6105bec1ea7SShraiysh Vaishay   return success();
6115bec1ea7SShraiysh Vaishay }
6125bec1ea7SShraiysh Vaishay 
parseCustomDirectiveOperands(OpAsmParser & parser,OpAsmParser::UnresolvedOperand & operand,Optional<OpAsmParser::UnresolvedOperand> & optOperand,SmallVectorImpl<OpAsmParser::UnresolvedOperand> & varOperands)61388c6e25eSRiver Riddle static ParseResult parseCustomDirectiveOperands(
614e13d23bcSMarkus Böck     OpAsmParser &parser, OpAsmParser::UnresolvedOperand &operand,
615e13d23bcSMarkus Böck     Optional<OpAsmParser::UnresolvedOperand> &optOperand,
616e13d23bcSMarkus Böck     SmallVectorImpl<OpAsmParser::UnresolvedOperand> &varOperands) {
61788c6e25eSRiver Riddle   if (parser.parseOperand(operand))
61888c6e25eSRiver Riddle     return failure();
61988c6e25eSRiver Riddle   if (succeeded(parser.parseOptionalComma())) {
62088c6e25eSRiver Riddle     optOperand.emplace();
62188c6e25eSRiver Riddle     if (parser.parseOperand(*optOperand))
62288c6e25eSRiver Riddle       return failure();
62388c6e25eSRiver Riddle   }
62488c6e25eSRiver Riddle   if (parser.parseArrow() || parser.parseLParen() ||
62588c6e25eSRiver Riddle       parser.parseOperandList(varOperands) || parser.parseRParen())
62688c6e25eSRiver Riddle     return failure();
62788c6e25eSRiver Riddle   return success();
62888c6e25eSRiver Riddle }
62988c6e25eSRiver Riddle static ParseResult
parseCustomDirectiveResults(OpAsmParser & parser,Type & operandType,Type & optOperandType,SmallVectorImpl<Type> & varOperandTypes)63088c6e25eSRiver Riddle parseCustomDirectiveResults(OpAsmParser &parser, Type &operandType,
63188c6e25eSRiver Riddle                             Type &optOperandType,
63288c6e25eSRiver Riddle                             SmallVectorImpl<Type> &varOperandTypes) {
63388c6e25eSRiver Riddle   if (parser.parseColon())
63488c6e25eSRiver Riddle     return failure();
63588c6e25eSRiver Riddle 
63688c6e25eSRiver Riddle   if (parser.parseType(operandType))
63788c6e25eSRiver Riddle     return failure();
63888c6e25eSRiver Riddle   if (succeeded(parser.parseOptionalComma())) {
63988c6e25eSRiver Riddle     if (parser.parseType(optOperandType))
64088c6e25eSRiver Riddle       return failure();
64188c6e25eSRiver Riddle   }
64288c6e25eSRiver Riddle   if (parser.parseArrow() || parser.parseLParen() ||
64388c6e25eSRiver Riddle       parser.parseTypeList(varOperandTypes) || parser.parseRParen())
64488c6e25eSRiver Riddle     return failure();
64588c6e25eSRiver Riddle   return success();
64688c6e25eSRiver Riddle }
64793fd30baSNicolas Vasilache static ParseResult
parseCustomDirectiveWithTypeRefs(OpAsmParser & parser,Type operandType,Type optOperandType,const SmallVectorImpl<Type> & varOperandTypes)64893fd30baSNicolas Vasilache parseCustomDirectiveWithTypeRefs(OpAsmParser &parser, Type operandType,
64993fd30baSNicolas Vasilache                                  Type optOperandType,
65093fd30baSNicolas Vasilache                                  const SmallVectorImpl<Type> &varOperandTypes) {
65193fd30baSNicolas Vasilache   if (parser.parseKeyword("type_refs_capture"))
65293fd30baSNicolas Vasilache     return failure();
65393fd30baSNicolas Vasilache 
65493fd30baSNicolas Vasilache   Type operandType2, optOperandType2;
65593fd30baSNicolas Vasilache   SmallVector<Type, 1> varOperandTypes2;
65693fd30baSNicolas Vasilache   if (parseCustomDirectiveResults(parser, operandType2, optOperandType2,
65793fd30baSNicolas Vasilache                                   varOperandTypes2))
65893fd30baSNicolas Vasilache     return failure();
65993fd30baSNicolas Vasilache 
66093fd30baSNicolas Vasilache   if (operandType != operandType2 || optOperandType != optOperandType2 ||
66193fd30baSNicolas Vasilache       varOperandTypes != varOperandTypes2)
66293fd30baSNicolas Vasilache     return failure();
66393fd30baSNicolas Vasilache 
66493fd30baSNicolas Vasilache   return success();
66593fd30baSNicolas Vasilache }
parseCustomDirectiveOperandsAndTypes(OpAsmParser & parser,OpAsmParser::UnresolvedOperand & operand,Optional<OpAsmParser::UnresolvedOperand> & optOperand,SmallVectorImpl<OpAsmParser::UnresolvedOperand> & varOperands,Type & operandType,Type & optOperandType,SmallVectorImpl<Type> & varOperandTypes)66688c6e25eSRiver Riddle static ParseResult parseCustomDirectiveOperandsAndTypes(
667e13d23bcSMarkus Böck     OpAsmParser &parser, OpAsmParser::UnresolvedOperand &operand,
668e13d23bcSMarkus Böck     Optional<OpAsmParser::UnresolvedOperand> &optOperand,
669e13d23bcSMarkus Böck     SmallVectorImpl<OpAsmParser::UnresolvedOperand> &varOperands,
670e13d23bcSMarkus Böck     Type &operandType, Type &optOperandType,
671e13d23bcSMarkus Böck     SmallVectorImpl<Type> &varOperandTypes) {
67288c6e25eSRiver Riddle   if (parseCustomDirectiveOperands(parser, operand, optOperand, varOperands) ||
67388c6e25eSRiver Riddle       parseCustomDirectiveResults(parser, operandType, optOperandType,
67488c6e25eSRiver Riddle                                   varOperandTypes))
67588c6e25eSRiver Riddle     return failure();
67688c6e25eSRiver Riddle   return success();
67788c6e25eSRiver Riddle }
parseCustomDirectiveRegions(OpAsmParser & parser,Region & region,SmallVectorImpl<std::unique_ptr<Region>> & varRegions)678eaeadce9SRiver Riddle static ParseResult parseCustomDirectiveRegions(
679eaeadce9SRiver Riddle     OpAsmParser &parser, Region &region,
680eaeadce9SRiver Riddle     SmallVectorImpl<std::unique_ptr<Region>> &varRegions) {
681eaeadce9SRiver Riddle   if (parser.parseRegion(region))
682eaeadce9SRiver Riddle     return failure();
683eaeadce9SRiver Riddle   if (failed(parser.parseOptionalComma()))
684eaeadce9SRiver Riddle     return success();
685eaeadce9SRiver Riddle   std::unique_ptr<Region> varRegion = std::make_unique<Region>();
686eaeadce9SRiver Riddle   if (parser.parseRegion(*varRegion))
687eaeadce9SRiver Riddle     return failure();
688eaeadce9SRiver Riddle   varRegions.emplace_back(std::move(varRegion));
689eaeadce9SRiver Riddle   return success();
690eaeadce9SRiver Riddle }
69188c6e25eSRiver Riddle static ParseResult
parseCustomDirectiveSuccessors(OpAsmParser & parser,Block * & successor,SmallVectorImpl<Block * > & varSuccessors)69288c6e25eSRiver Riddle parseCustomDirectiveSuccessors(OpAsmParser &parser, Block *&successor,
69388c6e25eSRiver Riddle                                SmallVectorImpl<Block *> &varSuccessors) {
69488c6e25eSRiver Riddle   if (parser.parseSuccessor(successor))
69588c6e25eSRiver Riddle     return failure();
69688c6e25eSRiver Riddle   if (failed(parser.parseOptionalComma()))
69788c6e25eSRiver Riddle     return success();
69888c6e25eSRiver Riddle   Block *varSuccessor;
69988c6e25eSRiver Riddle   if (parser.parseSuccessor(varSuccessor))
70088c6e25eSRiver Riddle     return failure();
70188c6e25eSRiver Riddle   varSuccessors.append(2, varSuccessor);
70288c6e25eSRiver Riddle   return success();
70388c6e25eSRiver Riddle }
parseCustomDirectiveAttributes(OpAsmParser & parser,IntegerAttr & attr,IntegerAttr & optAttr)704d14cfe10SMike Urbach static ParseResult parseCustomDirectiveAttributes(OpAsmParser &parser,
705d14cfe10SMike Urbach                                                   IntegerAttr &attr,
706d14cfe10SMike Urbach                                                   IntegerAttr &optAttr) {
707d14cfe10SMike Urbach   if (parser.parseAttribute(attr))
708d14cfe10SMike Urbach     return failure();
709d14cfe10SMike Urbach   if (succeeded(parser.parseOptionalComma())) {
710d14cfe10SMike Urbach     if (parser.parseAttribute(optAttr))
711d14cfe10SMike Urbach       return failure();
712d14cfe10SMike Urbach   }
713d14cfe10SMike Urbach   return success();
714d14cfe10SMike Urbach }
71588c6e25eSRiver Riddle 
parseCustomDirectiveAttrDict(OpAsmParser & parser,NamedAttrList & attrs)716035e12e6SJohn Demme static ParseResult parseCustomDirectiveAttrDict(OpAsmParser &parser,
717035e12e6SJohn Demme                                                 NamedAttrList &attrs) {
718035e12e6SJohn Demme   return parser.parseOptionalAttrDict(attrs);
719035e12e6SJohn Demme }
parseCustomDirectiveOptionalOperandRef(OpAsmParser & parser,Optional<OpAsmParser::UnresolvedOperand> & optOperand)7206e3292b0SRiver Riddle static ParseResult parseCustomDirectiveOptionalOperandRef(
721e13d23bcSMarkus Böck     OpAsmParser &parser, Optional<OpAsmParser::UnresolvedOperand> &optOperand) {
7226e3292b0SRiver Riddle   int64_t operandCount = 0;
7236e3292b0SRiver Riddle   if (parser.parseInteger(operandCount))
7246e3292b0SRiver Riddle     return failure();
7256e3292b0SRiver Riddle   bool expectedOptionalOperand = operandCount == 0;
726064a08cdSKazu Hirata   return success(expectedOptionalOperand != optOperand.has_value());
7276e3292b0SRiver Riddle }
728035e12e6SJohn Demme 
72988c6e25eSRiver Riddle //===----------------------------------------------------------------------===//
73088c6e25eSRiver Riddle // Printing
73188c6e25eSRiver Riddle 
printCustomOptionalOperand(OpAsmPrinter & printer,Operation *,Value optOperand)7325bec1ea7SShraiysh Vaishay static void printCustomOptionalOperand(OpAsmPrinter &printer, Operation *,
7335bec1ea7SShraiysh Vaishay                                        Value optOperand) {
7345bec1ea7SShraiysh Vaishay   if (optOperand)
7355bec1ea7SShraiysh Vaishay     printer << "(" << optOperand << ") ";
7365bec1ea7SShraiysh Vaishay }
7375bec1ea7SShraiysh Vaishay 
printCustomDirectiveOperands(OpAsmPrinter & printer,Operation *,Value operand,Value optOperand,OperandRange varOperands)738035e12e6SJohn Demme static void printCustomDirectiveOperands(OpAsmPrinter &printer, Operation *,
739035e12e6SJohn Demme                                          Value operand, Value optOperand,
74088c6e25eSRiver Riddle                                          OperandRange varOperands) {
74188c6e25eSRiver Riddle   printer << operand;
74288c6e25eSRiver Riddle   if (optOperand)
74388c6e25eSRiver Riddle     printer << ", " << optOperand;
74488c6e25eSRiver Riddle   printer << " -> (" << varOperands << ")";
74588c6e25eSRiver Riddle }
printCustomDirectiveResults(OpAsmPrinter & printer,Operation *,Type operandType,Type optOperandType,TypeRange varOperandTypes)746035e12e6SJohn Demme static void printCustomDirectiveResults(OpAsmPrinter &printer, Operation *,
747035e12e6SJohn Demme                                         Type operandType, Type optOperandType,
74888c6e25eSRiver Riddle                                         TypeRange varOperandTypes) {
74988c6e25eSRiver Riddle   printer << " : " << operandType;
75088c6e25eSRiver Riddle   if (optOperandType)
75188c6e25eSRiver Riddle     printer << ", " << optOperandType;
75288c6e25eSRiver Riddle   printer << " -> (" << varOperandTypes << ")";
75388c6e25eSRiver Riddle }
printCustomDirectiveWithTypeRefs(OpAsmPrinter & printer,Operation * op,Type operandType,Type optOperandType,TypeRange varOperandTypes)75493fd30baSNicolas Vasilache static void printCustomDirectiveWithTypeRefs(OpAsmPrinter &printer,
755035e12e6SJohn Demme                                              Operation *op, Type operandType,
75693fd30baSNicolas Vasilache                                              Type optOperandType,
75793fd30baSNicolas Vasilache                                              TypeRange varOperandTypes) {
75893fd30baSNicolas Vasilache   printer << " type_refs_capture ";
759035e12e6SJohn Demme   printCustomDirectiveResults(printer, op, operandType, optOperandType,
76093fd30baSNicolas Vasilache                               varOperandTypes);
76193fd30baSNicolas Vasilache }
printCustomDirectiveOperandsAndTypes(OpAsmPrinter & printer,Operation * op,Value operand,Value optOperand,OperandRange varOperands,Type operandType,Type optOperandType,TypeRange varOperandTypes)762035e12e6SJohn Demme static void printCustomDirectiveOperandsAndTypes(
763035e12e6SJohn Demme     OpAsmPrinter &printer, Operation *op, Value operand, Value optOperand,
764035e12e6SJohn Demme     OperandRange varOperands, Type operandType, Type optOperandType,
76588c6e25eSRiver Riddle     TypeRange varOperandTypes) {
766035e12e6SJohn Demme   printCustomDirectiveOperands(printer, op, operand, optOperand, varOperands);
767035e12e6SJohn Demme   printCustomDirectiveResults(printer, op, operandType, optOperandType,
76888c6e25eSRiver Riddle                               varOperandTypes);
76988c6e25eSRiver Riddle }
printCustomDirectiveRegions(OpAsmPrinter & printer,Operation *,Region & region,MutableArrayRef<Region> varRegions)770035e12e6SJohn Demme static void printCustomDirectiveRegions(OpAsmPrinter &printer, Operation *,
771035e12e6SJohn Demme                                         Region &region,
772eaeadce9SRiver Riddle                                         MutableArrayRef<Region> varRegions) {
773eaeadce9SRiver Riddle   printer.printRegion(region);
774eaeadce9SRiver Riddle   if (!varRegions.empty()) {
775eaeadce9SRiver Riddle     printer << ", ";
776eaeadce9SRiver Riddle     for (Region &region : varRegions)
777eaeadce9SRiver Riddle       printer.printRegion(region);
778eaeadce9SRiver Riddle   }
779eaeadce9SRiver Riddle }
printCustomDirectiveSuccessors(OpAsmPrinter & printer,Operation *,Block * successor,SuccessorRange varSuccessors)780035e12e6SJohn Demme static void printCustomDirectiveSuccessors(OpAsmPrinter &printer, Operation *,
78188c6e25eSRiver Riddle                                            Block *successor,
78288c6e25eSRiver Riddle                                            SuccessorRange varSuccessors) {
78388c6e25eSRiver Riddle   printer << successor;
78488c6e25eSRiver Riddle   if (!varSuccessors.empty())
78588c6e25eSRiver Riddle     printer << ", " << varSuccessors.front();
78688c6e25eSRiver Riddle }
printCustomDirectiveAttributes(OpAsmPrinter & printer,Operation *,Attribute attribute,Attribute optAttribute)787035e12e6SJohn Demme static void printCustomDirectiveAttributes(OpAsmPrinter &printer, Operation *,
788d14cfe10SMike Urbach                                            Attribute attribute,
789d14cfe10SMike Urbach                                            Attribute optAttribute) {
790d14cfe10SMike Urbach   printer << attribute;
791d14cfe10SMike Urbach   if (optAttribute)
792d14cfe10SMike Urbach     printer << ", " << optAttribute;
793d14cfe10SMike Urbach }
79488c6e25eSRiver Riddle 
printCustomDirectiveAttrDict(OpAsmPrinter & printer,Operation * op,DictionaryAttr attrs)795035e12e6SJohn Demme static void printCustomDirectiveAttrDict(OpAsmPrinter &printer, Operation *op,
796fc5cf50eSRiver Riddle                                          DictionaryAttr attrs) {
797fc5cf50eSRiver Riddle   printer.printOptionalAttrDict(attrs.getValue());
798035e12e6SJohn Demme }
7996e3292b0SRiver Riddle 
printCustomDirectiveOptionalOperandRef(OpAsmPrinter & printer,Operation * op,Value optOperand)8006e3292b0SRiver Riddle static void printCustomDirectiveOptionalOperandRef(OpAsmPrinter &printer,
8016e3292b0SRiver Riddle                                                    Operation *op,
8026e3292b0SRiver Riddle                                                    Value optOperand) {
8036e3292b0SRiver Riddle   printer << (optOperand ? "1" : "0");
8046e3292b0SRiver Riddle }
8056e3292b0SRiver Riddle 
80688c6e25eSRiver Riddle //===----------------------------------------------------------------------===//
807fec6c5acSUday Bondhugula // Test IsolatedRegionOp - parse passthrough region arguments.
808fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===//
809fec6c5acSUday Bondhugula 
parse(OpAsmParser & parser,OperationState & result)810d7f0083dSRiver Riddle ParseResult IsolatedRegionOp::parse(OpAsmParser &parser,
811fec6c5acSUday Bondhugula                                     OperationState &result) {
812fec6c5acSUday Bondhugula   // Parse the input operand.
813d85eb4e2SChris Lattner   OpAsmParser::Argument argInfo;
814d85eb4e2SChris Lattner   argInfo.type = parser.getBuilder().getIndexType();
815d85eb4e2SChris Lattner   if (parser.parseOperand(argInfo.ssaName) ||
816d85eb4e2SChris Lattner       parser.resolveOperand(argInfo.ssaName, argInfo.type, result.operands))
817fec6c5acSUday Bondhugula     return failure();
818fec6c5acSUday Bondhugula 
819fec6c5acSUday Bondhugula   // Parse the body region, and reuse the operand info as the argument info.
820fec6c5acSUday Bondhugula   Region *body = result.addRegion();
821d85eb4e2SChris Lattner   return parser.parseRegion(*body, argInfo, /*enableNameShadowing=*/true);
822fec6c5acSUday Bondhugula }
823fec6c5acSUday Bondhugula 
print(OpAsmPrinter & p)824d7f0083dSRiver Riddle void IsolatedRegionOp::print(OpAsmPrinter &p) {
825fec6c5acSUday Bondhugula   p << "test.isolated_region ";
826d7f0083dSRiver Riddle   p.printOperand(getOperand());
827d7f0083dSRiver Riddle   p.shadowRegionArgs(getRegion(), getOperand());
8285c36ee8dSMogball   p << ' ';
829d7f0083dSRiver Riddle   p.printRegion(getRegion(), /*printEntryBlockArgs=*/false);
830fec6c5acSUday Bondhugula }
831fec6c5acSUday Bondhugula 
832fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===//
83362828865SStephen Neuendorffer // Test SSACFGRegionOp
83462828865SStephen Neuendorffer //===----------------------------------------------------------------------===//
83562828865SStephen Neuendorffer 
getRegionKind(unsigned index)83662828865SStephen Neuendorffer RegionKind SSACFGRegionOp::getRegionKind(unsigned index) {
83762828865SStephen Neuendorffer   return RegionKind::SSACFG;
83862828865SStephen Neuendorffer }
83962828865SStephen Neuendorffer 
84062828865SStephen Neuendorffer //===----------------------------------------------------------------------===//
84162828865SStephen Neuendorffer // Test GraphRegionOp
84262828865SStephen Neuendorffer //===----------------------------------------------------------------------===//
84362828865SStephen Neuendorffer 
getRegionKind(unsigned index)84462828865SStephen Neuendorffer RegionKind GraphRegionOp::getRegionKind(unsigned index) {
84562828865SStephen Neuendorffer   return RegionKind::Graph;
84662828865SStephen Neuendorffer }
84762828865SStephen Neuendorffer 
84862828865SStephen Neuendorffer //===----------------------------------------------------------------------===//
84957d361bdSUday Bondhugula // Test AffineScopeOp
85048034538SUday Bondhugula //===----------------------------------------------------------------------===//
85148034538SUday Bondhugula 
parse(OpAsmParser & parser,OperationState & result)852d7f0083dSRiver Riddle ParseResult AffineScopeOp::parse(OpAsmParser &parser, OperationState &result) {
85348034538SUday Bondhugula   // Parse the body region, and reuse the operand info as the argument info.
85448034538SUday Bondhugula   Region *body = result.addRegion();
85548034538SUday Bondhugula   return parser.parseRegion(*body, /*arguments=*/{}, /*argTypes=*/{});
85648034538SUday Bondhugula }
85748034538SUday Bondhugula 
print(OpAsmPrinter & p)858d7f0083dSRiver Riddle void AffineScopeOp::print(OpAsmPrinter &p) {
85957d361bdSUday Bondhugula   p << "test.affine_scope ";
860d7f0083dSRiver Riddle   p.printRegion(getRegion(), /*printEntryBlockArgs=*/false);
86148034538SUday Bondhugula }
86248034538SUday Bondhugula 
86348034538SUday Bondhugula //===----------------------------------------------------------------------===//
864fec6c5acSUday Bondhugula // Test parser.
865fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===//
866fec6c5acSUday Bondhugula 
parse(OpAsmParser & parser,OperationState & result)867d7f0083dSRiver Riddle ParseResult ParseIntegerLiteralOp::parse(OpAsmParser &parser,
8686bc9439fSRiver Riddle                                          OperationState &result) {
8696bc9439fSRiver Riddle   if (parser.parseOptionalColon())
8706bc9439fSRiver Riddle     return success();
8716bc9439fSRiver Riddle   uint64_t numResults;
8726bc9439fSRiver Riddle   if (parser.parseInteger(numResults))
8736bc9439fSRiver Riddle     return failure();
8746bc9439fSRiver Riddle 
8756bc9439fSRiver Riddle   IndexType type = parser.getBuilder().getIndexType();
8766bc9439fSRiver Riddle   for (unsigned i = 0; i < numResults; ++i)
8776bc9439fSRiver Riddle     result.addTypes(type);
8786bc9439fSRiver Riddle   return success();
8796bc9439fSRiver Riddle }
8806bc9439fSRiver Riddle 
print(OpAsmPrinter & p)881d7f0083dSRiver Riddle void ParseIntegerLiteralOp::print(OpAsmPrinter &p) {
882d7f0083dSRiver Riddle   if (unsigned numResults = getNumResults())
8836bc9439fSRiver Riddle     p << " : " << numResults;
8846bc9439fSRiver Riddle }
8856bc9439fSRiver Riddle 
parse(OpAsmParser & parser,OperationState & result)886d7f0083dSRiver Riddle ParseResult ParseWrappedKeywordOp::parse(OpAsmParser &parser,
887fec6c5acSUday Bondhugula                                          OperationState &result) {
888fec6c5acSUday Bondhugula   StringRef keyword;
889fec6c5acSUday Bondhugula   if (parser.parseKeyword(&keyword))
890fec6c5acSUday Bondhugula     return failure();
891fec6c5acSUday Bondhugula   result.addAttribute("keyword", parser.getBuilder().getStringAttr(keyword));
892fec6c5acSUday Bondhugula   return success();
893fec6c5acSUday Bondhugula }
894fec6c5acSUday Bondhugula 
print(OpAsmPrinter & p)895d7f0083dSRiver Riddle void ParseWrappedKeywordOp::print(OpAsmPrinter &p) { p << " " << getKeyword(); }
896fec6c5acSUday Bondhugula 
897fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===//
898fec6c5acSUday Bondhugula // Test WrapRegionOp - wrapping op exercising `parseGenericOperation()`.
899fec6c5acSUday Bondhugula 
parse(OpAsmParser & parser,OperationState & result)900d7f0083dSRiver Riddle ParseResult WrappingRegionOp::parse(OpAsmParser &parser,
901fec6c5acSUday Bondhugula                                     OperationState &result) {
902fec6c5acSUday Bondhugula   if (parser.parseKeyword("wraps"))
903fec6c5acSUday Bondhugula     return failure();
904fec6c5acSUday Bondhugula 
905fec6c5acSUday Bondhugula   // Parse the wrapped op in a region
906fec6c5acSUday Bondhugula   Region &body = *result.addRegion();
907fec6c5acSUday Bondhugula   body.push_back(new Block);
908fec6c5acSUday Bondhugula   Block &block = body.back();
90902b6fb21SMehdi Amini   Operation *wrappedOp = parser.parseGenericOperation(&block, block.begin());
91002b6fb21SMehdi Amini   if (!wrappedOp)
911fec6c5acSUday Bondhugula     return failure();
912fec6c5acSUday Bondhugula 
913fec6c5acSUday Bondhugula   // Create a return terminator in the inner region, pass as operand to the
914fec6c5acSUday Bondhugula   // terminator the returned values from the wrapped operation.
91502b6fb21SMehdi Amini   SmallVector<Value, 8> returnOperands(wrappedOp->getResults());
916fb093c83SChris Lattner   OpBuilder builder(parser.getContext());
917fec6c5acSUday Bondhugula   builder.setInsertionPointToEnd(&block);
91802b6fb21SMehdi Amini   builder.create<TestReturnOp>(wrappedOp->getLoc(), returnOperands);
919fec6c5acSUday Bondhugula 
920fec6c5acSUday Bondhugula   // Get the results type for the wrapping op from the terminator operands.
92102b6fb21SMehdi Amini   Operation &returnOp = body.back().back();
92202b6fb21SMehdi Amini   result.types.append(returnOp.operand_type_begin(),
92302b6fb21SMehdi Amini                       returnOp.operand_type_end());
924fec6c5acSUday Bondhugula 
925fec6c5acSUday Bondhugula   // Use the location of the wrapped op for the "test.wrapping_region" op.
92602b6fb21SMehdi Amini   result.location = wrappedOp->getLoc();
927fec6c5acSUday Bondhugula 
928fec6c5acSUday Bondhugula   return success();
929fec6c5acSUday Bondhugula }
930fec6c5acSUday Bondhugula 
print(OpAsmPrinter & p)931d7f0083dSRiver Riddle void WrappingRegionOp::print(OpAsmPrinter &p) {
932c41b16c2SMehdi Amini   p << " wraps ";
933d7f0083dSRiver Riddle   p.printGenericOp(&getRegion().front().front());
934fec6c5acSUday Bondhugula }
935fec6c5acSUday Bondhugula 
936fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===//
937e5a8c8c8SSandeep Dasgupta // Test PrettyPrintedRegionOp -  exercising the following parser APIs
938e5a8c8c8SSandeep Dasgupta //   parseGenericOperationAfterOpName
939e5a8c8c8SSandeep Dasgupta //   parseCustomOperationName
940e5a8c8c8SSandeep Dasgupta //===----------------------------------------------------------------------===//
941e5a8c8c8SSandeep Dasgupta 
parse(OpAsmParser & parser,OperationState & result)942d7f0083dSRiver Riddle ParseResult PrettyPrintedRegionOp::parse(OpAsmParser &parser,
943e5a8c8c8SSandeep Dasgupta                                          OperationState &result) {
944e5a8c8c8SSandeep Dasgupta 
9456842ec42SRiver Riddle   SMLoc loc = parser.getCurrentLocation();
946e5a8c8c8SSandeep Dasgupta   Location currLocation = parser.getEncodedSourceLoc(loc);
947e5a8c8c8SSandeep Dasgupta 
948e5a8c8c8SSandeep Dasgupta   // Parse the operands.
949e13d23bcSMarkus Böck   SmallVector<OpAsmParser::UnresolvedOperand, 2> operands;
950e5a8c8c8SSandeep Dasgupta   if (parser.parseOperandList(operands))
951e5a8c8c8SSandeep Dasgupta     return failure();
952e5a8c8c8SSandeep Dasgupta 
953e5a8c8c8SSandeep Dasgupta   // Check if we are parsing the pretty-printed version
954e5a8c8c8SSandeep Dasgupta   //  test.pretty_printed_region start <inner-op> end : <functional-type>
955e5a8c8c8SSandeep Dasgupta   // Else fallback to parsing the "non pretty-printed" version.
956e5a8c8c8SSandeep Dasgupta   if (!succeeded(parser.parseOptionalKeyword("start")))
957e5a8c8c8SSandeep Dasgupta     return parser.parseGenericOperationAfterOpName(
958e5a8c8c8SSandeep Dasgupta         result, llvm::makeArrayRef(operands));
959e5a8c8c8SSandeep Dasgupta 
960e5a8c8c8SSandeep Dasgupta   FailureOr<OperationName> parseOpNameInfo = parser.parseCustomOperationName();
961e5a8c8c8SSandeep Dasgupta   if (failed(parseOpNameInfo))
962e5a8c8c8SSandeep Dasgupta     return failure();
963e5a8c8c8SSandeep Dasgupta 
96414ecafd0SChia-hung Duan   StringAttr innerOpName = parseOpNameInfo->getIdentifier();
965e5a8c8c8SSandeep Dasgupta 
966e5a8c8c8SSandeep Dasgupta   FunctionType opFntype;
967e5a8c8c8SSandeep Dasgupta   Optional<Location> explicitLoc;
968e5a8c8c8SSandeep Dasgupta   if (parser.parseKeyword("end") || parser.parseColon() ||
969e5a8c8c8SSandeep Dasgupta       parser.parseType(opFntype) ||
970e5a8c8c8SSandeep Dasgupta       parser.parseOptionalLocationSpecifier(explicitLoc))
971e5a8c8c8SSandeep Dasgupta     return failure();
972e5a8c8c8SSandeep Dasgupta 
973e5a8c8c8SSandeep Dasgupta   // If location of the op is explicitly provided, then use it; Else use
974e5a8c8c8SSandeep Dasgupta   // the parser's current location.
97530c67587SKazu Hirata   Location opLoc = explicitLoc.value_or(currLocation);
976e5a8c8c8SSandeep Dasgupta 
977e5a8c8c8SSandeep Dasgupta   // Derive the SSA-values for op's operands.
978e5a8c8c8SSandeep Dasgupta   if (parser.resolveOperands(operands, opFntype.getInputs(), loc,
979e5a8c8c8SSandeep Dasgupta                              result.operands))
980e5a8c8c8SSandeep Dasgupta     return failure();
981e5a8c8c8SSandeep Dasgupta 
982e5a8c8c8SSandeep Dasgupta   // Add a region for op.
983e5a8c8c8SSandeep Dasgupta   Region &region = *result.addRegion();
984e5a8c8c8SSandeep Dasgupta 
985e5a8c8c8SSandeep Dasgupta   // Create a basic-block inside op's region.
986e5a8c8c8SSandeep Dasgupta   Block &block = region.emplaceBlock();
987e5a8c8c8SSandeep Dasgupta 
988e5a8c8c8SSandeep Dasgupta   // Create and insert an "inner-op" operation in the block.
989e5a8c8c8SSandeep Dasgupta   // Just for testing purposes, we can assume that inner op is a binary op with
990e5a8c8c8SSandeep Dasgupta   // result and operand types all same as the test-op's first operand.
991e5a8c8c8SSandeep Dasgupta   Type innerOpType = opFntype.getInput(0);
992e5a8c8c8SSandeep Dasgupta   Value lhs = block.addArgument(innerOpType, opLoc);
993e5a8c8c8SSandeep Dasgupta   Value rhs = block.addArgument(innerOpType, opLoc);
994e5a8c8c8SSandeep Dasgupta 
995e5a8c8c8SSandeep Dasgupta   OpBuilder builder(parser.getBuilder().getContext());
996e5a8c8c8SSandeep Dasgupta   builder.setInsertionPointToStart(&block);
997e5a8c8c8SSandeep Dasgupta 
99814ecafd0SChia-hung Duan   Operation *innerOp =
99914ecafd0SChia-hung Duan       builder.create(opLoc, innerOpName, /*operands=*/{lhs, rhs}, innerOpType);
1000e5a8c8c8SSandeep Dasgupta 
1001e5a8c8c8SSandeep Dasgupta   // Insert a return statement in the block returning the inner-op's result.
1002e5a8c8c8SSandeep Dasgupta   builder.create<TestReturnOp>(innerOp->getLoc(), innerOp->getResults());
1003e5a8c8c8SSandeep Dasgupta 
1004e5a8c8c8SSandeep Dasgupta   // Populate the op operation-state with result-type and location.
1005e5a8c8c8SSandeep Dasgupta   result.addTypes(opFntype.getResults());
1006e5a8c8c8SSandeep Dasgupta   result.location = innerOp->getLoc();
1007e5a8c8c8SSandeep Dasgupta 
1008e5a8c8c8SSandeep Dasgupta   return success();
1009e5a8c8c8SSandeep Dasgupta }
1010e5a8c8c8SSandeep Dasgupta 
print(OpAsmPrinter & p)1011d7f0083dSRiver Riddle void PrettyPrintedRegionOp::print(OpAsmPrinter &p) {
1012e5a8c8c8SSandeep Dasgupta   p << ' ';
1013d7f0083dSRiver Riddle   p.printOperands(getOperands());
1014e5a8c8c8SSandeep Dasgupta 
1015d7f0083dSRiver Riddle   Operation &innerOp = getRegion().front().front();
1016e5a8c8c8SSandeep Dasgupta   // Assuming that region has a single non-terminator inner-op, if the inner-op
1017e5a8c8c8SSandeep Dasgupta   // meets some criteria (which in this case is a simple one  based on the name
1018e5a8c8c8SSandeep Dasgupta   // of inner-op), then we can print the entire region in a succinct way.
1019e5a8c8c8SSandeep Dasgupta   // Here we assume that the prototype of "special.op" can be trivially derived
1020e5a8c8c8SSandeep Dasgupta   // while parsing it back.
1021e5a8c8c8SSandeep Dasgupta   if (innerOp.getName().getStringRef().equals("special.op")) {
1022e5a8c8c8SSandeep Dasgupta     p << " start special.op end";
1023e5a8c8c8SSandeep Dasgupta   } else {
1024e5a8c8c8SSandeep Dasgupta     p << " (";
1025d7f0083dSRiver Riddle     p.printRegion(getRegion());
1026e5a8c8c8SSandeep Dasgupta     p << ")";
1027e5a8c8c8SSandeep Dasgupta   }
1028e5a8c8c8SSandeep Dasgupta 
1029e5a8c8c8SSandeep Dasgupta   p << " : ";
1030d7f0083dSRiver Riddle   p.printFunctionalType(*this);
1031e5a8c8c8SSandeep Dasgupta }
1032e5a8c8c8SSandeep Dasgupta 
1033e5a8c8c8SSandeep Dasgupta //===----------------------------------------------------------------------===//
1034fec6c5acSUday Bondhugula // Test PolyForOp - parse list of region arguments.
1035fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===//
1036fec6c5acSUday Bondhugula 
parse(OpAsmParser & parser,OperationState & result)1037d7f0083dSRiver Riddle ParseResult PolyForOp::parse(OpAsmParser &parser, OperationState &result) {
1038d85eb4e2SChris Lattner   SmallVector<OpAsmParser::Argument, 4> ivsInfo;
1039fec6c5acSUday Bondhugula   // Parse list of region arguments without a delimiter.
1040d85eb4e2SChris Lattner   if (parser.parseArgumentList(ivsInfo, OpAsmParser::Delimiter::None))
1041fec6c5acSUday Bondhugula     return failure();
1042fec6c5acSUday Bondhugula 
1043fec6c5acSUday Bondhugula   // Parse the body region.
1044fec6c5acSUday Bondhugula   Region *body = result.addRegion();
1045d85eb4e2SChris Lattner   for (auto &iv : ivsInfo)
1046d85eb4e2SChris Lattner     iv.type = parser.getBuilder().getIndexType();
1047d85eb4e2SChris Lattner   return parser.parseRegion(*body, ivsInfo);
1048fec6c5acSUday Bondhugula }
1049fec6c5acSUday Bondhugula 
print(OpAsmPrinter & p)1050d7f0083dSRiver Riddle void PolyForOp::print(OpAsmPrinter &p) { p.printGenericOp(*this); }
1051d7f0083dSRiver Riddle 
getAsmBlockArgumentNames(Region & region,OpAsmSetValueNameFn setNameFn)10527f9e9c7fSMehdi Amini void PolyForOp::getAsmBlockArgumentNames(Region &region,
10537f9e9c7fSMehdi Amini                                          OpAsmSetValueNameFn setNameFn) {
10547f9e9c7fSMehdi Amini   auto arrayAttr = getOperation()->getAttrOfType<ArrayAttr>("arg_names");
10557f9e9c7fSMehdi Amini   if (!arrayAttr)
10567f9e9c7fSMehdi Amini     return;
10577f9e9c7fSMehdi Amini   auto args = getRegion().front().getArguments();
10587f9e9c7fSMehdi Amini   auto e = std::min(arrayAttr.size(), args.size());
10597f9e9c7fSMehdi Amini   for (unsigned i = 0; i < e; ++i) {
10607f9e9c7fSMehdi Amini     if (auto strAttr = arrayAttr[i].dyn_cast<StringAttr>())
10617f9e9c7fSMehdi Amini       setNameFn(args[i], strAttr.getValue());
10627f9e9c7fSMehdi Amini   }
10637f9e9c7fSMehdi Amini }
10647f9e9c7fSMehdi Amini 
1065fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===//
1066fec6c5acSUday Bondhugula // Test removing op with inner ops.
1067fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===//
1068fec6c5acSUday Bondhugula 
1069fec6c5acSUday Bondhugula namespace {
1070fec6c5acSUday Bondhugula struct TestRemoveOpWithInnerOps
1071fec6c5acSUday Bondhugula     : public OpRewritePattern<TestOpWithRegionPattern> {
1072fec6c5acSUday Bondhugula   using OpRewritePattern<TestOpWithRegionPattern>::OpRewritePattern;
1073fec6c5acSUday Bondhugula 
initialize__anonf77d94721411::TestRemoveOpWithInnerOps10740289a269SRiver Riddle   void initialize() { setDebugName("TestRemoveOpWithInnerOps"); }
10750289a269SRiver Riddle 
matchAndRewrite__anonf77d94721411::TestRemoveOpWithInnerOps1076fec6c5acSUday Bondhugula   LogicalResult matchAndRewrite(TestOpWithRegionPattern op,
1077fec6c5acSUday Bondhugula                                 PatternRewriter &rewriter) const override {
1078fec6c5acSUday Bondhugula     rewriter.eraseOp(op);
1079fec6c5acSUday Bondhugula     return success();
1080fec6c5acSUday Bondhugula   }
1081fec6c5acSUday Bondhugula };
1082be0a7e9fSMehdi Amini } // namespace
1083fec6c5acSUday Bondhugula 
getCanonicalizationPatterns(RewritePatternSet & results,MLIRContext * context)1084fec6c5acSUday Bondhugula void TestOpWithRegionPattern::getCanonicalizationPatterns(
1085dc4e913bSChris Lattner     RewritePatternSet &results, MLIRContext *context) {
1086dc4e913bSChris Lattner   results.add<TestRemoveOpWithInnerOps>(context);
1087fec6c5acSUday Bondhugula }
1088fec6c5acSUday Bondhugula 
fold(ArrayRef<Attribute> operands)1089fec6c5acSUday Bondhugula OpFoldResult TestOpWithRegionFold::fold(ArrayRef<Attribute> operands) {
10906a994233SJacques Pienaar   return getOperand();
1091fec6c5acSUday Bondhugula }
1092fec6c5acSUday Bondhugula 
fold(ArrayRef<Attribute> operands)10932bf423b0SRob Suderman OpFoldResult TestOpConstant::fold(ArrayRef<Attribute> operands) {
10942bf423b0SRob Suderman   return getValue();
10952bf423b0SRob Suderman }
10962bf423b0SRob Suderman 
fold(ArrayRef<Attribute> operands,SmallVectorImpl<OpFoldResult> & results)1097fec6c5acSUday Bondhugula LogicalResult TestOpWithVariadicResultsAndFolder::fold(
1098fec6c5acSUday Bondhugula     ArrayRef<Attribute> operands, SmallVectorImpl<OpFoldResult> &results) {
109962bf8509SJacques Pienaar   for (Value input : this->getOperands()) {
1100fec6c5acSUday Bondhugula     results.push_back(input);
1101fec6c5acSUday Bondhugula   }
1102fec6c5acSUday Bondhugula   return success();
1103fec6c5acSUday Bondhugula }
1104fec6c5acSUday Bondhugula 
fold(ArrayRef<Attribute> operands)110526f93d9fSAlex Zinenko OpFoldResult TestOpInPlaceFold::fold(ArrayRef<Attribute> operands) {
110626f93d9fSAlex Zinenko   assert(operands.size() == 1);
110726f93d9fSAlex Zinenko   if (operands.front()) {
11081ffc1aaaSChristian Sigg     (*this)->setAttr("attr", operands.front());
110926f93d9fSAlex Zinenko     return getResult();
111026f93d9fSAlex Zinenko   }
111126f93d9fSAlex Zinenko   return {};
111226f93d9fSAlex Zinenko }
111326f93d9fSAlex Zinenko 
fold(ArrayRef<Attribute> operands)1114a1d5bdf8SMehdi Amini OpFoldResult TestPassthroughFold::fold(ArrayRef<Attribute> operands) {
1115a1d5bdf8SMehdi Amini   return getOperand();
1116a1d5bdf8SMehdi Amini }
1117a1d5bdf8SMehdi Amini 
inferReturnTypes(MLIRContext *,Optional<Location> location,ValueRange operands,DictionaryAttr attributes,RegionRange regions,SmallVectorImpl<Type> & inferredReturnTypes)111862828865SStephen Neuendorffer LogicalResult OpWithInferTypeInterfaceOp::inferReturnTypes(
1119fec6c5acSUday Bondhugula     MLIRContext *, Optional<Location> location, ValueRange operands,
11205eae715aSJacques Pienaar     DictionaryAttr attributes, RegionRange regions,
1121fec6c5acSUday Bondhugula     SmallVectorImpl<Type> &inferredReturnTypes) {
1122fec6c5acSUday Bondhugula   if (operands[0].getType() != operands[1].getType()) {
1123fec6c5acSUday Bondhugula     return emitOptionalError(location, "operand type mismatch ",
1124fec6c5acSUday Bondhugula                              operands[0].getType(), " vs ",
1125fec6c5acSUday Bondhugula                              operands[1].getType());
1126fec6c5acSUday Bondhugula   }
1127fec6c5acSUday Bondhugula   inferredReturnTypes.assign({operands[0].getType()});
1128fec6c5acSUday Bondhugula   return success();
1129fec6c5acSUday Bondhugula }
1130fec6c5acSUday Bondhugula 
1131*c8598fa2SJacques Pienaar // TODO: We should be able to only define either inferReturnType or
1132*c8598fa2SJacques Pienaar // refineReturnType, currently only refineReturnType can be omitted.
inferReturnTypes(MLIRContext * context,Optional<Location> location,ValueRange operands,DictionaryAttr attributes,RegionRange regions,SmallVectorImpl<Type> & returnTypes)1133*c8598fa2SJacques Pienaar LogicalResult OpWithRefineTypeInterfaceOp::inferReturnTypes(
1134*c8598fa2SJacques Pienaar     MLIRContext *context, Optional<Location> location, ValueRange operands,
1135*c8598fa2SJacques Pienaar     DictionaryAttr attributes, RegionRange regions,
1136*c8598fa2SJacques Pienaar     SmallVectorImpl<Type> &returnTypes) {
1137*c8598fa2SJacques Pienaar   returnTypes.clear();
1138*c8598fa2SJacques Pienaar   return OpWithRefineTypeInterfaceOp::refineReturnTypes(
1139*c8598fa2SJacques Pienaar       context, location, operands, attributes, regions, returnTypes);
1140*c8598fa2SJacques Pienaar }
1141*c8598fa2SJacques Pienaar 
refineReturnTypes(MLIRContext *,Optional<Location> location,ValueRange operands,DictionaryAttr attributes,RegionRange regions,SmallVectorImpl<Type> & returnTypes)1142*c8598fa2SJacques Pienaar LogicalResult OpWithRefineTypeInterfaceOp::refineReturnTypes(
1143*c8598fa2SJacques Pienaar     MLIRContext *, Optional<Location> location, ValueRange operands,
1144*c8598fa2SJacques Pienaar     DictionaryAttr attributes, RegionRange regions,
1145*c8598fa2SJacques Pienaar     SmallVectorImpl<Type> &returnTypes) {
1146*c8598fa2SJacques Pienaar   if (operands[0].getType() != operands[1].getType()) {
1147*c8598fa2SJacques Pienaar     return emitOptionalError(location, "operand type mismatch ",
1148*c8598fa2SJacques Pienaar                              operands[0].getType(), " vs ",
1149*c8598fa2SJacques Pienaar                              operands[1].getType());
1150*c8598fa2SJacques Pienaar   }
1151*c8598fa2SJacques Pienaar   // TODO: Add helper to make this more concise to write.
1152*c8598fa2SJacques Pienaar   if (returnTypes.empty())
1153*c8598fa2SJacques Pienaar     returnTypes.resize(1, nullptr);
1154*c8598fa2SJacques Pienaar   if (returnTypes[0] && returnTypes[0] != operands[0].getType())
1155*c8598fa2SJacques Pienaar     return emitOptionalError(location,
1156*c8598fa2SJacques Pienaar                              "required first operand and result to match");
1157*c8598fa2SJacques Pienaar   returnTypes[0] = operands[0].getType();
1158*c8598fa2SJacques Pienaar   return success();
1159*c8598fa2SJacques Pienaar }
1160*c8598fa2SJacques Pienaar 
inferReturnTypeComponents(MLIRContext * context,Optional<Location> location,ValueShapeRange operands,DictionaryAttr attributes,RegionRange regions,SmallVectorImpl<ShapedTypeComponents> & inferredReturnShapes)1161fec6c5acSUday Bondhugula LogicalResult OpWithShapedTypeInferTypeInterfaceOp::inferReturnTypeComponents(
1162ee7242c6SJacques Pienaar     MLIRContext *context, Optional<Location> location, ValueShapeRange operands,
11635eae715aSJacques Pienaar     DictionaryAttr attributes, RegionRange regions,
1164fec6c5acSUday Bondhugula     SmallVectorImpl<ShapedTypeComponents> &inferredReturnShapes) {
1165fec6c5acSUday Bondhugula   // Create return type consisting of the last element of the first operand.
1166d425f589SJacques Pienaar   auto operandType = operands.front().getType();
1167fec6c5acSUday Bondhugula   auto sval = operandType.dyn_cast<ShapedType>();
1168fec6c5acSUday Bondhugula   if (!sval) {
1169fec6c5acSUday Bondhugula     return emitOptionalError(location, "only shaped type operands allowed");
1170fec6c5acSUday Bondhugula   }
1171fec6c5acSUday Bondhugula   int64_t dim =
1172fec6c5acSUday Bondhugula       sval.hasRank() ? sval.getShape().front() : ShapedType::kDynamicSize;
11731b97cdf8SRiver Riddle   auto type = IntegerType::get(context, 17);
1174fec6c5acSUday Bondhugula   inferredReturnShapes.push_back(ShapedTypeComponents({dim}, type));
1175fec6c5acSUday Bondhugula   return success();
1176fec6c5acSUday Bondhugula }
1177fec6c5acSUday Bondhugula 
reifyReturnTypeShapes(OpBuilder & builder,ValueRange operands,llvm::SmallVectorImpl<Value> & shapes)1178fec6c5acSUday Bondhugula LogicalResult OpWithShapedTypeInferTypeInterfaceOp::reifyReturnTypeShapes(
1179851d02f6SWenyi Zhao     OpBuilder &builder, ValueRange operands,
1180851d02f6SWenyi Zhao     llvm::SmallVectorImpl<Value> &shapes) {
1181fec6c5acSUday Bondhugula   shapes = SmallVector<Value, 1>{
1182c0a6318dSMatthias Springer       builder.createOrFold<tensor::DimOp>(getLoc(), operands.front(), 0)};
1183fec6c5acSUday Bondhugula   return success();
1184fec6c5acSUday Bondhugula }
1185fec6c5acSUday Bondhugula 
reifyReturnTypeShapes(OpBuilder & builder,ValueRange operands,llvm::SmallVectorImpl<Value> & shapes)11863ed3e438SMaheshRavishankar LogicalResult OpWithResultShapeInterfaceOp::reifyReturnTypeShapes(
11873ed3e438SMaheshRavishankar     OpBuilder &builder, ValueRange operands,
11883ed3e438SMaheshRavishankar     llvm::SmallVectorImpl<Value> &shapes) {
11893ed3e438SMaheshRavishankar   Location loc = getLoc();
11903ed3e438SMaheshRavishankar   shapes.reserve(operands.size());
11913ed3e438SMaheshRavishankar   for (Value operand : llvm::reverse(operands)) {
1192f77e9f87SAlexander Belyaev     auto rank = operand.getType().cast<RankedTensorType>().getRank();
1193f77e9f87SAlexander Belyaev     auto currShape = llvm::to_vector<4>(
1194f77e9f87SAlexander Belyaev         llvm::map_range(llvm::seq<int64_t>(0, rank), [&](int64_t dim) -> Value {
1195c0a6318dSMatthias Springer           return builder.createOrFold<tensor::DimOp>(loc, operand, dim);
11963ed3e438SMaheshRavishankar         }));
11973ed3e438SMaheshRavishankar     shapes.push_back(builder.create<tensor::FromElementsOp>(
1198f77e9f87SAlexander Belyaev         getLoc(), RankedTensorType::get({rank}, builder.getIndexType()),
1199f77e9f87SAlexander Belyaev         currShape));
12003ed3e438SMaheshRavishankar   }
12013ed3e438SMaheshRavishankar   return success();
12023ed3e438SMaheshRavishankar }
12033ed3e438SMaheshRavishankar 
reifyResultShapes(OpBuilder & builder,ReifiedRankedShapedTypeDims & shapes)12049afc0657SMaheshRavishankar LogicalResult OpWithResultShapePerDimInterfaceOp::reifyResultShapes(
12059afc0657SMaheshRavishankar     OpBuilder &builder, ReifiedRankedShapedTypeDims &shapes) {
12063ed3e438SMaheshRavishankar   Location loc = getLoc();
12073ed3e438SMaheshRavishankar   shapes.reserve(getNumOperands());
12083ed3e438SMaheshRavishankar   for (Value operand : llvm::reverse(getOperands())) {
12093ed3e438SMaheshRavishankar     auto currShape = llvm::to_vector<4>(llvm::map_range(
12103ed3e438SMaheshRavishankar         llvm::seq<int64_t>(
12113ed3e438SMaheshRavishankar             0, operand.getType().cast<RankedTensorType>().getRank()),
12123ed3e438SMaheshRavishankar         [&](int64_t dim) -> Value {
1213c0a6318dSMatthias Springer           return builder.createOrFold<tensor::DimOp>(loc, operand, dim);
12143ed3e438SMaheshRavishankar         }));
12153ed3e438SMaheshRavishankar     shapes.emplace_back(std::move(currShape));
12163ed3e438SMaheshRavishankar   }
12179b051703SMaheshRavishankar   return success();
12189b051703SMaheshRavishankar }
12199b051703SMaheshRavishankar 
1220fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===//
1221fec6c5acSUday Bondhugula // Test SideEffect interfaces
1222fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===//
1223fec6c5acSUday Bondhugula 
1224fec6c5acSUday Bondhugula namespace {
1225fec6c5acSUday Bondhugula /// A test resource for side effects.
1226fec6c5acSUday Bondhugula struct TestResource : public SideEffects::Resource::Base<TestResource> {
MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID__anonf77d94721711::TestResource12275e50dd04SRiver Riddle   MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestResource)
12285e50dd04SRiver Riddle 
1229fec6c5acSUday Bondhugula   StringRef getName() final { return "<Test>"; }
1230fec6c5acSUday Bondhugula };
1231be0a7e9fSMehdi Amini } // namespace
1232fec6c5acSUday Bondhugula 
testSideEffectOpGetEffect(Operation * op,SmallVectorImpl<SideEffects::EffectInstance<TestEffects::Effect>> & effects)1233d905c103SMehdi Amini static void testSideEffectOpGetEffect(
1234d905c103SMehdi Amini     Operation *op,
1235d905c103SMehdi Amini     SmallVectorImpl<SideEffects::EffectInstance<TestEffects::Effect>>
1236d905c103SMehdi Amini         &effects) {
1237d905c103SMehdi Amini   auto effectsAttr = op->getAttrOfType<AffineMapAttr>("effect_parameter");
1238d905c103SMehdi Amini   if (!effectsAttr)
1239d905c103SMehdi Amini     return;
1240d905c103SMehdi Amini 
1241d905c103SMehdi Amini   effects.emplace_back(TestEffects::Concrete::get(), effectsAttr);
1242d905c103SMehdi Amini }
1243d905c103SMehdi Amini 
getEffects(SmallVectorImpl<MemoryEffects::EffectInstance> & effects)1244fec6c5acSUday Bondhugula void SideEffectOp::getEffects(
1245fec6c5acSUday Bondhugula     SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
1246fec6c5acSUday Bondhugula   // Check for an effects attribute on the op instance.
12470bf4a82aSChristian Sigg   ArrayAttr effectsAttr = (*this)->getAttrOfType<ArrayAttr>("effects");
1248fec6c5acSUday Bondhugula   if (!effectsAttr)
1249fec6c5acSUday Bondhugula     return;
1250fec6c5acSUday Bondhugula 
1251fec6c5acSUday Bondhugula   // If there is one, it is an array of dictionary attributes that hold
1252fec6c5acSUday Bondhugula   // information on the effects of this operation.
1253fec6c5acSUday Bondhugula   for (Attribute element : effectsAttr) {
1254fec6c5acSUday Bondhugula     DictionaryAttr effectElement = element.cast<DictionaryAttr>();
1255fec6c5acSUday Bondhugula 
1256fec6c5acSUday Bondhugula     // Get the specific memory effect.
1257fec6c5acSUday Bondhugula     MemoryEffects::Effect *effect =
1258cc83dc19SChristian Sigg         StringSwitch<MemoryEffects::Effect *>(
1259fec6c5acSUday Bondhugula             effectElement.get("effect").cast<StringAttr>().getValue())
1260fec6c5acSUday Bondhugula             .Case("allocate", MemoryEffects::Allocate::get())
1261fec6c5acSUday Bondhugula             .Case("free", MemoryEffects::Free::get())
1262fec6c5acSUday Bondhugula             .Case("read", MemoryEffects::Read::get())
1263fec6c5acSUday Bondhugula             .Case("write", MemoryEffects::Write::get());
1264fec6c5acSUday Bondhugula 
1265fec6c5acSUday Bondhugula     // Check for a non-default resource to use.
1266fec6c5acSUday Bondhugula     SideEffects::Resource *resource = SideEffects::DefaultResource::get();
1267fec6c5acSUday Bondhugula     if (effectElement.get("test_resource"))
1268fec6c5acSUday Bondhugula       resource = TestResource::get();
1269fec6c5acSUday Bondhugula 
1270c0958b7bSRiver Riddle     // Check for a result to affect.
1271c0958b7bSRiver Riddle     if (effectElement.get("on_result"))
1272c0958b7bSRiver Riddle       effects.emplace_back(effect, getResult(), resource);
1273c0958b7bSRiver Riddle     else if (Attribute ref = effectElement.get("on_reference"))
1274c0958b7bSRiver Riddle       effects.emplace_back(effect, ref.cast<SymbolRefAttr>(), resource);
1275c0958b7bSRiver Riddle     else
1276c0958b7bSRiver Riddle       effects.emplace_back(effect, resource);
1277fec6c5acSUday Bondhugula   }
1278fec6c5acSUday Bondhugula }
1279fec6c5acSUday Bondhugula 
getEffects(SmallVectorImpl<TestEffects::EffectInstance> & effects)1280052d24afSAlex Zinenko void SideEffectOp::getEffects(
1281052d24afSAlex Zinenko     SmallVectorImpl<TestEffects::EffectInstance> &effects) {
1282d905c103SMehdi Amini   testSideEffectOpGetEffect(getOperation(), effects);
1283052d24afSAlex Zinenko }
1284052d24afSAlex Zinenko 
1285fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===//
1286fec6c5acSUday Bondhugula // StringAttrPrettyNameOp
1287fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===//
1288fec6c5acSUday Bondhugula 
1289fec6c5acSUday Bondhugula // This op has fancy handling of its SSA result name.
parse(OpAsmParser & parser,OperationState & result)1290d7f0083dSRiver Riddle ParseResult StringAttrPrettyNameOp::parse(OpAsmParser &parser,
1291fec6c5acSUday Bondhugula                                           OperationState &result) {
1292fec6c5acSUday Bondhugula   // Add the result types.
1293fec6c5acSUday Bondhugula   for (size_t i = 0, e = parser.getNumResults(); i != e; ++i)
1294fec6c5acSUday Bondhugula     result.addTypes(parser.getBuilder().getIntegerType(32));
1295fec6c5acSUday Bondhugula 
1296fec6c5acSUday Bondhugula   if (parser.parseOptionalAttrDictWithKeyword(result.attributes))
1297fec6c5acSUday Bondhugula     return failure();
1298fec6c5acSUday Bondhugula 
1299fec6c5acSUday Bondhugula   // If the attribute dictionary contains no 'names' attribute, infer it from
1300fec6c5acSUday Bondhugula   // the SSA name (if specified).
1301fec6c5acSUday Bondhugula   bool hadNames = llvm::any_of(result.attributes, [](NamedAttribute attr) {
13020c7890c8SRiver Riddle     return attr.getName() == "names";
1303fec6c5acSUday Bondhugula   });
1304fec6c5acSUday Bondhugula 
1305fec6c5acSUday Bondhugula   // If there was no name specified, check to see if there was a useful name
1306fec6c5acSUday Bondhugula   // specified in the asm file.
1307fec6c5acSUday Bondhugula   if (hadNames || parser.getNumResults() == 0)
1308fec6c5acSUday Bondhugula     return success();
1309fec6c5acSUday Bondhugula 
1310fec6c5acSUday Bondhugula   SmallVector<StringRef, 4> names;
1311fec6c5acSUday Bondhugula   auto *context = result.getContext();
1312fec6c5acSUday Bondhugula 
1313fec6c5acSUday Bondhugula   for (size_t i = 0, e = parser.getNumResults(); i != e; ++i) {
1314fec6c5acSUday Bondhugula     auto resultName = parser.getResultName(i);
1315fec6c5acSUday Bondhugula     StringRef nameStr;
1316fec6c5acSUday Bondhugula     if (!resultName.first.empty() && !isdigit(resultName.first[0]))
1317fec6c5acSUday Bondhugula       nameStr = resultName.first;
1318fec6c5acSUday Bondhugula 
1319fec6c5acSUday Bondhugula     names.push_back(nameStr);
1320fec6c5acSUday Bondhugula   }
1321fec6c5acSUday Bondhugula 
1322fec6c5acSUday Bondhugula   auto namesAttr = parser.getBuilder().getStrArrayAttr(names);
1323195730a6SRiver Riddle   result.attributes.push_back({StringAttr::get(context, "names"), namesAttr});
1324fec6c5acSUday Bondhugula   return success();
1325fec6c5acSUday Bondhugula }
1326fec6c5acSUday Bondhugula 
print(OpAsmPrinter & p)1327d7f0083dSRiver Riddle void StringAttrPrettyNameOp::print(OpAsmPrinter &p) {
1328fec6c5acSUday Bondhugula   // Note that we only need to print the "name" attribute if the asmprinter
1329fec6c5acSUday Bondhugula   // result name disagrees with it.  This can happen in strange cases, e.g.
1330fec6c5acSUday Bondhugula   // when there are conflicts.
1331d7f0083dSRiver Riddle   bool namesDisagree = getNames().size() != getNumResults();
1332fec6c5acSUday Bondhugula 
1333fec6c5acSUday Bondhugula   SmallString<32> resultNameStr;
1334d7f0083dSRiver Riddle   for (size_t i = 0, e = getNumResults(); i != e && !namesDisagree; ++i) {
1335fec6c5acSUday Bondhugula     resultNameStr.clear();
1336fec6c5acSUday Bondhugula     llvm::raw_svector_ostream tmpStream(resultNameStr);
1337d7f0083dSRiver Riddle     p.printOperand(getResult(i), tmpStream);
1338fec6c5acSUday Bondhugula 
1339d7f0083dSRiver Riddle     auto expectedName = getNames()[i].dyn_cast<StringAttr>();
1340fec6c5acSUday Bondhugula     if (!expectedName ||
1341fec6c5acSUday Bondhugula         tmpStream.str().drop_front() != expectedName.getValue()) {
1342fec6c5acSUday Bondhugula       namesDisagree = true;
1343fec6c5acSUday Bondhugula     }
1344fec6c5acSUday Bondhugula   }
1345fec6c5acSUday Bondhugula 
1346fec6c5acSUday Bondhugula   if (namesDisagree)
1347d7f0083dSRiver Riddle     p.printOptionalAttrDictWithKeyword((*this)->getAttrs());
1348fec6c5acSUday Bondhugula   else
1349d7f0083dSRiver Riddle     p.printOptionalAttrDictWithKeyword((*this)->getAttrs(), {"names"});
1350fec6c5acSUday Bondhugula }
1351fec6c5acSUday Bondhugula 
1352fec6c5acSUday Bondhugula // We set the SSA name in the asm syntax to the contents of the name
1353fec6c5acSUday Bondhugula // attribute.
getAsmResultNames(function_ref<void (Value,StringRef)> setNameFn)1354fec6c5acSUday Bondhugula void StringAttrPrettyNameOp::getAsmResultNames(
1355fec6c5acSUday Bondhugula     function_ref<void(Value, StringRef)> setNameFn) {
1356fec6c5acSUday Bondhugula 
13576a994233SJacques Pienaar   auto value = getNames();
1358fec6c5acSUday Bondhugula   for (size_t i = 0, e = value.size(); i != e; ++i)
1359fec6c5acSUday Bondhugula     if (auto str = value[i].dyn_cast<StringAttr>())
1360fec6c5acSUday Bondhugula       if (!str.getValue().empty())
1361fec6c5acSUday Bondhugula         setNameFn(getResult(i), str.getValue());
1362fec6c5acSUday Bondhugula }
1363fec6c5acSUday Bondhugula 
getAsmResultNames(function_ref<void (Value,StringRef)> setNameFn)13643e8560f8Scpillmayer void CustomResultsNameOp::getAsmResultNames(
13653e8560f8Scpillmayer     function_ref<void(Value, StringRef)> setNameFn) {
13663e8560f8Scpillmayer   ArrayAttr value = getNames();
13673e8560f8Scpillmayer   for (size_t i = 0, e = value.size(); i != e; ++i)
13683e8560f8Scpillmayer     if (auto str = value[i].dyn_cast<StringAttr>())
13693e8560f8Scpillmayer       if (!str.getValue().empty())
13703e8560f8Scpillmayer         setNameFn(getResult(i), str.getValue());
13713e8560f8Scpillmayer }
13723e8560f8Scpillmayer 
1373fec6c5acSUday Bondhugula //===----------------------------------------------------------------------===//
137442e5f1d9SRiver Riddle // ResultTypeWithTraitOp
137542e5f1d9SRiver Riddle //===----------------------------------------------------------------------===//
137642e5f1d9SRiver Riddle 
verify()137742e5f1d9SRiver Riddle LogicalResult ResultTypeWithTraitOp::verify() {
137842e5f1d9SRiver Riddle   if ((*this)->getResultTypes()[0].hasTrait<TypeTrait::TestTypeTrait>())
137942e5f1d9SRiver Riddle     return success();
138042e5f1d9SRiver Riddle   return emitError("result type should have trait 'TestTypeTrait'");
138142e5f1d9SRiver Riddle }
138242e5f1d9SRiver Riddle 
138342e5f1d9SRiver Riddle //===----------------------------------------------------------------------===//
138442e5f1d9SRiver Riddle // AttrWithTraitOp
138542e5f1d9SRiver Riddle //===----------------------------------------------------------------------===//
138642e5f1d9SRiver Riddle 
verify()138742e5f1d9SRiver Riddle LogicalResult AttrWithTraitOp::verify() {
138842e5f1d9SRiver Riddle   if (getAttr().hasTrait<AttributeTrait::TestAttrTrait>())
138942e5f1d9SRiver Riddle     return success();
139042e5f1d9SRiver Riddle   return emitError("'attr' attribute should have trait 'TestAttrTrait'");
139142e5f1d9SRiver Riddle }
139242e5f1d9SRiver Riddle 
139342e5f1d9SRiver Riddle //===----------------------------------------------------------------------===//
13946f5da84fSMarcel Koester // RegionIfOp
13956f5da84fSMarcel Koester //===----------------------------------------------------------------------===//
13966f5da84fSMarcel Koester 
print(OpAsmPrinter & p)1397d7f0083dSRiver Riddle void RegionIfOp::print(OpAsmPrinter &p) {
1398c41b16c2SMehdi Amini   p << " ";
1399d7f0083dSRiver Riddle   p.printOperands(getOperands());
1400d7f0083dSRiver Riddle   p << ": " << getOperandTypes();
1401d7f0083dSRiver Riddle   p.printArrowTypeList(getResultTypes());
14026f5da84fSMarcel Koester   p << " then ";
1403d7f0083dSRiver Riddle   p.printRegion(getThenRegion(),
14046f5da84fSMarcel Koester                 /*printEntryBlockArgs=*/true,
14056f5da84fSMarcel Koester                 /*printBlockTerminators=*/true);
14066f5da84fSMarcel Koester   p << " else ";
1407d7f0083dSRiver Riddle   p.printRegion(getElseRegion(),
14086f5da84fSMarcel Koester                 /*printEntryBlockArgs=*/true,
14096f5da84fSMarcel Koester                 /*printBlockTerminators=*/true);
14106f5da84fSMarcel Koester   p << " join ";
1411d7f0083dSRiver Riddle   p.printRegion(getJoinRegion(),
14126f5da84fSMarcel Koester                 /*printEntryBlockArgs=*/true,
14136f5da84fSMarcel Koester                 /*printBlockTerminators=*/true);
14146f5da84fSMarcel Koester }
14156f5da84fSMarcel Koester 
parse(OpAsmParser & parser,OperationState & result)1416d7f0083dSRiver Riddle ParseResult RegionIfOp::parse(OpAsmParser &parser, OperationState &result) {
1417e13d23bcSMarkus Böck   SmallVector<OpAsmParser::UnresolvedOperand, 2> operandInfos;
14186f5da84fSMarcel Koester   SmallVector<Type, 2> operandTypes;
14196f5da84fSMarcel Koester 
14206f5da84fSMarcel Koester   result.regions.reserve(3);
14216f5da84fSMarcel Koester   Region *thenRegion = result.addRegion();
14226f5da84fSMarcel Koester   Region *elseRegion = result.addRegion();
14236f5da84fSMarcel Koester   Region *joinRegion = result.addRegion();
14246f5da84fSMarcel Koester 
14256f5da84fSMarcel Koester   // Parse operand, type and arrow type lists.
14266f5da84fSMarcel Koester   if (parser.parseOperandList(operandInfos) ||
14276f5da84fSMarcel Koester       parser.parseColonTypeList(operandTypes) ||
14286f5da84fSMarcel Koester       parser.parseArrowTypeList(result.types))
14296f5da84fSMarcel Koester     return failure();
14306f5da84fSMarcel Koester 
14316f5da84fSMarcel Koester   // Parse all attached regions.
14326f5da84fSMarcel Koester   if (parser.parseKeyword("then") || parser.parseRegion(*thenRegion, {}, {}) ||
14336f5da84fSMarcel Koester       parser.parseKeyword("else") || parser.parseRegion(*elseRegion, {}, {}) ||
14346f5da84fSMarcel Koester       parser.parseKeyword("join") || parser.parseRegion(*joinRegion, {}, {}))
14356f5da84fSMarcel Koester     return failure();
14366f5da84fSMarcel Koester 
14376f5da84fSMarcel Koester   return parser.resolveOperands(operandInfos, operandTypes,
14386f5da84fSMarcel Koester                                 parser.getCurrentLocation(), result.operands);
14396f5da84fSMarcel Koester }
14406f5da84fSMarcel Koester 
getSuccessorEntryOperands(Optional<unsigned> index)1441537f2208SMogball OperandRange RegionIfOp::getSuccessorEntryOperands(Optional<unsigned> index) {
1442537f2208SMogball   assert(index && *index < 2 && "invalid region index");
14436f5da84fSMarcel Koester   return getOperands();
14446f5da84fSMarcel Koester }
14456f5da84fSMarcel Koester 
getSuccessorRegions(Optional<unsigned> index,ArrayRef<Attribute> operands,SmallVectorImpl<RegionSuccessor> & regions)14466f5da84fSMarcel Koester void RegionIfOp::getSuccessorRegions(
14476f5da84fSMarcel Koester     Optional<unsigned> index, ArrayRef<Attribute> operands,
14486f5da84fSMarcel Koester     SmallVectorImpl<RegionSuccessor> &regions) {
14496f5da84fSMarcel Koester   // We always branch to the join region.
1450491d2701SKazu Hirata   if (index.has_value()) {
1451c27d8152SKazu Hirata     if (index.value() < 2)
14526a994233SJacques Pienaar       regions.push_back(RegionSuccessor(&getJoinRegion(), getJoinArgs()));
14536f5da84fSMarcel Koester     else
14546f5da84fSMarcel Koester       regions.push_back(RegionSuccessor(getResults()));
14556f5da84fSMarcel Koester     return;
14566f5da84fSMarcel Koester   }
14576f5da84fSMarcel Koester 
14586f5da84fSMarcel Koester   // The then and else regions are the entry regions of this op.
14596a994233SJacques Pienaar   regions.push_back(RegionSuccessor(&getThenRegion(), getThenArgs()));
14606a994233SJacques Pienaar   regions.push_back(RegionSuccessor(&getElseRegion(), getElseArgs()));
1461572fa964SMogball }
1462572fa964SMogball 
getRegionInvocationBounds(ArrayRef<Attribute> operands,SmallVectorImpl<InvocationBounds> & invocationBounds)1463572fa964SMogball void RegionIfOp::getRegionInvocationBounds(
1464572fa964SMogball     ArrayRef<Attribute> operands,
1465572fa964SMogball     SmallVectorImpl<InvocationBounds> &invocationBounds) {
1466572fa964SMogball   // Each region is invoked at most once.
1467572fa964SMogball   invocationBounds.assign(/*NumElts=*/3, /*Elt=*/{0, 1});
1468572fa964SMogball }
1469572fa964SMogball 
1470572fa964SMogball //===----------------------------------------------------------------------===//
1471572fa964SMogball // AnyCondOp
1472572fa964SMogball //===----------------------------------------------------------------------===//
1473572fa964SMogball 
getSuccessorRegions(Optional<unsigned> index,ArrayRef<Attribute> operands,SmallVectorImpl<RegionSuccessor> & regions)1474572fa964SMogball void AnyCondOp::getSuccessorRegions(Optional<unsigned> index,
1475572fa964SMogball                                     ArrayRef<Attribute> operands,
1476572fa964SMogball                                     SmallVectorImpl<RegionSuccessor> &regions) {
1477572fa964SMogball   // The parent op branches into the only region, and the region branches back
1478572fa964SMogball   // to the parent op.
1479537f2208SMogball   if (!index)
1480572fa964SMogball     regions.emplace_back(&getRegion());
1481572fa964SMogball   else
1482572fa964SMogball     regions.emplace_back(getResults());
1483572fa964SMogball }
1484572fa964SMogball 
getRegionInvocationBounds(ArrayRef<Attribute> operands,SmallVectorImpl<InvocationBounds> & invocationBounds)1485572fa964SMogball void AnyCondOp::getRegionInvocationBounds(
1486572fa964SMogball     ArrayRef<Attribute> operands,
1487572fa964SMogball     SmallVectorImpl<InvocationBounds> &invocationBounds) {
1488572fa964SMogball   invocationBounds.emplace_back(1, 1);
14896f5da84fSMarcel Koester }
14906f5da84fSMarcel Koester 
14914694097dSLei Zhang //===----------------------------------------------------------------------===//
14924694097dSLei Zhang // SingleNoTerminatorCustomAsmOp
14934694097dSLei Zhang //===----------------------------------------------------------------------===//
14944694097dSLei Zhang 
parse(OpAsmParser & parser,OperationState & state)1495d7f0083dSRiver Riddle ParseResult SingleNoTerminatorCustomAsmOp::parse(OpAsmParser &parser,
14964694097dSLei Zhang                                                  OperationState &state) {
14974694097dSLei Zhang   Region *body = state.addRegion();
14984694097dSLei Zhang   if (parser.parseRegion(*body, /*arguments=*/{}, /*argTypes=*/{}))
14994694097dSLei Zhang     return failure();
15004694097dSLei Zhang   return success();
15014694097dSLei Zhang }
15024694097dSLei Zhang 
print(OpAsmPrinter & printer)1503d7f0083dSRiver Riddle void SingleNoTerminatorCustomAsmOp::print(OpAsmPrinter &printer) {
15044694097dSLei Zhang   printer.printRegion(
1505d7f0083dSRiver Riddle       getRegion(), /*printEntryBlockArgs=*/false,
15064694097dSLei Zhang       // This op has a single block without terminators. But explicitly mark
15074694097dSLei Zhang       // as not printing block terminators for testing.
15084694097dSLei Zhang       /*printBlockTerminators=*/false);
15094694097dSLei Zhang }
15104694097dSLei Zhang 
15115232c5c5SChia-hung Duan //===----------------------------------------------------------------------===//
15125232c5c5SChia-hung Duan // TestVerifiersOp
15135232c5c5SChia-hung Duan //===----------------------------------------------------------------------===//
15145232c5c5SChia-hung Duan 
verify()15155232c5c5SChia-hung Duan LogicalResult TestVerifiersOp::verify() {
15165232c5c5SChia-hung Duan   if (!getRegion().hasOneBlock())
15175232c5c5SChia-hung Duan     return emitOpError("`hasOneBlock` trait hasn't been verified");
15185232c5c5SChia-hung Duan 
15195232c5c5SChia-hung Duan   Operation *definingOp = getInput().getDefiningOp();
15205232c5c5SChia-hung Duan   if (definingOp && failed(mlir::verify(definingOp)))
15215232c5c5SChia-hung Duan     return emitOpError("operand hasn't been verified");
15225232c5c5SChia-hung Duan 
15235232c5c5SChia-hung Duan   emitRemark("success run of verifier");
15245232c5c5SChia-hung Duan 
15255232c5c5SChia-hung Duan   return success();
15265232c5c5SChia-hung Duan }
15275232c5c5SChia-hung Duan 
verifyRegions()15285232c5c5SChia-hung Duan LogicalResult TestVerifiersOp::verifyRegions() {
15295232c5c5SChia-hung Duan   if (!getRegion().hasOneBlock())
15305232c5c5SChia-hung Duan     return emitOpError("`hasOneBlock` trait hasn't been verified");
15315232c5c5SChia-hung Duan 
15325232c5c5SChia-hung Duan   for (Block &block : getRegion())
15335232c5c5SChia-hung Duan     for (Operation &op : block)
15345232c5c5SChia-hung Duan       if (failed(mlir::verify(&op)))
15355232c5c5SChia-hung Duan         return emitOpError("nested op hasn't been verified");
15365232c5c5SChia-hung Duan 
15375232c5c5SChia-hung Duan   emitRemark("success run of region verifier");
15385232c5c5SChia-hung Duan 
15395232c5c5SChia-hung Duan   return success();
15405232c5c5SChia-hung Duan }
15415232c5c5SChia-hung Duan 
154295aff23eSKrzysztof Drewniak //===----------------------------------------------------------------------===//
154395aff23eSKrzysztof Drewniak // Test InferIntRangeInterface
154495aff23eSKrzysztof Drewniak //===----------------------------------------------------------------------===//
154595aff23eSKrzysztof Drewniak 
inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,SetIntRangeFn setResultRanges)154695aff23eSKrzysztof Drewniak void TestWithBoundsOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
154795aff23eSKrzysztof Drewniak                                          SetIntRangeFn setResultRanges) {
154895aff23eSKrzysztof Drewniak   setResultRanges(getResult(), {getUmin(), getUmax(), getSmin(), getSmax()});
154995aff23eSKrzysztof Drewniak }
155095aff23eSKrzysztof Drewniak 
parse(OpAsmParser & parser,OperationState & result)155195aff23eSKrzysztof Drewniak ParseResult TestWithBoundsRegionOp::parse(OpAsmParser &parser,
155295aff23eSKrzysztof Drewniak                                           OperationState &result) {
155395aff23eSKrzysztof Drewniak   if (parser.parseOptionalAttrDict(result.attributes))
155495aff23eSKrzysztof Drewniak     return failure();
155595aff23eSKrzysztof Drewniak 
155695aff23eSKrzysztof Drewniak   // Parse the input argument
155795aff23eSKrzysztof Drewniak   OpAsmParser::Argument argInfo;
155895aff23eSKrzysztof Drewniak   argInfo.type = parser.getBuilder().getIndexType();
155995aff23eSKrzysztof Drewniak   if (failed(parser.parseArgument(argInfo)))
156095aff23eSKrzysztof Drewniak     return failure();
156195aff23eSKrzysztof Drewniak 
156295aff23eSKrzysztof Drewniak   // Parse the body region, and reuse the operand info as the argument info.
156395aff23eSKrzysztof Drewniak   Region *body = result.addRegion();
156495aff23eSKrzysztof Drewniak   return parser.parseRegion(*body, argInfo, /*enableNameShadowing=*/false);
156595aff23eSKrzysztof Drewniak }
156695aff23eSKrzysztof Drewniak 
print(OpAsmPrinter & p)156795aff23eSKrzysztof Drewniak void TestWithBoundsRegionOp::print(OpAsmPrinter &p) {
156895aff23eSKrzysztof Drewniak   p.printOptionalAttrDict((*this)->getAttrs());
156995aff23eSKrzysztof Drewniak   p << ' ';
157095aff23eSKrzysztof Drewniak   p.printRegionArgument(getRegion().getArgument(0), /*argAttrs=*/{},
157195aff23eSKrzysztof Drewniak                         /*omitType=*/true);
157295aff23eSKrzysztof Drewniak   p << ' ';
157395aff23eSKrzysztof Drewniak   p.printRegion(getRegion(), /*printEntryBlockArgs=*/false);
157495aff23eSKrzysztof Drewniak }
157595aff23eSKrzysztof Drewniak 
inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,SetIntRangeFn setResultRanges)157695aff23eSKrzysztof Drewniak void TestWithBoundsRegionOp::inferResultRanges(
157795aff23eSKrzysztof Drewniak     ArrayRef<ConstantIntRanges> argRanges, SetIntRangeFn setResultRanges) {
157895aff23eSKrzysztof Drewniak   Value arg = getRegion().getArgument(0);
157995aff23eSKrzysztof Drewniak   setResultRanges(arg, {getUmin(), getUmax(), getSmin(), getSmax()});
158095aff23eSKrzysztof Drewniak }
158195aff23eSKrzysztof Drewniak 
inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,SetIntRangeFn setResultRanges)158295aff23eSKrzysztof Drewniak void TestIncrementOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
158395aff23eSKrzysztof Drewniak                                         SetIntRangeFn setResultRanges) {
158495aff23eSKrzysztof Drewniak   const ConstantIntRanges &range = argRanges[0];
158595aff23eSKrzysztof Drewniak   APInt one(range.umin().getBitWidth(), 1);
158695aff23eSKrzysztof Drewniak   setResultRanges(getResult(),
158795aff23eSKrzysztof Drewniak                   {range.umin().uadd_sat(one), range.umax().uadd_sat(one),
158895aff23eSKrzysztof Drewniak                    range.smin().sadd_sat(one), range.smax().sadd_sat(one)});
158995aff23eSKrzysztof Drewniak }
159095aff23eSKrzysztof Drewniak 
inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,SetIntRangeFn setResultRanges)159195aff23eSKrzysztof Drewniak void TestReflectBoundsOp::inferResultRanges(
159295aff23eSKrzysztof Drewniak     ArrayRef<ConstantIntRanges> argRanges, SetIntRangeFn setResultRanges) {
159395aff23eSKrzysztof Drewniak   const ConstantIntRanges &range = argRanges[0];
159495aff23eSKrzysztof Drewniak   MLIRContext *ctx = getContext();
159595aff23eSKrzysztof Drewniak   Builder b(ctx);
159695aff23eSKrzysztof Drewniak   setUminAttr(b.getIndexAttr(range.umin().getZExtValue()));
159795aff23eSKrzysztof Drewniak   setUmaxAttr(b.getIndexAttr(range.umax().getZExtValue()));
159895aff23eSKrzysztof Drewniak   setSminAttr(b.getIndexAttr(range.smin().getSExtValue()));
159995aff23eSKrzysztof Drewniak   setSmaxAttr(b.getIndexAttr(range.smax().getSExtValue()));
160095aff23eSKrzysztof Drewniak   setResultRanges(getResult(), range);
160195aff23eSKrzysztof Drewniak }
160295aff23eSKrzysztof Drewniak 
1603fec6c5acSUday Bondhugula #include "TestOpEnums.cpp.inc"
1604052d24afSAlex Zinenko #include "TestOpInterfaces.cpp.inc"
16052e2cdd0aSRiver Riddle #include "TestTypeInterfaces.cpp.inc"
1606fec6c5acSUday Bondhugula 
1607fec6c5acSUday Bondhugula #define GET_OP_CLASSES
1608fec6c5acSUday Bondhugula #include "TestOps.cpp.inc"
1609