15#ifndef LLVM_TRANSFORM_VECTORIZE_VPLANPATTERNMATCH_H
16#define LLVM_TRANSFORM_VECTORIZE_VPLANPATTERNMATCH_H
21namespace VPlanPatternMatch {
23template <
typename Val,
typename Pattern>
bool match(Val *V,
const Pattern &
P) {
28 auto *R = dyn_cast<VPRecipeBase>(U);
33 template <
typename ITy>
bool match(ITy *V)
const {
return isa<Class>(V); }
44 template <
typename ITy>
bool match(ITy *V)
const {
45 if (
auto *CV = dyn_cast<Class>(V)) {
86template <
typename Pred,
unsigned BitW
idth = 0>
struct int_pred_ty {
98 const auto *CI = dyn_cast<ConstantInt>(V);
99 if (!CI && V->getType()->isVectorTy())
100 if (
const auto *
C = dyn_cast<Constant>(V))
101 CI = dyn_cast_or_null<ConstantInt>(
102 C->getSplatValue(
false));
108 return P.isValue(CI->getValue());
123template <
unsigned Bitw
idth = 0>
165 template <
typename ITy>
bool match(ITy *V)
const {
166 return L.match(V) ||
R.match(V);
176 template <
typename ITy>
bool match(ITy *V)
const {
177 return L.match(V) &&
R.match(V);
182template <
typename LTy,
typename RTy>
188template <
typename LTy,
typename RTy>
199template <
typename Ops_t,
unsigned Opcode,
bool Commutative,
200 typename... RecipeTys>
205 static_assert(std::tuple_size<Ops_t>::value ==
sizeof...(Ops) &&
206 "number of operands in constructor doesn't match Ops_t");
207 static_assert((!Commutative || std::tuple_size<Ops_t>::value == 2) &&
208 "only binary ops can be commutative");
212 auto *DefR = V->getDefiningRecipe();
213 return DefR &&
match(DefR);
221 if (std::tuple_size<Ops_t>::value == 0) {
223 "can only match BuildVector with empty ops");
224 auto *VPI = dyn_cast<VPInstruction>(R);
228 if ((!matchRecipeAndOpcode<RecipeTys>(R) && ...))
231 if (R->getNumOperands() != std::tuple_size<Ops_t>::value) {
232 assert(Opcode == Instruction::PHI &&
233 "non-variadic recipe with matched opcode does not have the "
234 "expected number of operands");
238 auto IdxSeq = std::make_index_sequence<std::tuple_size<Ops_t>::value>();
239 if (all_of_tuple_elements(IdxSeq, [R](
auto Op,
unsigned Idx) {
240 return Op.match(R->getOperand(
Idx));
244 return Commutative &&
245 all_of_tuple_elements(IdxSeq, [R](
auto Op,
unsigned Idx) {
246 return Op.match(R->getOperand(R->getNumOperands() -
Idx - 1));
251 template <
typename RecipeTy>
252 static bool matchRecipeAndOpcode(
const VPRecipeBase *R) {
253 auto *DefR = dyn_cast<RecipeTy>(R);
255 if constexpr (std::is_same<RecipeTy, VPScalarIVStepsRecipe>::value ||
256 std::is_same<RecipeTy, VPCanonicalIVPHIRecipe>::value ||
257 std::is_same<RecipeTy, VPDerivedIVRecipe>::value ||
258 std::is_same<RecipeTy, VPWidenGEPRecipe>::value)
261 return DefR && DefR->getOpcode() == Opcode;
266 template <
typename Fn, std::size_t... Is>
267 bool all_of_tuple_elements(std::index_sequence<Is...>, Fn
P)
const {
268 return (
P(std::get<Is>(
Ops), Is) && ...);
272template <
unsigned Opcode,
typename... OpTys>
278template <
unsigned Opcode,
typename... OpTys>
283template <
unsigned Opcode,
typename... OpTys>
287template <
unsigned Opcode,
typename... OpTys>
296 return m_VPInstruction<VPInstruction::BuildVector>();
299template <
typename Op0_t>
300inline VPInstruction_match<Instruction::Freeze, Op0_t>
302 return m_VPInstruction<Instruction::Freeze>(Op0);
305template <
typename Op0_t>
306inline VPInstruction_match<VPInstruction::BranchOnCond, Op0_t>
308 return m_VPInstruction<VPInstruction::BranchOnCond>(Op0);
311template <
typename Op0_t>
312inline VPInstruction_match<VPInstruction::Broadcast, Op0_t>
314 return m_VPInstruction<VPInstruction::Broadcast>(Op0);
317template <
typename Op0_t>
318inline VPInstruction_match<VPInstruction::ExplicitVectorLength, Op0_t>
320 return m_VPInstruction<VPInstruction::ExplicitVectorLength>(Op0);
323template <
typename Op0_t>
324inline VPInstruction_match<VPInstruction::ExtractLastElement, Op0_t>
326 return m_VPInstruction<VPInstruction::ExtractLastElement>(Op0);
329template <
typename Op0_t,
typename Op1_t>
330inline VPInstruction_match<VPInstruction::ActiveLaneMask, Op0_t, Op1_t>
332 return m_VPInstruction<VPInstruction::ActiveLaneMask>(Op0, Op1);
335template <
typename Op0_t,
typename Op1_t>
336inline VPInstruction_match<VPInstruction::BranchOnCount, Op0_t, Op1_t>
338 return m_VPInstruction<VPInstruction::BranchOnCount>(Op0, Op1);
341template <
unsigned Opcode,
typename Op0_t>
346template <
typename Op0_t>
348 return m_Unary<Instruction::Trunc, Op0_t>(Op0);
351template <
typename Op0_t>
353 return m_Unary<Instruction::ZExt, Op0_t>(Op0);
356template <
typename Op0_t>
358 return m_Unary<Instruction::SExt, Op0_t>(Op0);
361template <
typename Op0_t>
363 AllRecipe_match<Instruction::SExt, Op0_t>>
368template <
typename Op0_t>
374template <
unsigned Opcode,
typename Op0_t,
typename Op1_t>
380template <
unsigned Opcode,
typename Op0_t,
typename Op1_t>
381inline AllRecipe_commutative_match<Opcode, Op0_t, Op1_t>
386template <
typename Op0_t,
typename Op1_t>
387inline AllRecipe_commutative_match<Instruction::Add, Op0_t, Op1_t>
389 return m_c_Binary<Instruction::Add, Op0_t, Op1_t>(Op0, Op1);
392template <
typename Op0_t,
typename Op1_t>
395 return m_Binary<Instruction::Sub, Op0_t, Op1_t>(Op0, Op1);
398template <
typename Op0_t,
typename Op1_t>
401 return m_Binary<Instruction::Mul, Op0_t, Op1_t>(Op0, Op1);
404template <
typename Op0_t,
typename Op1_t>
405inline AllRecipe_commutative_match<Instruction::Mul, Op0_t, Op1_t>
407 return m_c_Binary<Instruction::Mul, Op0_t, Op1_t>(Op0, Op1);
411template <
typename Op0_t,
typename Op1_t>
412inline AllRecipe_commutative_match<Instruction::And, Op0_t, Op1_t>
414 return m_c_Binary<Instruction::And, Op0_t, Op1_t>(Op0, Op1);
421template <
typename Op0_t,
typename Op1_t>
422inline AllRecipe_match<Instruction::Or, Op0_t, Op1_t>
424 return m_Binary<Instruction::Or, Op0_t, Op1_t>(Op0, Op1);
427template <
typename Op0_t,
typename Op1_t>
428inline AllRecipe_commutative_match<Instruction::Or, Op0_t, Op1_t>
430 return m_c_Binary<Instruction::Or, Op0_t, Op1_t>(Op0, Op1);
436template <
typename Op0_t,
typename Op1_t,
unsigned... Opcodes>
438 static_assert((
sizeof...(Opcodes) == 1 ||
sizeof...(Opcodes) == 2) &&
439 "Expected one or two opcodes");
441 ((Opcodes == Instruction::ICmp || Opcodes == Instruction::FCmp) && ...) &&
442 "Expected a compare instruction opcode");
453 auto *DefR = V->getDefiningRecipe();
454 return DefR &&
match(DefR);
458 if ((m_Binary<Opcodes>(
Op0,
Op1).
match(V) || ...)) {
460 *
Predicate = cast<VPRecipeWithIRFlags>(V)->getPredicate();
469template <
typename Op0_t,
typename Op1_t,
unsigned... Opcodes>
486template <
typename Op0_t,
typename Op1_t>
492template <
typename Op0_t,
typename Op1_t>
493inline Cmp_match<Op0_t, Op1_t, Instruction::ICmp>
498template <
typename Op0_t,
typename Op1_t>
499inline SpecificCmp_match<Op0_t, Op1_t, Instruction::ICmp>
505template <
typename Op0_t,
typename Op1_t>
506inline Cmp_match<Op0_t, Op1_t, Instruction::ICmp, Instruction::FCmp>
512template <
typename Op0_t,
typename Op1_t>
513inline Cmp_match<Op0_t, Op1_t, Instruction::ICmp, Instruction::FCmp>
519template <
typename Op0_t,
typename Op1_t>
520inline SpecificCmp_match<Op0_t, Op1_t, Instruction::ICmp, Instruction::FCmp>
523 MatchPred, Op0, Op1);
526template <
typename Op0_t,
typename Op1_t>
532template <
typename Op0_t,
typename Op1_t>
538template <
typename Op0_t,
typename Op1_t,
typename Op2_t>
539inline AllRecipe_match<Instruction::Select, Op0_t, Op1_t, Op2_t>
545template <
typename Op0_t>
548 Instruction::Xor, int_pred_ty<is_all_ones>,
Op0_t>>
550 return m_CombineOr(m_VPInstruction<VPInstruction::Not>(Op0),
551 m_c_Binary<Instruction::Xor>(
m_AllOnes(), Op0));
554template <
typename Op0_t,
typename Op1_t>
556 VPInstruction_match<VPInstruction::LogicalAnd, Op0_t, Op1_t>,
557 AllRecipe_match<Instruction::Select, Op0_t, Op1_t, specific_intval<1>>>
560 m_VPInstruction<VPInstruction::LogicalAnd, Op0_t, Op1_t>(Op0, Op1),
564template <
typename Op0_t,
typename Op1_t>
565inline AllRecipe_match<Instruction::Select, Op0_t, specific_intval<1>,
Op1_t>
570template <
typename Op0_t,
typename Op1_t,
typename Op2_t>
574template <
typename Op0_t,
typename Op1_t,
typename Op2_t>
580template <
typename Op0_t,
typename Op1_t,
typename Op2_t>
584template <
typename Op0_t,
typename Op1_t,
typename Op2_t>
598 template <
typename OpTy>
bool match(OpTy *V)
const {
599 if (
const auto *R = dyn_cast<VPWidenIntrinsicRecipe>(V))
600 return Val.match(R->getOperand(
OpI));
601 if (
const auto *R = dyn_cast<VPWidenCallRecipe>(V))
602 return Val.match(R->getOperand(
OpI));
603 if (
const auto *R = dyn_cast<VPReplicateRecipe>(V))
604 if (isa<CallInst>(R->getUnderlyingInstr()))
605 return Val.match(R->getOperand(
OpI + 1));
611template <
unsigned OpI,
typename Opnd_t>
622 template <
typename OpTy>
bool match(OpTy *V)
const {
623 if (
const auto *R = dyn_cast<VPWidenIntrinsicRecipe>(V))
624 return R->getVectorIntrinsicID() ==
ID;
625 if (
const auto *R = dyn_cast<VPWidenCallRecipe>(V))
626 return R->getCalledScalarFunction()->getIntrinsicID() ==
ID;
627 if (
const auto *R = dyn_cast<VPReplicateRecipe>(V))
628 if (
const auto *CI = dyn_cast<CallInst>(R->getUnderlyingInstr()))
629 if (
const auto *
F = CI->getCalledFunction())
630 return F->getIntrinsicID() ==
ID;
639template <
typename T0 = void,
typename T1 = void,
typename T2 = void,
649template <
typename T0,
typename T1,
typename T2>
654template <
typename T0,
typename T1,
typename T2,
typename T3>
666template <Intrinsic::ID IntrID,
typename T0>
668 return m_CombineAnd(m_Intrinsic<IntrID>(), m_Argument<0>(Op0));
671template <Intrinsic::ID IntrID,
typename T0,
typename T1>
674 return m_CombineAnd(m_Intrinsic<IntrID>(Op0), m_Argument<1>(Op1));
677template <Intrinsic::ID IntrID,
typename T0,
typename T1,
typename T2>
680 return m_CombineAnd(m_Intrinsic<IntrID>(Op0, Op1), m_Argument<2>(Op2));
687 return m_CombineAnd(m_Intrinsic<IntrID>(Op0, Op1, Op2), m_Argument<3>(Op3));
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
MachineInstr unsigned OpIdx
This file contains the declarations of the Vectorization Plan base classes:
Class for arbitrary precision integers.
static bool isSameValue(const APInt &I1, const APInt &I2)
Determine if two APInts have the same value, after zero-extending one of them (if needed!...
An abstraction over a floating-point predicate, and a pack of an integer predicate with samesign info...
static LLVM_ABI std::optional< CmpPredicate > getMatching(CmpPredicate A, CmpPredicate B)
Compares two CmpPredicates taking samesign into account and returns the canonicalized CmpPredicate if...
This class represents an Operation in the Expression.
A recipe for converting the input value IV value to the corresponding value of an IV with different s...
This is a concrete Recipe that models a single VPlan-level instruction.
@ BuildVector
Creates a fixed-width vector containing all operands.
VPRecipeBase is a base class modeling a sequence of one or more output IR instructions.
VPReplicateRecipe replicates a given instruction producing multiple scalar copies of the original sca...
A recipe for handling phi nodes of integer and floating-point inductions, producing their scalar valu...
VPSingleDef is a base class for recipes for modeling a sequence of one or more output IR that define ...
This class augments VPValue with operands which provide the inverse def-use edges from VPValue's user...
Value * getLiveInIRValue() const
Returns the underlying IR value, if this VPValue is defined outside the scope of VPlan.
bool isLiveIn() const
Returns true if this VPValue is a live-in, i.e. defined outside the VPlan.
VPWidenCastRecipe is a recipe to create vector cast instructions.
A recipe for handling GEP instructions.
VPWidenRecipe is a recipe for producing a widened instruction using the opcode and operands of the re...
LLVM Value Representation.
@ C
The default llvm calling convention, compatible with C.
auto m_LogicalOr()
Matches L || R where L and R are arbitrary values.
class_match< CmpInst > m_Cmp()
Matches any compare instruction and ignore it.
auto m_LogicalAnd()
Matches L && R where L and R are arbitrary values.
AllRecipe_match< Instruction::Select, Op0_t, Op1_t, Op2_t > m_Select(const Op0_t &Op0, const Op1_t &Op1, const Op2_t &Op2)
VPInstruction_match< Instruction::Freeze, Op0_t > m_Freeze(const Op0_t &Op0)
AllRecipe_commutative_match< Instruction::And, Op0_t, Op1_t > m_c_BinaryAnd(const Op0_t &Op0, const Op1_t &Op1)
Match a binary AND operation.
AllRecipe_match< Instruction::ZExt, Op0_t > m_ZExt(const Op0_t &Op0)
AllRecipe_match< Instruction::Or, Op0_t, Op1_t > m_BinaryOr(const Op0_t &Op0, const Op1_t &Op1)
Match a binary OR operation.
int_pred_ty< is_zero_int > m_ZeroInt()
Match an integer 0 or a vector with all elements equal to 0.
SpecificCmp_match< Op0_t, Op1_t, Instruction::ICmp, Instruction::FCmp > m_SpecificCmp(CmpPredicate MatchPred, const Op0_t &Op0, const Op1_t &Op1)
match_combine_or< VPInstruction_match< VPInstruction::Not, Op0_t >, AllRecipe_commutative_match< Instruction::Xor, int_pred_ty< is_all_ones >, Op0_t > > m_Not(const Op0_t &Op0)
int_pred_ty< is_all_ones > m_AllOnes()
Match an integer or vector with all bits set.
AllRecipe_commutative_match< Opcode, Op0_t, Op1_t > m_c_Binary(const Op0_t &Op0, const Op1_t &Op1)
AllRecipe_commutative_match< Instruction::Add, Op0_t, Op1_t > m_c_Add(const Op0_t &Op0, const Op1_t &Op1)
AllRecipe_commutative_match< Instruction::Or, Op0_t, Op1_t > m_c_BinaryOr(const Op0_t &Op0, const Op1_t &Op1)
VPInstruction_match< VPInstruction::ActiveLaneMask, Op0_t, Op1_t > m_ActiveLaneMask(const Op0_t &Op0, const Op1_t &Op1)
match_combine_or< AllRecipe_match< Instruction::ZExt, Op0_t >, AllRecipe_match< Instruction::SExt, Op0_t > > m_ZExtOrSExt(const Op0_t &Op0)
match_combine_and< LTy, RTy > m_CombineAnd(const LTy &L, const RTy &R)
Combine two pattern matchers matching L && R.
SpecificCmp_match< Op0_t, Op1_t, Instruction::ICmp > m_SpecificICmp(CmpPredicate MatchPred, const Op0_t &Op0, const Op1_t &Op1)
VPScalarIVSteps_match< Op0_t, Op1_t, Op2_t > m_ScalarIVSteps(const Op0_t &Op0, const Op1_t &Op1, const Op2_t &Op2)
match_combine_or< LTy, RTy > m_CombineOr(const LTy &L, const RTy &R)
Combine two pattern matchers matching L || R.
GEPLikeRecipe_match< Op0_t, Op1_t > m_GetElementPtr(const Op0_t &Op0, const Op1_t &Op1)
VPInstruction_match< VPInstruction::ExtractLastElement, Op0_t > m_ExtractLastElement(const Op0_t &Op0)
AllRecipe_match< Opcode, Op0_t, Op1_t > m_Binary(const Op0_t &Op0, const Op1_t &Op1)
AllRecipe_match< Opcode, Op0_t > m_Unary(const Op0_t &Op0)
AllRecipe_commutative_match< Instruction::Mul, Op0_t, Op1_t > m_c_Mul(const Op0_t &Op0, const Op1_t &Op1)
Recipe_match< std::tuple< OpTys... >, Opcode, true, VPWidenRecipe, VPReplicateRecipe, VPInstruction > AllRecipe_commutative_match
Cmp_match< Op0_t, Op1_t, Instruction::ICmp > m_ICmp(const Op0_t &Op0, const Op1_t &Op1)
AllRecipe_match< Instruction::Mul, Op0_t, Op1_t > m_Mul(const Op0_t &Op0, const Op1_t &Op1)
specificval_ty m_Specific(const VPValue *VPV)
specific_intval< 1 > m_False()
VPDerivedIV_match< Op0_t, Op1_t, Op2_t > m_DerivedIV(const Op0_t &Op0, const Op1_t &Op1, const Op2_t &Op2)
specific_intval< 0 > m_SpecificInt(uint64_t V)
VPInstruction_match< VPInstruction::BranchOnCount, Op0_t, Op1_t > m_BranchOnCount(const Op0_t &Op0, const Op1_t &Op1)
AllRecipe_match< Instruction::Sub, Op0_t, Op1_t > m_Sub(const Op0_t &Op0, const Op1_t &Op1)
AllRecipe_match< Instruction::SExt, Op0_t > m_SExt(const Op0_t &Op0)
specific_intval< 1 > m_True()
IntrinsicID_match m_Intrinsic()
Match intrinsic calls like this: m_Intrinsic<Intrinsic::fabs>(m_VPValue(X), ...)
deferredval_ty m_Deferred(VPValue *const &V)
Like m_Specific(), but works if the specific value to match is determined as part of the same match()...
VPInstruction_match< VPInstruction::Broadcast, Op0_t > m_Broadcast(const Op0_t &Op0)
bool match(Val *V, const Pattern &P)
class_match< VPValue > m_VPValue()
Match an arbitrary VPValue and ignore it.
VPInstruction_match< VPInstruction::ExplicitVectorLength, Op0_t > m_EVL(const Op0_t &Op0)
VPInstruction_match< VPInstruction::BuildVector > m_BuildVector()
BuildVector is matches only its opcode, w/o matching its operands as the number of operands is not fi...
AllRecipe_match< Instruction::Trunc, Op0_t > m_Trunc(const Op0_t &Op0)
match_combine_or< AllRecipe_match< Instruction::ZExt, Op0_t >, Op0_t > m_ZExtOrSelf(const Op0_t &Op0)
VPInstruction_match< VPInstruction::BranchOnCond, Op0_t > m_BranchOnCond(const Op0_t &Op0)
Argument_match< Opnd_t > m_Argument(const Opnd_t &Op)
Match a call argument.
bind_ty< VPInstruction > m_VPInstruction(VPInstruction *&V)
Match a VPInstruction, capturing if we match.
This is an optimization pass for GlobalISel generic memory operations.
constexpr unsigned BitWidth
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Implement std::hash so that hash_code can be used in STL containers.
Intrinsic matches are combinations of ID matchers, and argument matchers.
A recipe for widening select instructions.
Match a call argument at a given argument index.
unsigned OpI
Call argument index to match.
Argument_match(unsigned OpIdx, const Opnd_t &V)
bool match(OpTy *V) const
Cmp_match is a variant of BinaryRecipe_match that also binds the comparison predicate.
Cmp_match(CmpPredicate &Pred, const Op0_t &Op0, const Op1_t &Op1)
Cmp_match(const Op0_t &Op0, const Op1_t &Op1)
bool match(const VPValue *V) const
bool match(const VPRecipeBase *V) const
IntrinsicID_match(Intrinsic::ID IntrID)
bool match(OpTy *V) const
bool match(const VPSingleDefRecipe *R) const
Recipe_match(OpTy... Ops)
bool match(const VPValue *V) const
bool match(const VPRecipeBase *R) const
SpecificCmp_match is a variant of Cmp_match that matches the comparison predicate,...
SpecificCmp_match(CmpPredicate Pred, const Op0_t &LHS, const Op1_t &RHS)
const CmpPredicate Predicate
bool match(const VPValue *V) const
Stores a reference to the VPValue *, not the VPValue * itself, thus can be used in commutative matche...
deferredval_ty(VPValue *const &V)
bool match(VPValue *const V) const
Match an integer constant or vector of constants if Pred::isValue returns true for the APInt.
bool match(VPValue *VPV) const
bool isValue(const APInt &C) const
Match a specified integer value or vector of all elements of that value.
bool isValue(const APInt &C) const
is_specific_int(APInt Val)
bool isValue(const APInt &C) const
Intrinsic matches are combinations of ID matchers, and argument matchers.
match_combine_and(const LTy &Left, const RTy &Right)
match_combine_or(const LTy &Left, const RTy &Right)
Match a specified VPValue.
specificval_ty(const VPValue *V)
bool match(VPValue *VPV) const