LLVM 24.0.0git
SDPatternMatch.h
Go to the documentation of this file.
1//==--------------- llvm/CodeGen/SDPatternMatch.h ---------------*- 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/// \file
9/// Contains matchers for matching SelectionDAG nodes and values.
10///
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_CODEGEN_SDPATTERNMATCH_H
14#define LLVM_CODEGEN_SDPATTERNMATCH_H
15
16#include "llvm/ADT/APInt.h"
17#include "llvm/ADT/ArrayRef.h"
18#include "llvm/ADT/STLExtras.h"
20#include "llvm/ADT/bit.h"
26
27#include <type_traits>
28
29namespace llvm {
30namespace SDPatternMatch {
31
32template <typename Pattern>
33[[nodiscard]] bool sd_match(SDValue N, Pattern &&P) {
34 return P.match(N);
35}
36
37template <typename Pattern>
38[[nodiscard]] bool sd_match(SDNode *N, Pattern &&P) {
39 return sd_match(SDValue(N, 0), P);
40}
41
42// === Utilities ===
45
46 Value_match() = default;
47
48 explicit Value_match(SDValue Match) : MatchVal(Match) {}
49
50 bool match(SDValue N) {
51 if (MatchVal)
52 return MatchVal == N;
53 return N.getNode();
54 }
55};
56
57/// Match any valid SDValue.
58inline Value_match m_Value() { return Value_match(); }
59
61 assert(N);
62 return Value_match(N);
63}
64
65template <unsigned ResNo, typename Pattern> struct Result_match {
67
68 explicit Result_match(const Pattern &P) : P(P) {}
69
70 bool match(SDValue N) { return N.getResNo() == ResNo && P.match(N); }
71};
72
73/// Match only if the SDValue is a certain result at ResNo.
74template <unsigned ResNo, typename Pattern>
78
81
82 explicit DeferredValue_match(SDValue &Match) : MatchVal(Match) {}
83
84 bool match(SDValue N) { return N == MatchVal; }
85};
86
87/// Similar to m_Specific, but the specific value to match is determined by
88/// another sub-pattern in the same sd_match() expression. For instance,
89/// We cannot match `(add V, V)` with `m_Add(m_Value(X), m_Specific(X))` since
90/// `X` is not initialized at the time it got copied into `m_Specific`. Instead,
91/// we should use `m_Add(m_Value(X), m_Deferred(X))`.
95
97 unsigned Opcode;
98
99 explicit Opcode_match(unsigned Opc) : Opcode(Opc) {}
100
101 bool match(SDValue N) { return N->getOpcode() == Opcode; }
102};
103
104template <unsigned Opcode> struct FixedOpcode_match {
105 bool match(SDValue N) { return N->getOpcode() == Opcode; }
106};
107
108// === Patterns combinators ===
109template <typename... Preds> struct And {
110 bool match(SDValue N) { return true; }
111};
112
113template <typename Pred, typename... Preds>
114struct And<Pred, Preds...> : And<Preds...> {
115 Pred P;
116 And(const Pred &p, const Preds &...preds) : And<Preds...>(preds...), P(p) {}
117
118 bool match(SDValue N) { return P.match(N) && And<Preds...>::match(N); }
119};
120
121template <typename... Preds> struct Or {
122 bool match(SDValue N) { return false; }
123};
124
125template <typename Pred, typename... Preds>
126struct Or<Pred, Preds...> : Or<Preds...> {
127 Pred P;
128 Or(const Pred &p, const Preds &...preds) : Or<Preds...>(preds...), P(p) {}
129
130 bool match(SDValue N) { return P.match(N) || Or<Preds...>::match(N); }
131};
132
133template <typename Pred> struct Not {
134 Pred P;
135
136 explicit Not(const Pred &P) : P(P) {}
137
138 bool match(SDValue N) { return !P.match(N); }
139};
140// Explicit deduction guide.
141template <typename Pred> Not(const Pred &P) -> Not<Pred>;
142
143/// Match if the inner pattern does NOT match.
144template <typename Pred> inline Not<Pred> m_Unless(const Pred &P) {
145 return Not{P};
146}
147
148template <typename... Preds> And<Preds...> m_AllOf(const Preds &...preds) {
149 return And<Preds...>(preds...);
150}
151
152template <typename... Preds> Or<Preds...> m_AnyOf(const Preds &...preds) {
153 return Or<Preds...>(preds...);
154}
155
156template <typename... Preds> auto m_NoneOf(const Preds &...preds) {
157 return m_Unless(m_AnyOf(preds...));
158}
159
160template <unsigned Opcode> inline auto m_SpecificOpc() {
162}
163
164inline Opcode_match m_SpecificOpc(unsigned Opcode) {
165 return Opcode_match(Opcode);
166}
167
168inline auto m_Undef() {
170}
171
173
174template <unsigned NumUses, typename Pattern> struct NUses_match {
176
177 explicit NUses_match(const Pattern &P) : P(P) {}
178
180 // SDNode::hasNUsesOfValue is pretty expensive when the SDNode produces
181 // multiple results, hence we check the subsequent pattern here before
182 // checking the number of value users.
183 return P.match(N) && N->hasNUsesOfValue(NumUses, N.getResNo());
184 }
185};
186
187template <typename Pattern>
191template <unsigned N, typename Pattern>
195
199template <unsigned N> inline NUses_match<N, Value_match> m_NUses() {
201}
202
205
207
209 BindVal = N;
210 return true;
211 }
212};
213
214inline auto m_Value(SDValue &N) { return Value_bind(N); }
215/// Conditionally bind an SDValue based on the predicate.
216template <typename PredPattern>
217inline auto m_Value(SDValue &N, const PredPattern &P) {
218 return m_AllOf(P, Value_bind(N));
219}
220
221template <typename Pattern, typename PredFuncT> struct TLI_pred_match {
223 PredFuncT PredFunc;
224
225 TLI_pred_match(const PredFuncT &Pred, const Pattern &P)
226 : P(P), PredFunc(Pred) {}
227
228 bool match(SDValue N) { return PredFunc(N) && P.match(N); }
229};
230
231// Explicit deduction guide.
232template <typename PredFuncT, typename Pattern>
233TLI_pred_match(const PredFuncT &Pred, const Pattern &P)
235
236/// Match legal SDNodes based on the information provided by TargetLowering.
237template <typename Pattern>
238inline auto m_LegalOp(const SelectionDAG &DAG, const Pattern &P) {
239 return TLI_pred_match{[&DAG](SDValue N) {
241 N->getOpcode(), N.getValueType());
242 },
243 P};
244}
245
246// === Value type ===
247
248template <typename Pattern> struct ValueType_bind {
251
252 explicit ValueType_bind(EVT &Bind, const Pattern &P) : BindVT(Bind), P(P) {}
253
255 BindVT = N.getValueType();
256 return P.match(N);
257 }
258};
259
260template <typename Pattern>
262
263/// Retreive the ValueType of the current SDValue.
264inline auto m_VT(EVT &VT) { return ValueType_bind(VT, m_Value()); }
265
266template <typename Pattern> inline auto m_VT(EVT &VT, const Pattern &P) {
267 return ValueType_bind(VT, P);
268}
269
270template <typename Pattern, typename PredFuncT> struct ValueType_match {
271 PredFuncT PredFunc;
273
274 ValueType_match(const PredFuncT &Pred, const Pattern &P)
275 : PredFunc(Pred), P(P) {}
276
277 bool match(SDValue N) { return PredFunc(N.getValueType()) && P.match(N); }
278};
279
280// Explicit deduction guide.
281template <typename PredFuncT, typename Pattern>
282ValueType_match(const PredFuncT &Pred, const Pattern &P)
284
285/// Match a specific ValueType.
286template <typename Pattern>
287inline auto m_SpecificVT(EVT RefVT, const Pattern &P) {
288 return ValueType_match{[=](EVT VT) { return VT == RefVT; }, P};
289}
290inline auto m_SpecificVT(EVT RefVT) {
291 return ValueType_match{[=](EVT VT) { return VT == RefVT; }, m_Value()};
292}
293
294inline auto m_Glue() { return m_SpecificVT(MVT::Glue); }
295inline auto m_OtherVT() { return m_SpecificVT(MVT::Other); }
296
297/// Match a scalar ValueType.
298template <typename Pattern>
299inline auto m_SpecificScalarVT(EVT RefVT, const Pattern &P) {
300 return ValueType_match{[=](EVT VT) { return VT.getScalarType() == RefVT; },
301 P};
302}
303inline auto m_SpecificScalarVT(EVT RefVT) {
304 return ValueType_match{[=](EVT VT) { return VT.getScalarType() == RefVT; },
305 m_Value()};
306}
307
308/// Match a vector ValueType.
309template <typename Pattern>
310inline auto m_SpecificVectorElementVT(EVT RefVT, const Pattern &P) {
311 return ValueType_match{[=](EVT VT) {
312 return VT.isVector() &&
313 VT.getVectorElementType() == RefVT;
314 },
315 P};
316}
317inline auto m_SpecificVectorElementVT(EVT RefVT) {
318 return ValueType_match{[=](EVT VT) {
319 return VT.isVector() &&
320 VT.getVectorElementType() == RefVT;
321 },
322 m_Value()};
323}
324
325/// Match any integer ValueTypes.
326template <typename Pattern> inline auto m_IntegerVT(const Pattern &P) {
327 return ValueType_match{[](EVT VT) { return VT.isInteger(); }, P};
328}
329inline auto m_IntegerVT() {
330 return ValueType_match{[](EVT VT) { return VT.isInteger(); }, m_Value()};
331}
332
333/// Match any floating point ValueTypes.
334template <typename Pattern> inline auto m_FloatingPointVT(const Pattern &P) {
335 return ValueType_match{[](EVT VT) { return VT.isFloatingPoint(); }, P};
336}
337inline auto m_FloatingPointVT() {
338 return ValueType_match{[](EVT VT) { return VT.isFloatingPoint(); },
339 m_Value()};
340}
341
342/// Match any vector ValueTypes.
343template <typename Pattern> inline auto m_VectorVT(const Pattern &P) {
344 return ValueType_match{[](EVT VT) { return VT.isVector(); }, P};
345}
346inline auto m_VectorVT() {
347 return ValueType_match{[](EVT VT) { return VT.isVector(); }, m_Value()};
348}
349
350/// Match fixed-length vector ValueTypes.
351template <typename Pattern> inline auto m_FixedVectorVT(const Pattern &P) {
352 return ValueType_match{[](EVT VT) { return VT.isFixedLengthVector(); }, P};
353}
354inline auto m_FixedVectorVT() {
355 return ValueType_match{[](EVT VT) { return VT.isFixedLengthVector(); },
356 m_Value()};
357}
358
359/// Match scalable vector ValueTypes.
360template <typename Pattern> inline auto m_ScalableVectorVT(const Pattern &P) {
361 return ValueType_match{[](EVT VT) { return VT.isScalableVector(); }, P};
362}
363inline auto m_ScalableVectorVT() {
364 return ValueType_match{[](EVT VT) { return VT.isScalableVector(); },
365 m_Value()};
366}
367
368/// Match legal ValueTypes based on the information provided by TargetLowering.
369template <typename Pattern>
370inline auto m_LegalType(const SelectionDAG &DAG, const Pattern &P) {
371 return TLI_pred_match{[&DAG](SDValue N) {
373 N.getValueType());
374 },
375 P};
376}
377
378// === Generic node matching ===
379template <unsigned OpIdx, typename... OpndPreds> struct Operands_match {
381 // Returns false if there are more operands than predicates;
382 return N->getNumOperands() == OpIdx;
383 }
384};
385
386template <unsigned OpIdx, typename OpndPred, typename... OpndPreds>
387struct Operands_match<OpIdx, OpndPred, OpndPreds...>
388 : Operands_match<OpIdx + 1, OpndPreds...> {
389 OpndPred P;
390
391 Operands_match(const OpndPred &p, const OpndPreds &...preds)
392 : Operands_match<OpIdx + 1, OpndPreds...>(preds...), P(p) {}
393
395 if (OpIdx < N->getNumOperands())
396 return P.match(N->getOperand(OpIdx)) &&
398
399 // This is the case where there are more predicates than operands.
400 return false;
401 }
402};
403
404template <unsigned Opcode, typename... OpndPreds>
405auto m_Node(const OpndPreds &...Preds) {
408}
409
410template <typename... OpndPreds>
411auto m_Node(unsigned Opcode, const OpndPreds &...preds) {
412 return m_AllOf(m_SpecificOpc(Opcode),
414}
415
416/// Provide number of operands that are not chain or glue, as well as the first
417/// index of such operand.
418template <bool ExcludeChain> struct EffectiveOperands {
419 unsigned Size = 0;
420 unsigned FirstIndex = 0;
421
422 explicit EffectiveOperands(SDValue N) : Size(N->getNumOperands()) {
423 if (ExcludeChain) {
424 // Glue if present, is the last operand.
425 if (Size != 0 && N->getOperand(Size - 1).getValueType() == MVT::Glue)
426 --Size;
427 // Chain if present, is the first operand.
428 if (Size != 0 && N->getOperand(0).getValueType() == MVT::Other) {
429 ++FirstIndex;
430 --Size;
431 }
432 }
433 }
434};
435
436// === Ternary operations ===
437template <typename T0_P, typename T1_P, typename T2_P, bool Commutable = false,
438 bool ExcludeChain = false>
440 unsigned Opcode;
441 T0_P Op0;
442 T1_P Op1;
443 T2_P Op2;
444
445 TernaryOpc_match(unsigned Opc, const T0_P &Op0, const T1_P &Op1,
446 const T2_P &Op2)
447 : Opcode(Opc), Op0(Op0), Op1(Op1), Op2(Op2) {}
448
452 assert(EO.Size == 3);
453 return ((Op0.match(N->getOperand(EO.FirstIndex)) &&
454 Op1.match(N->getOperand(EO.FirstIndex + 1))) ||
455 (Commutable && Op0.match(N->getOperand(EO.FirstIndex + 1)) &&
456 Op1.match(N->getOperand(EO.FirstIndex)))) &&
457 Op2.match(N->getOperand(EO.FirstIndex + 2));
458 }
459
460 return false;
461 }
462};
463
465 std::optional<ISD::CondCode> CCToMatch;
467
469
471
473 if (auto *CC = dyn_cast<CondCodeSDNode>(N.getNode())) {
474 if (CCToMatch && *CCToMatch != CC->get())
475 return false;
476
477 if (BindCC)
478 *BindCC = CC->get();
479 return true;
480 }
481
482 return false;
483 }
484};
485
486/// Match any conditional code SDNode.
487inline CondCode_match m_CondCode() { return CondCode_match(nullptr); }
488/// Match any conditional code SDNode and return its ISD::CondCode value.
492/// Match a conditional code SDNode with a specific ISD::CondCode.
496
497/// Match a SETCC with any condition code.
498template <typename T0_P, typename T1_P>
504
505/// Match a SETCC with any condition code and bind the condition code to CC.
506template <typename T0_P, typename T1_P>
507inline TernaryOpc_match<T0_P, T1_P, CondCode_match>
512
513/// Match a SETCC with a specific condition code.
514template <typename T0_P, typename T1_P>
515inline TernaryOpc_match<T0_P, T1_P, CondCode_match>
520
521/// Match a SETCC with any condition code, allowing the operands to be
522/// commuted.
523template <typename T0_P, typename T1_P>
524inline TernaryOpc_match<T0_P, T1_P, CondCode_match, true, false>
529
530/// Match a SETCC with any condition code, allowing the operands to be
531/// commuted, and bind the condition code to CC.
532template <typename T0_P, typename T1_P>
533inline TernaryOpc_match<T0_P, T1_P, CondCode_match, true, false>
538
539/// Match a SETCC with a specific condition code, allowing the operands to be
540/// commuted.
541template <typename T0_P, typename T1_P>
542inline TernaryOpc_match<T0_P, T1_P, CondCode_match, true, false>
547
548template <typename T0_P, typename T1_P, typename T2_P>
549inline TernaryOpc_match<T0_P, T1_P, T2_P>
550m_Select(const T0_P &Cond, const T1_P &T, const T2_P &F) {
552}
553
554template <typename T0_P, typename T1_P, typename T2_P>
555inline TernaryOpc_match<T0_P, T1_P, T2_P>
556m_VSelect(const T0_P &Cond, const T1_P &T, const T2_P &F) {
558}
559
560template <typename T0_P, typename T1_P, typename T2_P>
561inline auto m_SelectLike(const T0_P &Cond, const T1_P &T, const T2_P &F) {
562 return m_AnyOf(m_Select(Cond, T, F), m_VSelect(Cond, T, F));
563}
564
565template <typename T0_P, typename T1_P, typename T2_P>
566inline Result_match<0, TernaryOpc_match<T0_P, T1_P, T2_P>>
567m_Load(const T0_P &Ch, const T1_P &Ptr, const T2_P &Offset) {
568 return m_Result<0>(
570}
571
572template <typename T0_P, typename T1_P, typename T2_P>
573inline TernaryOpc_match<T0_P, T1_P, T2_P>
574m_InsertElt(const T0_P &Vec, const T1_P &Val, const T2_P &Idx) {
576 Idx);
577}
578
579template <typename LHS, typename RHS, typename IDX>
580inline TernaryOpc_match<LHS, RHS, IDX>
581m_InsertSubvector(const LHS &Base, const RHS &Sub, const IDX &Idx) {
583}
584
585template <typename T0_P, typename T1_P, typename T2_P>
586inline TernaryOpc_match<T0_P, T1_P, T2_P>
587m_SpliceRight(const T0_P &V1, const T1_P &V2, const T2_P &Offset) {
589 Offset);
590}
591
592template <typename T0_P, typename T1_P, typename T2_P>
593inline TernaryOpc_match<T0_P, T1_P, T2_P>
594m_TernaryOp(unsigned Opc, const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
595 return TernaryOpc_match<T0_P, T1_P, T2_P>(Opc, Op0, Op1, Op2);
596}
597
598template <typename T0_P, typename T1_P, typename T2_P>
599inline TernaryOpc_match<T0_P, T1_P, T2_P, true>
600m_c_TernaryOp(unsigned Opc, const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
601 return TernaryOpc_match<T0_P, T1_P, T2_P, true>(Opc, Op0, Op1, Op2);
602}
603
604/// Match a SELECT_CC with any condition code.
605template <typename LTy, typename RTy, typename TTy, typename FTy>
606inline auto m_SelectCC(const LTy &L, const RTy &R, const TTy &T, const FTy &F) {
607 return m_Node(ISD::SELECT_CC, L, R, T, F, m_CondCode());
608}
609
610/// Match a SELECT_CC with any condition code and bind the condition code to
611/// CC.
612template <typename LTy, typename RTy, typename TTy, typename FTy>
613inline auto m_SelectCC(ISD::CondCode &CC, const LTy &L, const RTy &R,
614 const TTy &T, const FTy &F) {
615 return m_Node(ISD::SELECT_CC, L, R, T, F, m_CondCode(CC));
616}
617
618/// Match a SELECT_CC with a specific condition code.
619template <typename LTy, typename RTy, typename TTy, typename FTy>
620inline auto m_SpecificSelectCC(ISD::CondCode CC, const LTy &L, const RTy &R,
621 const TTy &T, const FTy &F) {
622 return m_Node(ISD::SELECT_CC, L, R, T, F, m_SpecificCondCode(CC));
623}
624
625/// Match a SELECT of a SETCC or a SELECT_CC with any condition code.
626template <typename LTy, typename RTy, typename TTy, typename FTy>
627inline auto m_SelectCCLike(const LTy &L, const RTy &R, const TTy &T,
628 const FTy &F) {
629 return m_AnyOf(m_Select(m_SetCC(L, R), T, F), m_SelectCC(L, R, T, F));
630}
631
632/// Match a SELECT of a SETCC or a SELECT_CC with any condition code and bind
633/// the condition code to CC.
634template <typename LTy, typename RTy, typename TTy, typename FTy>
635inline auto m_SelectCCLike(ISD::CondCode &CC, const LTy &L, const RTy &R,
636 const TTy &T, const FTy &F) {
637 return m_AnyOf(m_Select(m_SetCC(CC, L, R), T, F), m_SelectCC(CC, L, R, T, F));
638}
639
640/// Match a SELECT of a SETCC or a SELECT_CC with a specific condition code.
641template <typename LTy, typename RTy, typename TTy, typename FTy>
642inline auto m_SpecificSelectCCLike(ISD::CondCode CC, const LTy &L, const RTy &R,
643 const TTy &T, const FTy &F) {
644 return m_AnyOf(m_Select(m_SpecificSetCC(CC, L, R), T, F),
645 m_SpecificSelectCC(CC, L, R, T, F));
646}
647
648// === Binary operations ===
649template <typename LHS_P, typename RHS_P, bool Commutable = false,
650 bool ExcludeChain = false>
652 unsigned Opcode;
653 LHS_P LHS;
654 RHS_P RHS;
656 BinaryOpc_match(unsigned Opc, const LHS_P &L, const RHS_P &R,
657 SDNodeFlags Flgs = SDNodeFlags())
658 : Opcode(Opc), LHS(L), RHS(R), Flags(Flgs) {}
659
663 assert(EO.Size == 2);
664 if (!((LHS.match(N->getOperand(EO.FirstIndex)) &&
665 RHS.match(N->getOperand(EO.FirstIndex + 1))) ||
666 (Commutable && LHS.match(N->getOperand(EO.FirstIndex + 1)) &&
667 RHS.match(N->getOperand(EO.FirstIndex)))))
668 return false;
669
670 return (Flags & N->getFlags()) == Flags;
671 }
672
673 return false;
674 }
675};
676
677/// Matching while capturing mask
678template <typename T0, typename T1, typename T2> struct SDShuffle_match {
679 T0 Op1;
682
683 SDShuffle_match(const T0 &Op1, const T1 &Op2, const T2 &Mask)
684 : Op1(Op1), Op2(Op2), Mask(Mask) {}
685
687 if (auto *I = dyn_cast<ShuffleVectorSDNode>(N)) {
688 return Op1.match(I->getOperand(0)) && Op2.match(I->getOperand(1)) &&
689 Mask.match(I->getMask());
690 }
691 return false;
692 }
693};
694struct m_Mask {
697 bool match(ArrayRef<int> Mask) {
698 MaskRef = Mask;
699 return true;
700 }
701};
702
708
709template <typename LHS_P, typename RHS_P, typename Pred_t,
710 bool Commutable = false>
712 using PredType = Pred_t;
713 LHS_P LHS;
714 RHS_P RHS;
715
716 MaxMin_match(const LHS_P &L, const RHS_P &R) : LHS(L), RHS(R) {}
717
719 auto MatchMinMax = [&](SDValue L, SDValue R, SDValue TrueValue,
720 SDValue FalseValue, ISD::CondCode CC) {
721 if ((TrueValue != L || FalseValue != R) &&
722 (TrueValue != R || FalseValue != L))
723 return false;
724
726 TrueValue == L ? CC : getSetCCInverse(CC, L.getValueType());
727 if (!Pred_t::match(Cond))
728 return false;
729
730 return (LHS.match(L) && RHS.match(R)) ||
731 (Commutable && LHS.match(R) && RHS.match(L));
732 };
733
734 if (N.getOpcode() == ISD::SELECT || N.getOpcode() == ISD::VSELECT) {
735 assert(N.getNumOperands() == 3);
736 SDValue Cond = N.getOperand(0);
737 SDValue TrueValue = N.getOperand(1);
738 SDValue FalseValue = N.getOperand(2);
739
740 if (Cond.getOpcode() == ISD::SETCC) {
741 assert(Cond.getNumOperands() == 3);
742 SDValue L = Cond.getOperand(0);
743 SDValue R = Cond.getOperand(1);
744 ISD::CondCode CC = cast<CondCodeSDNode>(Cond.getOperand(2))->get();
745 return MatchMinMax(L, R, TrueValue, FalseValue, CC);
746 }
747 }
748
749 if (N.getOpcode() == ISD::SELECT_CC) {
750 assert(N.getNumOperands() == 5);
751 SDValue L = N.getOperand(0);
752 SDValue R = N.getOperand(1);
753 SDValue TrueValue = N.getOperand(2);
754 SDValue FalseValue = N.getOperand(3);
755 ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(4))->get();
756 return MatchMinMax(L, R, TrueValue, FalseValue, CC);
757 }
758
759 return false;
760 }
761};
762
763// Helper class for identifying signed max predicates.
765 static bool match(ISD::CondCode Cond) {
767 }
768};
769
770// Helper class for identifying unsigned max predicates.
775};
776
777// Helper class for identifying signed min predicates.
779 static bool match(ISD::CondCode Cond) {
781 }
782};
783
784// Helper class for identifying unsigned min predicates.
789};
790
791template <typename LHS, typename RHS>
792inline BinaryOpc_match<LHS, RHS> m_BinOp(unsigned Opc, const LHS &L,
793 const RHS &R,
794 SDNodeFlags Flgs = SDNodeFlags()) {
795 return BinaryOpc_match<LHS, RHS>(Opc, L, R, Flgs);
796}
797template <typename LHS, typename RHS>
799m_c_BinOp(unsigned Opc, const LHS &L, const RHS &R,
800 SDNodeFlags Flgs = SDNodeFlags()) {
801 return BinaryOpc_match<LHS, RHS, true>(Opc, L, R, Flgs);
802}
803
804template <typename LHS, typename RHS>
806m_ChainedBinOp(unsigned Opc, const LHS &L, const RHS &R) {
808}
809template <typename LHS, typename RHS>
811m_c_ChainedBinOp(unsigned Opc, const LHS &L, const RHS &R) {
813}
814
815// Common binary operations
816template <typename LHS, typename RHS>
817inline BinaryOpc_match<LHS, RHS, true> m_Add(const LHS &L, const RHS &R) {
819}
820
821template <typename LHS, typename RHS>
822inline auto m_NUWAdd(const LHS &L, const RHS &R) {
825}
826
827template <typename LHS, typename RHS>
828inline auto m_NSWAdd(const LHS &L, const RHS &R) {
831}
832
833template <typename LHS, typename RHS>
834inline BinaryOpc_match<LHS, RHS> m_Sub(const LHS &L, const RHS &R) {
836}
837
838template <typename LHS, typename RHS>
839inline BinaryOpc_match<LHS, RHS, true> m_Mul(const LHS &L, const RHS &R) {
841}
842
843template <typename LHS, typename RHS>
844inline BinaryOpc_match<LHS, RHS, true> m_And(const LHS &L, const RHS &R) {
846}
847
848template <typename LHS, typename RHS>
849inline BinaryOpc_match<LHS, RHS, true> m_Or(const LHS &L, const RHS &R) {
851}
852
853template <typename LHS, typename RHS>
858
859template <typename LHS, typename RHS>
860inline auto m_AddLike(const LHS &L, const RHS &R) {
861 return m_AnyOf(m_Add(L, R), m_DisjointOr(L, R));
862}
863
864template <typename LHS, typename RHS>
865inline auto m_NSWAddLike(const LHS &L, const RHS &R) {
866 return m_AnyOf(m_NSWAdd(L, R), m_DisjointOr(L, R));
867}
868
869template <typename LHS, typename RHS>
870inline auto m_NUWAddLike(const LHS &L, const RHS &R) {
871 return m_AnyOf(m_NUWAdd(L, R), m_DisjointOr(L, R));
872}
873
874template <typename LHS, typename RHS>
875inline BinaryOpc_match<LHS, RHS, true> m_Xor(const LHS &L, const RHS &R) {
877}
878
879template <typename LHS, typename RHS>
880inline auto m_BitwiseLogic(const LHS &L, const RHS &R) {
881 return m_AnyOf(m_And(L, R), m_Or(L, R), m_Xor(L, R));
882}
883
884template <unsigned Opc, typename Pred, typename LHS, typename RHS>
885inline auto m_MaxMinLike(const LHS &L, const RHS &R) {
888}
889
890template <typename LHS, typename RHS>
891inline BinaryOpc_match<LHS, RHS, true> m_SMin(const LHS &L, const RHS &R) {
893}
894
895template <typename LHS, typename RHS>
896inline auto m_SMinLike(const LHS &L, const RHS &R) {
898}
899
900template <typename LHS, typename RHS>
901inline BinaryOpc_match<LHS, RHS, true> m_SMax(const LHS &L, const RHS &R) {
903}
904
905template <typename LHS, typename RHS>
906inline auto m_SMaxLike(const LHS &L, const RHS &R) {
908}
909
910template <typename LHS, typename RHS>
911inline BinaryOpc_match<LHS, RHS, true> m_UMin(const LHS &L, const RHS &R) {
913}
914
915template <typename LHS, typename RHS>
916inline auto m_UMinLike(const LHS &L, const RHS &R) {
918}
919
920template <typename LHS, typename RHS>
921inline BinaryOpc_match<LHS, RHS, true> m_UMax(const LHS &L, const RHS &R) {
923}
924
925template <typename LHS, typename RHS>
926inline auto m_UMaxLike(const LHS &L, const RHS &R) {
928}
929
930template <typename LHS, typename RHS>
931inline BinaryOpc_match<LHS, RHS> m_UDiv(const LHS &L, const RHS &R) {
933}
934template <typename LHS, typename RHS>
935inline BinaryOpc_match<LHS, RHS> m_SDiv(const LHS &L, const RHS &R) {
937}
938
939template <typename LHS, typename RHS>
940inline BinaryOpc_match<LHS, RHS> m_URem(const LHS &L, const RHS &R) {
942}
943template <typename LHS, typename RHS>
944inline BinaryOpc_match<LHS, RHS> m_SRem(const LHS &L, const RHS &R) {
946}
947
948template <typename LHS, typename RHS>
949inline BinaryOpc_match<LHS, RHS> m_Shl(const LHS &L, const RHS &R) {
951}
952
953template <typename LHS, typename RHS>
954inline BinaryOpc_match<LHS, RHS> m_Sra(const LHS &L, const RHS &R) {
956}
957template <typename LHS, typename RHS>
958inline BinaryOpc_match<LHS, RHS> m_Srl(const LHS &L, const RHS &R) {
960}
961template <typename LHS, typename RHS>
966
967template <typename LHS, typename RHS>
968inline BinaryOpc_match<LHS, RHS> m_Rotl(const LHS &L, const RHS &R) {
970}
971
972template <typename LHS, typename RHS>
973inline BinaryOpc_match<LHS, RHS> m_Rotr(const LHS &L, const RHS &R) {
975}
976
977template <typename T0_P, typename T1_P, typename T2_P>
978inline TernaryOpc_match<T0_P, T1_P, T2_P>
979m_FShL(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
980 return m_TernaryOp(ISD::FSHL, Op0, Op1, Op2);
981}
982
983template <typename T0_P, typename T1_P, typename T2_P>
984inline TernaryOpc_match<T0_P, T1_P, T2_P>
985m_FShR(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
986 return m_TernaryOp(ISD::FSHR, Op0, Op1, Op2);
987}
988
989template <typename T0_P, typename T1_P, typename T2_P, bool Left>
991 T0_P Op0;
992 T1_P Op1;
993 T2_P Op2;
994
995 FunnelShiftLike_match(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2)
996 : Op0(Op0), Op1(Op1), Op2(Op2) {}
997
998 static bool hasComplementaryConstantShifts(const APInt &ShlV,
999 const APInt &SrlV,
1000 unsigned BitWidth) {
1001 unsigned SumWidth = std::max(ShlV.getBitWidth(), SrlV.getBitWidth()) + 1;
1002 unsigned BitWidthBits = llvm::bit_width(BitWidth);
1003 if (BitWidthBits > SumWidth)
1004 return false;
1005
1006 return ShlV.zext(SumWidth) + SrlV.zext(SumWidth) ==
1007 APInt(SumWidth, BitWidth);
1008 }
1009
1011 return Op0.match(X) && Op1.match(Y) && Op2.match(Z);
1012 }
1013
1014 bool matchShiftOr(SDValue N, unsigned BitWidth);
1015
1017 if (sd_match(N, Left ? m_FShL(Op0, Op1, Op2) : m_FShR(Op0, Op1, Op2)))
1018 return true;
1019
1020 SDValue X, Z;
1021 if (sd_match(N, Left ? m_Rotl(m_Value(X), m_Value(Z))
1022 : m_Rotr(m_Value(X), m_Value(Z))))
1023 return matchOperands(X, X, Z);
1024
1025 return matchShiftOr(N, N.getValueType().getScalarSizeInBits());
1026 }
1027};
1028
1029template <typename T0_P, typename T1_P, typename T2_P>
1030inline FunnelShiftLike_match<T0_P, T1_P, T2_P, true>
1031m_FShLLike(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
1033}
1034
1035template <typename T0_P, typename T1_P, typename T2_P>
1036inline FunnelShiftLike_match<T0_P, T1_P, T2_P, false>
1037m_FShRLike(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
1039}
1040
1041template <typename LHS, typename RHS>
1044}
1045
1046template <typename LHS, typename RHS>
1047inline BinaryOpc_match<LHS, RHS, true> m_FAdd(const LHS &L, const RHS &R) {
1049}
1050
1051template <typename LHS, typename RHS>
1052inline BinaryOpc_match<LHS, RHS> m_FSub(const LHS &L, const RHS &R) {
1054}
1055
1056template <typename LHS, typename RHS>
1057inline BinaryOpc_match<LHS, RHS, true> m_FMul(const LHS &L, const RHS &R) {
1059}
1060
1061template <typename LHS, typename RHS>
1062inline BinaryOpc_match<LHS, RHS> m_FDiv(const LHS &L, const RHS &R) {
1064}
1065
1066template <typename LHS, typename RHS>
1067inline BinaryOpc_match<LHS, RHS> m_FRem(const LHS &L, const RHS &R) {
1069}
1070
1071template <typename V1_t, typename V2_t>
1072inline BinaryOpc_match<V1_t, V2_t> m_Shuffle(const V1_t &v1, const V2_t &v2) {
1074}
1075
1076template <typename V1_t, typename V2_t, typename Mask_t>
1077inline SDShuffle_match<V1_t, V2_t, Mask_t>
1078m_Shuffle(const V1_t &v1, const V2_t &v2, const Mask_t &mask) {
1080}
1081
1082template <typename LHS, typename RHS>
1083inline BinaryOpc_match<LHS, RHS> m_ExtractElt(const LHS &Vec, const RHS &Idx) {
1085}
1086
1087template <typename LHS, typename RHS>
1089 const RHS &Idx) {
1091}
1092
1093// === Unary operations ===
1094template <typename Opnd_P, bool ExcludeChain = false> struct UnaryOpc_match {
1095 unsigned Opcode;
1096 Opnd_P Opnd;
1098 UnaryOpc_match(unsigned Opc, const Opnd_P &Op,
1099 SDNodeFlags Flgs = SDNodeFlags())
1100 : Opcode(Opc), Opnd(Op), Flags(Flgs) {}
1101
1103 if (sd_match(N, m_SpecificOpc(Opcode))) {
1105 assert(EO.Size == 1);
1106 if (!Opnd.match(N->getOperand(EO.FirstIndex)))
1107 return false;
1108
1109 return (Flags & N->getFlags()) == Flags;
1110 }
1111
1112 return false;
1113 }
1114};
1115
1116template <typename Opnd>
1117inline UnaryOpc_match<Opnd> m_UnaryOp(unsigned Opc, const Opnd &Op) {
1118 return UnaryOpc_match<Opnd>(Opc, Op);
1119}
1120template <typename Opnd>
1122 const Opnd &Op) {
1124}
1125
1126template <typename Opnd> inline UnaryOpc_match<Opnd> m_BitCast(const Opnd &Op) {
1128}
1129
1130template <typename Opnd>
1131inline UnaryOpc_match<Opnd> m_BSwap(const Opnd &Op) {
1133}
1134
1135template <typename Opnd>
1139
1140template <typename Opnd> inline UnaryOpc_match<Opnd> m_ZExt(const Opnd &Op) {
1142}
1143
1144template <typename Opnd>
1148
1149template <typename Opnd> inline auto m_SExt(const Opnd &Op) {
1151}
1152
1153template <typename Opnd> inline UnaryOpc_match<Opnd> m_AnyExt(const Opnd &Op) {
1155}
1156
1157template <typename Opnd> inline UnaryOpc_match<Opnd> m_Trunc(const Opnd &Op) {
1159}
1160
1161template <typename Opnd> inline auto m_Abs(const Opnd &Op) {
1164}
1165
1166template <typename Opnd> inline UnaryOpc_match<Opnd> m_FAbs(const Opnd &Op) {
1168}
1169
1170/// Match a zext or identity
1171/// Allows to peek through optional extensions
1172template <typename Opnd> inline auto m_ZExtOrSelf(const Opnd &Op) {
1173 return m_AnyOf(m_ZExt(Op), Op);
1174}
1175
1176/// Match a sext or identity
1177/// Allows to peek through optional extensions
1178template <typename Opnd> inline auto m_SExtOrSelf(const Opnd &Op) {
1179 return m_AnyOf(m_SExt(Op), Op);
1180}
1181
1182template <typename Opnd> inline auto m_SExtLike(const Opnd &Op) {
1183 return m_AnyOf(m_SExt(Op), m_NNegZExt(Op));
1184}
1185
1186/// Match a zext or sext
1187template <typename Opnd> inline auto m_ZExtOrSExt(const Opnd &Op) {
1188 return m_AnyOf(m_ZExt(Op), m_SExt(Op));
1189}
1190
1191/// Match a aext or identity
1192/// Allows to peek through optional extensions
1193template <typename Opnd>
1194inline Or<UnaryOpc_match<Opnd>, Opnd> m_AExtOrSelf(const Opnd &Op) {
1195 return Or<UnaryOpc_match<Opnd>, Opnd>(m_AnyExt(Op), Op);
1196}
1197
1198/// Match a trunc or identity
1199/// Allows to peek through optional truncations
1200template <typename Opnd>
1201inline Or<UnaryOpc_match<Opnd>, Opnd> m_TruncOrSelf(const Opnd &Op) {
1202 return Or<UnaryOpc_match<Opnd>, Opnd>(m_Trunc(Op), Op);
1203}
1204
1205template <typename Opnd> inline UnaryOpc_match<Opnd> m_VScale(const Opnd &Op) {
1207}
1208
1209template <typename Opnd> inline UnaryOpc_match<Opnd> m_FPToUI(const Opnd &Op) {
1211}
1212
1213template <typename Opnd> inline UnaryOpc_match<Opnd> m_FPToSI(const Opnd &Op) {
1215}
1216
1217template <typename Opnd> inline UnaryOpc_match<Opnd> m_Ctpop(const Opnd &Op) {
1219}
1220
1221template <typename Opnd> inline UnaryOpc_match<Opnd> m_Ctlz(const Opnd &Op) {
1223}
1224
1225template <typename Opnd> inline UnaryOpc_match<Opnd> m_Cttz(const Opnd &Op) {
1227}
1228
1229template <typename Opnd> inline UnaryOpc_match<Opnd> m_FNeg(const Opnd &Op) {
1231}
1232
1233template <typename Opnd>
1237
1238// === Constants ===
1241
1242 explicit ConstantInt_match(APInt *V) : BindVal(V) {}
1243
1245 // The logics here are similar to that in
1246 // SelectionDAG::isConstantIntBuildVectorOrConstantInt, but the latter also
1247 // treats GlobalAddressSDNode as a constant, which is difficult to turn into
1248 // APInt.
1249 if (auto *C = dyn_cast_or_null<ConstantSDNode>(N.getNode())) {
1250 if (BindVal)
1251 *BindVal = C->getAPIntValue();
1252 return true;
1253 }
1254
1255 APInt Discard;
1256 return ISD::isConstantSplatVector(N.getNode(),
1257 BindVal ? *BindVal : Discard);
1258 }
1259};
1260
1261template <typename T> struct Constant64_match {
1262 static_assert(sizeof(T) == 8, "T must be 64 bits wide");
1263
1265
1266 explicit Constant64_match(T &V) : BindVal(V) {}
1267
1269 APInt V;
1270 if (!ConstantInt_match(&V).match(N))
1271 return false;
1272
1273 if constexpr (std::is_signed_v<T>) {
1274 if (std::optional<int64_t> TrySExt = V.trySExtValue()) {
1275 BindVal = *TrySExt;
1276 return true;
1277 }
1278 }
1279
1280 if constexpr (std::is_unsigned_v<T>) {
1281 if (std::optional<uint64_t> TryZExt = V.tryZExtValue()) {
1282 BindVal = *TryZExt;
1283 return true;
1284 }
1285 }
1286
1287 return false;
1288 }
1289};
1290
1291/// Match any integer constants or splat of an integer constant.
1293/// Match any integer constants or splat of an integer constant; return the
1294/// specific constant or constant splat value.
1296/// Match any integer constants or splat of an integer constant that can fit in
1297/// 64 bits; return the specific constant or constant splat value, zero-extended
1298/// to 64 bits.
1302/// Match any integer constants or splat of an integer constant that can fit in
1303/// 64 bits; return the specific constant or constant splat value, sign-extended
1304/// to 64 bits.
1306 return Constant64_match<int64_t>(V);
1307}
1308
1309template <typename T0_P, typename T1_P, typename T2_P, bool Left>
1311 SDValue N, unsigned BitWidth) {
1312 SDValue X, Y, ShlAmt, SrlAmt;
1313 APInt ShlConst, SrlConst;
1314 if (!sd_match(
1315 N, m_Or(m_Shl(m_Value(X), m_Value(ShlAmt, m_ConstInt(ShlConst))),
1316 m_Srl(m_Value(Y), m_Value(SrlAmt, m_ConstInt(SrlConst))))) ||
1317 !hasComplementaryConstantShifts(ShlConst, SrlConst, BitWidth))
1318 return false;
1319
1320 return matchOperands(X, Y, Left ? ShlAmt : SrlAmt);
1321}
1322
1325
1326 explicit SpecificInt_match(APInt APV) : IntVal(std::move(APV)) {}
1327
1329 APInt ConstInt;
1330 if (sd_match(N, m_ConstInt(ConstInt)))
1331 return APInt::isSameValue(IntVal, ConstInt);
1332 return false;
1333 }
1334};
1335
1336/// Match a specific integer constant or constant splat value.
1338 return SpecificInt_match(std::move(V));
1339}
1341 return SpecificInt_match(APInt(64, V));
1342}
1343
1346
1347 explicit SpecificFP_match(APFloat V) : Val(V) {}
1348
1349 bool match(SDValue V) {
1350 if (const auto *CFP = dyn_cast<ConstantFPSDNode>(V.getNode()))
1351 return CFP->isExactlyValue(Val);
1352 if (ConstantFPSDNode *C = isConstOrConstSplatFP(V, /*AllowUndefs=*/true))
1353 return C->getValueAPF().compare(Val) == APFloat::cmpEqual;
1354 return false;
1355 }
1356};
1357
1358/// Match a specific float constant.
1360
1362 return SpecificFP_match(APFloat(V));
1363}
1364
1368 return C->isZero();
1369 return false;
1370 }
1371};
1372
1373/// Match a floating-point +0.0 or -0.0 constant or splat.
1375
1378
1380
1381 bool match(SDValue N) const { return isZeroOrZeroSplat(N, AllowUndefs); }
1382};
1383
1391
1399
1400inline One_match m_One(bool AllowUndefs = false) {
1401 return One_match(AllowUndefs);
1402}
1403inline Zero_match m_Zero(bool AllowUndefs = false) {
1404 return Zero_match(AllowUndefs);
1405}
1406inline AllOnes_match m_AllOnes(bool AllowUndefs = false) {
1407 return AllOnes_match(AllowUndefs);
1408}
1409
1410template <bool Expected> struct Bool_match {
1412
1414
1416 auto Res = DAG.isBoolConstant(N);
1417 return Res && *Res == Expected;
1418 }
1419};
1420
1421/// Match true boolean value based on the information provided by
1422/// TargetLowering.
1423inline auto m_True(const SelectionDAG &DAG) { return Bool_match<true>(DAG); }
1424
1425/// Match false boolean value based on the information provided by
1426/// TargetLowering.
1427inline auto m_False(const SelectionDAG &DAG) { return Bool_match<false>(DAG); }
1428
1429/// Match a negate as a sub(0, v)
1430template <typename ValTy>
1432 return m_Sub(m_Zero(), V);
1433}
1434
1435/// Match a Not as a xor(v, -1) or xor(-1, v)
1436template <typename ValTy>
1438 return m_Xor(V, m_AllOnes());
1439}
1440
1441template <typename TS> struct TypeSize_match {
1443
1444 explicit TypeSize_match(TS &V) : BindVal(V) {}
1445
1447 bool Scalable;
1448 APInt KnownMin;
1449
1450 if (sd_match(N, m_VScale(m_ConstInt(KnownMin))))
1451 Scalable = true;
1452 else if (sd_match(N, m_ConstInt(KnownMin)))
1453 Scalable = false;
1454 else
1455 return false;
1456
1457 if (KnownMin.isNegative() ||
1458 !KnownMin.isIntN(std::numeric_limits<typename TS::ScalarTy>::digits))
1459 return false;
1460
1461 BindVal = TS::get(KnownMin.getZExtValue(), Scalable);
1462 return true;
1463 }
1464};
1465
1466/// Match any integer constant or constant multiple of VSCALE that can be
1467/// represented using ElementCount.
1471
1472template <unsigned IntrinsicId, typename... OpndPreds>
1473inline auto m_IntrinsicWOChain(const OpndPreds &...Opnds) {
1474 return m_Node(ISD::INTRINSIC_WO_CHAIN, m_SpecificInt(IntrinsicId), Opnds...);
1475}
1476
1479
1481
1483 if (sd_match(N, m_Neg(m_Specific(V))))
1484 return true;
1485
1488 return LHS->getAPIntValue() == -RHS->getAPIntValue();
1489 });
1490 }
1491};
1492
1493/// Match a negation of a specific value V, either as sub(0, V) or as
1494/// constant(s) that are the negation of V's constant(s).
1498
1499template <typename... PatternTs> struct ReassociatableOpc_match {
1500 unsigned Opcode;
1501 std::tuple<PatternTs...> Patterns;
1502 constexpr static size_t NumPatterns =
1503 std::tuple_size_v<std::tuple<PatternTs...>>;
1504
1506
1507 ReassociatableOpc_match(unsigned Opcode, const PatternTs &...Patterns)
1508 : Opcode(Opcode), Patterns(Patterns...) {}
1509
1511 const PatternTs &...Patterns)
1513
1515 std::array<SDValue, NumPatterns> Leaves;
1516 size_t LeavesIdx = 0;
1517 if (!(collectLeaves(N, Leaves, LeavesIdx) && (LeavesIdx == NumPatterns)))
1518 return false;
1519
1521 return std::apply(
1522 [&](auto &...P) -> bool {
1523 return reassociatableMatchHelper(Leaves, Used, P...);
1524 },
1525 Patterns);
1526 }
1527
1528 bool collectLeaves(SDValue V, std::array<SDValue, NumPatterns> &Leaves,
1529 std::size_t &LeafIdx) {
1530 if (V->getOpcode() == Opcode && (Flags & V->getFlags()) == Flags) {
1531 for (size_t I = 0, N = V->getNumOperands(); I < N; I++)
1532 if ((LeafIdx == NumPatterns) ||
1533 !collectLeaves(V->getOperand(I), Leaves, LeafIdx))
1534 return false;
1535 } else {
1536 Leaves[LeafIdx] = V;
1537 LeafIdx++;
1538 }
1539 return true;
1540 }
1541
1542 // Searchs for a matching leaf for every sub-pattern.
1543 template <typename PatternHd, typename... PatternTl>
1544 [[nodiscard]] inline bool
1546 PatternHd &HeadPattern,
1547 PatternTl &...TailPatterns) {
1548 for (size_t Match = 0, N = Used.size(); Match < N; Match++) {
1549 if (Used[Match] || !(sd_match(Leaves[Match], HeadPattern)))
1550 continue;
1551 Used.set(Match);
1552 if (reassociatableMatchHelper(Leaves, Used, TailPatterns...))
1553 return true;
1554 Used.reset(Match);
1555 }
1556 return false;
1557 }
1558
1559 [[nodiscard]] inline bool
1561 Bitset<NumPatterns> &Used) {
1562 return true;
1563 }
1564};
1565
1566template <typename... PatternTs>
1567inline ReassociatableOpc_match<PatternTs...>
1568m_ReassociatableAdd(const PatternTs &...Patterns) {
1569 return ReassociatableOpc_match<PatternTs...>(ISD::ADD, Patterns...);
1570}
1571
1572template <typename... PatternTs>
1573inline ReassociatableOpc_match<PatternTs...>
1574m_ReassociatableOr(const PatternTs &...Patterns) {
1575 return ReassociatableOpc_match<PatternTs...>(ISD::OR, Patterns...);
1576}
1577
1578template <typename... PatternTs>
1579inline ReassociatableOpc_match<PatternTs...>
1580m_ReassociatableAnd(const PatternTs &...Patterns) {
1581 return ReassociatableOpc_match<PatternTs...>(ISD::AND, Patterns...);
1582}
1583
1584template <typename... PatternTs>
1585inline ReassociatableOpc_match<PatternTs...>
1586m_ReassociatableMul(const PatternTs &...Patterns) {
1587 return ReassociatableOpc_match<PatternTs...>(ISD::MUL, Patterns...);
1588}
1589
1590template <typename... PatternTs>
1591inline ReassociatableOpc_match<PatternTs...>
1592m_ReassociatableNSWAdd(const PatternTs &...Patterns) {
1593 return ReassociatableOpc_match<PatternTs...>(
1594 ISD::ADD, SDNodeFlags::NoSignedWrap, Patterns...);
1595}
1596
1597template <typename... PatternTs>
1598inline ReassociatableOpc_match<PatternTs...>
1599m_ReassociatableNUWAdd(const PatternTs &...Patterns) {
1600 return ReassociatableOpc_match<PatternTs...>(
1602}
1603
1604} // namespace SDPatternMatch
1605} // namespace llvm
1606#endif
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
uint64_t uint64_t
This file implements a class to represent arbitrary precision integral constant values and operations...
#define X(NUM, ENUM, NAME)
Definition ELF.h:665
static constexpr unsigned long long mask(BlockVerifier::State S)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define T
#define T1
#define P(N)
SmallVector< MachineOperand, 4 > Cond
RISCVCC::CondCode CC
This file contains some templates that are useful if you are working with the STL at all.
This file implements the SmallBitVector class.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
This file describes how to lower LLVM code to machine code.
Value * RHS
Value * LHS
This file implements the C++20 <bit> header.
Class for arbitrary precision integers.
Definition APInt.h:78
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
Definition APInt.cpp:1057
uint64_t getZExtValue() const
Get zero extended value.
Definition APInt.h:1560
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition APInt.h:1508
bool isNegative() const
Determine sign of this APInt.
Definition APInt.h:325
static bool isSameValue(const APInt &I1, const APInt &I2, bool SignedCompare=false)
Determine if two APInts have the same value, after zero-extending or sign-extending (if SignedCompare...
Definition APInt.h:550
bool isIntN(unsigned N) const
Check if this APInt has an N-bits unsigned integer value.
Definition APInt.h:428
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
This is a constexpr reimplementation of a subset of std::bitset.
Definition Bitset.h:30
Tagged union holding either a T or a Error.
Definition Error.h:485
Represents one node in the SelectionDAG.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
const TargetLowering & getTargetLoweringInfo() const
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
bool isOperationLegal(unsigned Op, EVT VT) const
Return true if the specified operation is legal on this target.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
Definition ISDOpcodes.h:845
@ POISON
POISON - A poison node.
Definition ISDOpcodes.h:238
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
Definition ISDOpcodes.h:605
@ BSWAP
Byte Swap and Counting operators.
Definition ISDOpcodes.h:805
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:266
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
Definition ISDOpcodes.h:879
@ FADD
Simple binary floating point operators.
Definition ISDOpcodes.h:420
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
Definition ISDOpcodes.h:765
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ CLMUL
Carry-less multiplication operations.
Definition ISDOpcodes.h:796
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:870
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
Definition ISDOpcodes.h:822
@ UNDEF
UNDEF - An undefined node.
Definition ISDOpcodes.h:235
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:787
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
Definition ISDOpcodes.h:659
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
Definition ISDOpcodes.h:619
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
Definition ISDOpcodes.h:581
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition ISDOpcodes.h:876
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
Definition ISDOpcodes.h:837
@ VSCALE
VSCALE(IMM) - Returns the runtime scaling factor used to calculate the number of elements within a sc...
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
Definition ISDOpcodes.h:745
@ VECTOR_REVERSE
VECTOR_REVERSE(VECTOR) - Returns a vector, of the same type as VECTOR, whose elements are shuffled us...
Definition ISDOpcodes.h:650
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
Definition ISDOpcodes.h:831
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition ISDOpcodes.h:952
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:757
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
Definition ISDOpcodes.h:207
@ VECTOR_SPLICE_RIGHT
VECTOR_SPLICE_RIGHT(VEC1, VEC2, OFFSET) - Shifts CONCAT_VECTORS(VEC1,VEC2) right by OFFSET elements a...
Definition ISDOpcodes.h:667
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
Definition ISDOpcodes.h:570
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition ISDOpcodes.h:882
@ ABS_MIN_POISON
ABS with a poison result for INT_MIN.
Definition ISDOpcodes.h:769
LLVM_ABI bool matchBinaryPredicate(SDValue LHS, SDValue RHS, const APInt &DemandedElts, std::function< bool(ConstantSDNode *, ConstantSDNode *)> Match, bool AllowUndefs=false, bool AllowTypeMismatch=false)
Attempt to match a binary predicate against a pair of scalar/splat constants or every element of a pa...
LLVM_ABI bool isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
AllOnesConstantMatch m_AllOnes()
cst_pred_ty< is_one > m_One()
Match an integer 1 or a vector with all elements equal to 1.
auto m_BinOp()
Match an arbitrary binary operation and ignore it.
auto m_VScale()
Matches a call to llvm.vscale().
is_zero< true > m_Zero()
Match any null constant or a vector with all elements equal to 0.
BinaryOpc_match< Zero_match, ValTy, false > m_Neg(const ValTy &V)
Match a negate as a sub(0, v)
Result_match< 0, TernaryOpc_match< T0_P, T1_P, T2_P > > m_Load(const T0_P &Ch, const T1_P &Ptr, const T2_P &Offset)
ReassociatableOpc_match< PatternTs... > m_ReassociatableMul(const PatternTs &...Patterns)
auto m_ExactSr(const LHS &L, const RHS &R)
BinaryOpc_match< LHS, RHS > m_Srl(const LHS &L, const RHS &R)
auto m_SExtLike(const Opnd &Op)
auto m_SpecificVT(EVT RefVT, const Pattern &P)
Match a specific ValueType.
BinaryOpc_match< LHS, RHS > m_Sra(const LHS &L, const RHS &R)
BinaryOpc_match< LHS, RHS > m_FRem(const LHS &L, const RHS &R)
auto m_False(const SelectionDAG &DAG)
Match false boolean value based on the information provided by TargetLowering.
TLI_pred_match(const PredFuncT &Pred, const Pattern &P) -> TLI_pred_match< Pattern, PredFuncT >
TernaryOpc_match< T0_P, T1_P, CondCode_match, true, false > m_c_SetCC(const T0_P &LHS, const T1_P &RHS)
Match a SETCC with any condition code, allowing the operands to be commuted.
auto m_Abs(const Opnd &Op)
Result_match< ResNo, Pattern > m_Result(const Pattern &P)
Match only if the SDValue is a certain result at ResNo.
auto m_MaxMinLike(const LHS &L, const RHS &R)
BinaryOpc_match< LHS, RHS, true > m_c_BinOp(unsigned Opc, const LHS &L, const RHS &R, SDNodeFlags Flgs=SDNodeFlags())
auto m_Node(const OpndPreds &...Preds)
BinaryOpc_match< LHS, RHS, true > m_Mul(const LHS &L, const RHS &R)
BinaryOpc_match< LHS, RHS, true > m_Clmul(const LHS &L, const RHS &R)
auto m_UMinLike(const LHS &L, const RHS &R)
auto m_SelectCC(const LTy &L, const RTy &R, const TTy &T, const FTy &F)
Match a SELECT_CC with any condition code.
auto m_SelectLike(const T0_P &Cond, const T1_P &T, const T2_P &F)
TernaryOpc_match< LHS, RHS, IDX > m_InsertSubvector(const LHS &Base, const RHS &Sub, const IDX &Idx)
auto m_UMaxLike(const LHS &L, const RHS &R)
BinaryOpc_match< LHS, RHS, true > m_Or(const LHS &L, const RHS &R)
TernaryOpc_match< T0_P, T1_P, T2_P > m_TernaryOp(unsigned Opc, const T0_P &Op0, const T1_P &Op1, const T2_P &Op2)
TernaryOpc_match< T0_P, T1_P, T2_P > m_InsertElt(const T0_P &Vec, const T1_P &Val, const T2_P &Idx)
BinaryOpc_match< LHS, RHS, false, true > m_ChainedBinOp(unsigned Opc, const LHS &L, const RHS &R)
BinaryOpc_match< LHS, RHS, true > m_SMin(const LHS &L, const RHS &R)
auto m_IntrinsicWOChain(const OpndPreds &...Opnds)
UnaryOpc_match< Opnd > m_Trunc(const Opnd &Op)
BinaryOpc_match< LHS, RHS > m_FSub(const LHS &L, const RHS &R)
auto m_AddLike(const LHS &L, const RHS &R)
auto m_SpecificSelectCCLike(ISD::CondCode CC, const LTy &L, const RTy &R, const TTy &T, const FTy &F)
Match a SELECT of a SETCC or a SELECT_CC with a specific condition code.
BinaryOpc_match< LHS, RHS > m_URem(const LHS &L, const RHS &R)
AnyZeroFP_match m_AnyZeroFP()
Match a floating-point +0.0 or -0.0 constant or splat.
UnaryOpc_match< Opnd > m_BSwap(const Opnd &Op)
Or< Preds... > m_AnyOf(const Preds &...preds)
BinaryOpc_match< LHS, RHS, true, true > m_c_ChainedBinOp(unsigned Opc, const LHS &L, const RHS &R)
Or< UnaryOpc_match< Opnd >, Opnd > m_TruncOrSelf(const Opnd &Op)
Match a trunc or identity Allows to peek through optional truncations.
UnaryOpc_match< Opnd > m_NNegZExt(const Opnd &Op)
TernaryOpc_match< T0_P, T1_P, T2_P > m_FShR(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2)
And< Preds... > m_AllOf(const Preds &...preds)
UnaryOpc_match< Opnd > m_VectorReverse(const Opnd &Op)
BinaryOpc_match< LHS, RHS > m_FDiv(const LHS &L, const RHS &R)
auto m_NSWAdd(const LHS &L, const RHS &R)
UnaryOpc_match< Opnd > m_BitCast(const Opnd &Op)
UnaryOpc_match< Opnd > m_FNeg(const Opnd &Op)
FunnelShiftLike_match< T0_P, T1_P, T2_P, false > m_FShRLike(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2)
Opcode_match m_Poison()
auto m_LegalType(const SelectionDAG &DAG, const Pattern &P)
Match legal ValueTypes based on the information provided by TargetLowering.
BinaryOpc_match< LHS, RHS, true > m_UMin(const LHS &L, const RHS &R)
Not< Pred > m_Unless(const Pred &P)
Match if the inner pattern does NOT match.
BinaryOpc_match< LHS, RHS, true > m_SMax(const LHS &L, const RHS &R)
auto m_SpecificScalarVT(EVT RefVT, const Pattern &P)
Match a scalar ValueType.
auto m_True(const SelectionDAG &DAG)
Match true boolean value based on the information provided by TargetLowering.
NUses_match< N, Value_match > m_NUses()
UnaryOpc_match< Opnd, true > m_ChainedUnaryOp(unsigned Opc, const Opnd &Op)
ValueType_match(const PredFuncT &Pred, const Pattern &P) -> ValueType_match< Pattern, PredFuncT >
SpecificInt_match m_SpecificInt(APInt V)
Match a specific integer constant or constant splat value.
UnaryOpc_match< Opnd > m_FPToUI(const Opnd &Op)
auto m_NUWAddLike(const LHS &L, const RHS &R)
SpecificFP_match m_SpecificFP(APFloat V)
Match a specific float constant.
Value_match m_Specific(SDValue N)
BinaryOpc_match< LHS, RHS > m_ExtractElt(const LHS &Vec, const RHS &Idx)
BinaryOpc_match< LHS, RHS > m_ExtractSubvector(const LHS &Vec, const RHS &Idx)
UnaryOpc_match< Opnd > m_BitReverse(const Opnd &Op)
BinaryOpc_match< LHS, RHS, true > m_And(const LHS &L, const RHS &R)
BinaryOpc_match< LHS, RHS > m_Sub(const LHS &L, const RHS &R)
TernaryOpc_match< T0_P, T1_P, CondCode_match > m_SpecificSetCC(ISD::CondCode CC, const T0_P &LHS, const T1_P &RHS)
Match a SETCC with a specific condition code.
TernaryOpc_match< T0_P, T1_P, T2_P, true > m_c_TernaryOp(unsigned Opc, const T0_P &Op0, const T1_P &Op1, const T2_P &Op2)
ReassociatableOpc_match< PatternTs... > m_ReassociatableNUWAdd(const PatternTs &...Patterns)
auto m_NSWAddLike(const LHS &L, const RHS &R)
auto m_VT(EVT &VT)
Retreive the ValueType of the current SDValue.
BinaryOpc_match< ValTy, AllOnes_match, true > m_Not(const ValTy &V)
Match a Not as a xor(v, -1) or xor(-1, v)
ReassociatableOpc_match< PatternTs... > m_ReassociatableOr(const PatternTs &...Patterns)
BinaryOpc_match< LHS, RHS > m_Rotr(const LHS &L, const RHS &R)
auto m_ZExtOrSExt(const Opnd &Op)
Match a zext or sext.
ReassociatableOpc_match< PatternTs... > m_ReassociatableAdd(const PatternTs &...Patterns)
UnaryOpc_match< Opnd > m_AnyExt(const Opnd &Op)
BinaryOpc_match< LHS, RHS > m_Rotl(const LHS &L, const RHS &R)
UnaryOpc_match< Opnd > m_Cttz(const Opnd &Op)
auto m_SelectCCLike(const LTy &L, const RTy &R, const TTy &T, const FTy &F)
Match a SELECT of a SETCC or a SELECT_CC with any condition code.
TernaryOpc_match< T0_P, T1_P, CondCode_match, true, false > m_c_SpecificSetCC(ISD::CondCode CC, const T0_P &LHS, const T1_P &RHS)
Match a SETCC with a specific condition code, allowing the operands to be commuted.
BinaryOpc_match< LHS, RHS, true > m_DisjointOr(const LHS &L, const RHS &R)
auto m_SMaxLike(const LHS &L, const RHS &R)
TernaryOpc_match< T0_P, T1_P, T2_P > m_Select(const T0_P &Cond, const T1_P &T, const T2_P &F)
BinaryOpc_match< LHS, RHS > m_UDiv(const LHS &L, const RHS &R)
UnaryOpc_match< Opnd > m_Ctlz(const Opnd &Op)
SpecificNeg_match m_SpecificNeg(SDValue V)
Match a negation of a specific value V, either as sub(0, V) or as constant(s) that are the negation o...
BinaryOpc_match< LHS, RHS > m_SDiv(const LHS &L, const RHS &R)
BinaryOpc_match< LHS, RHS, true > m_FAdd(const LHS &L, const RHS &R)
Or< UnaryOpc_match< Opnd >, Opnd > m_AExtOrSelf(const Opnd &Op)
Match a aext or identity Allows to peek through optional extensions.
BinaryOpc_match< LHS, RHS, true > m_UMax(const LHS &L, const RHS &R)
TernaryOpc_match< T0_P, T1_P, T2_P > m_VSelect(const T0_P &Cond, const T1_P &T, const T2_P &F)
TypeSize_match< ElementCount > m_ElementCount(ElementCount &V)
Match any integer constant or constant multiple of VSCALE that can be represented using ElementCount.
TernaryOpc_match< T0_P, T1_P, T2_P > m_FShL(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2)
UnaryOpc_match< Opnd > m_UnaryOp(unsigned Opc, const Opnd &Op)
auto m_SExt(const Opnd &Op)
bool sd_match(SDValue N, Pattern &&P)
ReassociatableOpc_match< PatternTs... > m_ReassociatableNSWAdd(const PatternTs &...Patterns)
BinaryOpc_match< LHS, RHS, true > m_Xor(const LHS &L, const RHS &R)
auto m_SMinLike(const LHS &L, const RHS &R)
BinaryOpc_match< LHS, RHS > m_SRem(const LHS &L, const RHS &R)
auto m_NoneOf(const Preds &...preds)
CondCode_match m_SpecificCondCode(ISD::CondCode CC)
Match a conditional code SDNode with a specific ISD::CondCode.
UnaryOpc_match< Opnd > m_ZExt(const Opnd &Op)
Value_match m_Value()
Match any valid SDValue.
BinaryOpc_match< LHS, RHS, true > m_Add(const LHS &L, const RHS &R)
auto m_SpecificVectorElementVT(EVT RefVT, const Pattern &P)
Match a vector ValueType.
BinaryOpc_match< LHS, RHS > m_Shl(const LHS &L, const RHS &R)
auto m_BitwiseLogic(const LHS &L, const RHS &R)
UnaryOpc_match< Opnd > m_Ctpop(const Opnd &Op)
auto m_LegalOp(const SelectionDAG &DAG, const Pattern &P)
Match legal SDNodes based on the information provided by TargetLowering.
TernaryOpc_match< T0_P, T1_P, CondCode_match > m_SetCC(const T0_P &LHS, const T1_P &RHS)
Match a SETCC with any condition code.
ReassociatableOpc_match< PatternTs... > m_ReassociatableAnd(const PatternTs &...Patterns)
TernaryOpc_match< T0_P, T1_P, T2_P > m_SpliceRight(const T0_P &V1, const T1_P &V2, const T2_P &Offset)
UnaryOpc_match< Opnd > m_FPToSI(const Opnd &Op)
NUses_match< 1, Value_match > m_OneUse()
auto m_NUWAdd(const LHS &L, const RHS &R)
auto m_SExtOrSelf(const Opnd &Op)
Match a sext or identity Allows to peek through optional extensions.
CondCode_match m_CondCode()
Match any conditional code SDNode.
UnaryOpc_match< Opnd > m_FAbs(const Opnd &Op)
Not(const Pred &P) -> Not< Pred >
DeferredValue_match m_Deferred(SDValue &V)
Similar to m_Specific, but the specific value to match is determined by another sub-pattern in the sa...
BinaryOpc_match< LHS, RHS, true > m_FMul(const LHS &L, const RHS &R)
BinaryOpc_match< V1_t, V2_t > m_Shuffle(const V1_t &v1, const V2_t &v2)
auto m_SpecificSelectCC(ISD::CondCode CC, const LTy &L, const RTy &R, const TTy &T, const FTy &F)
Match a SELECT_CC with a specific condition code.
ValueType_bind(const Pattern &P) -> ValueType_bind< Pattern >
ConstantInt_match m_ConstInt()
Match any integer constants or splat of an integer constant.
FunnelShiftLike_match< T0_P, T1_P, T2_P, true > m_FShLLike(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2)
auto m_ZExtOrSelf(const Opnd &Op)
Match a zext or identity Allows to peek through optional extensions.
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
LLVM_ABI bool isAllOnesOrAllOnesSplat(const MachineInstr &MI, const MachineRegisterInfo &MRI, bool AllowUndefs=false)
Return true if the value is a constant -1 integer or a splatted vector of a constant -1 integer (with...
Definition Utils.cpp:1558
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
Definition bit.h:325
LLVM_ABI ConstantFPSDNode * isConstOrConstSplatFP(SDValue N, bool AllowUndefs=false)
Returns the SDNode if it is a constant splat BuildVector or constant float.
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
LLVM_ABI bool isOneOrOneSplat(SDValue V, bool AllowUndefs=false)
Return true if the value is a constant 1 integer or a splatted vector of a constant 1 integer (with n...
@ Sub
Subtraction of integers.
DWARFExpression::Operation Op
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.
Definition STLExtras.h:1933
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
LLVM_ABI bool isZeroOrZeroSplat(SDValue N, bool AllowUndefs=false)
Return true if the value is a constant 0 integer or a splatted vector of a constant 0 integer (with n...
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
#define N
Extended Value Type.
Definition ValueTypes.h:35
These are IR-level optimization flags that may be propagated to SDNodes.
And(const Pred &p, const Preds &...preds)
BinaryOpc_match(unsigned Opc, const LHS_P &L, const RHS_P &R, SDNodeFlags Flgs=SDNodeFlags())
Bool_match(const SelectionDAG &DAG)
std::optional< ISD::CondCode > CCToMatch
Provide number of operands that are not chain or glue, as well as the first index of such operand.
bool matchShiftOr(SDValue N, unsigned BitWidth)
bool matchOperands(SDValue X, SDValue Y, SDValue Z)
static bool hasComplementaryConstantShifts(const APInt &ShlV, const APInt &SrlV, unsigned BitWidth)
FunnelShiftLike_match(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2)
MaxMin_match(const LHS_P &L, const RHS_P &R)
Operands_match(const OpndPred &p, const OpndPreds &...preds)
Or(const Pred &p, const Preds &...preds)
bool reassociatableMatchHelper(ArrayRef< SDValue > Leaves, Bitset< NumPatterns > &Used)
bool reassociatableMatchHelper(ArrayRef< SDValue > Leaves, Bitset< NumPatterns > &Used, PatternHd &HeadPattern, PatternTl &...TailPatterns)
bool collectLeaves(SDValue V, std::array< SDValue, NumPatterns > &Leaves, std::size_t &LeafIdx)
ReassociatableOpc_match(unsigned Opcode, const PatternTs &...Patterns)
ReassociatableOpc_match(unsigned Opcode, SDNodeFlags Flags, const PatternTs &...Patterns)
Matching while capturing mask.
SDShuffle_match(const T0 &Op1, const T1 &Op2, const T2 &Mask)
TLI_pred_match(const PredFuncT &Pred, const Pattern &P)
TernaryOpc_match(unsigned Opc, const T0_P &Op0, const T1_P &Op1, const T2_P &Op2)
UnaryOpc_match(unsigned Opc, const Opnd_P &Op, SDNodeFlags Flgs=SDNodeFlags())
ValueType_bind(EVT &Bind, const Pattern &P)
ValueType_match(const PredFuncT &Pred, const Pattern &P)
bool match(ArrayRef< int > Mask)
m_Mask(ArrayRef< int > &MaskRef)
m_SpecificMask(ArrayRef< int > MaskRef)
bool match(ArrayRef< int > Mask)
static bool match(ISD::CondCode Cond)
static bool match(ISD::CondCode Cond)
static bool match(ISD::CondCode Cond)
static bool match(ISD::CondCode Cond)