12435dcd8SFlorian Hahn //===- VPlanPatternMatch.h - Match on VPValues and recipes ------*- C++ -*-===// 22435dcd8SFlorian Hahn // 32435dcd8SFlorian Hahn // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42435dcd8SFlorian Hahn // See https://llvm.org/LICENSE.txt for license information. 52435dcd8SFlorian Hahn // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 62435dcd8SFlorian Hahn // 72435dcd8SFlorian Hahn //===----------------------------------------------------------------------===// 82435dcd8SFlorian Hahn // 92435dcd8SFlorian Hahn // This file provides a simple and efficient mechanism for performing general 102435dcd8SFlorian Hahn // tree-based pattern matches on the VPlan values and recipes, based on 112435dcd8SFlorian Hahn // LLVM's IR pattern matchers. 122435dcd8SFlorian Hahn // 132435dcd8SFlorian Hahn // Currently it provides generic matchers for unary and binary VPInstructions, 142435dcd8SFlorian Hahn // and specialized matchers like m_Not, m_ActiveLaneMask, m_BranchOnCond, 152435dcd8SFlorian Hahn // m_BranchOnCount to match specific VPInstructions. 162435dcd8SFlorian Hahn // TODO: Add missing matchers for additional opcodes and recipes as needed. 172435dcd8SFlorian Hahn // 182435dcd8SFlorian Hahn //===----------------------------------------------------------------------===// 192435dcd8SFlorian Hahn 202435dcd8SFlorian Hahn #ifndef LLVM_TRANSFORM_VECTORIZE_VPLANPATTERNMATCH_H 212435dcd8SFlorian Hahn #define LLVM_TRANSFORM_VECTORIZE_VPLANPATTERNMATCH_H 222435dcd8SFlorian Hahn 232435dcd8SFlorian Hahn #include "VPlan.h" 242435dcd8SFlorian Hahn 252435dcd8SFlorian Hahn namespace llvm { 262435dcd8SFlorian Hahn namespace VPlanPatternMatch { 272435dcd8SFlorian Hahn 282435dcd8SFlorian Hahn template <typename Val, typename Pattern> bool match(Val *V, const Pattern &P) { 2928047750SRamkumar Ramachandra return P.match(V); 302435dcd8SFlorian Hahn } 312435dcd8SFlorian Hahn 3299741ac2SFlorian Hahn template <typename Pattern> bool match(VPUser *U, const Pattern &P) { 3399741ac2SFlorian Hahn auto *R = dyn_cast<VPRecipeBase>(U); 3499741ac2SFlorian Hahn return R && match(R, P); 3599741ac2SFlorian Hahn } 3699741ac2SFlorian Hahn 372435dcd8SFlorian Hahn template <typename Class> struct class_match { 3828047750SRamkumar Ramachandra template <typename ITy> bool match(ITy *V) const { return isa<Class>(V); } 392435dcd8SFlorian Hahn }; 402435dcd8SFlorian Hahn 412435dcd8SFlorian Hahn /// Match an arbitrary VPValue and ignore it. 422435dcd8SFlorian Hahn inline class_match<VPValue> m_VPValue() { return class_match<VPValue>(); } 432435dcd8SFlorian Hahn 442435dcd8SFlorian Hahn template <typename Class> struct bind_ty { 452435dcd8SFlorian Hahn Class *&VR; 462435dcd8SFlorian Hahn 472435dcd8SFlorian Hahn bind_ty(Class *&V) : VR(V) {} 482435dcd8SFlorian Hahn 4928047750SRamkumar Ramachandra template <typename ITy> bool match(ITy *V) const { 502435dcd8SFlorian Hahn if (auto *CV = dyn_cast<Class>(V)) { 512435dcd8SFlorian Hahn VR = CV; 522435dcd8SFlorian Hahn return true; 532435dcd8SFlorian Hahn } 542435dcd8SFlorian Hahn return false; 552435dcd8SFlorian Hahn } 562435dcd8SFlorian Hahn }; 572435dcd8SFlorian Hahn 584480a22cSMel Chen /// Match a specified VPValue. 594480a22cSMel Chen struct specificval_ty { 604480a22cSMel Chen const VPValue *Val; 614480a22cSMel Chen 624480a22cSMel Chen specificval_ty(const VPValue *V) : Val(V) {} 634480a22cSMel Chen 644480a22cSMel Chen bool match(VPValue *VPV) const { return VPV == Val; } 654480a22cSMel Chen }; 664480a22cSMel Chen 674480a22cSMel Chen inline specificval_ty m_Specific(const VPValue *VPV) { return VPV; } 684480a22cSMel Chen 69fd93a5e3SFlorian Hahn /// Match a specified integer value or vector of all elements of that 70dadf6f2cSFlorian Hahn /// value. \p BitWidth optionally specifies the bitwidth the matched constant 71dadf6f2cSFlorian Hahn /// must have. If it is 0, the matched constant can have any bitwidth. 72dadf6f2cSFlorian Hahn template <unsigned BitWidth = 0> struct specific_intval { 73fd93a5e3SFlorian Hahn APInt Val; 74fd93a5e3SFlorian Hahn 75fd93a5e3SFlorian Hahn specific_intval(APInt V) : Val(std::move(V)) {} 76fd93a5e3SFlorian Hahn 7728047750SRamkumar Ramachandra bool match(VPValue *VPV) const { 78fd93a5e3SFlorian Hahn if (!VPV->isLiveIn()) 79fd93a5e3SFlorian Hahn return false; 80fd93a5e3SFlorian Hahn Value *V = VPV->getLiveInIRValue(); 81e1833e3aSFlorian Hahn if (!V) 82e1833e3aSFlorian Hahn return false; 83fd93a5e3SFlorian Hahn const auto *CI = dyn_cast<ConstantInt>(V); 84fd93a5e3SFlorian Hahn if (!CI && V->getType()->isVectorTy()) 85fd93a5e3SFlorian Hahn if (const auto *C = dyn_cast<Constant>(V)) 86fd93a5e3SFlorian Hahn CI = dyn_cast_or_null<ConstantInt>( 871baa3850SNikita Popov C->getSplatValue(/*AllowPoison=*/false)); 88dadf6f2cSFlorian Hahn if (!CI) 89dadf6f2cSFlorian Hahn return false; 90fd93a5e3SFlorian Hahn 911d9b3222SFlorian Hahn if (BitWidth != 0 && CI->getBitWidth() != BitWidth) 921d9b3222SFlorian Hahn return false; 93dadf6f2cSFlorian Hahn return APInt::isSameValue(CI->getValue(), Val); 94fd93a5e3SFlorian Hahn } 95fd93a5e3SFlorian Hahn }; 96fd93a5e3SFlorian Hahn 97dadf6f2cSFlorian Hahn inline specific_intval<0> m_SpecificInt(uint64_t V) { 98dadf6f2cSFlorian Hahn return specific_intval<0>(APInt(64, V)); 99fd93a5e3SFlorian Hahn } 100fd93a5e3SFlorian Hahn 101dadf6f2cSFlorian Hahn inline specific_intval<1> m_False() { return specific_intval<1>(APInt(64, 0)); } 102dadf6f2cSFlorian Hahn 1031d9b3222SFlorian Hahn inline specific_intval<1> m_True() { return specific_intval<1>(APInt(64, 1)); } 1041d9b3222SFlorian Hahn 105fd93a5e3SFlorian Hahn /// Matching combinators 106fd93a5e3SFlorian Hahn template <typename LTy, typename RTy> struct match_combine_or { 107fd93a5e3SFlorian Hahn LTy L; 108fd93a5e3SFlorian Hahn RTy R; 109fd93a5e3SFlorian Hahn 110fd93a5e3SFlorian Hahn match_combine_or(const LTy &Left, const RTy &Right) : L(Left), R(Right) {} 111fd93a5e3SFlorian Hahn 11228047750SRamkumar Ramachandra template <typename ITy> bool match(ITy *V) const { 113fd93a5e3SFlorian Hahn if (L.match(V)) 114fd93a5e3SFlorian Hahn return true; 115fd93a5e3SFlorian Hahn if (R.match(V)) 116fd93a5e3SFlorian Hahn return true; 117fd93a5e3SFlorian Hahn return false; 118fd93a5e3SFlorian Hahn } 119fd93a5e3SFlorian Hahn }; 120fd93a5e3SFlorian Hahn 121fd93a5e3SFlorian Hahn template <typename LTy, typename RTy> 122fd93a5e3SFlorian Hahn inline match_combine_or<LTy, RTy> m_CombineOr(const LTy &L, const RTy &R) { 123fd93a5e3SFlorian Hahn return match_combine_or<LTy, RTy>(L, R); 124fd93a5e3SFlorian Hahn } 125fd93a5e3SFlorian Hahn 1262435dcd8SFlorian Hahn /// Match a VPValue, capturing it if we match. 1272435dcd8SFlorian Hahn inline bind_ty<VPValue> m_VPValue(VPValue *&V) { return V; } 1282435dcd8SFlorian Hahn 129fd93a5e3SFlorian Hahn namespace detail { 130fd93a5e3SFlorian Hahn 131fd93a5e3SFlorian Hahn /// A helper to match an opcode against multiple recipe types. 132fd93a5e3SFlorian Hahn template <unsigned Opcode, typename...> struct MatchRecipeAndOpcode {}; 133fd93a5e3SFlorian Hahn 134fd93a5e3SFlorian Hahn template <unsigned Opcode, typename RecipeTy> 135fd93a5e3SFlorian Hahn struct MatchRecipeAndOpcode<Opcode, RecipeTy> { 136fd93a5e3SFlorian Hahn static bool match(const VPRecipeBase *R) { 137fd93a5e3SFlorian Hahn auto *DefR = dyn_cast<RecipeTy>(R); 138dac0f7e8SFlorian Hahn // Check for recipes that do not have opcodes. 139dac0f7e8SFlorian Hahn if constexpr (std::is_same<RecipeTy, VPScalarIVStepsRecipe>::value || 1401d9b3222SFlorian Hahn std::is_same<RecipeTy, VPCanonicalIVPHIRecipe>::value || 141e1833e3aSFlorian Hahn std::is_same<RecipeTy, VPWidenSelectRecipe>::value || 142*df4a615cSFlorian Hahn std::is_same<RecipeTy, VPDerivedIVRecipe>::value || 143*df4a615cSFlorian Hahn std::is_same<RecipeTy, VPWidenGEPRecipe>::value) 144dac0f7e8SFlorian Hahn return DefR; 145dac0f7e8SFlorian Hahn else 146fd93a5e3SFlorian Hahn return DefR && DefR->getOpcode() == Opcode; 147fd93a5e3SFlorian Hahn } 148fd93a5e3SFlorian Hahn }; 149fd93a5e3SFlorian Hahn 150fd93a5e3SFlorian Hahn template <unsigned Opcode, typename RecipeTy, typename... RecipeTys> 151fd93a5e3SFlorian Hahn struct MatchRecipeAndOpcode<Opcode, RecipeTy, RecipeTys...> { 152fd93a5e3SFlorian Hahn static bool match(const VPRecipeBase *R) { 153fd93a5e3SFlorian Hahn return MatchRecipeAndOpcode<Opcode, RecipeTy>::match(R) || 154fd93a5e3SFlorian Hahn MatchRecipeAndOpcode<Opcode, RecipeTys...>::match(R); 155fd93a5e3SFlorian Hahn } 156fd93a5e3SFlorian Hahn }; 157dac0f7e8SFlorian Hahn template <typename TupleTy, typename Fn, std::size_t... Is> 158dac0f7e8SFlorian Hahn bool CheckTupleElements(const TupleTy &Ops, Fn P, std::index_sequence<Is...>) { 159dac0f7e8SFlorian Hahn return (P(std::get<Is>(Ops), Is) && ...); 160dac0f7e8SFlorian Hahn } 161dac0f7e8SFlorian Hahn 162dac0f7e8SFlorian Hahn /// Helper to check if predicate \p P holds on all tuple elements in \p Ops 163dac0f7e8SFlorian Hahn template <typename TupleTy, typename Fn> 164dac0f7e8SFlorian Hahn bool all_of_tuple_elements(const TupleTy &Ops, Fn P) { 165dac0f7e8SFlorian Hahn return CheckTupleElements( 166dac0f7e8SFlorian Hahn Ops, P, std::make_index_sequence<std::tuple_size<TupleTy>::value>{}); 167dac0f7e8SFlorian Hahn } 168fd93a5e3SFlorian Hahn } // namespace detail 169fd93a5e3SFlorian Hahn 170dac0f7e8SFlorian Hahn template <typename Ops_t, unsigned Opcode, bool Commutative, 171dac0f7e8SFlorian Hahn typename... RecipeTys> 172dac0f7e8SFlorian Hahn struct Recipe_match { 173dac0f7e8SFlorian Hahn Ops_t Ops; 1742435dcd8SFlorian Hahn 175dac0f7e8SFlorian Hahn Recipe_match() : Ops() { 176dac0f7e8SFlorian Hahn static_assert(std::tuple_size<Ops_t>::value == 0 && 177dac0f7e8SFlorian Hahn "constructor can only be used with zero operands"); 178dac0f7e8SFlorian Hahn } 179dac0f7e8SFlorian Hahn Recipe_match(Ops_t Ops) : Ops(Ops) {} 180dac0f7e8SFlorian Hahn template <typename A_t, typename B_t> 181dac0f7e8SFlorian Hahn Recipe_match(A_t A, B_t B) : Ops({A, B}) { 182dac0f7e8SFlorian Hahn static_assert(std::tuple_size<Ops_t>::value == 2 && 183dac0f7e8SFlorian Hahn "constructor can only be used for binary matcher"); 184dac0f7e8SFlorian Hahn } 1852435dcd8SFlorian Hahn 18628047750SRamkumar Ramachandra bool match(const VPValue *V) const { 1872435dcd8SFlorian Hahn auto *DefR = V->getDefiningRecipe(); 1882435dcd8SFlorian Hahn return DefR && match(DefR); 1892435dcd8SFlorian Hahn } 1902435dcd8SFlorian Hahn 19128047750SRamkumar Ramachandra bool match(const VPSingleDefRecipe *R) const { 1928ec40675SFlorian Hahn return match(static_cast<const VPRecipeBase *>(R)); 1938ec40675SFlorian Hahn } 1948ec40675SFlorian Hahn 19528047750SRamkumar Ramachandra bool match(const VPRecipeBase *R) const { 196fd93a5e3SFlorian Hahn if (!detail::MatchRecipeAndOpcode<Opcode, RecipeTys...>::match(R)) 1972435dcd8SFlorian Hahn return false; 198dac0f7e8SFlorian Hahn assert(R->getNumOperands() == std::tuple_size<Ops_t>::value && 199dac0f7e8SFlorian Hahn "recipe with matched opcode the expected number of operands"); 200dac0f7e8SFlorian Hahn 201dac0f7e8SFlorian Hahn if (detail::all_of_tuple_elements(Ops, [R](auto Op, unsigned Idx) { 202dac0f7e8SFlorian Hahn return Op.match(R->getOperand(Idx)); 203dac0f7e8SFlorian Hahn })) 204dac0f7e8SFlorian Hahn return true; 205dac0f7e8SFlorian Hahn 206dac0f7e8SFlorian Hahn return Commutative && 207dac0f7e8SFlorian Hahn detail::all_of_tuple_elements(Ops, [R](auto Op, unsigned Idx) { 208dac0f7e8SFlorian Hahn return Op.match(R->getOperand(R->getNumOperands() - Idx - 1)); 209dac0f7e8SFlorian Hahn }); 210fd93a5e3SFlorian Hahn } 211fd93a5e3SFlorian Hahn }; 212fd93a5e3SFlorian Hahn 213dac0f7e8SFlorian Hahn template <typename Op0_t, unsigned Opcode, typename... RecipeTys> 214dac0f7e8SFlorian Hahn using UnaryRecipe_match = 215dac0f7e8SFlorian Hahn Recipe_match<std::tuple<Op0_t>, Opcode, false, RecipeTys...>; 216dac0f7e8SFlorian Hahn 217fd93a5e3SFlorian Hahn template <typename Op0_t, unsigned Opcode> 218fd93a5e3SFlorian Hahn using UnaryVPInstruction_match = 219fd93a5e3SFlorian Hahn UnaryRecipe_match<Op0_t, Opcode, VPInstruction>; 220fd93a5e3SFlorian Hahn 221fd93a5e3SFlorian Hahn template <typename Op0_t, unsigned Opcode> 222fd93a5e3SFlorian Hahn using AllUnaryRecipe_match = 223fd93a5e3SFlorian Hahn UnaryRecipe_match<Op0_t, Opcode, VPWidenRecipe, VPReplicateRecipe, 224fd93a5e3SFlorian Hahn VPWidenCastRecipe, VPInstruction>; 225fd93a5e3SFlorian Hahn 22682c5d350SFlorian Hahn template <typename Op0_t, typename Op1_t, unsigned Opcode, bool Commutative, 227fd93a5e3SFlorian Hahn typename... RecipeTys> 228dac0f7e8SFlorian Hahn using BinaryRecipe_match = 229dac0f7e8SFlorian Hahn Recipe_match<std::tuple<Op0_t, Op1_t>, Opcode, Commutative, RecipeTys...>; 2302435dcd8SFlorian Hahn 2312435dcd8SFlorian Hahn template <typename Op0_t, typename Op1_t, unsigned Opcode> 232fd93a5e3SFlorian Hahn using BinaryVPInstruction_match = 23382c5d350SFlorian Hahn BinaryRecipe_match<Op0_t, Op1_t, Opcode, /*Commutative*/ false, 23482c5d350SFlorian Hahn VPInstruction>; 2352435dcd8SFlorian Hahn 23682c5d350SFlorian Hahn template <typename Op0_t, typename Op1_t, unsigned Opcode, 23782c5d350SFlorian Hahn bool Commutative = false> 238fd93a5e3SFlorian Hahn using AllBinaryRecipe_match = 23982c5d350SFlorian Hahn BinaryRecipe_match<Op0_t, Op1_t, Opcode, Commutative, VPWidenRecipe, 24082c5d350SFlorian Hahn VPReplicateRecipe, VPWidenCastRecipe, VPInstruction>; 2412435dcd8SFlorian Hahn 2422435dcd8SFlorian Hahn template <unsigned Opcode, typename Op0_t> 2432435dcd8SFlorian Hahn inline UnaryVPInstruction_match<Op0_t, Opcode> 2442435dcd8SFlorian Hahn m_VPInstruction(const Op0_t &Op0) { 2452435dcd8SFlorian Hahn return UnaryVPInstruction_match<Op0_t, Opcode>(Op0); 2462435dcd8SFlorian Hahn } 2472435dcd8SFlorian Hahn 2482435dcd8SFlorian Hahn template <unsigned Opcode, typename Op0_t, typename Op1_t> 2492435dcd8SFlorian Hahn inline BinaryVPInstruction_match<Op0_t, Op1_t, Opcode> 2502435dcd8SFlorian Hahn m_VPInstruction(const Op0_t &Op0, const Op1_t &Op1) { 2512435dcd8SFlorian Hahn return BinaryVPInstruction_match<Op0_t, Op1_t, Opcode>(Op0, Op1); 2522435dcd8SFlorian Hahn } 2532435dcd8SFlorian Hahn 2542435dcd8SFlorian Hahn template <typename Op0_t> 2552435dcd8SFlorian Hahn inline UnaryVPInstruction_match<Op0_t, VPInstruction::Not> 2562435dcd8SFlorian Hahn m_Not(const Op0_t &Op0) { 2572435dcd8SFlorian Hahn return m_VPInstruction<VPInstruction::Not>(Op0); 2582435dcd8SFlorian Hahn } 2592435dcd8SFlorian Hahn 2602435dcd8SFlorian Hahn template <typename Op0_t> 2612435dcd8SFlorian Hahn inline UnaryVPInstruction_match<Op0_t, VPInstruction::BranchOnCond> 2622435dcd8SFlorian Hahn m_BranchOnCond(const Op0_t &Op0) { 2632435dcd8SFlorian Hahn return m_VPInstruction<VPInstruction::BranchOnCond>(Op0); 2642435dcd8SFlorian Hahn } 2652435dcd8SFlorian Hahn 2662435dcd8SFlorian Hahn template <typename Op0_t, typename Op1_t> 2672435dcd8SFlorian Hahn inline BinaryVPInstruction_match<Op0_t, Op1_t, VPInstruction::ActiveLaneMask> 2682435dcd8SFlorian Hahn m_ActiveLaneMask(const Op0_t &Op0, const Op1_t &Op1) { 2692435dcd8SFlorian Hahn return m_VPInstruction<VPInstruction::ActiveLaneMask>(Op0, Op1); 2702435dcd8SFlorian Hahn } 2712435dcd8SFlorian Hahn 2722435dcd8SFlorian Hahn template <typename Op0_t, typename Op1_t> 2732435dcd8SFlorian Hahn inline BinaryVPInstruction_match<Op0_t, Op1_t, VPInstruction::BranchOnCount> 2742435dcd8SFlorian Hahn m_BranchOnCount(const Op0_t &Op0, const Op1_t &Op1) { 2752435dcd8SFlorian Hahn return m_VPInstruction<VPInstruction::BranchOnCount>(Op0, Op1); 2762435dcd8SFlorian Hahn } 277fd93a5e3SFlorian Hahn 278fd93a5e3SFlorian Hahn template <unsigned Opcode, typename Op0_t> 279fd93a5e3SFlorian Hahn inline AllUnaryRecipe_match<Op0_t, Opcode> m_Unary(const Op0_t &Op0) { 280fd93a5e3SFlorian Hahn return AllUnaryRecipe_match<Op0_t, Opcode>(Op0); 281fd93a5e3SFlorian Hahn } 282fd93a5e3SFlorian Hahn 283fd93a5e3SFlorian Hahn template <typename Op0_t> 284fd93a5e3SFlorian Hahn inline AllUnaryRecipe_match<Op0_t, Instruction::Trunc> 285fd93a5e3SFlorian Hahn m_Trunc(const Op0_t &Op0) { 286fd93a5e3SFlorian Hahn return m_Unary<Instruction::Trunc, Op0_t>(Op0); 287fd93a5e3SFlorian Hahn } 288fd93a5e3SFlorian Hahn 289fd93a5e3SFlorian Hahn template <typename Op0_t> 290fd93a5e3SFlorian Hahn inline AllUnaryRecipe_match<Op0_t, Instruction::ZExt> m_ZExt(const Op0_t &Op0) { 291fd93a5e3SFlorian Hahn return m_Unary<Instruction::ZExt, Op0_t>(Op0); 292fd93a5e3SFlorian Hahn } 293fd93a5e3SFlorian Hahn 294fd93a5e3SFlorian Hahn template <typename Op0_t> 295fd93a5e3SFlorian Hahn inline AllUnaryRecipe_match<Op0_t, Instruction::SExt> m_SExt(const Op0_t &Op0) { 296fd93a5e3SFlorian Hahn return m_Unary<Instruction::SExt, Op0_t>(Op0); 297fd93a5e3SFlorian Hahn } 298fd93a5e3SFlorian Hahn 299fd93a5e3SFlorian Hahn template <typename Op0_t> 300fd93a5e3SFlorian Hahn inline match_combine_or<AllUnaryRecipe_match<Op0_t, Instruction::ZExt>, 301fd93a5e3SFlorian Hahn AllUnaryRecipe_match<Op0_t, Instruction::SExt>> 302fd93a5e3SFlorian Hahn m_ZExtOrSExt(const Op0_t &Op0) { 303fd93a5e3SFlorian Hahn return m_CombineOr(m_ZExt(Op0), m_SExt(Op0)); 304fd93a5e3SFlorian Hahn } 305fd93a5e3SFlorian Hahn 30682c5d350SFlorian Hahn template <unsigned Opcode, typename Op0_t, typename Op1_t, 30782c5d350SFlorian Hahn bool Commutative = false> 30882c5d350SFlorian Hahn inline AllBinaryRecipe_match<Op0_t, Op1_t, Opcode, Commutative> 30982c5d350SFlorian Hahn m_Binary(const Op0_t &Op0, const Op1_t &Op1) { 31082c5d350SFlorian Hahn return AllBinaryRecipe_match<Op0_t, Op1_t, Opcode, Commutative>(Op0, Op1); 311fd93a5e3SFlorian Hahn } 312fd93a5e3SFlorian Hahn 313*df4a615cSFlorian Hahn template <unsigned Opcode, typename Op0_t, typename Op1_t> 314*df4a615cSFlorian Hahn inline AllBinaryRecipe_match<Op0_t, Op1_t, Opcode, true> 315*df4a615cSFlorian Hahn m_c_Binary(const Op0_t &Op0, const Op1_t &Op1) { 316*df4a615cSFlorian Hahn return AllBinaryRecipe_match<Op0_t, Op1_t, Opcode, true>(Op0, Op1); 317*df4a615cSFlorian Hahn } 318*df4a615cSFlorian Hahn 319fd93a5e3SFlorian Hahn template <typename Op0_t, typename Op1_t> 320fd93a5e3SFlorian Hahn inline AllBinaryRecipe_match<Op0_t, Op1_t, Instruction::Mul> 321fd93a5e3SFlorian Hahn m_Mul(const Op0_t &Op0, const Op1_t &Op1) { 322fd93a5e3SFlorian Hahn return m_Binary<Instruction::Mul, Op0_t, Op1_t>(Op0, Op1); 323fd93a5e3SFlorian Hahn } 324fd93a5e3SFlorian Hahn 3250e743eccSRamkumar Ramachandra template <typename Op0_t, typename Op1_t> 3260e743eccSRamkumar Ramachandra inline AllBinaryRecipe_match<Op0_t, Op1_t, Instruction::Mul, 3270e743eccSRamkumar Ramachandra /* Commutative =*/true> 3280e743eccSRamkumar Ramachandra m_c_Mul(const Op0_t &Op0, const Op1_t &Op1) { 3290e743eccSRamkumar Ramachandra return m_Binary<Instruction::Mul, Op0_t, Op1_t, true>(Op0, Op1); 3300e743eccSRamkumar Ramachandra } 3310e743eccSRamkumar Ramachandra 33282c5d350SFlorian Hahn /// Match a binary OR operation. Note that while conceptually the operands can 33382c5d350SFlorian Hahn /// be matched commutatively, \p Commutative defaults to false in line with the 33482c5d350SFlorian Hahn /// IR-based pattern matching infrastructure. Use m_c_BinaryOr for a commutative 33582c5d350SFlorian Hahn /// version of the matcher. 33682c5d350SFlorian Hahn template <typename Op0_t, typename Op1_t, bool Commutative = false> 33782c5d350SFlorian Hahn inline AllBinaryRecipe_match<Op0_t, Op1_t, Instruction::Or, Commutative> 338b050048dSFlorian Hahn m_BinaryOr(const Op0_t &Op0, const Op1_t &Op1) { 33982c5d350SFlorian Hahn return m_Binary<Instruction::Or, Op0_t, Op1_t, Commutative>(Op0, Op1); 34082c5d350SFlorian Hahn } 34182c5d350SFlorian Hahn 34282c5d350SFlorian Hahn template <typename Op0_t, typename Op1_t> 34382c5d350SFlorian Hahn inline AllBinaryRecipe_match<Op0_t, Op1_t, Instruction::Or, 34482c5d350SFlorian Hahn /*Commutative*/ true> 34582c5d350SFlorian Hahn m_c_BinaryOr(const Op0_t &Op0, const Op1_t &Op1) { 34682c5d350SFlorian Hahn return m_BinaryOr<Op0_t, Op1_t, /*Commutative*/ true>(Op0, Op1); 3476ef82994SFlorian Hahn } 348b050048dSFlorian Hahn 349*df4a615cSFlorian Hahn template <typename Op0_t, typename Op1_t> 350*df4a615cSFlorian Hahn using GEPLikeRecipe_match = 351*df4a615cSFlorian Hahn BinaryRecipe_match<Op0_t, Op1_t, Instruction::GetElementPtr, false, 352*df4a615cSFlorian Hahn VPWidenRecipe, VPReplicateRecipe, VPWidenGEPRecipe, 353*df4a615cSFlorian Hahn VPInstruction>; 354*df4a615cSFlorian Hahn 355*df4a615cSFlorian Hahn template <typename Op0_t, typename Op1_t> 356*df4a615cSFlorian Hahn inline GEPLikeRecipe_match<Op0_t, Op1_t> m_GetElementPtr(const Op0_t &Op0, 357*df4a615cSFlorian Hahn const Op1_t &Op1) { 358*df4a615cSFlorian Hahn return GEPLikeRecipe_match<Op0_t, Op1_t>(Op0, Op1); 359*df4a615cSFlorian Hahn } 360*df4a615cSFlorian Hahn 3611d9b3222SFlorian Hahn template <typename Op0_t, typename Op1_t, typename Op2_t, unsigned Opcode> 3621d9b3222SFlorian Hahn using AllTernaryRecipe_match = 3631d9b3222SFlorian Hahn Recipe_match<std::tuple<Op0_t, Op1_t, Op2_t>, Opcode, false, 3641d9b3222SFlorian Hahn VPReplicateRecipe, VPInstruction, VPWidenSelectRecipe>; 3651d9b3222SFlorian Hahn 3661d9b3222SFlorian Hahn template <typename Op0_t, typename Op1_t, typename Op2_t> 3671d9b3222SFlorian Hahn inline AllTernaryRecipe_match<Op0_t, Op1_t, Op2_t, Instruction::Select> 3681d9b3222SFlorian Hahn m_Select(const Op0_t &Op0, const Op1_t &Op1, const Op2_t &Op2) { 3691d9b3222SFlorian Hahn return AllTernaryRecipe_match<Op0_t, Op1_t, Op2_t, Instruction::Select>( 3701d9b3222SFlorian Hahn {Op0, Op1, Op2}); 3711d9b3222SFlorian Hahn } 3721d9b3222SFlorian Hahn 373b050048dSFlorian Hahn template <typename Op0_t, typename Op1_t> 3741d9b3222SFlorian Hahn inline match_combine_or< 3751d9b3222SFlorian Hahn BinaryVPInstruction_match<Op0_t, Op1_t, VPInstruction::LogicalAnd>, 3761d9b3222SFlorian Hahn AllTernaryRecipe_match<Op0_t, Op1_t, specific_intval<1>, 3771d9b3222SFlorian Hahn Instruction::Select>> 378b050048dSFlorian Hahn m_LogicalAnd(const Op0_t &Op0, const Op1_t &Op1) { 3791d9b3222SFlorian Hahn return m_CombineOr( 3801d9b3222SFlorian Hahn m_VPInstruction<VPInstruction::LogicalAnd, Op0_t, Op1_t>(Op0, Op1), 3811d9b3222SFlorian Hahn m_Select(Op0, Op1, m_False())); 3821d9b3222SFlorian Hahn } 3831d9b3222SFlorian Hahn 3841d9b3222SFlorian Hahn template <typename Op0_t, typename Op1_t> 3851d9b3222SFlorian Hahn inline AllTernaryRecipe_match<Op0_t, specific_intval<1>, Op1_t, 3861d9b3222SFlorian Hahn Instruction::Select> 3871d9b3222SFlorian Hahn m_LogicalOr(const Op0_t &Op0, const Op1_t &Op1) { 3881d9b3222SFlorian Hahn return m_Select(Op0, m_True(), Op1); 389b050048dSFlorian Hahn } 390c008647bSFlorian Hahn 391dac0f7e8SFlorian Hahn using VPCanonicalIVPHI_match = 392dac0f7e8SFlorian Hahn Recipe_match<std::tuple<>, 0, false, VPCanonicalIVPHIRecipe>; 393c008647bSFlorian Hahn 394c008647bSFlorian Hahn inline VPCanonicalIVPHI_match m_CanonicalIV() { 395c008647bSFlorian Hahn return VPCanonicalIVPHI_match(); 396c008647bSFlorian Hahn } 397c008647bSFlorian Hahn 398dac0f7e8SFlorian Hahn template <typename Op0_t, typename Op1_t> 399dac0f7e8SFlorian Hahn using VPScalarIVSteps_match = 400dac0f7e8SFlorian Hahn Recipe_match<std::tuple<Op0_t, Op1_t>, 0, false, VPScalarIVStepsRecipe>; 401c008647bSFlorian Hahn 402c008647bSFlorian Hahn template <typename Op0_t, typename Op1_t> 403c008647bSFlorian Hahn inline VPScalarIVSteps_match<Op0_t, Op1_t> m_ScalarIVSteps(const Op0_t &Op0, 404c008647bSFlorian Hahn const Op1_t &Op1) { 405c008647bSFlorian Hahn return VPScalarIVSteps_match<Op0_t, Op1_t>(Op0, Op1); 406c008647bSFlorian Hahn } 407e1833e3aSFlorian Hahn 408e1833e3aSFlorian Hahn template <typename Op0_t, typename Op1_t, typename Op2_t> 409e1833e3aSFlorian Hahn using VPDerivedIV_match = 410e1833e3aSFlorian Hahn Recipe_match<std::tuple<Op0_t, Op1_t, Op2_t>, 0, false, VPDerivedIVRecipe>; 411e1833e3aSFlorian Hahn 412e1833e3aSFlorian Hahn template <typename Op0_t, typename Op1_t, typename Op2_t> 413e1833e3aSFlorian Hahn inline VPDerivedIV_match<Op0_t, Op1_t, Op2_t> 414e1833e3aSFlorian Hahn m_DerivedIV(const Op0_t &Op0, const Op1_t &Op1, const Op2_t &Op2) { 415e1833e3aSFlorian Hahn return VPDerivedIV_match<Op0_t, Op1_t, Op2_t>({Op0, Op1, Op2}); 416e1833e3aSFlorian Hahn } 417e1833e3aSFlorian Hahn 4182435dcd8SFlorian Hahn } // namespace VPlanPatternMatch 4192435dcd8SFlorian Hahn } // namespace llvm 4202435dcd8SFlorian Hahn 4212435dcd8SFlorian Hahn #endif 422