1 //===- VPlanPatternMatch.h - Match on VPValues and recipes ------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file provides a simple and efficient mechanism for performing general 10 // tree-based pattern matches on the VPlan values and recipes, based on 11 // LLVM's IR pattern matchers. 12 // 13 // Currently it provides generic matchers for unary and binary VPInstructions, 14 // and specialized matchers like m_Not, m_ActiveLaneMask, m_BranchOnCond, 15 // m_BranchOnCount to match specific VPInstructions. 16 // TODO: Add missing matchers for additional opcodes and recipes as needed. 17 // 18 //===----------------------------------------------------------------------===// 19 20 #ifndef LLVM_TRANSFORM_VECTORIZE_VPLANPATTERNMATCH_H 21 #define LLVM_TRANSFORM_VECTORIZE_VPLANPATTERNMATCH_H 22 23 #include "VPlan.h" 24 25 namespace llvm { 26 namespace VPlanPatternMatch { 27 28 template <typename Val, typename Pattern> bool match(Val *V, const Pattern &P) { 29 return const_cast<Pattern &>(P).match(V); 30 } 31 32 template <typename Class> struct class_match { 33 template <typename ITy> bool match(ITy *V) { return isa<Class>(V); } 34 }; 35 36 /// Match an arbitrary VPValue and ignore it. 37 inline class_match<VPValue> m_VPValue() { return class_match<VPValue>(); } 38 39 template <typename Class> struct bind_ty { 40 Class *&VR; 41 42 bind_ty(Class *&V) : VR(V) {} 43 44 template <typename ITy> bool match(ITy *V) { 45 if (auto *CV = dyn_cast<Class>(V)) { 46 VR = CV; 47 return true; 48 } 49 return false; 50 } 51 }; 52 53 /// Match a VPValue, capturing it if we match. 54 inline bind_ty<VPValue> m_VPValue(VPValue *&V) { return V; } 55 56 template <typename Op0_t, unsigned Opcode> struct UnaryVPInstruction_match { 57 Op0_t Op0; 58 59 UnaryVPInstruction_match(Op0_t Op0) : Op0(Op0) {} 60 61 bool match(const VPValue *V) { 62 auto *DefR = V->getDefiningRecipe(); 63 return DefR && match(DefR); 64 } 65 66 bool match(const VPRecipeBase *R) { 67 auto *DefR = dyn_cast<VPInstruction>(R); 68 if (!DefR || DefR->getOpcode() != Opcode) 69 return false; 70 assert(DefR->getNumOperands() == 1 && 71 "recipe with matched opcode does not have 1 operands"); 72 return Op0.match(DefR->getOperand(0)); 73 } 74 }; 75 76 template <typename Op0_t, typename Op1_t, unsigned Opcode> 77 struct BinaryVPInstruction_match { 78 Op0_t Op0; 79 Op1_t Op1; 80 81 BinaryVPInstruction_match(Op0_t Op0, Op1_t Op1) : Op0(Op0), Op1(Op1) {} 82 83 bool match(const VPValue *V) { 84 auto *DefR = V->getDefiningRecipe(); 85 return DefR && match(DefR); 86 } 87 88 bool match(const VPRecipeBase *R) { 89 auto *DefR = dyn_cast<VPInstruction>(R); 90 if (!DefR || DefR->getOpcode() != Opcode) 91 return false; 92 assert(DefR->getNumOperands() == 2 && 93 "recipe with matched opcode does not have 2 operands"); 94 return Op0.match(DefR->getOperand(0)) && Op1.match(DefR->getOperand(1)); 95 } 96 }; 97 98 template <unsigned Opcode, typename Op0_t> 99 inline UnaryVPInstruction_match<Op0_t, Opcode> 100 m_VPInstruction(const Op0_t &Op0) { 101 return UnaryVPInstruction_match<Op0_t, Opcode>(Op0); 102 } 103 104 template <unsigned Opcode, typename Op0_t, typename Op1_t> 105 inline BinaryVPInstruction_match<Op0_t, Op1_t, Opcode> 106 m_VPInstruction(const Op0_t &Op0, const Op1_t &Op1) { 107 return BinaryVPInstruction_match<Op0_t, Op1_t, Opcode>(Op0, Op1); 108 } 109 110 template <typename Op0_t> 111 inline UnaryVPInstruction_match<Op0_t, VPInstruction::Not> 112 m_Not(const Op0_t &Op0) { 113 return m_VPInstruction<VPInstruction::Not>(Op0); 114 } 115 116 template <typename Op0_t> 117 inline UnaryVPInstruction_match<Op0_t, VPInstruction::BranchOnCond> 118 m_BranchOnCond(const Op0_t &Op0) { 119 return m_VPInstruction<VPInstruction::BranchOnCond>(Op0); 120 } 121 122 template <typename Op0_t, typename Op1_t> 123 inline BinaryVPInstruction_match<Op0_t, Op1_t, VPInstruction::ActiveLaneMask> 124 m_ActiveLaneMask(const Op0_t &Op0, const Op1_t &Op1) { 125 return m_VPInstruction<VPInstruction::ActiveLaneMask>(Op0, Op1); 126 } 127 128 template <typename Op0_t, typename Op1_t> 129 inline BinaryVPInstruction_match<Op0_t, Op1_t, VPInstruction::BranchOnCount> 130 m_BranchOnCount(const Op0_t &Op0, const Op1_t &Op1) { 131 return m_VPInstruction<VPInstruction::BranchOnCount>(Op0, Op1); 132 } 133 } // namespace VPlanPatternMatch 134 } // namespace llvm 135 136 #endif 137