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"
10ade58a26SNicolas Vasilache #include "mlir/IR/Function.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.
18*80aca1eaSRiver 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.
24ade58a26SNicolas Vasilache template <typename Matcher> unsigned countMatches(FuncOp f, Matcher &matcher) {
25ade58a26SNicolas Vasilache   unsigned count = 0;
26ade58a26SNicolas Vasilache   f.walk([&count, &matcher](Operation *op) {
277b19bd54SNicolas Vasilache     if (matcher.match(op))
28ade58a26SNicolas Vasilache       ++count;
29ade58a26SNicolas Vasilache   });
30ade58a26SNicolas Vasilache   return count;
31ade58a26SNicolas Vasilache }
32ade58a26SNicolas Vasilache 
337b19bd54SNicolas Vasilache using mlir::matchers::m_Any;
347b19bd54SNicolas Vasilache using mlir::matchers::m_Val;
35ade58a26SNicolas Vasilache static void test1(FuncOp f) {
36ade58a26SNicolas Vasilache   assert(f.getNumArguments() == 3 && "matcher test funcs must have 3 args");
37ade58a26SNicolas Vasilache 
387b19bd54SNicolas Vasilache   auto a = m_Val(f.getArgument(0));
397b19bd54SNicolas Vasilache   auto b = m_Val(f.getArgument(1));
407b19bd54SNicolas Vasilache   auto c = m_Val(f.getArgument(2));
41ade58a26SNicolas Vasilache 
42ade58a26SNicolas Vasilache   auto p0 = m_Op<AddFOp>(); // using 0-arity matcher
43ade58a26SNicolas Vasilache   llvm::outs() << "Pattern add(*) matched " << countMatches(f, p0)
44ade58a26SNicolas Vasilache                << " times\n";
45ade58a26SNicolas Vasilache 
46ade58a26SNicolas Vasilache   auto p1 = m_Op<MulFOp>(); // using 0-arity matcher
47ade58a26SNicolas Vasilache   llvm::outs() << "Pattern mul(*) matched " << countMatches(f, p1)
48ade58a26SNicolas Vasilache                << " times\n";
49ade58a26SNicolas Vasilache 
507b19bd54SNicolas Vasilache   auto p2 = m_Op<AddFOp>(m_Op<AddFOp>(), m_Any());
51ade58a26SNicolas Vasilache   llvm::outs() << "Pattern add(add(*), *) matched " << countMatches(f, p2)
52ade58a26SNicolas Vasilache                << " times\n";
53ade58a26SNicolas Vasilache 
547b19bd54SNicolas Vasilache   auto p3 = m_Op<AddFOp>(m_Any(), m_Op<AddFOp>());
55ade58a26SNicolas Vasilache   llvm::outs() << "Pattern add(*, add(*)) matched " << countMatches(f, p3)
56ade58a26SNicolas Vasilache                << " times\n";
57ade58a26SNicolas Vasilache 
587b19bd54SNicolas Vasilache   auto p4 = m_Op<MulFOp>(m_Op<AddFOp>(), m_Any());
59ade58a26SNicolas Vasilache   llvm::outs() << "Pattern mul(add(*), *) matched " << countMatches(f, p4)
60ade58a26SNicolas Vasilache                << " times\n";
61ade58a26SNicolas Vasilache 
627b19bd54SNicolas Vasilache   auto p5 = m_Op<MulFOp>(m_Any(), m_Op<AddFOp>());
63ade58a26SNicolas Vasilache   llvm::outs() << "Pattern mul(*, add(*)) matched " << countMatches(f, p5)
64ade58a26SNicolas Vasilache                << " times\n";
65ade58a26SNicolas Vasilache 
667b19bd54SNicolas Vasilache   auto p6 = m_Op<MulFOp>(m_Op<MulFOp>(), m_Any());
67ade58a26SNicolas Vasilache   llvm::outs() << "Pattern mul(mul(*), *) matched " << countMatches(f, p6)
68ade58a26SNicolas Vasilache                << " times\n";
69ade58a26SNicolas Vasilache 
70ade58a26SNicolas Vasilache   auto p7 = m_Op<MulFOp>(m_Op<MulFOp>(), m_Op<MulFOp>());
71ade58a26SNicolas Vasilache   llvm::outs() << "Pattern mul(mul(*), mul(*)) matched " << countMatches(f, p7)
72ade58a26SNicolas Vasilache                << " times\n";
73ade58a26SNicolas Vasilache 
74ade58a26SNicolas Vasilache   auto mul_of_mulmul = m_Op<MulFOp>(m_Op<MulFOp>(), m_Op<MulFOp>());
75ade58a26SNicolas Vasilache   auto p8 = m_Op<MulFOp>(mul_of_mulmul, mul_of_mulmul);
76ade58a26SNicolas Vasilache   llvm::outs()
77ade58a26SNicolas Vasilache       << "Pattern mul(mul(mul(*), mul(*)), mul(mul(*), mul(*))) matched "
78ade58a26SNicolas Vasilache       << countMatches(f, p8) << " times\n";
79ade58a26SNicolas Vasilache 
80ade58a26SNicolas Vasilache   // clang-format off
81ade58a26SNicolas Vasilache   auto mul_of_muladd = m_Op<MulFOp>(m_Op<MulFOp>(), m_Op<AddFOp>());
827b19bd54SNicolas Vasilache   auto mul_of_anyadd = m_Op<MulFOp>(m_Any(), m_Op<AddFOp>());
83ade58a26SNicolas Vasilache   auto p9 = m_Op<MulFOp>(m_Op<MulFOp>(
84ade58a26SNicolas Vasilache                      mul_of_muladd, m_Op<MulFOp>()),
85ade58a26SNicolas Vasilache                    m_Op<MulFOp>(mul_of_anyadd, mul_of_anyadd));
86ade58a26SNicolas Vasilache   // clang-format on
87ade58a26SNicolas Vasilache   llvm::outs() << "Pattern mul(mul(mul(mul(*), add(*)), mul(*)), mul(mul(*, "
88ade58a26SNicolas Vasilache                   "add(*)), mul(*, add(*)))) matched "
89ade58a26SNicolas Vasilache                << countMatches(f, p9) << " times\n";
90ade58a26SNicolas Vasilache 
91ade58a26SNicolas Vasilache   auto p10 = m_Op<AddFOp>(a, b);
92ade58a26SNicolas Vasilache   llvm::outs() << "Pattern add(a, b) matched " << countMatches(f, p10)
93ade58a26SNicolas Vasilache                << " times\n";
94ade58a26SNicolas Vasilache 
95ade58a26SNicolas Vasilache   auto p11 = m_Op<AddFOp>(a, c);
96ade58a26SNicolas Vasilache   llvm::outs() << "Pattern add(a, c) matched " << countMatches(f, p11)
97ade58a26SNicolas Vasilache                << " times\n";
98ade58a26SNicolas Vasilache 
99ade58a26SNicolas Vasilache   auto p12 = m_Op<AddFOp>(b, a);
100ade58a26SNicolas Vasilache   llvm::outs() << "Pattern add(b, a) matched " << countMatches(f, p12)
101ade58a26SNicolas Vasilache                << " times\n";
102ade58a26SNicolas Vasilache 
103ade58a26SNicolas Vasilache   auto p13 = m_Op<AddFOp>(c, a);
104ade58a26SNicolas Vasilache   llvm::outs() << "Pattern add(c, a) matched " << countMatches(f, p13)
105ade58a26SNicolas Vasilache                << " times\n";
106ade58a26SNicolas Vasilache 
107ade58a26SNicolas Vasilache   auto p14 = m_Op<MulFOp>(a, m_Op<AddFOp>(c, b));
108ade58a26SNicolas Vasilache   llvm::outs() << "Pattern mul(a, add(c, b)) matched " << countMatches(f, p14)
109ade58a26SNicolas Vasilache                << " times\n";
110ade58a26SNicolas Vasilache 
111ade58a26SNicolas Vasilache   auto p15 = m_Op<MulFOp>(a, m_Op<AddFOp>(b, c));
112ade58a26SNicolas Vasilache   llvm::outs() << "Pattern mul(a, add(b, c)) matched " << countMatches(f, p15)
113ade58a26SNicolas Vasilache                << " times\n";
114ade58a26SNicolas Vasilache 
1157b19bd54SNicolas Vasilache   auto mul_of_aany = m_Op<MulFOp>(a, m_Any());
116ade58a26SNicolas Vasilache   auto p16 = m_Op<MulFOp>(mul_of_aany, m_Op<AddFOp>(a, c));
117ade58a26SNicolas Vasilache   llvm::outs() << "Pattern mul(mul(a, *), add(a, c)) matched "
118ade58a26SNicolas Vasilache                << countMatches(f, p16) << " times\n";
119ade58a26SNicolas Vasilache 
120ade58a26SNicolas Vasilache   auto p17 = m_Op<MulFOp>(mul_of_aany, m_Op<AddFOp>(c, b));
121ade58a26SNicolas Vasilache   llvm::outs() << "Pattern mul(mul(a, *), add(c, b)) matched "
122ade58a26SNicolas Vasilache                << countMatches(f, p17) << " times\n";
123ade58a26SNicolas Vasilache }
124ade58a26SNicolas Vasilache 
1257b19bd54SNicolas Vasilache void test2(FuncOp f) {
1267b19bd54SNicolas Vasilache   auto a = m_Val(f.getArgument(0));
1277b19bd54SNicolas Vasilache   FloatAttr floatAttr;
1287b19bd54SNicolas Vasilache   auto p = m_Op<MulFOp>(a, m_Op<AddFOp>(a, m_Constant(&floatAttr)));
12981e7922eSLorenzo Chelini   auto p1 = m_Op<MulFOp>(a, m_Op<AddFOp>(a, m_Constant()));
1307b19bd54SNicolas Vasilache   // Last operation that is not the terminator.
1317b19bd54SNicolas Vasilache   Operation *lastOp = f.getBody().front().back().getPrevNode();
1327b19bd54SNicolas Vasilache   if (p.match(lastOp))
1337b19bd54SNicolas Vasilache     llvm::outs()
1347b19bd54SNicolas Vasilache         << "Pattern add(add(a, constant), a) matched and bound constant to: "
1357b19bd54SNicolas Vasilache         << floatAttr.getValueAsDouble() << "\n";
13681e7922eSLorenzo Chelini   if (p1.match(lastOp))
13781e7922eSLorenzo Chelini     llvm::outs() << "Pattern add(add(a, constant), a) matched\n";
1387b19bd54SNicolas Vasilache }
1397b19bd54SNicolas Vasilache 
1407b19bd54SNicolas Vasilache void TestMatchers::runOnFunction() {
1417b19bd54SNicolas Vasilache   auto f = getFunction();
1427b19bd54SNicolas Vasilache   llvm::outs() << f.getName() << "\n";
143ade58a26SNicolas Vasilache   if (f.getName() == "test1")
144ade58a26SNicolas Vasilache     test1(f);
1457b19bd54SNicolas Vasilache   if (f.getName() == "test2")
1467b19bd54SNicolas Vasilache     test2(f);
147ade58a26SNicolas Vasilache }
148ade58a26SNicolas Vasilache 
149c6477050SMehdi Amini namespace mlir {
150c6477050SMehdi Amini void registerTestMatchers() {
151c6477050SMehdi Amini   PassRegistration<TestMatchers>("test-matchers", "Test C++ pattern matchers.");
152c6477050SMehdi Amini }
153c6477050SMehdi Amini } // namespace mlir
154