1ade58a26SNicolas Vasilache //===- TestMatchers.cpp - Pass to test matchers ---------------------------===//
2ade58a26SNicolas Vasilache //
330857107SMehdi Amini // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
456222a06SMehdi Amini // See https://llvm.org/LICENSE.txt for license information.
556222a06SMehdi Amini // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ade58a26SNicolas Vasilache //
756222a06SMehdi Amini //===----------------------------------------------------------------------===//
8ade58a26SNicolas Vasilache 
969d757c0SRob Suderman #include "mlir/Dialect/StandardOps/IR/Ops.h"
1065fcddffSRiver Riddle #include "mlir/IR/BuiltinOps.h"
11ade58a26SNicolas Vasilache #include "mlir/IR/Matchers.h"
12ade58a26SNicolas Vasilache #include "mlir/Pass/Pass.h"
13ade58a26SNicolas Vasilache 
14ade58a26SNicolas Vasilache using namespace mlir;
15ade58a26SNicolas Vasilache 
16ade58a26SNicolas Vasilache namespace {
17ade58a26SNicolas Vasilache /// This is a test pass for verifying matchers.
1880aca1eaSRiver Riddle struct TestMatchers : public PassWrapper<TestMatchers, FunctionPass> {
197b19bd54SNicolas Vasilache   void runOnFunction() override;
20b5e22e6dSMehdi Amini   StringRef getArgument() const final { return "test-matchers"; }
21b5e22e6dSMehdi Amini   StringRef getDescription() const final {
22b5e22e6dSMehdi Amini     return "Test C++ pattern matchers.";
23b5e22e6dSMehdi Amini   }
24ade58a26SNicolas Vasilache };
25ade58a26SNicolas Vasilache } // end anonymous namespace
26ade58a26SNicolas Vasilache 
27ade58a26SNicolas Vasilache // This could be done better but is not worth the variadic template trouble.
28350dadaaSBenjamin Kramer template <typename Matcher>
29350dadaaSBenjamin Kramer static unsigned countMatches(FuncOp f, Matcher &matcher) {
30ade58a26SNicolas Vasilache   unsigned count = 0;
31ade58a26SNicolas Vasilache   f.walk([&count, &matcher](Operation *op) {
327b19bd54SNicolas Vasilache     if (matcher.match(op))
33ade58a26SNicolas Vasilache       ++count;
34ade58a26SNicolas Vasilache   });
35ade58a26SNicolas Vasilache   return count;
36ade58a26SNicolas Vasilache }
37ade58a26SNicolas Vasilache 
387b19bd54SNicolas Vasilache using mlir::matchers::m_Any;
397b19bd54SNicolas Vasilache using mlir::matchers::m_Val;
40ade58a26SNicolas Vasilache static void test1(FuncOp f) {
41ade58a26SNicolas Vasilache   assert(f.getNumArguments() == 3 && "matcher test funcs must have 3 args");
42ade58a26SNicolas Vasilache 
437b19bd54SNicolas Vasilache   auto a = m_Val(f.getArgument(0));
447b19bd54SNicolas Vasilache   auto b = m_Val(f.getArgument(1));
457b19bd54SNicolas Vasilache   auto c = m_Val(f.getArgument(2));
46ade58a26SNicolas Vasilache 
47*a54f4eaeSMogball   auto p0 = m_Op<arith::AddFOp>(); // using 0-arity matcher
48ade58a26SNicolas Vasilache   llvm::outs() << "Pattern add(*) matched " << countMatches(f, p0)
49ade58a26SNicolas Vasilache                << " times\n";
50ade58a26SNicolas Vasilache 
51*a54f4eaeSMogball   auto p1 = m_Op<arith::MulFOp>(); // using 0-arity matcher
52ade58a26SNicolas Vasilache   llvm::outs() << "Pattern mul(*) matched " << countMatches(f, p1)
53ade58a26SNicolas Vasilache                << " times\n";
54ade58a26SNicolas Vasilache 
55*a54f4eaeSMogball   auto p2 = m_Op<arith::AddFOp>(m_Op<arith::AddFOp>(), m_Any());
56ade58a26SNicolas Vasilache   llvm::outs() << "Pattern add(add(*), *) matched " << countMatches(f, p2)
57ade58a26SNicolas Vasilache                << " times\n";
58ade58a26SNicolas Vasilache 
59*a54f4eaeSMogball   auto p3 = m_Op<arith::AddFOp>(m_Any(), m_Op<arith::AddFOp>());
60ade58a26SNicolas Vasilache   llvm::outs() << "Pattern add(*, add(*)) matched " << countMatches(f, p3)
61ade58a26SNicolas Vasilache                << " times\n";
62ade58a26SNicolas Vasilache 
63*a54f4eaeSMogball   auto p4 = m_Op<arith::MulFOp>(m_Op<arith::AddFOp>(), m_Any());
64ade58a26SNicolas Vasilache   llvm::outs() << "Pattern mul(add(*), *) matched " << countMatches(f, p4)
65ade58a26SNicolas Vasilache                << " times\n";
66ade58a26SNicolas Vasilache 
67*a54f4eaeSMogball   auto p5 = m_Op<arith::MulFOp>(m_Any(), m_Op<arith::AddFOp>());
68ade58a26SNicolas Vasilache   llvm::outs() << "Pattern mul(*, add(*)) matched " << countMatches(f, p5)
69ade58a26SNicolas Vasilache                << " times\n";
70ade58a26SNicolas Vasilache 
71*a54f4eaeSMogball   auto p6 = m_Op<arith::MulFOp>(m_Op<arith::MulFOp>(), m_Any());
72ade58a26SNicolas Vasilache   llvm::outs() << "Pattern mul(mul(*), *) matched " << countMatches(f, p6)
73ade58a26SNicolas Vasilache                << " times\n";
74ade58a26SNicolas Vasilache 
75*a54f4eaeSMogball   auto p7 = m_Op<arith::MulFOp>(m_Op<arith::MulFOp>(), m_Op<arith::MulFOp>());
76ade58a26SNicolas Vasilache   llvm::outs() << "Pattern mul(mul(*), mul(*)) matched " << countMatches(f, p7)
77ade58a26SNicolas Vasilache                << " times\n";
78ade58a26SNicolas Vasilache 
79*a54f4eaeSMogball   auto mul_of_mulmul =
80*a54f4eaeSMogball       m_Op<arith::MulFOp>(m_Op<arith::MulFOp>(), m_Op<arith::MulFOp>());
81*a54f4eaeSMogball   auto p8 = m_Op<arith::MulFOp>(mul_of_mulmul, mul_of_mulmul);
82ade58a26SNicolas Vasilache   llvm::outs()
83ade58a26SNicolas Vasilache       << "Pattern mul(mul(mul(*), mul(*)), mul(mul(*), mul(*))) matched "
84ade58a26SNicolas Vasilache       << countMatches(f, p8) << " times\n";
85ade58a26SNicolas Vasilache 
86ade58a26SNicolas Vasilache   // clang-format off
87*a54f4eaeSMogball   auto mul_of_muladd = m_Op<arith::MulFOp>(m_Op<arith::MulFOp>(), m_Op<arith::AddFOp>());
88*a54f4eaeSMogball   auto mul_of_anyadd = m_Op<arith::MulFOp>(m_Any(), m_Op<arith::AddFOp>());
89*a54f4eaeSMogball   auto p9 = m_Op<arith::MulFOp>(m_Op<arith::MulFOp>(
90*a54f4eaeSMogball                      mul_of_muladd, m_Op<arith::MulFOp>()),
91*a54f4eaeSMogball                    m_Op<arith::MulFOp>(mul_of_anyadd, mul_of_anyadd));
92ade58a26SNicolas Vasilache   // clang-format on
93ade58a26SNicolas Vasilache   llvm::outs() << "Pattern mul(mul(mul(mul(*), add(*)), mul(*)), mul(mul(*, "
94ade58a26SNicolas Vasilache                   "add(*)), mul(*, add(*)))) matched "
95ade58a26SNicolas Vasilache                << countMatches(f, p9) << " times\n";
96ade58a26SNicolas Vasilache 
97*a54f4eaeSMogball   auto p10 = m_Op<arith::AddFOp>(a, b);
98ade58a26SNicolas Vasilache   llvm::outs() << "Pattern add(a, b) matched " << countMatches(f, p10)
99ade58a26SNicolas Vasilache                << " times\n";
100ade58a26SNicolas Vasilache 
101*a54f4eaeSMogball   auto p11 = m_Op<arith::AddFOp>(a, c);
102ade58a26SNicolas Vasilache   llvm::outs() << "Pattern add(a, c) matched " << countMatches(f, p11)
103ade58a26SNicolas Vasilache                << " times\n";
104ade58a26SNicolas Vasilache 
105*a54f4eaeSMogball   auto p12 = m_Op<arith::AddFOp>(b, a);
106ade58a26SNicolas Vasilache   llvm::outs() << "Pattern add(b, a) matched " << countMatches(f, p12)
107ade58a26SNicolas Vasilache                << " times\n";
108ade58a26SNicolas Vasilache 
109*a54f4eaeSMogball   auto p13 = m_Op<arith::AddFOp>(c, a);
110ade58a26SNicolas Vasilache   llvm::outs() << "Pattern add(c, a) matched " << countMatches(f, p13)
111ade58a26SNicolas Vasilache                << " times\n";
112ade58a26SNicolas Vasilache 
113*a54f4eaeSMogball   auto p14 = m_Op<arith::MulFOp>(a, m_Op<arith::AddFOp>(c, b));
114ade58a26SNicolas Vasilache   llvm::outs() << "Pattern mul(a, add(c, b)) matched " << countMatches(f, p14)
115ade58a26SNicolas Vasilache                << " times\n";
116ade58a26SNicolas Vasilache 
117*a54f4eaeSMogball   auto p15 = m_Op<arith::MulFOp>(a, m_Op<arith::AddFOp>(b, c));
118ade58a26SNicolas Vasilache   llvm::outs() << "Pattern mul(a, add(b, c)) matched " << countMatches(f, p15)
119ade58a26SNicolas Vasilache                << " times\n";
120ade58a26SNicolas Vasilache 
121*a54f4eaeSMogball   auto mul_of_aany = m_Op<arith::MulFOp>(a, m_Any());
122*a54f4eaeSMogball   auto p16 = m_Op<arith::MulFOp>(mul_of_aany, m_Op<arith::AddFOp>(a, c));
123ade58a26SNicolas Vasilache   llvm::outs() << "Pattern mul(mul(a, *), add(a, c)) matched "
124ade58a26SNicolas Vasilache                << countMatches(f, p16) << " times\n";
125ade58a26SNicolas Vasilache 
126*a54f4eaeSMogball   auto p17 = m_Op<arith::MulFOp>(mul_of_aany, m_Op<arith::AddFOp>(c, b));
127ade58a26SNicolas Vasilache   llvm::outs() << "Pattern mul(mul(a, *), add(c, b)) matched "
128ade58a26SNicolas Vasilache                << countMatches(f, p17) << " times\n";
129ade58a26SNicolas Vasilache }
130ade58a26SNicolas Vasilache 
1317b19bd54SNicolas Vasilache void test2(FuncOp f) {
1327b19bd54SNicolas Vasilache   auto a = m_Val(f.getArgument(0));
1337b19bd54SNicolas Vasilache   FloatAttr floatAttr;
134*a54f4eaeSMogball   auto p =
135*a54f4eaeSMogball       m_Op<arith::MulFOp>(a, m_Op<arith::AddFOp>(a, m_Constant(&floatAttr)));
136*a54f4eaeSMogball   auto p1 = m_Op<arith::MulFOp>(a, m_Op<arith::AddFOp>(a, m_Constant()));
1377b19bd54SNicolas Vasilache   // Last operation that is not the terminator.
1387b19bd54SNicolas Vasilache   Operation *lastOp = f.getBody().front().back().getPrevNode();
1397b19bd54SNicolas Vasilache   if (p.match(lastOp))
1407b19bd54SNicolas Vasilache     llvm::outs()
1417b19bd54SNicolas Vasilache         << "Pattern add(add(a, constant), a) matched and bound constant to: "
1427b19bd54SNicolas Vasilache         << floatAttr.getValueAsDouble() << "\n";
14381e7922eSLorenzo Chelini   if (p1.match(lastOp))
14481e7922eSLorenzo Chelini     llvm::outs() << "Pattern add(add(a, constant), a) matched\n";
1457b19bd54SNicolas Vasilache }
1467b19bd54SNicolas Vasilache 
1477b19bd54SNicolas Vasilache void TestMatchers::runOnFunction() {
1487b19bd54SNicolas Vasilache   auto f = getFunction();
1497b19bd54SNicolas Vasilache   llvm::outs() << f.getName() << "\n";
150ade58a26SNicolas Vasilache   if (f.getName() == "test1")
151ade58a26SNicolas Vasilache     test1(f);
1527b19bd54SNicolas Vasilache   if (f.getName() == "test2")
1537b19bd54SNicolas Vasilache     test2(f);
154ade58a26SNicolas Vasilache }
155ade58a26SNicolas Vasilache 
156c6477050SMehdi Amini namespace mlir {
157b5e22e6dSMehdi Amini void registerTestMatchers() { PassRegistration<TestMatchers>(); }
158c6477050SMehdi Amini } // namespace mlir
159