LLVM 23.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"
24
25namespace llvm {
26namespace SDPatternMatch {
27
28/// MatchContext can repurpose existing patterns to behave differently under
29/// a certain context. For instance, `m_Opc(ISD::ADD)` matches plain ADD nodes
30/// in normal circumstances, but matches VP_ADD nodes under a custom
31/// VPMatchContext. This design is meant to facilitate code / pattern reusing.
33 const SelectionDAG *DAG;
34 const TargetLowering *TLI;
35
36public:
37 explicit BasicMatchContext(const SelectionDAG *DAG)
38 : DAG(DAG), TLI(DAG ? &DAG->getTargetLoweringInfo() : nullptr) {}
39
40 explicit BasicMatchContext(const TargetLowering *TLI)
41 : DAG(nullptr), TLI(TLI) {}
42
43 // A valid MatchContext has to implement the following functions.
44
45 const SelectionDAG *getDAG() const { return DAG; }
46
47 const TargetLowering *getTLI() const { return TLI; }
48
49 /// Return true if N effectively has opcode Opcode.
50 bool match(SDValue N, unsigned Opcode) const {
51 return N->getOpcode() == Opcode;
52 }
53
54 unsigned getNumOperands(SDValue N) const { return N->getNumOperands(); }
55};
56
57template <typename Pattern, typename MatchContext>
58[[nodiscard]] bool sd_context_match(SDValue N, const MatchContext &Ctx,
59 Pattern &&P) {
60 return P.match(Ctx, N);
61}
62
63template <typename Pattern, typename MatchContext>
64[[nodiscard]] bool sd_context_match(SDNode *N, const MatchContext &Ctx,
65 Pattern &&P) {
66 return sd_context_match(SDValue(N, 0), Ctx, P);
67}
68
69template <typename Pattern>
70[[nodiscard]] bool sd_match(SDNode *N, const SelectionDAG *DAG, Pattern &&P) {
72}
73
74template <typename Pattern>
75[[nodiscard]] bool sd_match(SDValue N, const SelectionDAG *DAG, Pattern &&P) {
77}
78
79template <typename Pattern>
80[[nodiscard]] bool sd_match(SDNode *N, Pattern &&P) {
81 return sd_match(N, nullptr, P);
82}
83
84template <typename Pattern>
85[[nodiscard]] bool sd_match(SDValue N, Pattern &&P) {
86 return sd_match(N, nullptr, P);
87}
88
89// === Utilities ===
92
93 Value_match() = default;
94
95 explicit Value_match(SDValue Match) : MatchVal(Match) {}
96
97 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
98 if (MatchVal)
99 return MatchVal == N;
100 return N.getNode();
101 }
102};
103
104/// Match any valid SDValue.
105inline Value_match m_Value() { return Value_match(); }
106
108 assert(N);
109 return Value_match(N);
110}
111
112template <unsigned ResNo, typename Pattern> struct Result_match {
114
115 explicit Result_match(const Pattern &P) : P(P) {}
116
117 template <typename MatchContext>
118 bool match(const MatchContext &Ctx, SDValue N) {
119 return N.getResNo() == ResNo && P.match(Ctx, N);
120 }
121};
122
123/// Match only if the SDValue is a certain result at ResNo.
124template <unsigned ResNo, typename Pattern>
128
131
132 explicit DeferredValue_match(SDValue &Match) : MatchVal(Match) {}
133
134 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
135 return N == MatchVal;
136 }
137};
138
139/// Similar to m_Specific, but the specific value to match is determined by
140/// another sub-pattern in the same sd_match() expression. For instance,
141/// We cannot match `(add V, V)` with `m_Add(m_Value(X), m_Specific(X))` since
142/// `X` is not initialized at the time it got copied into `m_Specific`. Instead,
143/// we should use `m_Add(m_Value(X), m_Deferred(X))`.
147
149 unsigned Opcode;
150
151 explicit Opcode_match(unsigned Opc) : Opcode(Opc) {}
152
153 template <typename MatchContext>
154 bool match(const MatchContext &Ctx, SDValue N) {
155 return Ctx.match(N, Opcode);
156 }
157};
158
159// === Patterns combinators ===
160template <typename... Preds> struct And {
161 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
162 return true;
163 }
164};
165
166template <typename Pred, typename... Preds>
167struct And<Pred, Preds...> : And<Preds...> {
168 Pred P;
169 And(const Pred &p, const Preds &...preds) : And<Preds...>(preds...), P(p) {}
170
171 template <typename MatchContext>
172 bool match(const MatchContext &Ctx, SDValue N) {
173 return P.match(Ctx, N) && And<Preds...>::match(Ctx, N);
174 }
175};
176
177template <typename... Preds> struct Or {
178 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
179 return false;
180 }
181};
182
183template <typename Pred, typename... Preds>
184struct Or<Pred, Preds...> : Or<Preds...> {
185 Pred P;
186 Or(const Pred &p, const Preds &...preds) : Or<Preds...>(preds...), P(p) {}
187
188 template <typename MatchContext>
189 bool match(const MatchContext &Ctx, SDValue N) {
190 return P.match(Ctx, N) || Or<Preds...>::match(Ctx, N);
191 }
192};
193
194template <typename Pred> struct Not {
195 Pred P;
196
197 explicit Not(const Pred &P) : P(P) {}
198
199 template <typename MatchContext>
200 bool match(const MatchContext &Ctx, SDValue N) {
201 return !P.match(Ctx, N);
202 }
203};
204// Explicit deduction guide.
205template <typename Pred> Not(const Pred &P) -> Not<Pred>;
206
207/// Match if the inner pattern does NOT match.
208template <typename Pred> inline Not<Pred> m_Unless(const Pred &P) {
209 return Not{P};
210}
211
212template <typename... Preds> And<Preds...> m_AllOf(const Preds &...preds) {
213 return And<Preds...>(preds...);
214}
215
216template <typename... Preds> Or<Preds...> m_AnyOf(const Preds &...preds) {
217 return Or<Preds...>(preds...);
218}
219
220template <typename... Preds> auto m_NoneOf(const Preds &...preds) {
221 return m_Unless(m_AnyOf(preds...));
222}
223
224inline Opcode_match m_Opc(unsigned Opcode) { return Opcode_match(Opcode); }
225
226inline auto m_Undef() {
228}
229
231
232template <unsigned NumUses, typename Pattern> struct NUses_match {
234
235 explicit NUses_match(const Pattern &P) : P(P) {}
236
237 template <typename MatchContext>
238 bool match(const MatchContext &Ctx, SDValue N) {
239 // SDNode::hasNUsesOfValue is pretty expensive when the SDNode produces
240 // multiple results, hence we check the subsequent pattern here before
241 // checking the number of value users.
242 return P.match(Ctx, N) && N->hasNUsesOfValue(NumUses, N.getResNo());
243 }
244};
245
246template <typename Pattern>
250template <unsigned N, typename Pattern>
254
258template <unsigned N> inline NUses_match<N, Value_match> m_NUses() {
260}
261
264
265 explicit Value_bind(SDValue &N) : BindVal(N) {}
266
267 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
268 BindVal = N;
269 return true;
270 }
271};
272
273inline Value_bind m_Value(SDValue &N) { return Value_bind(N); }
274
275template <typename Pattern, typename PredFuncT> struct TLI_pred_match {
277 PredFuncT PredFunc;
278
279 TLI_pred_match(const PredFuncT &Pred, const Pattern &P)
280 : P(P), PredFunc(Pred) {}
281
282 template <typename MatchContext>
283 bool match(const MatchContext &Ctx, SDValue N) {
284 assert(Ctx.getTLI() && "TargetLowering is required for this pattern.");
285 return PredFunc(*Ctx.getTLI(), N) && P.match(Ctx, N);
286 }
287};
288
289// Explicit deduction guide.
290template <typename PredFuncT, typename Pattern>
291TLI_pred_match(const PredFuncT &Pred, const Pattern &P)
293
294/// Match legal SDNodes based on the information provided by TargetLowering.
295template <typename Pattern> inline auto m_LegalOp(const Pattern &P) {
296 return TLI_pred_match{[](const TargetLowering &TLI, SDValue N) {
297 return TLI.isOperationLegal(N->getOpcode(),
298 N.getValueType());
299 },
300 P};
301}
302
303/// Switch to a different MatchContext for subsequent patterns.
304template <typename NewMatchContext, typename Pattern> struct SwitchContext {
305 const NewMatchContext &Ctx;
307
308 template <typename OrigMatchContext>
309 bool match(const OrigMatchContext &, SDValue N) {
310 return P.match(Ctx, N);
311 }
312};
313
314template <typename MatchContext, typename Pattern>
315inline SwitchContext<MatchContext, Pattern> m_Context(const MatchContext &Ctx,
316 Pattern &&P) {
317 return SwitchContext<MatchContext, Pattern>{Ctx, std::move(P)};
318}
319
320// === Value type ===
323
324 explicit ValueType_bind(EVT &Bind) : BindVT(Bind) {}
325
326 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
327 BindVT = N.getValueType();
328 return true;
329 }
330};
331
332/// Retreive the ValueType of the current SDValue.
333inline ValueType_bind m_VT(EVT &VT) { return ValueType_bind(VT); }
334
335template <typename Pattern, typename PredFuncT> struct ValueType_match {
336 PredFuncT PredFunc;
338
339 ValueType_match(const PredFuncT &Pred, const Pattern &P)
340 : PredFunc(Pred), P(P) {}
341
342 template <typename MatchContext>
343 bool match(const MatchContext &Ctx, SDValue N) {
344 return PredFunc(N.getValueType()) && P.match(Ctx, N);
345 }
346};
347
348// Explicit deduction guide.
349template <typename PredFuncT, typename Pattern>
350ValueType_match(const PredFuncT &Pred, const Pattern &P)
352
353/// Match a specific ValueType.
354template <typename Pattern>
355inline auto m_SpecificVT(EVT RefVT, const Pattern &P) {
356 return ValueType_match{[=](EVT VT) { return VT == RefVT; }, P};
357}
358inline auto m_SpecificVT(EVT RefVT) {
359 return ValueType_match{[=](EVT VT) { return VT == RefVT; }, m_Value()};
360}
361
362inline auto m_Glue() { return m_SpecificVT(MVT::Glue); }
363inline auto m_OtherVT() { return m_SpecificVT(MVT::Other); }
364
365/// Match a scalar ValueType.
366template <typename Pattern>
367inline auto m_SpecificScalarVT(EVT RefVT, const Pattern &P) {
368 return ValueType_match{[=](EVT VT) { return VT.getScalarType() == RefVT; },
369 P};
370}
371inline auto m_SpecificScalarVT(EVT RefVT) {
372 return ValueType_match{[=](EVT VT) { return VT.getScalarType() == RefVT; },
373 m_Value()};
374}
375
376/// Match a vector ValueType.
377template <typename Pattern>
378inline auto m_SpecificVectorElementVT(EVT RefVT, const Pattern &P) {
379 return ValueType_match{[=](EVT VT) {
380 return VT.isVector() &&
381 VT.getVectorElementType() == RefVT;
382 },
383 P};
384}
385inline auto m_SpecificVectorElementVT(EVT RefVT) {
386 return ValueType_match{[=](EVT VT) {
387 return VT.isVector() &&
388 VT.getVectorElementType() == RefVT;
389 },
390 m_Value()};
391}
392
393/// Match any integer ValueTypes.
394template <typename Pattern> inline auto m_IntegerVT(const Pattern &P) {
395 return ValueType_match{[](EVT VT) { return VT.isInteger(); }, P};
396}
397inline auto m_IntegerVT() {
398 return ValueType_match{[](EVT VT) { return VT.isInteger(); }, m_Value()};
399}
400
401/// Match any floating point ValueTypes.
402template <typename Pattern> inline auto m_FloatingPointVT(const Pattern &P) {
403 return ValueType_match{[](EVT VT) { return VT.isFloatingPoint(); }, P};
404}
405inline auto m_FloatingPointVT() {
406 return ValueType_match{[](EVT VT) { return VT.isFloatingPoint(); },
407 m_Value()};
408}
409
410/// Match any vector ValueTypes.
411template <typename Pattern> inline auto m_VectorVT(const Pattern &P) {
412 return ValueType_match{[](EVT VT) { return VT.isVector(); }, P};
413}
414inline auto m_VectorVT() {
415 return ValueType_match{[](EVT VT) { return VT.isVector(); }, m_Value()};
416}
417
418/// Match fixed-length vector ValueTypes.
419template <typename Pattern> inline auto m_FixedVectorVT(const Pattern &P) {
420 return ValueType_match{[](EVT VT) { return VT.isFixedLengthVector(); }, P};
421}
422inline auto m_FixedVectorVT() {
423 return ValueType_match{[](EVT VT) { return VT.isFixedLengthVector(); },
424 m_Value()};
425}
426
427/// Match scalable vector ValueTypes.
428template <typename Pattern> inline auto m_ScalableVectorVT(const Pattern &P) {
429 return ValueType_match{[](EVT VT) { return VT.isScalableVector(); }, P};
430}
431inline auto m_ScalableVectorVT() {
432 return ValueType_match{[](EVT VT) { return VT.isScalableVector(); },
433 m_Value()};
434}
435
436/// Match legal ValueTypes based on the information provided by TargetLowering.
437template <typename Pattern> inline auto m_LegalType(const Pattern &P) {
438 return TLI_pred_match{[](const TargetLowering &TLI, SDValue N) {
439 return TLI.isTypeLegal(N.getValueType());
440 },
441 P};
442}
443
444// === Generic node matching ===
445template <unsigned OpIdx, typename... OpndPreds> struct Operands_match {
446 template <typename MatchContext>
447 bool match(const MatchContext &Ctx, SDValue N) {
448 // Returns false if there are more operands than predicates;
449 // Ignores the last two operands if both the Context and the Node are VP
450 return Ctx.getNumOperands(N) == OpIdx;
451 }
452};
453
454template <unsigned OpIdx, typename OpndPred, typename... OpndPreds>
455struct Operands_match<OpIdx, OpndPred, OpndPreds...>
456 : Operands_match<OpIdx + 1, OpndPreds...> {
457 OpndPred P;
458
459 Operands_match(const OpndPred &p, const OpndPreds &...preds)
460 : Operands_match<OpIdx + 1, OpndPreds...>(preds...), P(p) {}
461
462 template <typename MatchContext>
463 bool match(const MatchContext &Ctx, SDValue N) {
464 if (OpIdx < N->getNumOperands())
465 return P.match(Ctx, N->getOperand(OpIdx)) &&
467
468 // This is the case where there are more predicates than operands.
469 return false;
470 }
471};
472
473template <typename... OpndPreds>
474auto m_Node(unsigned Opcode, const OpndPreds &...preds) {
475 return m_AllOf(m_Opc(Opcode), Operands_match<0, OpndPreds...>(preds...));
476}
477
478/// Provide number of operands that are not chain or glue, as well as the first
479/// index of such operand.
480template <bool ExcludeChain> struct EffectiveOperands {
481 unsigned Size = 0;
482 unsigned FirstIndex = 0;
483
484 template <typename MatchContext>
485 explicit EffectiveOperands(SDValue N, const MatchContext &Ctx) {
486 const unsigned TotalNumOps = Ctx.getNumOperands(N);
487 FirstIndex = TotalNumOps;
488 for (unsigned I = 0; I < TotalNumOps; ++I) {
489 // Count the number of non-chain and non-glue nodes (we ignore chain
490 // and glue by default) and retreive the operand index offset.
491 EVT VT = N->getOperand(I).getValueType();
492 if (VT != MVT::Glue && VT != MVT::Other) {
493 ++Size;
494 if (FirstIndex == TotalNumOps)
495 FirstIndex = I;
496 }
497 }
498 }
499};
500
501template <> struct EffectiveOperands<false> {
502 unsigned Size = 0;
503 unsigned FirstIndex = 0;
504
505 template <typename MatchContext>
506 explicit EffectiveOperands(SDValue N, const MatchContext &Ctx)
507 : Size(Ctx.getNumOperands(N)) {}
508};
509
510// === Ternary operations ===
511template <typename T0_P, typename T1_P, typename T2_P, bool Commutable = false,
512 bool ExcludeChain = false>
514 unsigned Opcode;
515 T0_P Op0;
516 T1_P Op1;
517 T2_P Op2;
518
519 TernaryOpc_match(unsigned Opc, const T0_P &Op0, const T1_P &Op1,
520 const T2_P &Op2)
521 : Opcode(Opc), Op0(Op0), Op1(Op1), Op2(Op2) {}
522
523 template <typename MatchContext>
524 bool match(const MatchContext &Ctx, SDValue N) {
525 if (sd_context_match(N, Ctx, m_Opc(Opcode))) {
527 assert(EO.Size == 3);
528 return ((Op0.match(Ctx, N->getOperand(EO.FirstIndex)) &&
529 Op1.match(Ctx, N->getOperand(EO.FirstIndex + 1))) ||
530 (Commutable && Op0.match(Ctx, N->getOperand(EO.FirstIndex + 1)) &&
531 Op1.match(Ctx, N->getOperand(EO.FirstIndex)))) &&
532 Op2.match(Ctx, N->getOperand(EO.FirstIndex + 2));
533 }
534
535 return false;
536 }
537};
538
539template <typename T0_P, typename T1_P, typename T2_P>
540inline TernaryOpc_match<T0_P, T1_P, T2_P>
541m_SetCC(const T0_P &LHS, const T1_P &RHS, const T2_P &CC) {
543}
544
545template <typename T0_P, typename T1_P, typename T2_P>
546inline TernaryOpc_match<T0_P, T1_P, T2_P, true, false>
547m_c_SetCC(const T0_P &LHS, const T1_P &RHS, const T2_P &CC) {
549 CC);
550}
551
552template <typename T0_P, typename T1_P, typename T2_P>
553inline TernaryOpc_match<T0_P, T1_P, T2_P>
554m_Select(const T0_P &Cond, const T1_P &T, const T2_P &F) {
556}
557
558template <typename T0_P, typename T1_P, typename T2_P>
559inline TernaryOpc_match<T0_P, T1_P, T2_P>
560m_VSelect(const T0_P &Cond, const T1_P &T, const T2_P &F) {
562}
563
564template <typename T0_P, typename T1_P, typename T2_P>
565inline auto m_SelectLike(const T0_P &Cond, const T1_P &T, const T2_P &F) {
566 return m_AnyOf(m_Select(Cond, T, F), m_VSelect(Cond, T, F));
567}
568
569template <typename T0_P, typename T1_P, typename T2_P>
570inline Result_match<0, TernaryOpc_match<T0_P, T1_P, T2_P>>
571m_Load(const T0_P &Ch, const T1_P &Ptr, const T2_P &Offset) {
572 return m_Result<0>(
574}
575
576template <typename T0_P, typename T1_P, typename T2_P>
577inline TernaryOpc_match<T0_P, T1_P, T2_P>
578m_InsertElt(const T0_P &Vec, const T1_P &Val, const T2_P &Idx) {
580 Idx);
581}
582
583template <typename LHS, typename RHS, typename IDX>
584inline TernaryOpc_match<LHS, RHS, IDX>
585m_InsertSubvector(const LHS &Base, const RHS &Sub, const IDX &Idx) {
587}
588
589template <typename T0_P, typename T1_P, typename T2_P>
590inline TernaryOpc_match<T0_P, T1_P, T2_P>
591m_TernaryOp(unsigned Opc, const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
592 return TernaryOpc_match<T0_P, T1_P, T2_P>(Opc, Op0, Op1, Op2);
593}
594
595template <typename T0_P, typename T1_P, typename T2_P>
596inline TernaryOpc_match<T0_P, T1_P, T2_P, true>
597m_c_TernaryOp(unsigned Opc, const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
598 return TernaryOpc_match<T0_P, T1_P, T2_P, true>(Opc, Op0, Op1, Op2);
599}
600
601template <typename LTy, typename RTy, typename TTy, typename FTy, typename CCTy>
602inline auto m_SelectCC(const LTy &L, const RTy &R, const TTy &T, const FTy &F,
603 const CCTy &CC) {
604 return m_Node(ISD::SELECT_CC, L, R, T, F, CC);
605}
606
607template <typename LTy, typename RTy, typename TTy, typename FTy, typename CCTy>
608inline auto m_SelectCCLike(const LTy &L, const RTy &R, const TTy &T,
609 const FTy &F, const CCTy &CC) {
610 return m_AnyOf(m_Select(m_SetCC(L, R, CC), T, F), m_SelectCC(L, R, T, F, CC));
611}
612
613// === Binary operations ===
614template <typename LHS_P, typename RHS_P, bool Commutable = false,
615 bool ExcludeChain = false>
617 unsigned Opcode;
618 LHS_P LHS;
619 RHS_P RHS;
621 BinaryOpc_match(unsigned Opc, const LHS_P &L, const RHS_P &R,
622 SDNodeFlags Flgs = SDNodeFlags())
623 : Opcode(Opc), LHS(L), RHS(R), Flags(Flgs) {}
624
625 template <typename MatchContext>
626 bool match(const MatchContext &Ctx, SDValue N) {
627 if (sd_context_match(N, Ctx, m_Opc(Opcode))) {
629 assert(EO.Size == 2);
630 if (!((LHS.match(Ctx, N->getOperand(EO.FirstIndex)) &&
631 RHS.match(Ctx, N->getOperand(EO.FirstIndex + 1))) ||
632 (Commutable && LHS.match(Ctx, N->getOperand(EO.FirstIndex + 1)) &&
633 RHS.match(Ctx, N->getOperand(EO.FirstIndex)))))
634 return false;
635
636 return (Flags & N->getFlags()) == Flags;
637 }
638
639 return false;
640 }
641};
642
643/// Matching while capturing mask
644template <typename T0, typename T1, typename T2> struct SDShuffle_match {
645 T0 Op1;
648
649 SDShuffle_match(const T0 &Op1, const T1 &Op2, const T2 &Mask)
650 : Op1(Op1), Op2(Op2), Mask(Mask) {}
651
652 template <typename MatchContext>
653 bool match(const MatchContext &Ctx, SDValue N) {
654 if (auto *I = dyn_cast<ShuffleVectorSDNode>(N)) {
655 return Op1.match(Ctx, I->getOperand(0)) &&
656 Op2.match(Ctx, I->getOperand(1)) && Mask.match(I->getMask());
657 }
658 return false;
659 }
660};
661struct m_Mask {
664 bool match(ArrayRef<int> Mask) {
665 MaskRef = Mask;
666 return true;
667 }
668};
669
675
676template <typename LHS_P, typename RHS_P, typename Pred_t,
677 bool Commutable = false, bool ExcludeChain = false>
679 using PredType = Pred_t;
680 LHS_P LHS;
681 RHS_P RHS;
682
683 MaxMin_match(const LHS_P &L, const RHS_P &R) : LHS(L), RHS(R) {}
684
685 template <typename MatchContext>
686 bool match(const MatchContext &Ctx, SDValue N) {
687 auto MatchMinMax = [&](SDValue L, SDValue R, SDValue TrueValue,
688 SDValue FalseValue, ISD::CondCode CC) {
689 if ((TrueValue != L || FalseValue != R) &&
690 (TrueValue != R || FalseValue != L))
691 return false;
692
694 TrueValue == L ? CC : getSetCCInverse(CC, L.getValueType());
695 if (!Pred_t::match(Cond))
696 return false;
697
698 return (LHS.match(Ctx, L) && RHS.match(Ctx, R)) ||
699 (Commutable && LHS.match(Ctx, R) && RHS.match(Ctx, L));
700 };
701
702 if (sd_context_match(N, Ctx, m_Opc(ISD::SELECT)) ||
704 EffectiveOperands<ExcludeChain> EO_SELECT(N, Ctx);
705 assert(EO_SELECT.Size == 3);
706 SDValue Cond = N->getOperand(EO_SELECT.FirstIndex);
707 SDValue TrueValue = N->getOperand(EO_SELECT.FirstIndex + 1);
708 SDValue FalseValue = N->getOperand(EO_SELECT.FirstIndex + 2);
709
712 assert(EO_SETCC.Size == 3);
713 SDValue L = Cond->getOperand(EO_SETCC.FirstIndex);
714 SDValue R = Cond->getOperand(EO_SETCC.FirstIndex + 1);
715 auto *CondNode =
716 cast<CondCodeSDNode>(Cond->getOperand(EO_SETCC.FirstIndex + 2));
717 return MatchMinMax(L, R, TrueValue, FalseValue, CondNode->get());
718 }
719 }
720
722 EffectiveOperands<ExcludeChain> EO_SELECT(N, Ctx);
723 assert(EO_SELECT.Size == 5);
724 SDValue L = N->getOperand(EO_SELECT.FirstIndex);
725 SDValue R = N->getOperand(EO_SELECT.FirstIndex + 1);
726 SDValue TrueValue = N->getOperand(EO_SELECT.FirstIndex + 2);
727 SDValue FalseValue = N->getOperand(EO_SELECT.FirstIndex + 3);
728 auto *CondNode =
729 cast<CondCodeSDNode>(N->getOperand(EO_SELECT.FirstIndex + 4));
730 return MatchMinMax(L, R, TrueValue, FalseValue, CondNode->get());
731 }
732
733 return false;
734 }
735};
736
737// Helper class for identifying signed max predicates.
739 static bool match(ISD::CondCode Cond) {
741 }
742};
743
744// Helper class for identifying unsigned max predicates.
749};
750
751// Helper class for identifying signed min predicates.
753 static bool match(ISD::CondCode Cond) {
755 }
756};
757
758// Helper class for identifying unsigned min predicates.
763};
764
765template <typename LHS, typename RHS>
766inline BinaryOpc_match<LHS, RHS> m_BinOp(unsigned Opc, const LHS &L,
767 const RHS &R,
768 SDNodeFlags Flgs = SDNodeFlags()) {
769 return BinaryOpc_match<LHS, RHS>(Opc, L, R, Flgs);
770}
771template <typename LHS, typename RHS>
773m_c_BinOp(unsigned Opc, const LHS &L, const RHS &R,
774 SDNodeFlags Flgs = SDNodeFlags()) {
775 return BinaryOpc_match<LHS, RHS, true>(Opc, L, R, Flgs);
776}
777
778template <typename LHS, typename RHS>
780m_ChainedBinOp(unsigned Opc, const LHS &L, const RHS &R) {
782}
783template <typename LHS, typename RHS>
785m_c_ChainedBinOp(unsigned Opc, const LHS &L, const RHS &R) {
787}
788
789// Common binary operations
790template <typename LHS, typename RHS>
791inline BinaryOpc_match<LHS, RHS, true> m_Add(const LHS &L, const RHS &R) {
793}
794
795template <typename LHS, typename RHS>
796inline BinaryOpc_match<LHS, RHS> m_Sub(const LHS &L, const RHS &R) {
798}
799
800template <typename LHS, typename RHS>
801inline BinaryOpc_match<LHS, RHS, true> m_Mul(const LHS &L, const RHS &R) {
803}
804
805template <typename LHS, typename RHS>
806inline BinaryOpc_match<LHS, RHS, true> m_And(const LHS &L, const RHS &R) {
808}
809
810template <typename LHS, typename RHS>
811inline BinaryOpc_match<LHS, RHS, true> m_Or(const LHS &L, const RHS &R) {
813}
814
815template <typename LHS, typename RHS>
820
821template <typename LHS, typename RHS>
822inline auto m_AddLike(const LHS &L, const RHS &R) {
823 return m_AnyOf(m_Add(L, R), m_DisjointOr(L, R));
824}
825
826template <typename LHS, typename RHS>
827inline BinaryOpc_match<LHS, RHS, true> m_Xor(const LHS &L, const RHS &R) {
829}
830
831template <typename LHS, typename RHS>
832inline auto m_BitwiseLogic(const LHS &L, const RHS &R) {
833 return m_AnyOf(m_And(L, R), m_Or(L, R), m_Xor(L, R));
834}
835
836template <unsigned Opc, typename Pred, typename LHS, typename RHS>
837inline auto m_MaxMinLike(const LHS &L, const RHS &R) {
840}
841
842template <typename LHS, typename RHS>
843inline BinaryOpc_match<LHS, RHS, true> m_SMin(const LHS &L, const RHS &R) {
845}
846
847template <typename LHS, typename RHS>
854
855template <typename LHS, typename RHS>
856inline BinaryOpc_match<LHS, RHS, true> m_SMax(const LHS &L, const RHS &R) {
858}
859
860template <typename LHS, typename RHS>
867
868template <typename LHS, typename RHS>
869inline BinaryOpc_match<LHS, RHS, true> m_UMin(const LHS &L, const RHS &R) {
871}
872
873template <typename LHS, typename RHS>
880
881template <typename LHS, typename RHS>
882inline BinaryOpc_match<LHS, RHS, true> m_UMax(const LHS &L, const RHS &R) {
884}
885
886template <typename LHS, typename RHS>
893
894template <typename LHS, typename RHS>
895inline BinaryOpc_match<LHS, RHS> m_UDiv(const LHS &L, const RHS &R) {
897}
898template <typename LHS, typename RHS>
899inline BinaryOpc_match<LHS, RHS> m_SDiv(const LHS &L, const RHS &R) {
901}
902
903template <typename LHS, typename RHS>
904inline BinaryOpc_match<LHS, RHS> m_URem(const LHS &L, const RHS &R) {
906}
907template <typename LHS, typename RHS>
908inline BinaryOpc_match<LHS, RHS> m_SRem(const LHS &L, const RHS &R) {
910}
911
912template <typename LHS, typename RHS>
913inline BinaryOpc_match<LHS, RHS> m_Shl(const LHS &L, const RHS &R) {
915}
916
917template <typename LHS, typename RHS>
918inline BinaryOpc_match<LHS, RHS> m_Sra(const LHS &L, const RHS &R) {
920}
921template <typename LHS, typename RHS>
922inline BinaryOpc_match<LHS, RHS> m_Srl(const LHS &L, const RHS &R) {
924}
925template <typename LHS, typename RHS>
930
931template <typename LHS, typename RHS>
932inline BinaryOpc_match<LHS, RHS> m_Rotl(const LHS &L, const RHS &R) {
934}
935
936template <typename LHS, typename RHS>
937inline BinaryOpc_match<LHS, RHS> m_Rotr(const LHS &L, const RHS &R) {
939}
940
941template <typename LHS, typename RHS>
945
946template <typename LHS, typename RHS>
947inline BinaryOpc_match<LHS, RHS, true> m_FAdd(const LHS &L, const RHS &R) {
949}
950
951template <typename LHS, typename RHS>
952inline BinaryOpc_match<LHS, RHS> m_FSub(const LHS &L, const RHS &R) {
954}
955
956template <typename LHS, typename RHS>
957inline BinaryOpc_match<LHS, RHS, true> m_FMul(const LHS &L, const RHS &R) {
959}
960
961template <typename LHS, typename RHS>
962inline BinaryOpc_match<LHS, RHS> m_FDiv(const LHS &L, const RHS &R) {
964}
965
966template <typename LHS, typename RHS>
967inline BinaryOpc_match<LHS, RHS> m_FRem(const LHS &L, const RHS &R) {
969}
970
971template <typename V1_t, typename V2_t>
972inline BinaryOpc_match<V1_t, V2_t> m_Shuffle(const V1_t &v1, const V2_t &v2) {
974}
975
976template <typename V1_t, typename V2_t, typename Mask_t>
977inline SDShuffle_match<V1_t, V2_t, Mask_t>
978m_Shuffle(const V1_t &v1, const V2_t &v2, const Mask_t &mask) {
980}
981
982template <typename LHS, typename RHS>
983inline BinaryOpc_match<LHS, RHS> m_ExtractElt(const LHS &Vec, const RHS &Idx) {
985}
986
987template <typename LHS, typename RHS>
989 const RHS &Idx) {
991}
992
993// === Unary operations ===
994template <typename Opnd_P, bool ExcludeChain = false> struct UnaryOpc_match {
995 unsigned Opcode;
996 Opnd_P Opnd;
998 UnaryOpc_match(unsigned Opc, const Opnd_P &Op,
999 SDNodeFlags Flgs = SDNodeFlags())
1000 : Opcode(Opc), Opnd(Op), Flags(Flgs) {}
1001
1002 template <typename MatchContext>
1003 bool match(const MatchContext &Ctx, SDValue N) {
1004 if (sd_context_match(N, Ctx, m_Opc(Opcode))) {
1006 assert(EO.Size == 1);
1007 if (!Opnd.match(Ctx, N->getOperand(EO.FirstIndex)))
1008 return false;
1009
1010 return (Flags & N->getFlags()) == Flags;
1011 }
1012
1013 return false;
1014 }
1015};
1016
1017template <typename Opnd>
1018inline UnaryOpc_match<Opnd> m_UnaryOp(unsigned Opc, const Opnd &Op) {
1019 return UnaryOpc_match<Opnd>(Opc, Op);
1020}
1021template <typename Opnd>
1023 const Opnd &Op) {
1025}
1026
1027template <typename Opnd> inline UnaryOpc_match<Opnd> m_BitCast(const Opnd &Op) {
1029}
1030
1031template <typename Opnd>
1032inline UnaryOpc_match<Opnd> m_BSwap(const Opnd &Op) {
1034}
1035
1036template <typename Opnd>
1040
1041template <typename Opnd> inline UnaryOpc_match<Opnd> m_ZExt(const Opnd &Op) {
1043}
1044
1045template <typename Opnd>
1049
1050template <typename Opnd> inline auto m_SExt(const Opnd &Op) {
1052}
1053
1054template <typename Opnd> inline UnaryOpc_match<Opnd> m_AnyExt(const Opnd &Op) {
1056}
1057
1058template <typename Opnd> inline UnaryOpc_match<Opnd> m_Trunc(const Opnd &Op) {
1060}
1061
1062template <typename Opnd> inline UnaryOpc_match<Opnd> m_Abs(const Opnd &Op) {
1064}
1065
1066template <typename Opnd> inline UnaryOpc_match<Opnd> m_FAbs(const Opnd &Op) {
1068}
1069
1070/// Match a zext or identity
1071/// Allows to peek through optional extensions
1072template <typename Opnd> inline auto m_ZExtOrSelf(const Opnd &Op) {
1073 return m_AnyOf(m_ZExt(Op), Op);
1074}
1075
1076/// Match a sext or identity
1077/// Allows to peek through optional extensions
1078template <typename Opnd> inline auto m_SExtOrSelf(const Opnd &Op) {
1079 return m_AnyOf(m_SExt(Op), Op);
1080}
1081
1082template <typename Opnd> inline auto m_SExtLike(const Opnd &Op) {
1083 return m_AnyOf(m_SExt(Op), m_NNegZExt(Op));
1084}
1085
1086/// Match a aext or identity
1087/// Allows to peek through optional extensions
1088template <typename Opnd>
1089inline Or<UnaryOpc_match<Opnd>, Opnd> m_AExtOrSelf(const Opnd &Op) {
1090 return Or<UnaryOpc_match<Opnd>, Opnd>(m_AnyExt(Op), Op);
1091}
1092
1093/// Match a trunc or identity
1094/// Allows to peek through optional truncations
1095template <typename Opnd>
1096inline Or<UnaryOpc_match<Opnd>, Opnd> m_TruncOrSelf(const Opnd &Op) {
1097 return Or<UnaryOpc_match<Opnd>, Opnd>(m_Trunc(Op), Op);
1098}
1099
1100template <typename Opnd> inline UnaryOpc_match<Opnd> m_VScale(const Opnd &Op) {
1102}
1103
1104template <typename Opnd> inline UnaryOpc_match<Opnd> m_FPToUI(const Opnd &Op) {
1106}
1107
1108template <typename Opnd> inline UnaryOpc_match<Opnd> m_FPToSI(const Opnd &Op) {
1110}
1111
1112template <typename Opnd> inline UnaryOpc_match<Opnd> m_Ctpop(const Opnd &Op) {
1114}
1115
1116template <typename Opnd> inline UnaryOpc_match<Opnd> m_Ctlz(const Opnd &Op) {
1118}
1119
1120template <typename Opnd> inline UnaryOpc_match<Opnd> m_Cttz(const Opnd &Op) {
1122}
1123
1124template <typename Opnd> inline UnaryOpc_match<Opnd> m_FNeg(const Opnd &Op) {
1126}
1127
1128// === Constants ===
1131
1132 explicit ConstantInt_match(APInt *V) : BindVal(V) {}
1133
1134 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
1135 // The logics here are similar to that in
1136 // SelectionDAG::isConstantIntBuildVectorOrConstantInt, but the latter also
1137 // treats GlobalAddressSDNode as a constant, which is difficult to turn into
1138 // APInt.
1139 if (auto *C = dyn_cast_or_null<ConstantSDNode>(N.getNode())) {
1140 if (BindVal)
1141 *BindVal = C->getAPIntValue();
1142 return true;
1143 }
1144
1145 APInt Discard;
1146 return ISD::isConstantSplatVector(N.getNode(),
1147 BindVal ? *BindVal : Discard);
1148 }
1149};
1150/// Match any integer constants or splat of an integer constant.
1152/// Match any integer constants or splat of an integer constant; return the
1153/// specific constant or constant splat value.
1155
1158
1159 explicit SpecificInt_match(APInt APV) : IntVal(std::move(APV)) {}
1160
1161 template <typename MatchContext>
1162 bool match(const MatchContext &Ctx, SDValue N) {
1163 APInt ConstInt;
1164 if (sd_context_match(N, Ctx, m_ConstInt(ConstInt)))
1165 return APInt::isSameValue(IntVal, ConstInt);
1166 return false;
1167 }
1168};
1169
1170/// Match a specific integer constant or constant splat value.
1172 return SpecificInt_match(std::move(V));
1173}
1175 return SpecificInt_match(APInt(64, V));
1176}
1177
1180
1181 explicit SpecificFP_match(APFloat V) : Val(V) {}
1182
1183 template <typename MatchContext>
1184 bool match(const MatchContext &Ctx, SDValue V) {
1185 if (const auto *CFP = dyn_cast<ConstantFPSDNode>(V.getNode()))
1186 return CFP->isExactlyValue(Val);
1187 if (ConstantFPSDNode *C = isConstOrConstSplatFP(V, /*AllowUndefs=*/true))
1188 return C->getValueAPF().compare(Val) == APFloat::cmpEqual;
1189 return false;
1190 }
1191};
1192
1193/// Match a specific float constant.
1195
1197 return SpecificFP_match(APFloat(V));
1198}
1199
1201 template <typename MatchContext>
1202 bool match(const MatchContext &Ctx, SDValue N) {
1203 const SelectionDAG *DAG = Ctx.getDAG();
1204 return DAG && DAG->computeKnownBits(N).isNegative();
1205 }
1206};
1207
1209 template <typename MatchContext>
1210 bool match(const MatchContext &Ctx, SDValue N) {
1211 const SelectionDAG *DAG = Ctx.getDAG();
1212 return DAG && DAG->computeKnownBits(N).isNonNegative();
1213 }
1214};
1215
1217 template <typename MatchContext>
1218 bool match(const MatchContext &Ctx, SDValue N) {
1219 const SelectionDAG *DAG = Ctx.getDAG();
1220 return DAG && DAG->computeKnownBits(N).isStrictlyPositive();
1221 }
1222};
1223
1225 template <typename MatchContext>
1226 bool match(const MatchContext &Ctx, SDValue N) {
1227 const SelectionDAG *DAG = Ctx.getDAG();
1228 return DAG && DAG->computeKnownBits(N).isNonPositive();
1229 }
1230};
1231
1233 template <typename MatchContext>
1234 bool match(const MatchContext &Ctx, SDValue N) {
1235 const SelectionDAG *DAG = Ctx.getDAG();
1236 return DAG && DAG->computeKnownBits(N).isNonZero();
1237 }
1238};
1239
1242
1244
1245 template <typename MatchContext>
1246 bool match(const MatchContext &, SDValue N) const {
1248 }
1249};
1250
1253
1255
1256 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
1258 }
1259};
1260
1263
1265
1266 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
1268 }
1269};
1270
1272template <typename Pattern> inline auto m_Negative(const Pattern &P) {
1273 return m_AllOf(m_Negative(), P);
1274}
1276template <typename Pattern> inline auto m_NonNegative(const Pattern &P) {
1277 return m_AllOf(m_NonNegative(), P);
1278}
1282template <typename Pattern> inline auto m_StrictlyPositive(const Pattern &P) {
1283 return m_AllOf(m_StrictlyPositive(), P);
1284}
1286template <typename Pattern> inline auto m_NonPositive(const Pattern &P) {
1287 return m_AllOf(m_NonPositive(), P);
1288}
1290template <typename Pattern> inline auto m_NonZero(const Pattern &P) {
1291 return m_AllOf(m_NonZero(), P);
1292}
1293inline Ones_match m_One(bool AllowUndefs = false) {
1294 return Ones_match(AllowUndefs);
1295}
1296inline Zero_match m_Zero(bool AllowUndefs = false) {
1297 return Zero_match(AllowUndefs);
1298}
1299inline AllOnes_match m_AllOnes(bool AllowUndefs = false) {
1300 return AllOnes_match(AllowUndefs);
1301}
1302
1303/// Match true boolean value based on the information provided by
1304/// TargetLowering.
1305inline auto m_True() {
1306 return TLI_pred_match{
1307 [](const TargetLowering &TLI, SDValue N) {
1308 APInt ConstVal;
1309 if (sd_match(N, m_ConstInt(ConstVal)))
1310 switch (TLI.getBooleanContents(N.getValueType())) {
1312 return ConstVal.isOne();
1314 return ConstVal.isAllOnes();
1316 return (ConstVal & 0x01) == 1;
1317 }
1318
1319 return false;
1320 },
1321 m_Value()};
1322}
1323/// Match false boolean value based on the information provided by
1324/// TargetLowering.
1325inline auto m_False() {
1326 return TLI_pred_match{
1327 [](const TargetLowering &TLI, SDValue N) {
1328 APInt ConstVal;
1329 if (sd_match(N, m_ConstInt(ConstVal)))
1330 switch (TLI.getBooleanContents(N.getValueType())) {
1333 return ConstVal.isZero();
1335 return (ConstVal & 0x01) == 0;
1336 }
1337
1338 return false;
1339 },
1340 m_Value()};
1341}
1342
1344 std::optional<ISD::CondCode> CCToMatch;
1346
1348
1349 explicit CondCode_match(ISD::CondCode *CC) : BindCC(CC) {}
1350
1351 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
1352 if (auto *CC = dyn_cast<CondCodeSDNode>(N.getNode())) {
1353 if (CCToMatch && *CCToMatch != CC->get())
1354 return false;
1355
1356 if (BindCC)
1357 *BindCC = CC->get();
1358 return true;
1359 }
1360
1361 return false;
1362 }
1363};
1364
1365/// Match any conditional code SDNode.
1366inline CondCode_match m_CondCode() { return CondCode_match(nullptr); }
1367/// Match any conditional code SDNode and return its ISD::CondCode value.
1369 return CondCode_match(&CC);
1370}
1371/// Match a conditional code SDNode with a specific ISD::CondCode.
1375
1376/// Match a negate as a sub(0, v)
1377template <typename ValTy>
1379 return m_Sub(m_Zero(), V);
1380}
1381
1382/// Match a Not as a xor(v, -1) or xor(-1, v)
1383template <typename ValTy>
1385 return m_Xor(V, m_AllOnes());
1386}
1387
1388template <unsigned IntrinsicId, typename... OpndPreds>
1389inline auto m_IntrinsicWOChain(const OpndPreds &...Opnds) {
1390 return m_Node(ISD::INTRINSIC_WO_CHAIN, m_SpecificInt(IntrinsicId), Opnds...);
1391}
1392
1395
1397
1398 template <typename MatchContext>
1399 bool match(const MatchContext &Ctx, SDValue N) {
1400 if (sd_context_match(N, Ctx, m_Neg(m_Specific(V))))
1401 return true;
1402
1405 return LHS->getAPIntValue() == -RHS->getAPIntValue();
1406 });
1407 }
1408};
1409
1410/// Match a negation of a specific value V, either as sub(0, V) or as
1411/// constant(s) that are the negation of V's constant(s).
1415
1416template <typename... PatternTs> struct ReassociatableOpc_match {
1417 unsigned Opcode;
1418 std::tuple<PatternTs...> Patterns;
1419 constexpr static size_t NumPatterns =
1420 std::tuple_size_v<std::tuple<PatternTs...>>;
1421
1423
1424 ReassociatableOpc_match(unsigned Opcode, const PatternTs &...Patterns)
1425 : Opcode(Opcode), Patterns(Patterns...) {}
1426
1428 const PatternTs &...Patterns)
1430
1431 template <typename MatchContext>
1432 bool match(const MatchContext &Ctx, SDValue N) {
1433 std::array<SDValue, NumPatterns> Leaves;
1434 size_t LeavesIdx = 0;
1435 if (!(collectLeaves(N, Leaves, LeavesIdx) && (LeavesIdx == NumPatterns)))
1436 return false;
1437
1439 return std::apply(
1440 [&](auto &...P) -> bool {
1441 return reassociatableMatchHelper(Ctx, Leaves, Used, P...);
1442 },
1443 Patterns);
1444 }
1445
1446 bool collectLeaves(SDValue V, std::array<SDValue, NumPatterns> &Leaves,
1447 std::size_t &LeafIdx) {
1448 if (V->getOpcode() == Opcode && (Flags & V->getFlags()) == Flags) {
1449 for (size_t I = 0, N = V->getNumOperands(); I < N; I++)
1450 if ((LeafIdx == NumPatterns) ||
1451 !collectLeaves(V->getOperand(I), Leaves, LeafIdx))
1452 return false;
1453 } else {
1454 Leaves[LeafIdx] = V;
1455 LeafIdx++;
1456 }
1457 return true;
1458 }
1459
1460 // Searchs for a matching leaf for every sub-pattern.
1461 template <typename MatchContext, typename PatternHd, typename... PatternTl>
1462 [[nodiscard]] inline bool
1463 reassociatableMatchHelper(const MatchContext &Ctx, ArrayRef<SDValue> Leaves,
1464 Bitset<NumPatterns> &Used, PatternHd &HeadPattern,
1465 PatternTl &...TailPatterns) {
1466 for (size_t Match = 0, N = Used.size(); Match < N; Match++) {
1467 if (Used[Match] || !(sd_context_match(Leaves[Match], Ctx, HeadPattern)))
1468 continue;
1469 Used.set(Match);
1470 if (reassociatableMatchHelper(Ctx, Leaves, Used, TailPatterns...))
1471 return true;
1472 Used.reset(Match);
1473 }
1474 return false;
1475 }
1476
1477 template <typename MatchContext>
1478 [[nodiscard]] inline bool
1479 reassociatableMatchHelper(const MatchContext &Ctx, ArrayRef<SDValue> Leaves,
1480 Bitset<NumPatterns> &Used) {
1481 return true;
1482 }
1483};
1484
1485template <typename... PatternTs>
1486inline ReassociatableOpc_match<PatternTs...>
1487m_ReassociatableAdd(const PatternTs &...Patterns) {
1488 return ReassociatableOpc_match<PatternTs...>(ISD::ADD, Patterns...);
1489}
1490
1491template <typename... PatternTs>
1492inline ReassociatableOpc_match<PatternTs...>
1493m_ReassociatableOr(const PatternTs &...Patterns) {
1494 return ReassociatableOpc_match<PatternTs...>(ISD::OR, Patterns...);
1495}
1496
1497template <typename... PatternTs>
1498inline ReassociatableOpc_match<PatternTs...>
1499m_ReassociatableAnd(const PatternTs &...Patterns) {
1500 return ReassociatableOpc_match<PatternTs...>(ISD::AND, Patterns...);
1501}
1502
1503template <typename... PatternTs>
1504inline ReassociatableOpc_match<PatternTs...>
1505m_ReassociatableMul(const PatternTs &...Patterns) {
1506 return ReassociatableOpc_match<PatternTs...>(ISD::MUL, Patterns...);
1507}
1508
1509template <typename... PatternTs>
1510inline ReassociatableOpc_match<PatternTs...>
1511m_ReassociatableNSWAdd(const PatternTs &...Patterns) {
1512 return ReassociatableOpc_match<PatternTs...>(
1513 ISD::ADD, SDNodeFlags::NoSignedWrap, Patterns...);
1514}
1515
1516template <typename... PatternTs>
1517inline ReassociatableOpc_match<PatternTs...>
1518m_ReassociatableNUWAdd(const PatternTs &...Patterns) {
1519 return ReassociatableOpc_match<PatternTs...>(
1521}
1522
1523} // namespace SDPatternMatch
1524} // namespace llvm
1525#endif
return SDValue()
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements a class to represent arbitrary precision integral constant values and operations...
static constexpr unsigned long long mask(BlockVerifier::State S)
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define T
#define T1
MachineInstr unsigned OpIdx
#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.
This file describes how to lower LLVM code to machine code.
Value * RHS
Value * LHS
Class for arbitrary precision integers.
Definition APInt.h:78
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
Definition APInt.h:372
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
Definition APInt.h:381
static bool isSameValue(const APInt &I1, const APInt &I2)
Determine if two APInts have the same value, after zero-extending one of them (if needed!...
Definition APInt.h:554
bool isOne() const
Determine if this is a value of 1.
Definition APInt.h:390
ArrayRef - 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
Represents one node in the SelectionDAG.
MatchContext can repurpose existing patterns to behave differently under a certain context.
const TargetLowering * getTLI() const
const SelectionDAG * getDAG() const
BasicMatchContext(const TargetLowering *TLI)
BasicMatchContext(const SelectionDAG *DAG)
bool match(SDValue N, unsigned Opcode) const
Return true if N effectively has opcode Opcode.
unsigned getNumOperands(SDValue N) const
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...
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
BooleanContent getBooleanContents(bool isVec, bool isFloat) const
For targets without i1 registers, this gives the nature of the high-bits of boolean values held in ty...
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.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
Definition ISDOpcodes.h:819
@ POISON
POISON - A poison node.
Definition ISDOpcodes.h:236
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
Definition ISDOpcodes.h:600
@ BSWAP
Byte Swap and Counting operators.
Definition ISDOpcodes.h:779
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:264
@ 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:853
@ FADD
Simple binary floating point operators.
Definition ISDOpcodes.h:417
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
Definition ISDOpcodes.h:747
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
Definition ISDOpcodes.h:993
@ CLMUL
Carry-less multiplication operations.
Definition ISDOpcodes.h:774
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:844
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
Definition ISDOpcodes.h:796
@ UNDEF
UNDEF - An undefined node.
Definition ISDOpcodes.h:233
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:765
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
Definition ISDOpcodes.h:649
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
Definition ISDOpcodes.h:614
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
Definition ISDOpcodes.h:576
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition ISDOpcodes.h:850
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
Definition ISDOpcodes.h:811
@ 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:727
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
Definition ISDOpcodes.h:805
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition ISDOpcodes.h:926
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:739
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
Definition ISDOpcodes.h:205
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
Definition ISDOpcodes.h:565
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition ISDOpcodes.h:856
LLVM_ABI bool isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
LLVM_ABI bool matchBinaryPredicate(SDValue LHS, SDValue RHS, 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...
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
cst_pred_ty< is_all_ones > m_AllOnes()
Match an integer or vector with all bits set.
class_match< BinaryOperator > m_BinOp()
Match an arbitrary binary operation and ignore it.
cst_pred_ty< is_one > m_One()
Match an integer 1 or a vector with all elements equal to 1.
IntrinsicID_match 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)
Opcode_match m_Opc(unsigned Opcode)
auto m_SelectCCLike(const LTy &L, const RTy &R, const TTy &T, const FTy &F, const CCTy &CC)
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.
auto m_SelectCC(const LTy &L, const RTy &R, const TTy &T, const FTy &F, const CCTy &CC)
BinaryOpc_match< LHS, RHS > m_Sra(const LHS &L, const RHS &R)
BinaryOpc_match< LHS, RHS > m_FRem(const LHS &L, const RHS &R)
TLI_pred_match(const PredFuncT &Pred, const Pattern &P) -> TLI_pred_match< Pattern, PredFuncT >
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())
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_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)
UnaryOpc_match< Opnd > m_Abs(const Opnd &Op)
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)
StrictlyPositive_match m_StrictlyPositive()
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)
BinaryOpc_match< LHS, RHS > m_URem(const LHS &L, const RHS &R)
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)
And< Preds... > m_AllOf(const Preds &...preds)
BinaryOpc_match< LHS, RHS > m_FDiv(const LHS &L, const RHS &R)
NonPositive_match m_NonPositive()
auto m_LegalType(const Pattern &P)
Match legal ValueTypes based on the information provided by TargetLowering.
UnaryOpc_match< Opnd > m_BitCast(const Opnd &Op)
UnaryOpc_match< Opnd > m_FNeg(const Opnd &Op)
Opcode_match m_Poison()
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.
NUses_match< N, Value_match > m_NUses()
UnaryOpc_match< Opnd, true > m_ChainedUnaryOp(unsigned Opc, const Opnd &Op)
NonZero_match m_NonZero()
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)
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)
ValueType_bind m_VT(EVT &VT)
Retreive the ValueType of the current SDValue.
BinaryOpc_match< LHS, RHS > m_Sub(const LHS &L, const RHS &R)
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)
TernaryOpc_match< T0_P, T1_P, T2_P > m_SetCC(const T0_P &LHS, const T1_P &RHS, const T2_P &CC)
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)
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_Node(unsigned Opcode, const OpndPreds &...preds)
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)
SwitchContext< MatchContext, Pattern > m_Context(const MatchContext &Ctx, Pattern &&P)
NonNegative_match m_NonNegative()
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)
bool sd_match(SDNode *N, const SelectionDAG *DAG, Pattern &&P)
UnaryOpc_match< Opnd > m_UnaryOp(unsigned Opc, const Opnd &Op)
auto m_SExt(const Opnd &Op)
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_LegalOp(const Pattern &P)
Match legal SDNodes based on the information provided by TargetLowering.
auto m_BitwiseLogic(const LHS &L, const RHS &R)
auto m_True()
Match true boolean value based on the information provided by TargetLowering.
Negative_match m_Negative()
UnaryOpc_match< Opnd > m_Ctpop(const Opnd &Op)
ReassociatableOpc_match< PatternTs... > m_ReassociatableAnd(const PatternTs &...Patterns)
UnaryOpc_match< Opnd > m_FPToSI(const Opnd &Op)
NUses_match< 1, Value_match > m_OneUse()
auto m_False()
Match false boolean value based on the information provided by TargetLowering.
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...
TernaryOpc_match< T0_P, T1_P, T2_P, true, false > m_c_SetCC(const T0_P &LHS, const T1_P &RHS, const T2_P &CC)
bool sd_context_match(SDValue N, const MatchContext &Ctx, Pattern &&P)
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)
ConstantInt_match m_ConstInt()
Match any integer constants or splat of an integer constant.
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.
Definition Types.h:26
@ Offset
Definition DWP.cpp:532
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:1613
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
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
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:1915
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:870
#define N
Extended Value Type.
Definition ValueTypes.h:35
bool isNonNegative() const
Returns true if this value is known to be non-negative.
Definition KnownBits.h:108
bool isNonZero() const
Returns true if this value is known to be non-zero.
Definition KnownBits.h:111
bool isStrictlyPositive() const
Returns true if this value is known to be positive.
Definition KnownBits.h:114
bool isNegative() const
Returns true if this value is known to be negative.
Definition KnownBits.h:105
bool isNonPositive() const
Returns true if this value is known to be non-positive.
Definition KnownBits.h:119
These are IR-level optimization flags that may be propagated to SDNodes.
bool match(const MatchContext &, SDValue N)
And(const Pred &p, const Preds &...preds)
bool match(const MatchContext &Ctx, SDValue N)
bool match(const MatchContext &, SDValue N)
bool match(const MatchContext &Ctx, SDValue N)
BinaryOpc_match(unsigned Opc, const LHS_P &L, const RHS_P &R, SDNodeFlags Flgs=SDNodeFlags())
bool match(const MatchContext &, SDValue N)
std::optional< ISD::CondCode > CCToMatch
bool match(const MatchContext &, SDValue N)
bool match(const MatchContext &, SDValue N)
EffectiveOperands(SDValue N, const MatchContext &Ctx)
Provide number of operands that are not chain or glue, as well as the first index of such operand.
EffectiveOperands(SDValue N, const MatchContext &Ctx)
MaxMin_match(const LHS_P &L, const RHS_P &R)
bool match(const MatchContext &Ctx, SDValue N)
bool match(const MatchContext &Ctx, SDValue N)
bool match(const MatchContext &Ctx, SDValue N)
bool match(const MatchContext &Ctx, SDValue N)
bool match(const MatchContext &Ctx, SDValue N)
bool match(const MatchContext &Ctx, SDValue N)
bool match(const MatchContext &Ctx, SDValue N)
bool match(const MatchContext &, SDValue N)
bool match(const MatchContext &Ctx, SDValue N)
Operands_match(const OpndPred &p, const OpndPreds &...preds)
bool match(const MatchContext &Ctx, SDValue N)
Or(const Pred &p, const Preds &...preds)
bool match(const MatchContext &Ctx, SDValue N)
bool match(const MatchContext &, SDValue N)
bool match(const MatchContext &Ctx, SDValue N)
bool reassociatableMatchHelper(const MatchContext &Ctx, ArrayRef< SDValue > Leaves, Bitset< NumPatterns > &Used, PatternHd &HeadPattern, PatternTl &...TailPatterns)
bool collectLeaves(SDValue V, std::array< SDValue, NumPatterns > &Leaves, std::size_t &LeafIdx)
bool reassociatableMatchHelper(const MatchContext &Ctx, ArrayRef< SDValue > Leaves, Bitset< NumPatterns > &Used)
ReassociatableOpc_match(unsigned Opcode, const PatternTs &...Patterns)
ReassociatableOpc_match(unsigned Opcode, SDNodeFlags Flags, const PatternTs &...Patterns)
bool match(const MatchContext &Ctx, SDValue N)
Matching while capturing mask.
bool match(const MatchContext &Ctx, SDValue N)
SDShuffle_match(const T0 &Op1, const T1 &Op2, const T2 &Mask)
bool match(const MatchContext &Ctx, SDValue V)
bool match(const MatchContext &Ctx, SDValue N)
bool match(const MatchContext &Ctx, SDValue N)
bool match(const MatchContext &Ctx, SDValue N)
Switch to a different MatchContext for subsequent patterns.
bool match(const OrigMatchContext &, SDValue N)
bool match(const MatchContext &Ctx, SDValue N)
TLI_pred_match(const PredFuncT &Pred, const Pattern &P)
bool match(const MatchContext &Ctx, SDValue N)
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())
bool match(const MatchContext &Ctx, SDValue N)
bool match(const MatchContext &, SDValue N)
ValueType_match(const PredFuncT &Pred, const Pattern &P)
bool match(const MatchContext &Ctx, SDValue N)
bool match(const MatchContext &, SDValue N)
bool match(const MatchContext &, SDValue N)
bool match(const MatchContext &, SDValue N) const
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)