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