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"
25
26#include <type_traits>
27
28namespace llvm {
29namespace SDPatternMatch {
30
31template <typename Pattern>
32[[nodiscard]] bool sd_match(SDValue N, Pattern &&P) {
33 return P.match(N);
34}
35
36template <typename Pattern>
37[[nodiscard]] bool sd_match(SDNode *N, Pattern &&P) {
38 return sd_match(SDValue(N, 0), P);
39}
40
41// === Utilities ===
44
45 Value_match() = default;
46
47 explicit Value_match(SDValue Match) : MatchVal(Match) {}
48
49 bool match(SDValue N) {
50 if (MatchVal)
51 return MatchVal == N;
52 return N.getNode();
53 }
54};
55
56/// Match any valid SDValue.
57inline Value_match m_Value() { return Value_match(); }
58
60 assert(N);
61 return Value_match(N);
62}
63
64template <unsigned ResNo, typename Pattern> struct Result_match {
66
67 explicit Result_match(const Pattern &P) : P(P) {}
68
69 bool match(SDValue N) { return N.getResNo() == ResNo && P.match(N); }
70};
71
72/// Match only if the SDValue is a certain result at ResNo.
73template <unsigned ResNo, typename Pattern>
77
80
81 explicit DeferredValue_match(SDValue &Match) : MatchVal(Match) {}
82
83 bool match(SDValue N) { return N == MatchVal; }
84};
85
86/// Similar to m_Specific, but the specific value to match is determined by
87/// another sub-pattern in the same sd_match() expression. For instance,
88/// We cannot match `(add V, V)` with `m_Add(m_Value(X), m_Specific(X))` since
89/// `X` is not initialized at the time it got copied into `m_Specific`. Instead,
90/// we should use `m_Add(m_Value(X), m_Deferred(X))`.
94
96 unsigned Opcode;
97
98 explicit Opcode_match(unsigned Opc) : Opcode(Opc) {}
99
100 bool match(SDValue N) { return N->getOpcode() == Opcode; }
101};
102
103template <unsigned Opcode> struct FixedOpcode_match {
104 bool match(SDValue N) { return N->getOpcode() == Opcode; }
105};
106
107// === Patterns combinators ===
108template <typename... Preds> struct And {
109 bool match(SDValue N) { return true; }
110};
111
112template <typename Pred, typename... Preds>
113struct And<Pred, Preds...> : And<Preds...> {
114 Pred P;
115 And(const Pred &p, const Preds &...preds) : And<Preds...>(preds...), P(p) {}
116
117 bool match(SDValue N) { return P.match(N) && And<Preds...>::match(N); }
118};
119
120template <typename... Preds> struct Or {
121 bool match(SDValue N) { return false; }
122};
123
124template <typename Pred, typename... Preds>
125struct Or<Pred, Preds...> : Or<Preds...> {
126 Pred P;
127 Or(const Pred &p, const Preds &...preds) : Or<Preds...>(preds...), P(p) {}
128
129 bool match(SDValue N) { return P.match(N) || Or<Preds...>::match(N); }
130};
131
132template <typename Pred> struct Not {
133 Pred P;
134
135 explicit Not(const Pred &P) : P(P) {}
136
137 bool match(SDValue N) { return !P.match(N); }
138};
139// Explicit deduction guide.
140template <typename Pred> Not(const Pred &P) -> Not<Pred>;
141
142/// Match if the inner pattern does NOT match.
143template <typename Pred> inline Not<Pred> m_Unless(const Pred &P) {
144 return Not{P};
145}
146
147template <typename... Preds> And<Preds...> m_AllOf(const Preds &...preds) {
148 return And<Preds...>(preds...);
149}
150
151template <typename... Preds> Or<Preds...> m_AnyOf(const Preds &...preds) {
152 return Or<Preds...>(preds...);
153}
154
155template <typename... Preds> auto m_NoneOf(const Preds &...preds) {
156 return m_Unless(m_AnyOf(preds...));
157}
158
159template <unsigned Opcode> inline auto m_SpecificOpc() {
161}
162
163inline Opcode_match m_SpecificOpc(unsigned Opcode) {
164 return Opcode_match(Opcode);
165}
166
167inline auto m_Undef() {
169}
170
172
173template <unsigned NumUses, typename Pattern> struct NUses_match {
175
176 explicit NUses_match(const Pattern &P) : P(P) {}
177
179 // SDNode::hasNUsesOfValue is pretty expensive when the SDNode produces
180 // multiple results, hence we check the subsequent pattern here before
181 // checking the number of value users.
182 return P.match(N) && N->hasNUsesOfValue(NumUses, N.getResNo());
183 }
184};
185
186template <typename Pattern>
190template <unsigned N, typename Pattern>
194
198template <unsigned N> inline NUses_match<N, Value_match> m_NUses() {
200}
201
204
206
208 BindVal = N;
209 return true;
210 }
211};
212
213inline auto m_Value(SDValue &N) { return Value_bind(N); }
214/// Conditionally bind an SDValue based on the predicate.
215template <typename PredPattern>
216inline auto m_Value(SDValue &N, const PredPattern &P) {
217 return m_AllOf(P, Value_bind(N));
218}
219
220template <typename Pattern, typename PredFuncT> struct TLI_pred_match {
222 PredFuncT PredFunc;
223
224 TLI_pred_match(const PredFuncT &Pred, const Pattern &P)
225 : P(P), PredFunc(Pred) {}
226
227 bool match(SDValue N) { return PredFunc(N) && P.match(N); }
228};
229
230// Explicit deduction guide.
231template <typename PredFuncT, typename Pattern>
232TLI_pred_match(const PredFuncT &Pred, const Pattern &P)
234
235/// Match legal SDNodes based on the information provided by TargetLowering.
236template <typename Pattern>
237inline auto m_LegalOp(const SelectionDAG &DAG, const Pattern &P) {
238 return TLI_pred_match{[&DAG](SDValue N) {
240 N->getOpcode(), N.getValueType());
241 },
242 P};
243}
244
245// === Value type ===
246
247template <typename Pattern> struct ValueType_bind {
250
251 explicit ValueType_bind(EVT &Bind, const Pattern &P) : BindVT(Bind), P(P) {}
252
254 BindVT = N.getValueType();
255 return P.match(N);
256 }
257};
258
259template <typename Pattern>
261
262/// Retreive the ValueType of the current SDValue.
263inline auto m_VT(EVT &VT) { return ValueType_bind(VT, m_Value()); }
264
265template <typename Pattern> inline auto m_VT(EVT &VT, const Pattern &P) {
266 return ValueType_bind(VT, P);
267}
268
269template <typename Pattern, typename PredFuncT> struct ValueType_match {
270 PredFuncT PredFunc;
272
273 ValueType_match(const PredFuncT &Pred, const Pattern &P)
274 : PredFunc(Pred), P(P) {}
275
276 bool match(SDValue N) { return PredFunc(N.getValueType()) && P.match(N); }
277};
278
279// Explicit deduction guide.
280template <typename PredFuncT, typename Pattern>
281ValueType_match(const PredFuncT &Pred, const Pattern &P)
283
284/// Match a specific ValueType.
285template <typename Pattern>
286inline auto m_SpecificVT(EVT RefVT, const Pattern &P) {
287 return ValueType_match{[=](EVT VT) { return VT == RefVT; }, P};
288}
289inline auto m_SpecificVT(EVT RefVT) {
290 return ValueType_match{[=](EVT VT) { return VT == RefVT; }, m_Value()};
291}
292
293inline auto m_Glue() { return m_SpecificVT(MVT::Glue); }
294inline auto m_OtherVT() { return m_SpecificVT(MVT::Other); }
295
296/// Match a scalar ValueType.
297template <typename Pattern>
298inline auto m_SpecificScalarVT(EVT RefVT, const Pattern &P) {
299 return ValueType_match{[=](EVT VT) { return VT.getScalarType() == RefVT; },
300 P};
301}
302inline auto m_SpecificScalarVT(EVT RefVT) {
303 return ValueType_match{[=](EVT VT) { return VT.getScalarType() == RefVT; },
304 m_Value()};
305}
306
307/// Match a vector ValueType.
308template <typename Pattern>
309inline auto m_SpecificVectorElementVT(EVT RefVT, const Pattern &P) {
310 return ValueType_match{[=](EVT VT) {
311 return VT.isVector() &&
312 VT.getVectorElementType() == RefVT;
313 },
314 P};
315}
316inline auto m_SpecificVectorElementVT(EVT RefVT) {
317 return ValueType_match{[=](EVT VT) {
318 return VT.isVector() &&
319 VT.getVectorElementType() == RefVT;
320 },
321 m_Value()};
322}
323
324/// Match any integer ValueTypes.
325template <typename Pattern> inline auto m_IntegerVT(const Pattern &P) {
326 return ValueType_match{[](EVT VT) { return VT.isInteger(); }, P};
327}
328inline auto m_IntegerVT() {
329 return ValueType_match{[](EVT VT) { return VT.isInteger(); }, m_Value()};
330}
331
332/// Match any floating point ValueTypes.
333template <typename Pattern> inline auto m_FloatingPointVT(const Pattern &P) {
334 return ValueType_match{[](EVT VT) { return VT.isFloatingPoint(); }, P};
335}
336inline auto m_FloatingPointVT() {
337 return ValueType_match{[](EVT VT) { return VT.isFloatingPoint(); },
338 m_Value()};
339}
340
341/// Match any vector ValueTypes.
342template <typename Pattern> inline auto m_VectorVT(const Pattern &P) {
343 return ValueType_match{[](EVT VT) { return VT.isVector(); }, P};
344}
345inline auto m_VectorVT() {
346 return ValueType_match{[](EVT VT) { return VT.isVector(); }, m_Value()};
347}
348
349/// Match fixed-length vector ValueTypes.
350template <typename Pattern> inline auto m_FixedVectorVT(const Pattern &P) {
351 return ValueType_match{[](EVT VT) { return VT.isFixedLengthVector(); }, P};
352}
353inline auto m_FixedVectorVT() {
354 return ValueType_match{[](EVT VT) { return VT.isFixedLengthVector(); },
355 m_Value()};
356}
357
358/// Match scalable vector ValueTypes.
359template <typename Pattern> inline auto m_ScalableVectorVT(const Pattern &P) {
360 return ValueType_match{[](EVT VT) { return VT.isScalableVector(); }, P};
361}
362inline auto m_ScalableVectorVT() {
363 return ValueType_match{[](EVT VT) { return VT.isScalableVector(); },
364 m_Value()};
365}
366
367/// Match legal ValueTypes based on the information provided by TargetLowering.
368template <typename Pattern>
369inline auto m_LegalType(const SelectionDAG &DAG, const Pattern &P) {
370 return TLI_pred_match{[&DAG](SDValue N) {
372 N.getValueType());
373 },
374 P};
375}
376
377// === Generic node matching ===
378template <unsigned OpIdx, typename... OpndPreds> struct Operands_match {
380 // Returns false if there are more operands than predicates;
381 return N->getNumOperands() == OpIdx;
382 }
383};
384
385template <unsigned OpIdx, typename OpndPred, typename... OpndPreds>
386struct Operands_match<OpIdx, OpndPred, OpndPreds...>
387 : Operands_match<OpIdx + 1, OpndPreds...> {
388 OpndPred P;
389
390 Operands_match(const OpndPred &p, const OpndPreds &...preds)
391 : Operands_match<OpIdx + 1, OpndPreds...>(preds...), P(p) {}
392
394 if (OpIdx < N->getNumOperands())
395 return P.match(N->getOperand(OpIdx)) &&
397
398 // This is the case where there are more predicates than operands.
399 return false;
400 }
401};
402
403template <unsigned Opcode, typename... OpndPreds>
404auto m_Node(const OpndPreds &...Preds) {
407}
408
409template <typename... OpndPreds>
410auto m_Node(unsigned Opcode, const OpndPreds &...preds) {
411 return m_AllOf(m_SpecificOpc(Opcode),
413}
414
415/// Provide number of operands that are not chain or glue, as well as the first
416/// index of such operand.
417template <bool ExcludeChain> struct EffectiveOperands {
418 unsigned Size = 0;
419 unsigned FirstIndex = 0;
420
421 explicit EffectiveOperands(SDValue N) : Size(N->getNumOperands()) {
422 if (ExcludeChain) {
423 // Glue if present, is the last operand.
424 if (Size != 0 && N->getOperand(Size - 1).getValueType() == MVT::Glue)
425 --Size;
426 // Chain if present, is the first operand.
427 if (Size != 0 && N->getOperand(0).getValueType() == MVT::Other) {
428 ++FirstIndex;
429 --Size;
430 }
431 }
432 }
433};
434
435// === Ternary operations ===
436template <typename T0_P, typename T1_P, typename T2_P, bool Commutable = false,
437 bool ExcludeChain = false>
439 unsigned Opcode;
440 T0_P Op0;
441 T1_P Op1;
442 T2_P Op2;
443
444 TernaryOpc_match(unsigned Opc, const T0_P &Op0, const T1_P &Op1,
445 const T2_P &Op2)
446 : Opcode(Opc), Op0(Op0), Op1(Op1), Op2(Op2) {}
447
451 assert(EO.Size == 3);
452 return ((Op0.match(N->getOperand(EO.FirstIndex)) &&
453 Op1.match(N->getOperand(EO.FirstIndex + 1))) ||
454 (Commutable && Op0.match(N->getOperand(EO.FirstIndex + 1)) &&
455 Op1.match(N->getOperand(EO.FirstIndex)))) &&
456 Op2.match(N->getOperand(EO.FirstIndex + 2));
457 }
458
459 return false;
460 }
461};
462
464 std::optional<ISD::CondCode> CCToMatch;
466
468
469 explicit CondCode_match(ISD::CondCode *CC) : BindCC(CC) {}
470
472 if (auto *CC = dyn_cast<CondCodeSDNode>(N.getNode())) {
473 if (CCToMatch && *CCToMatch != CC->get())
474 return false;
475
476 if (BindCC)
477 *BindCC = CC->get();
478 return true;
479 }
480
481 return false;
482 }
483};
484
485/// Match any conditional code SDNode.
486inline CondCode_match m_CondCode() { return CondCode_match(nullptr); }
487/// Match any conditional code SDNode and return its ISD::CondCode value.
489 return CondCode_match(&CC);
490}
491/// Match a conditional code SDNode with a specific ISD::CondCode.
495
496/// Match a SETCC with any condition code.
497template <typename T0_P, typename T1_P>
503
504/// Match a SETCC with any condition code and bind the condition code to CC.
505template <typename T0_P, typename T1_P>
506inline TernaryOpc_match<T0_P, T1_P, CondCode_match>
507m_SetCC(ISD::CondCode &CC, const T0_P &LHS, const T1_P &RHS) {
509 m_CondCode(CC));
510}
511
512/// Match a SETCC with a specific condition code.
513template <typename T0_P, typename T1_P>
514inline TernaryOpc_match<T0_P, T1_P, CondCode_match>
519
520/// Match a SETCC with any condition code, allowing the operands to be
521/// commuted.
522template <typename T0_P, typename T1_P>
523inline TernaryOpc_match<T0_P, T1_P, CondCode_match, true, false>
528
529/// Match a SETCC with any condition code, allowing the operands to be
530/// commuted, and bind the condition code to CC.
531template <typename T0_P, typename T1_P>
532inline TernaryOpc_match<T0_P, T1_P, CondCode_match, true, false>
537
538/// Match a SETCC with a specific condition code, allowing the operands to be
539/// commuted.
540template <typename T0_P, typename T1_P>
541inline TernaryOpc_match<T0_P, T1_P, CondCode_match, true, false>
546
547template <typename T0_P, typename T1_P, typename T2_P>
548inline TernaryOpc_match<T0_P, T1_P, T2_P>
549m_Select(const T0_P &Cond, const T1_P &T, const T2_P &F) {
551}
552
553template <typename T0_P, typename T1_P, typename T2_P>
554inline TernaryOpc_match<T0_P, T1_P, T2_P>
555m_VSelect(const T0_P &Cond, const T1_P &T, const T2_P &F) {
557}
558
559template <typename T0_P, typename T1_P, typename T2_P>
560inline auto m_SelectLike(const T0_P &Cond, const T1_P &T, const T2_P &F) {
561 return m_AnyOf(m_Select(Cond, T, F), m_VSelect(Cond, T, F));
562}
563
564template <typename T0_P, typename T1_P, typename T2_P>
565inline Result_match<0, TernaryOpc_match<T0_P, T1_P, T2_P>>
566m_Load(const T0_P &Ch, const T1_P &Ptr, const T2_P &Offset) {
567 return m_Result<0>(
569}
570
571template <typename T0_P, typename T1_P, typename T2_P>
572inline TernaryOpc_match<T0_P, T1_P, T2_P>
573m_InsertElt(const T0_P &Vec, const T1_P &Val, const T2_P &Idx) {
575 Idx);
576}
577
578template <typename LHS, typename RHS, typename IDX>
579inline TernaryOpc_match<LHS, RHS, IDX>
580m_InsertSubvector(const LHS &Base, const RHS &Sub, const IDX &Idx) {
582}
583
584template <typename T0_P, typename T1_P, typename T2_P>
585inline TernaryOpc_match<T0_P, T1_P, T2_P>
586m_SpliceRight(const T0_P &V1, const T1_P &V2, const T2_P &Offset) {
588 Offset);
589}
590
591template <typename T0_P, typename T1_P, typename T2_P>
592inline TernaryOpc_match<T0_P, T1_P, T2_P>
593m_TernaryOp(unsigned Opc, const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
594 return TernaryOpc_match<T0_P, T1_P, T2_P>(Opc, Op0, Op1, Op2);
595}
596
597template <typename T0_P, typename T1_P, typename T2_P>
598inline TernaryOpc_match<T0_P, T1_P, T2_P, true>
599m_c_TernaryOp(unsigned Opc, const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
600 return TernaryOpc_match<T0_P, T1_P, T2_P, true>(Opc, Op0, Op1, Op2);
601}
602
603/// Match a SELECT_CC with any condition code.
604template <typename LTy, typename RTy, typename TTy, typename FTy>
605inline auto m_SelectCC(const LTy &L, const RTy &R, const TTy &T, const FTy &F) {
606 return m_Node(ISD::SELECT_CC, L, R, T, F, m_CondCode());
607}
608
609/// Match a SELECT_CC with any condition code and bind the condition code to
610/// CC.
611template <typename LTy, typename RTy, typename TTy, typename FTy>
612inline auto m_SelectCC(ISD::CondCode &CC, const LTy &L, const RTy &R,
613 const TTy &T, const FTy &F) {
614 return m_Node(ISD::SELECT_CC, L, R, T, F, m_CondCode(CC));
615}
616
617/// Match a SELECT_CC with a specific condition code.
618template <typename LTy, typename RTy, typename TTy, typename FTy>
619inline auto m_SpecificSelectCC(ISD::CondCode CC, const LTy &L, const RTy &R,
620 const TTy &T, const FTy &F) {
621 return m_Node(ISD::SELECT_CC, L, R, T, F, m_SpecificCondCode(CC));
622}
623
624/// Match a SELECT of a SETCC or a SELECT_CC with any condition code.
625template <typename LTy, typename RTy, typename TTy, typename FTy>
626inline auto m_SelectCCLike(const LTy &L, const RTy &R, const TTy &T,
627 const FTy &F) {
628 return m_AnyOf(m_Select(m_SetCC(L, R), T, F), m_SelectCC(L, R, T, F));
629}
630
631/// Match a SELECT of a SETCC or a SELECT_CC with any condition code and bind
632/// the condition code to CC.
633template <typename LTy, typename RTy, typename TTy, typename FTy>
634inline auto m_SelectCCLike(ISD::CondCode &CC, const LTy &L, const RTy &R,
635 const TTy &T, const FTy &F) {
636 return m_AnyOf(m_Select(m_SetCC(CC, L, R), T, F), m_SelectCC(CC, L, R, T, F));
637}
638
639/// Match a SELECT of a SETCC or a SELECT_CC with a specific condition code.
640template <typename LTy, typename RTy, typename TTy, typename FTy>
641inline auto m_SpecificSelectCCLike(ISD::CondCode CC, const LTy &L, const RTy &R,
642 const TTy &T, const FTy &F) {
643 return m_AnyOf(m_Select(m_SpecificSetCC(CC, L, R), T, F),
644 m_SpecificSelectCC(CC, L, R, T, F));
645}
646
647// === Binary operations ===
648template <typename LHS_P, typename RHS_P, bool Commutable = false,
649 bool ExcludeChain = false>
651 unsigned Opcode;
652 LHS_P LHS;
653 RHS_P RHS;
655 BinaryOpc_match(unsigned Opc, const LHS_P &L, const RHS_P &R,
656 SDNodeFlags Flgs = SDNodeFlags())
657 : Opcode(Opc), LHS(L), RHS(R), Flags(Flgs) {}
658
662 assert(EO.Size == 2);
663 if (!((LHS.match(N->getOperand(EO.FirstIndex)) &&
664 RHS.match(N->getOperand(EO.FirstIndex + 1))) ||
665 (Commutable && LHS.match(N->getOperand(EO.FirstIndex + 1)) &&
666 RHS.match(N->getOperand(EO.FirstIndex)))))
667 return false;
668
669 return (Flags & N->getFlags()) == Flags;
670 }
671
672 return false;
673 }
674};
675
676/// Matching while capturing mask
677template <typename T0, typename T1, typename T2> struct SDShuffle_match {
678 T0 Op1;
681
682 SDShuffle_match(const T0 &Op1, const T1 &Op2, const T2 &Mask)
683 : Op1(Op1), Op2(Op2), Mask(Mask) {}
684
686 if (auto *I = dyn_cast<ShuffleVectorSDNode>(N)) {
687 return Op1.match(I->getOperand(0)) && Op2.match(I->getOperand(1)) &&
688 Mask.match(I->getMask());
689 }
690 return false;
691 }
692};
693struct m_Mask {
696 bool match(ArrayRef<int> Mask) {
697 MaskRef = Mask;
698 return true;
699 }
700};
701
707
708template <typename LHS_P, typename RHS_P, typename Pred_t,
709 bool Commutable = false>
711 using PredType = Pred_t;
712 LHS_P LHS;
713 RHS_P RHS;
714
715 MaxMin_match(const LHS_P &L, const RHS_P &R) : LHS(L), RHS(R) {}
716
718 auto MatchMinMax = [&](SDValue L, SDValue R, SDValue TrueValue,
719 SDValue FalseValue, ISD::CondCode CC) {
720 if ((TrueValue != L || FalseValue != R) &&
721 (TrueValue != R || FalseValue != L))
722 return false;
723
725 TrueValue == L ? CC : getSetCCInverse(CC, L.getValueType());
726 if (!Pred_t::match(Cond))
727 return false;
728
729 return (LHS.match(L) && RHS.match(R)) ||
730 (Commutable && LHS.match(R) && RHS.match(L));
731 };
732
733 if (N.getOpcode() == ISD::SELECT || N.getOpcode() == ISD::VSELECT) {
734 assert(N.getNumOperands() == 3);
735 SDValue Cond = N.getOperand(0);
736 SDValue TrueValue = N.getOperand(1);
737 SDValue FalseValue = N.getOperand(2);
738
739 if (Cond.getOpcode() == ISD::SETCC) {
740 assert(Cond.getNumOperands() == 3);
741 SDValue L = Cond.getOperand(0);
742 SDValue R = Cond.getOperand(1);
743 ISD::CondCode CC = cast<CondCodeSDNode>(Cond.getOperand(2))->get();
744 return MatchMinMax(L, R, TrueValue, FalseValue, CC);
745 }
746 }
747
748 if (N.getOpcode() == ISD::SELECT_CC) {
749 assert(N.getNumOperands() == 5);
750 SDValue L = N.getOperand(0);
751 SDValue R = N.getOperand(1);
752 SDValue TrueValue = N.getOperand(2);
753 SDValue FalseValue = N.getOperand(3);
754 ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(4))->get();
755 return MatchMinMax(L, R, TrueValue, FalseValue, CC);
756 }
757
758 return false;
759 }
760};
761
762// Helper class for identifying signed max predicates.
764 static bool match(ISD::CondCode Cond) {
766 }
767};
768
769// Helper class for identifying unsigned max predicates.
774};
775
776// Helper class for identifying signed min predicates.
778 static bool match(ISD::CondCode Cond) {
780 }
781};
782
783// Helper class for identifying unsigned min predicates.
788};
789
790template <typename LHS, typename RHS>
791inline BinaryOpc_match<LHS, RHS> m_BinOp(unsigned Opc, const LHS &L,
792 const RHS &R,
793 SDNodeFlags Flgs = SDNodeFlags()) {
794 return BinaryOpc_match<LHS, RHS>(Opc, L, R, Flgs);
795}
796template <typename LHS, typename RHS>
798m_c_BinOp(unsigned Opc, const LHS &L, const RHS &R,
799 SDNodeFlags Flgs = SDNodeFlags()) {
800 return BinaryOpc_match<LHS, RHS, true>(Opc, L, R, Flgs);
801}
802
803template <typename LHS, typename RHS>
805m_ChainedBinOp(unsigned Opc, const LHS &L, const RHS &R) {
807}
808template <typename LHS, typename RHS>
810m_c_ChainedBinOp(unsigned Opc, const LHS &L, const RHS &R) {
812}
813
814// Common binary operations
815template <typename LHS, typename RHS>
816inline BinaryOpc_match<LHS, RHS, true> m_Add(const LHS &L, const RHS &R) {
818}
819
820template <typename LHS, typename RHS>
821inline auto m_NUWAdd(const LHS &L, const RHS &R) {
824}
825
826template <typename LHS, typename RHS>
827inline auto m_NSWAdd(const LHS &L, const RHS &R) {
830}
831
832template <typename LHS, typename RHS>
833inline BinaryOpc_match<LHS, RHS> m_Sub(const LHS &L, const RHS &R) {
835}
836
837template <typename LHS, typename RHS>
838inline BinaryOpc_match<LHS, RHS, true> m_Mul(const LHS &L, const RHS &R) {
840}
841
842template <typename LHS, typename RHS>
843inline BinaryOpc_match<LHS, RHS, true> m_And(const LHS &L, const RHS &R) {
845}
846
847template <typename LHS, typename RHS>
848inline BinaryOpc_match<LHS, RHS, true> m_Or(const LHS &L, const RHS &R) {
850}
851
852template <typename LHS, typename RHS>
857
858template <typename LHS, typename RHS>
859inline auto m_AddLike(const LHS &L, const RHS &R) {
860 return m_AnyOf(m_Add(L, R), m_DisjointOr(L, R));
861}
862
863template <typename LHS, typename RHS>
864inline auto m_NSWAddLike(const LHS &L, const RHS &R) {
865 return m_AnyOf(m_NSWAdd(L, R), m_DisjointOr(L, R));
866}
867
868template <typename LHS, typename RHS>
869inline auto m_NUWAddLike(const LHS &L, const RHS &R) {
870 return m_AnyOf(m_NUWAdd(L, R), m_DisjointOr(L, R));
871}
872
873template <typename LHS, typename RHS>
874inline BinaryOpc_match<LHS, RHS, true> m_Xor(const LHS &L, const RHS &R) {
876}
877
878template <typename LHS, typename RHS>
879inline auto m_BitwiseLogic(const LHS &L, const RHS &R) {
880 return m_AnyOf(m_And(L, R), m_Or(L, R), m_Xor(L, R));
881}
882
883template <unsigned Opc, typename Pred, typename LHS, typename RHS>
884inline auto m_MaxMinLike(const LHS &L, const RHS &R) {
887}
888
889template <typename LHS, typename RHS>
890inline BinaryOpc_match<LHS, RHS, true> m_SMin(const LHS &L, const RHS &R) {
892}
893
894template <typename LHS, typename RHS>
895inline auto m_SMinLike(const LHS &L, const RHS &R) {
897}
898
899template <typename LHS, typename RHS>
900inline BinaryOpc_match<LHS, RHS, true> m_SMax(const LHS &L, const RHS &R) {
902}
903
904template <typename LHS, typename RHS>
905inline auto m_SMaxLike(const LHS &L, const RHS &R) {
907}
908
909template <typename LHS, typename RHS>
910inline BinaryOpc_match<LHS, RHS, true> m_UMin(const LHS &L, const RHS &R) {
912}
913
914template <typename LHS, typename RHS>
915inline auto m_UMinLike(const LHS &L, const RHS &R) {
917}
918
919template <typename LHS, typename RHS>
920inline BinaryOpc_match<LHS, RHS, true> m_UMax(const LHS &L, const RHS &R) {
922}
923
924template <typename LHS, typename RHS>
925inline auto m_UMaxLike(const LHS &L, const RHS &R) {
927}
928
929template <typename LHS, typename RHS>
930inline BinaryOpc_match<LHS, RHS> m_UDiv(const LHS &L, const RHS &R) {
932}
933template <typename LHS, typename RHS>
934inline BinaryOpc_match<LHS, RHS> m_SDiv(const LHS &L, const RHS &R) {
936}
937
938template <typename LHS, typename RHS>
939inline BinaryOpc_match<LHS, RHS> m_URem(const LHS &L, const RHS &R) {
941}
942template <typename LHS, typename RHS>
943inline BinaryOpc_match<LHS, RHS> m_SRem(const LHS &L, const RHS &R) {
945}
946
947template <typename LHS, typename RHS>
948inline BinaryOpc_match<LHS, RHS> m_Shl(const LHS &L, const RHS &R) {
950}
951
952template <typename LHS, typename RHS>
953inline BinaryOpc_match<LHS, RHS> m_Sra(const LHS &L, const RHS &R) {
955}
956template <typename LHS, typename RHS>
957inline BinaryOpc_match<LHS, RHS> m_Srl(const LHS &L, const RHS &R) {
959}
960template <typename LHS, typename RHS>
965
966template <typename LHS, typename RHS>
967inline BinaryOpc_match<LHS, RHS> m_Rotl(const LHS &L, const RHS &R) {
969}
970
971template <typename LHS, typename RHS>
972inline BinaryOpc_match<LHS, RHS> m_Rotr(const LHS &L, const RHS &R) {
974}
975
976template <typename T0_P, typename T1_P, typename T2_P>
977inline TernaryOpc_match<T0_P, T1_P, T2_P>
978m_FShL(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
979 return m_TernaryOp(ISD::FSHL, Op0, Op1, Op2);
980}
981
982template <typename T0_P, typename T1_P, typename T2_P>
983inline TernaryOpc_match<T0_P, T1_P, T2_P>
984m_FShR(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
985 return m_TernaryOp(ISD::FSHR, Op0, Op1, Op2);
986}
987
988template <typename T0_P, typename T1_P, typename T2_P, bool Left>
990 T0_P Op0;
991 T1_P Op1;
992 T2_P Op2;
993
994 FunnelShiftLike_match(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2)
995 : Op0(Op0), Op1(Op1), Op2(Op2) {}
996
997 static bool hasComplementaryConstantShifts(const APInt &ShlV,
998 const APInt &SrlV,
999 unsigned BitWidth) {
1000 unsigned SumWidth = std::max(ShlV.getBitWidth(), SrlV.getBitWidth()) + 1;
1001 unsigned BitWidthBits = llvm::bit_width(BitWidth);
1002 if (BitWidthBits > SumWidth)
1003 return false;
1004
1005 return ShlV.zext(SumWidth) + SrlV.zext(SumWidth) ==
1006 APInt(SumWidth, BitWidth);
1007 }
1008
1010 return Op0.match(X) && Op1.match(Y) && Op2.match(Z);
1011 }
1012
1013 bool matchShiftOr(SDValue N, unsigned BitWidth);
1014
1016 if (sd_match(N, Left ? m_FShL(Op0, Op1, Op2) : m_FShR(Op0, Op1, Op2)))
1017 return true;
1018
1019 SDValue X, Z;
1020 if (sd_match(N, Left ? m_Rotl(m_Value(X), m_Value(Z))
1021 : m_Rotr(m_Value(X), m_Value(Z))))
1022 return matchOperands(X, X, Z);
1023
1024 return matchShiftOr(N, N.getValueType().getScalarSizeInBits());
1025 }
1026};
1027
1028template <typename T0_P, typename T1_P, typename T2_P>
1029inline FunnelShiftLike_match<T0_P, T1_P, T2_P, true>
1030m_FShLLike(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
1032}
1033
1034template <typename T0_P, typename T1_P, typename T2_P>
1035inline FunnelShiftLike_match<T0_P, T1_P, T2_P, false>
1036m_FShRLike(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
1038}
1039
1040template <typename LHS, typename RHS>
1043}
1044
1045template <typename LHS, typename RHS>
1046inline BinaryOpc_match<LHS, RHS, true> m_FAdd(const LHS &L, const RHS &R) {
1048}
1049
1050template <typename LHS, typename RHS>
1051inline BinaryOpc_match<LHS, RHS> m_FSub(const LHS &L, const RHS &R) {
1053}
1054
1055template <typename LHS, typename RHS>
1056inline BinaryOpc_match<LHS, RHS, true> m_FMul(const LHS &L, const RHS &R) {
1058}
1059
1060template <typename LHS, typename RHS>
1061inline BinaryOpc_match<LHS, RHS> m_FDiv(const LHS &L, const RHS &R) {
1063}
1064
1065template <typename LHS, typename RHS>
1066inline BinaryOpc_match<LHS, RHS> m_FRem(const LHS &L, const RHS &R) {
1068}
1069
1070template <typename V1_t, typename V2_t>
1071inline BinaryOpc_match<V1_t, V2_t> m_Shuffle(const V1_t &v1, const V2_t &v2) {
1073}
1074
1075template <typename V1_t, typename V2_t, typename Mask_t>
1076inline SDShuffle_match<V1_t, V2_t, Mask_t>
1077m_Shuffle(const V1_t &v1, const V2_t &v2, const Mask_t &mask) {
1079}
1080
1081template <typename LHS, typename RHS>
1082inline BinaryOpc_match<LHS, RHS> m_ExtractElt(const LHS &Vec, const RHS &Idx) {
1084}
1085
1086template <typename LHS, typename RHS>
1088 const RHS &Idx) {
1090}
1091
1092// === Unary operations ===
1093template <typename Opnd_P, bool ExcludeChain = false> struct UnaryOpc_match {
1094 unsigned Opcode;
1095 Opnd_P Opnd;
1097 UnaryOpc_match(unsigned Opc, const Opnd_P &Op,
1098 SDNodeFlags Flgs = SDNodeFlags())
1099 : Opcode(Opc), Opnd(Op), Flags(Flgs) {}
1100
1102 if (sd_match(N, m_SpecificOpc(Opcode))) {
1104 assert(EO.Size == 1);
1105 if (!Opnd.match(N->getOperand(EO.FirstIndex)))
1106 return false;
1107
1108 return (Flags & N->getFlags()) == Flags;
1109 }
1110
1111 return false;
1112 }
1113};
1114
1115template <typename Opnd>
1116inline UnaryOpc_match<Opnd> m_UnaryOp(unsigned Opc, const Opnd &Op) {
1117 return UnaryOpc_match<Opnd>(Opc, Op);
1118}
1119template <typename Opnd>
1121 const Opnd &Op) {
1123}
1124
1125template <typename Opnd> inline UnaryOpc_match<Opnd> m_BitCast(const Opnd &Op) {
1127}
1128
1129template <typename Opnd>
1130inline UnaryOpc_match<Opnd> m_BSwap(const Opnd &Op) {
1132}
1133
1134template <typename Opnd>
1138
1139template <typename Opnd> inline UnaryOpc_match<Opnd> m_ZExt(const Opnd &Op) {
1141}
1142
1143template <typename Opnd>
1147
1148template <typename Opnd> inline auto m_SExt(const Opnd &Op) {
1150}
1151
1152template <typename Opnd> inline UnaryOpc_match<Opnd> m_AnyExt(const Opnd &Op) {
1154}
1155
1156template <typename Opnd> inline UnaryOpc_match<Opnd> m_Trunc(const Opnd &Op) {
1158}
1159
1160template <typename Opnd> inline auto m_Abs(const Opnd &Op) {
1163}
1164
1165template <typename Opnd> inline UnaryOpc_match<Opnd> m_FAbs(const Opnd &Op) {
1167}
1168
1169/// Match a zext or identity
1170/// Allows to peek through optional extensions
1171template <typename Opnd> inline auto m_ZExtOrSelf(const Opnd &Op) {
1172 return m_AnyOf(m_ZExt(Op), Op);
1173}
1174
1175/// Match a sext or identity
1176/// Allows to peek through optional extensions
1177template <typename Opnd> inline auto m_SExtOrSelf(const Opnd &Op) {
1178 return m_AnyOf(m_SExt(Op), Op);
1179}
1180
1181template <typename Opnd> inline auto m_SExtLike(const Opnd &Op) {
1182 return m_AnyOf(m_SExt(Op), m_NNegZExt(Op));
1183}
1184
1185/// Match a zext or sext
1186template <typename Opnd> inline auto m_ZExtOrSExt(const Opnd &Op) {
1187 return m_AnyOf(m_ZExt(Op), m_SExt(Op));
1188}
1189
1190/// Match a aext or identity
1191/// Allows to peek through optional extensions
1192template <typename Opnd>
1193inline Or<UnaryOpc_match<Opnd>, Opnd> m_AExtOrSelf(const Opnd &Op) {
1194 return Or<UnaryOpc_match<Opnd>, Opnd>(m_AnyExt(Op), Op);
1195}
1196
1197/// Match a trunc or identity
1198/// Allows to peek through optional truncations
1199template <typename Opnd>
1200inline Or<UnaryOpc_match<Opnd>, Opnd> m_TruncOrSelf(const Opnd &Op) {
1201 return Or<UnaryOpc_match<Opnd>, Opnd>(m_Trunc(Op), Op);
1202}
1203
1204template <typename Opnd> inline UnaryOpc_match<Opnd> m_VScale(const Opnd &Op) {
1206}
1207
1208template <typename Opnd> inline UnaryOpc_match<Opnd> m_FPToUI(const Opnd &Op) {
1210}
1211
1212template <typename Opnd> inline UnaryOpc_match<Opnd> m_FPToSI(const Opnd &Op) {
1214}
1215
1216template <typename Opnd> inline UnaryOpc_match<Opnd> m_Ctpop(const Opnd &Op) {
1218}
1219
1220template <typename Opnd> inline UnaryOpc_match<Opnd> m_Ctlz(const Opnd &Op) {
1222}
1223
1224template <typename Opnd> inline UnaryOpc_match<Opnd> m_Cttz(const Opnd &Op) {
1226}
1227
1228template <typename Opnd> inline UnaryOpc_match<Opnd> m_FNeg(const Opnd &Op) {
1230}
1231
1232template <typename Opnd>
1236
1237// === Constants ===
1240
1241 explicit ConstantInt_match(APInt *V) : BindVal(V) {}
1242
1244 // The logics here are similar to that in
1245 // SelectionDAG::isConstantIntBuildVectorOrConstantInt, but the latter also
1246 // treats GlobalAddressSDNode as a constant, which is difficult to turn into
1247 // APInt.
1248 if (auto *C = dyn_cast_or_null<ConstantSDNode>(N.getNode())) {
1249 if (BindVal)
1250 *BindVal = C->getAPIntValue();
1251 return true;
1252 }
1253
1254 APInt Discard;
1255 return ISD::isConstantSplatVector(N.getNode(),
1256 BindVal ? *BindVal : Discard);
1257 }
1258};
1259
1260template <typename T> struct Constant64_match {
1261 static_assert(sizeof(T) == 8, "T must be 64 bits wide");
1262
1264
1265 explicit Constant64_match(T &V) : BindVal(V) {}
1266
1268 APInt V;
1269 if (!ConstantInt_match(&V).match(N))
1270 return false;
1271
1272 if constexpr (std::is_signed_v<T>) {
1273 if (std::optional<int64_t> TrySExt = V.trySExtValue()) {
1274 BindVal = *TrySExt;
1275 return true;
1276 }
1277 }
1278
1279 if constexpr (std::is_unsigned_v<T>) {
1280 if (std::optional<uint64_t> TryZExt = V.tryZExtValue()) {
1281 BindVal = *TryZExt;
1282 return true;
1283 }
1284 }
1285
1286 return false;
1287 }
1288};
1289
1290/// Match any integer constants or splat of an integer constant.
1292/// Match any integer constants or splat of an integer constant; return the
1293/// specific constant or constant splat value.
1295/// Match any integer constants or splat of an integer constant that can fit in
1296/// 64 bits; return the specific constant or constant splat value, zero-extended
1297/// to 64 bits.
1301/// Match any integer constants or splat of an integer constant that can fit in
1302/// 64 bits; return the specific constant or constant splat value, sign-extended
1303/// to 64 bits.
1305 return Constant64_match<int64_t>(V);
1306}
1307
1308template <typename T0_P, typename T1_P, typename T2_P, bool Left>
1310 SDValue N, unsigned BitWidth) {
1311 SDValue X, Y, ShlAmt, SrlAmt;
1312 APInt ShlConst, SrlConst;
1313 if (!sd_match(
1314 N, m_Or(m_Shl(m_Value(X), m_Value(ShlAmt, m_ConstInt(ShlConst))),
1315 m_Srl(m_Value(Y), m_Value(SrlAmt, m_ConstInt(SrlConst))))) ||
1316 !hasComplementaryConstantShifts(ShlConst, SrlConst, BitWidth))
1317 return false;
1318
1319 return matchOperands(X, Y, Left ? ShlAmt : SrlAmt);
1320}
1321
1324
1325 explicit SpecificInt_match(APInt APV) : IntVal(std::move(APV)) {}
1326
1328 APInt ConstInt;
1329 if (sd_match(N, m_ConstInt(ConstInt)))
1330 return APInt::isSameValue(IntVal, ConstInt);
1331 return false;
1332 }
1333};
1334
1335/// Match a specific integer constant or constant splat value.
1337 return SpecificInt_match(std::move(V));
1338}
1340 return SpecificInt_match(APInt(64, V));
1341}
1342
1345
1346 explicit SpecificFP_match(APFloat V) : Val(V) {}
1347
1348 bool match(SDValue V) {
1349 if (const auto *CFP = dyn_cast<ConstantFPSDNode>(V.getNode()))
1350 return CFP->isExactlyValue(Val);
1351 if (ConstantFPSDNode *C = isConstOrConstSplatFP(V, /*AllowUndefs=*/true))
1352 return C->getValueAPF().compare(Val) == APFloat::cmpEqual;
1353 return false;
1354 }
1355};
1356
1357/// Match a specific float constant.
1359
1361 return SpecificFP_match(APFloat(V));
1362}
1363
1367 return C->isZero();
1368 return false;
1369 }
1370};
1371
1372/// Match a floating-point +0.0 or -0.0 constant or splat.
1374
1377
1379
1380 bool match(SDValue N) const { return isZeroOrZeroSplat(N, AllowUndefs); }
1381};
1382
1390
1398
1399inline Ones_match m_One(bool AllowUndefs = false) {
1400 return Ones_match(AllowUndefs);
1401}
1402inline Zero_match m_Zero(bool AllowUndefs = false) {
1403 return Zero_match(AllowUndefs);
1404}
1405inline AllOnes_match m_AllOnes(bool AllowUndefs = false) {
1406 return AllOnes_match(AllowUndefs);
1407}
1408
1409template <bool Expected> struct Bool_match {
1411
1413
1415 auto Res = DAG.isBoolConstant(N);
1416 return Res && *Res == Expected;
1417 }
1418};
1419
1420/// Match true boolean value based on the information provided by
1421/// TargetLowering.
1422inline auto m_True(const SelectionDAG &DAG) { return Bool_match<true>(DAG); }
1423
1424/// Match false boolean value based on the information provided by
1425/// TargetLowering.
1426inline auto m_False(const SelectionDAG &DAG) { return Bool_match<false>(DAG); }
1427
1428/// Match a negate as a sub(0, v)
1429template <typename ValTy>
1431 return m_Sub(m_Zero(), V);
1432}
1433
1434/// Match a Not as a xor(v, -1) or xor(-1, v)
1435template <typename ValTy>
1437 return m_Xor(V, m_AllOnes());
1438}
1439
1440template <unsigned IntrinsicId, typename... OpndPreds>
1441inline auto m_IntrinsicWOChain(const OpndPreds &...Opnds) {
1442 return m_Node(ISD::INTRINSIC_WO_CHAIN, m_SpecificInt(IntrinsicId), Opnds...);
1443}
1444
1447
1449
1451 if (sd_match(N, m_Neg(m_Specific(V))))
1452 return true;
1453
1456 return LHS->getAPIntValue() == -RHS->getAPIntValue();
1457 });
1458 }
1459};
1460
1461/// Match a negation of a specific value V, either as sub(0, V) or as
1462/// constant(s) that are the negation of V's constant(s).
1466
1467template <typename... PatternTs> struct ReassociatableOpc_match {
1468 unsigned Opcode;
1469 std::tuple<PatternTs...> Patterns;
1470 constexpr static size_t NumPatterns =
1471 std::tuple_size_v<std::tuple<PatternTs...>>;
1472
1474
1475 ReassociatableOpc_match(unsigned Opcode, const PatternTs &...Patterns)
1476 : Opcode(Opcode), Patterns(Patterns...) {}
1477
1479 const PatternTs &...Patterns)
1481
1483 std::array<SDValue, NumPatterns> Leaves;
1484 size_t LeavesIdx = 0;
1485 if (!(collectLeaves(N, Leaves, LeavesIdx) && (LeavesIdx == NumPatterns)))
1486 return false;
1487
1489 return std::apply(
1490 [&](auto &...P) -> bool {
1491 return reassociatableMatchHelper(Leaves, Used, P...);
1492 },
1493 Patterns);
1494 }
1495
1496 bool collectLeaves(SDValue V, std::array<SDValue, NumPatterns> &Leaves,
1497 std::size_t &LeafIdx) {
1498 if (V->getOpcode() == Opcode && (Flags & V->getFlags()) == Flags) {
1499 for (size_t I = 0, N = V->getNumOperands(); I < N; I++)
1500 if ((LeafIdx == NumPatterns) ||
1501 !collectLeaves(V->getOperand(I), Leaves, LeafIdx))
1502 return false;
1503 } else {
1504 Leaves[LeafIdx] = V;
1505 LeafIdx++;
1506 }
1507 return true;
1508 }
1509
1510 // Searchs for a matching leaf for every sub-pattern.
1511 template <typename PatternHd, typename... PatternTl>
1512 [[nodiscard]] inline bool
1514 PatternHd &HeadPattern,
1515 PatternTl &...TailPatterns) {
1516 for (size_t Match = 0, N = Used.size(); Match < N; Match++) {
1517 if (Used[Match] || !(sd_match(Leaves[Match], HeadPattern)))
1518 continue;
1519 Used.set(Match);
1520 if (reassociatableMatchHelper(Leaves, Used, TailPatterns...))
1521 return true;
1522 Used.reset(Match);
1523 }
1524 return false;
1525 }
1526
1527 [[nodiscard]] inline bool
1529 Bitset<NumPatterns> &Used) {
1530 return true;
1531 }
1532};
1533
1534template <typename... PatternTs>
1535inline ReassociatableOpc_match<PatternTs...>
1536m_ReassociatableAdd(const PatternTs &...Patterns) {
1537 return ReassociatableOpc_match<PatternTs...>(ISD::ADD, Patterns...);
1538}
1539
1540template <typename... PatternTs>
1541inline ReassociatableOpc_match<PatternTs...>
1542m_ReassociatableOr(const PatternTs &...Patterns) {
1543 return ReassociatableOpc_match<PatternTs...>(ISD::OR, Patterns...);
1544}
1545
1546template <typename... PatternTs>
1547inline ReassociatableOpc_match<PatternTs...>
1548m_ReassociatableAnd(const PatternTs &...Patterns) {
1549 return ReassociatableOpc_match<PatternTs...>(ISD::AND, Patterns...);
1550}
1551
1552template <typename... PatternTs>
1553inline ReassociatableOpc_match<PatternTs...>
1554m_ReassociatableMul(const PatternTs &...Patterns) {
1555 return ReassociatableOpc_match<PatternTs...>(ISD::MUL, Patterns...);
1556}
1557
1558template <typename... PatternTs>
1559inline ReassociatableOpc_match<PatternTs...>
1560m_ReassociatableNSWAdd(const PatternTs &...Patterns) {
1561 return ReassociatableOpc_match<PatternTs...>(
1562 ISD::ADD, SDNodeFlags::NoSignedWrap, Patterns...);
1563}
1564
1565template <typename... PatternTs>
1566inline ReassociatableOpc_match<PatternTs...>
1567m_ReassociatableNUWAdd(const PatternTs &...Patterns) {
1568 return ReassociatableOpc_match<PatternTs...>(
1570}
1571
1572} // namespace SDPatternMatch
1573} // namespace llvm
1574#endif
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned uint64_t
This file implements a class to represent arbitrary precision integral constant values and operations...
#define X(NUM, ENUM, NAME)
Definition ELF.h:857
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)
const SmallVectorImpl< MachineOperand > & Cond
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
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition APInt.h:1508
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
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:837
@ 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:797
@ 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:871
@ 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:757
@ 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:788
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:862
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
Definition ISDOpcodes.h:814
@ UNDEF
UNDEF - An undefined node.
Definition ISDOpcodes.h:235
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:779
@ 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:868
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
Definition ISDOpcodes.h:829
@ 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:737
@ 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:823
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition ISDOpcodes.h:944
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:749
@ 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:874
@ ABS_MIN_POISON
ABS with a poison result for INT_MIN.
Definition ISDOpcodes.h:761
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 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)
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:1557
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
@ 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...
LLVM_ABI bool isOnesOrOnesSplat(SDValue N, bool AllowUndefs=false)
Return true if the value is a constant 1 integer or a splatted vector of a constant 1 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)