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"
10*65fcddffSRiver 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;
20ade58a26SNicolas Vasilache };
21ade58a26SNicolas Vasilache } // end anonymous namespace
22ade58a26SNicolas Vasilache 
23ade58a26SNicolas Vasilache // This could be done better but is not worth the variadic template trouble.
24350dadaaSBenjamin Kramer template <typename Matcher>
25350dadaaSBenjamin Kramer static unsigned countMatches(FuncOp f, Matcher &matcher) {
26ade58a26SNicolas Vasilache   unsigned count = 0;
27ade58a26SNicolas Vasilache   f.walk([&count, &matcher](Operation *op) {
287b19bd54SNicolas Vasilache     if (matcher.match(op))
29ade58a26SNicolas Vasilache       ++count;
30ade58a26SNicolas Vasilache   });
31ade58a26SNicolas Vasilache   return count;
32ade58a26SNicolas Vasilache }
33ade58a26SNicolas Vasilache 
347b19bd54SNicolas Vasilache using mlir::matchers::m_Any;
357b19bd54SNicolas Vasilache using mlir::matchers::m_Val;
36ade58a26SNicolas Vasilache static void test1(FuncOp f) {
37ade58a26SNicolas Vasilache   assert(f.getNumArguments() == 3 && "matcher test funcs must have 3 args");
38ade58a26SNicolas Vasilache 
397b19bd54SNicolas Vasilache   auto a = m_Val(f.getArgument(0));
407b19bd54SNicolas Vasilache   auto b = m_Val(f.getArgument(1));
417b19bd54SNicolas Vasilache   auto c = m_Val(f.getArgument(2));
42ade58a26SNicolas Vasilache 
43ade58a26SNicolas Vasilache   auto p0 = m_Op<AddFOp>(); // using 0-arity matcher
44ade58a26SNicolas Vasilache   llvm::outs() << "Pattern add(*) matched " << countMatches(f, p0)
45ade58a26SNicolas Vasilache                << " times\n";
46ade58a26SNicolas Vasilache 
47ade58a26SNicolas Vasilache   auto p1 = m_Op<MulFOp>(); // using 0-arity matcher
48ade58a26SNicolas Vasilache   llvm::outs() << "Pattern mul(*) matched " << countMatches(f, p1)
49ade58a26SNicolas Vasilache                << " times\n";
50ade58a26SNicolas Vasilache 
517b19bd54SNicolas Vasilache   auto p2 = m_Op<AddFOp>(m_Op<AddFOp>(), m_Any());
52ade58a26SNicolas Vasilache   llvm::outs() << "Pattern add(add(*), *) matched " << countMatches(f, p2)
53ade58a26SNicolas Vasilache                << " times\n";
54ade58a26SNicolas Vasilache 
557b19bd54SNicolas Vasilache   auto p3 = m_Op<AddFOp>(m_Any(), m_Op<AddFOp>());
56ade58a26SNicolas Vasilache   llvm::outs() << "Pattern add(*, add(*)) matched " << countMatches(f, p3)
57ade58a26SNicolas Vasilache                << " times\n";
58ade58a26SNicolas Vasilache 
597b19bd54SNicolas Vasilache   auto p4 = m_Op<MulFOp>(m_Op<AddFOp>(), m_Any());
60ade58a26SNicolas Vasilache   llvm::outs() << "Pattern mul(add(*), *) matched " << countMatches(f, p4)
61ade58a26SNicolas Vasilache                << " times\n";
62ade58a26SNicolas Vasilache 
637b19bd54SNicolas Vasilache   auto p5 = m_Op<MulFOp>(m_Any(), m_Op<AddFOp>());
64ade58a26SNicolas Vasilache   llvm::outs() << "Pattern mul(*, add(*)) matched " << countMatches(f, p5)
65ade58a26SNicolas Vasilache                << " times\n";
66ade58a26SNicolas Vasilache 
677b19bd54SNicolas Vasilache   auto p6 = m_Op<MulFOp>(m_Op<MulFOp>(), m_Any());
68ade58a26SNicolas Vasilache   llvm::outs() << "Pattern mul(mul(*), *) matched " << countMatches(f, p6)
69ade58a26SNicolas Vasilache                << " times\n";
70ade58a26SNicolas Vasilache 
71ade58a26SNicolas Vasilache   auto p7 = m_Op<MulFOp>(m_Op<MulFOp>(), m_Op<MulFOp>());
72ade58a26SNicolas Vasilache   llvm::outs() << "Pattern mul(mul(*), mul(*)) matched " << countMatches(f, p7)
73ade58a26SNicolas Vasilache                << " times\n";
74ade58a26SNicolas Vasilache 
75ade58a26SNicolas Vasilache   auto mul_of_mulmul = m_Op<MulFOp>(m_Op<MulFOp>(), m_Op<MulFOp>());
76ade58a26SNicolas Vasilache   auto p8 = m_Op<MulFOp>(mul_of_mulmul, mul_of_mulmul);
77ade58a26SNicolas Vasilache   llvm::outs()
78ade58a26SNicolas Vasilache       << "Pattern mul(mul(mul(*), mul(*)), mul(mul(*), mul(*))) matched "
79ade58a26SNicolas Vasilache       << countMatches(f, p8) << " times\n";
80ade58a26SNicolas Vasilache 
81ade58a26SNicolas Vasilache   // clang-format off
82ade58a26SNicolas Vasilache   auto mul_of_muladd = m_Op<MulFOp>(m_Op<MulFOp>(), m_Op<AddFOp>());
837b19bd54SNicolas Vasilache   auto mul_of_anyadd = m_Op<MulFOp>(m_Any(), m_Op<AddFOp>());
84ade58a26SNicolas Vasilache   auto p9 = m_Op<MulFOp>(m_Op<MulFOp>(
85ade58a26SNicolas Vasilache                      mul_of_muladd, m_Op<MulFOp>()),
86ade58a26SNicolas Vasilache                    m_Op<MulFOp>(mul_of_anyadd, mul_of_anyadd));
87ade58a26SNicolas Vasilache   // clang-format on
88ade58a26SNicolas Vasilache   llvm::outs() << "Pattern mul(mul(mul(mul(*), add(*)), mul(*)), mul(mul(*, "
89ade58a26SNicolas Vasilache                   "add(*)), mul(*, add(*)))) matched "
90ade58a26SNicolas Vasilache                << countMatches(f, p9) << " times\n";
91ade58a26SNicolas Vasilache 
92ade58a26SNicolas Vasilache   auto p10 = m_Op<AddFOp>(a, b);
93ade58a26SNicolas Vasilache   llvm::outs() << "Pattern add(a, b) matched " << countMatches(f, p10)
94ade58a26SNicolas Vasilache                << " times\n";
95ade58a26SNicolas Vasilache 
96ade58a26SNicolas Vasilache   auto p11 = m_Op<AddFOp>(a, c);
97ade58a26SNicolas Vasilache   llvm::outs() << "Pattern add(a, c) matched " << countMatches(f, p11)
98ade58a26SNicolas Vasilache                << " times\n";
99ade58a26SNicolas Vasilache 
100ade58a26SNicolas Vasilache   auto p12 = m_Op<AddFOp>(b, a);
101ade58a26SNicolas Vasilache   llvm::outs() << "Pattern add(b, a) matched " << countMatches(f, p12)
102ade58a26SNicolas Vasilache                << " times\n";
103ade58a26SNicolas Vasilache 
104ade58a26SNicolas Vasilache   auto p13 = m_Op<AddFOp>(c, a);
105ade58a26SNicolas Vasilache   llvm::outs() << "Pattern add(c, a) matched " << countMatches(f, p13)
106ade58a26SNicolas Vasilache                << " times\n";
107ade58a26SNicolas Vasilache 
108ade58a26SNicolas Vasilache   auto p14 = m_Op<MulFOp>(a, m_Op<AddFOp>(c, b));
109ade58a26SNicolas Vasilache   llvm::outs() << "Pattern mul(a, add(c, b)) matched " << countMatches(f, p14)
110ade58a26SNicolas Vasilache                << " times\n";
111ade58a26SNicolas Vasilache 
112ade58a26SNicolas Vasilache   auto p15 = m_Op<MulFOp>(a, m_Op<AddFOp>(b, c));
113ade58a26SNicolas Vasilache   llvm::outs() << "Pattern mul(a, add(b, c)) matched " << countMatches(f, p15)
114ade58a26SNicolas Vasilache                << " times\n";
115ade58a26SNicolas Vasilache 
1167b19bd54SNicolas Vasilache   auto mul_of_aany = m_Op<MulFOp>(a, m_Any());
117ade58a26SNicolas Vasilache   auto p16 = m_Op<MulFOp>(mul_of_aany, m_Op<AddFOp>(a, c));
118ade58a26SNicolas Vasilache   llvm::outs() << "Pattern mul(mul(a, *), add(a, c)) matched "
119ade58a26SNicolas Vasilache                << countMatches(f, p16) << " times\n";
120ade58a26SNicolas Vasilache 
121ade58a26SNicolas Vasilache   auto p17 = m_Op<MulFOp>(mul_of_aany, m_Op<AddFOp>(c, b));
122ade58a26SNicolas Vasilache   llvm::outs() << "Pattern mul(mul(a, *), add(c, b)) matched "
123ade58a26SNicolas Vasilache                << countMatches(f, p17) << " times\n";
124ade58a26SNicolas Vasilache }
125ade58a26SNicolas Vasilache 
1267b19bd54SNicolas Vasilache void test2(FuncOp f) {
1277b19bd54SNicolas Vasilache   auto a = m_Val(f.getArgument(0));
1287b19bd54SNicolas Vasilache   FloatAttr floatAttr;
1297b19bd54SNicolas Vasilache   auto p = m_Op<MulFOp>(a, m_Op<AddFOp>(a, m_Constant(&floatAttr)));
13081e7922eSLorenzo Chelini   auto p1 = m_Op<MulFOp>(a, m_Op<AddFOp>(a, m_Constant()));
1317b19bd54SNicolas Vasilache   // Last operation that is not the terminator.
1327b19bd54SNicolas Vasilache   Operation *lastOp = f.getBody().front().back().getPrevNode();
1337b19bd54SNicolas Vasilache   if (p.match(lastOp))
1347b19bd54SNicolas Vasilache     llvm::outs()
1357b19bd54SNicolas Vasilache         << "Pattern add(add(a, constant), a) matched and bound constant to: "
1367b19bd54SNicolas Vasilache         << floatAttr.getValueAsDouble() << "\n";
13781e7922eSLorenzo Chelini   if (p1.match(lastOp))
13881e7922eSLorenzo Chelini     llvm::outs() << "Pattern add(add(a, constant), a) matched\n";
1397b19bd54SNicolas Vasilache }
1407b19bd54SNicolas Vasilache 
1417b19bd54SNicolas Vasilache void TestMatchers::runOnFunction() {
1427b19bd54SNicolas Vasilache   auto f = getFunction();
1437b19bd54SNicolas Vasilache   llvm::outs() << f.getName() << "\n";
144ade58a26SNicolas Vasilache   if (f.getName() == "test1")
145ade58a26SNicolas Vasilache     test1(f);
1467b19bd54SNicolas Vasilache   if (f.getName() == "test2")
1477b19bd54SNicolas Vasilache     test2(f);
148ade58a26SNicolas Vasilache }
149ade58a26SNicolas Vasilache 
150c6477050SMehdi Amini namespace mlir {
151c6477050SMehdi Amini void registerTestMatchers() {
152c6477050SMehdi Amini   PassRegistration<TestMatchers>("test-matchers", "Test C++ pattern matchers.");
153c6477050SMehdi Amini }
154c6477050SMehdi Amini } // namespace mlir
155