@@ -75,8 +75,8 @@ template <unsigned BitWidth = 0> struct specific_intval {
7575 if (!CI)
7676 return false ;
7777
78- assert (( BitWidth == 0 || CI->getBitWidth () == BitWidth) &&
79- " Trying the match constant with unexpected bitwidth. " ) ;
78+ if ( BitWidth != 0 && CI->getBitWidth () != BitWidth)
79+ return false ;
8080 return APInt::isSameValue (CI->getValue (), Val);
8181 }
8282};
@@ -87,6 +87,8 @@ inline specific_intval<0> m_SpecificInt(uint64_t V) {
8787
8888inline specific_intval<1 > m_False () { return specific_intval<1 >(APInt (64 , 0 )); }
8989
90+ inline specific_intval<1 > m_True () { return specific_intval<1 >(APInt (64 , 1 )); }
91+
9092// / Matching combinators
9193template <typename LTy, typename RTy> struct match_combine_or {
9294 LTy L;
@@ -122,7 +124,8 @@ struct MatchRecipeAndOpcode<Opcode, RecipeTy> {
122124 auto *DefR = dyn_cast<RecipeTy>(R);
123125 // Check for recipes that do not have opcodes.
124126 if constexpr (std::is_same<RecipeTy, VPScalarIVStepsRecipe>::value ||
125- std::is_same<RecipeTy, VPCanonicalIVPHIRecipe>::value)
127+ std::is_same<RecipeTy, VPCanonicalIVPHIRecipe>::value ||
128+ std::is_same<RecipeTy, VPWidenSelectRecipe>::value)
126129 return DefR;
127130 else
128131 return DefR && DefR->getOpcode () == Opcode;
@@ -322,10 +325,34 @@ m_c_BinaryOr(const Op0_t &Op0, const Op1_t &Op1) {
322325 return m_BinaryOr<Op0_t, Op1_t, /* Commutative*/ true >(Op0, Op1);
323326}
324327
328+ template <typename Op0_t, typename Op1_t, typename Op2_t, unsigned Opcode>
329+ using AllTernaryRecipe_match =
330+ Recipe_match<std::tuple<Op0_t, Op1_t, Op2_t>, Opcode, false ,
331+ VPReplicateRecipe, VPInstruction, VPWidenSelectRecipe>;
332+
333+ template <typename Op0_t, typename Op1_t, typename Op2_t>
334+ inline AllTernaryRecipe_match<Op0_t, Op1_t, Op2_t, Instruction::Select>
335+ m_Select (const Op0_t &Op0, const Op1_t &Op1, const Op2_t &Op2) {
336+ return AllTernaryRecipe_match<Op0_t, Op1_t, Op2_t, Instruction::Select>(
337+ {Op0, Op1, Op2});
338+ }
339+
325340template <typename Op0_t, typename Op1_t>
326- inline BinaryVPInstruction_match<Op0_t, Op1_t, VPInstruction::LogicalAnd>
341+ inline match_combine_or<
342+ BinaryVPInstruction_match<Op0_t, Op1_t, VPInstruction::LogicalAnd>,
343+ AllTernaryRecipe_match<Op0_t, Op1_t, specific_intval<1 >,
344+ Instruction::Select>>
327345m_LogicalAnd (const Op0_t &Op0, const Op1_t &Op1) {
328- return m_VPInstruction<VPInstruction::LogicalAnd, Op0_t, Op1_t>(Op0, Op1);
346+ return m_CombineOr (
347+ m_VPInstruction<VPInstruction::LogicalAnd, Op0_t, Op1_t>(Op0, Op1),
348+ m_Select (Op0, Op1, m_False ()));
349+ }
350+
351+ template <typename Op0_t, typename Op1_t>
352+ inline AllTernaryRecipe_match<Op0_t, specific_intval<1 >, Op1_t,
353+ Instruction::Select>
354+ m_LogicalOr (const Op0_t &Op0, const Op1_t &Op1) {
355+ return m_Select (Op0, m_True (), Op1);
329356}
330357
331358using VPCanonicalIVPHI_match =
@@ -344,7 +371,6 @@ inline VPScalarIVSteps_match<Op0_t, Op1_t> m_ScalarIVSteps(const Op0_t &Op0,
344371 const Op1_t &Op1) {
345372 return VPScalarIVSteps_match<Op0_t, Op1_t>(Op0, Op1);
346373}
347-
348374} // namespace VPlanPatternMatch
349375} // namespace llvm
350376
0 commit comments