//===- VPlanPatternMatch.h - Match on VPValues and recipes ------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file provides a simple and efficient mechanism for performing general // tree-based pattern matches on the VPlan values and recipes, based on // LLVM's IR pattern matchers. // // Currently it provides generic matchers for unary and binary VPInstructions, // and specialized matchers like m_Not, m_ActiveLaneMask, m_BranchOnCond, // m_BranchOnCount to match specific VPInstructions. // TODO: Add missing matchers for additional opcodes and recipes as needed. // //===----------------------------------------------------------------------===// #ifndef LLVM_TRANSFORM_VECTORIZE_VPLANPATTERNMATCH_H #define LLVM_TRANSFORM_VECTORIZE_VPLANPATTERNMATCH_H #include "VPlan.h" namespace llvm { namespace VPlanPatternMatch { template bool match(Val *V, const Pattern &P) { return const_cast(P).match(V); } template struct class_match { template bool match(ITy *V) { return isa(V); } }; /// Match an arbitrary VPValue and ignore it. inline class_match m_VPValue() { return class_match(); } template struct bind_ty { Class *&VR; bind_ty(Class *&V) : VR(V) {} template bool match(ITy *V) { if (auto *CV = dyn_cast(V)) { VR = CV; return true; } return false; } }; /// Match a VPValue, capturing it if we match. inline bind_ty m_VPValue(VPValue *&V) { return V; } template struct UnaryVPInstruction_match { Op0_t Op0; UnaryVPInstruction_match(Op0_t Op0) : Op0(Op0) {} bool match(const VPValue *V) { auto *DefR = V->getDefiningRecipe(); return DefR && match(DefR); } bool match(const VPRecipeBase *R) { auto *DefR = dyn_cast(R); if (!DefR || DefR->getOpcode() != Opcode) return false; assert(DefR->getNumOperands() == 1 && "recipe with matched opcode does not have 1 operands"); return Op0.match(DefR->getOperand(0)); } }; template struct BinaryVPInstruction_match { Op0_t Op0; Op1_t Op1; BinaryVPInstruction_match(Op0_t Op0, Op1_t Op1) : Op0(Op0), Op1(Op1) {} bool match(const VPValue *V) { auto *DefR = V->getDefiningRecipe(); return DefR && match(DefR); } bool match(const VPRecipeBase *R) { auto *DefR = dyn_cast(R); if (!DefR || DefR->getOpcode() != Opcode) return false; assert(DefR->getNumOperands() == 2 && "recipe with matched opcode does not have 2 operands"); return Op0.match(DefR->getOperand(0)) && Op1.match(DefR->getOperand(1)); } }; template inline UnaryVPInstruction_match m_VPInstruction(const Op0_t &Op0) { return UnaryVPInstruction_match(Op0); } template inline BinaryVPInstruction_match m_VPInstruction(const Op0_t &Op0, const Op1_t &Op1) { return BinaryVPInstruction_match(Op0, Op1); } template inline UnaryVPInstruction_match m_Not(const Op0_t &Op0) { return m_VPInstruction(Op0); } template inline UnaryVPInstruction_match m_BranchOnCond(const Op0_t &Op0) { return m_VPInstruction(Op0); } template inline BinaryVPInstruction_match m_ActiveLaneMask(const Op0_t &Op0, const Op1_t &Op1) { return m_VPInstruction(Op0, Op1); } template inline BinaryVPInstruction_match m_BranchOnCount(const Op0_t &Op0, const Op1_t &Op1) { return m_VPInstruction(Op0, Op1); } } // namespace VPlanPatternMatch } // namespace llvm #endif