LLVM 20.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/STLExtras.h"
21
22namespace llvm {
23namespace SDPatternMatch {
24
25/// MatchContext can repurpose existing patterns to behave differently under
26/// a certain context. For instance, `m_Opc(ISD::ADD)` matches plain ADD nodes
27/// in normal circumstances, but matches VP_ADD nodes under a custom
28/// VPMatchContext. This design is meant to facilitate code / pattern reusing.
30 const SelectionDAG *DAG;
31 const TargetLowering *TLI;
32
33public:
34 explicit BasicMatchContext(const SelectionDAG *DAG)
35 : DAG(DAG), TLI(DAG ? &DAG->getTargetLoweringInfo() : nullptr) {}
36
37 explicit BasicMatchContext(const TargetLowering *TLI)
38 : DAG(nullptr), TLI(TLI) {}
39
40 // A valid MatchContext has to implement the following functions.
41
42 const SelectionDAG *getDAG() const { return DAG; }
43
44 const TargetLowering *getTLI() const { return TLI; }
45
46 /// Return true if N effectively has opcode Opcode.
47 bool match(SDValue N, unsigned Opcode) const {
48 return N->getOpcode() == Opcode;
49 }
50
51 unsigned getNumOperands(SDValue N) const { return N->getNumOperands(); }
52};
53
54template <typename Pattern, typename MatchContext>
55[[nodiscard]] bool sd_context_match(SDValue N, const MatchContext &Ctx,
56 Pattern &&P) {
57 return P.match(Ctx, N);
58}
59
60template <typename Pattern, typename MatchContext>
61[[nodiscard]] bool sd_context_match(SDNode *N, const MatchContext &Ctx,
62 Pattern &&P) {
63 return sd_context_match(SDValue(N, 0), Ctx, P);
64}
65
66template <typename Pattern>
67[[nodiscard]] bool sd_match(SDNode *N, const SelectionDAG *DAG, Pattern &&P) {
69}
70
71template <typename Pattern>
72[[nodiscard]] bool sd_match(SDValue N, const SelectionDAG *DAG, Pattern &&P) {
74}
75
76template <typename Pattern>
77[[nodiscard]] bool sd_match(SDNode *N, Pattern &&P) {
78 return sd_match(N, nullptr, P);
79}
80
81template <typename Pattern>
82[[nodiscard]] bool sd_match(SDValue N, Pattern &&P) {
83 return sd_match(N, nullptr, P);
84}
85
86// === Utilities ===
89
90 Value_match() = default;
91
93
94 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
95 if (MatchVal)
96 return MatchVal == N;
97 return N.getNode();
98 }
99};
100
101/// Match any valid SDValue.
102inline Value_match m_Value() { return Value_match(); }
103
105 assert(N);
106 return Value_match(N);
107}
108
111
113
114 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
115 return N == MatchVal;
116 }
117};
118
119/// Similar to m_Specific, but the specific value to match is determined by
120/// another sub-pattern in the same sd_match() expression. For instance,
121/// We cannot match `(add V, V)` with `m_Add(m_Value(X), m_Specific(X))` since
122/// `X` is not initialized at the time it got copied into `m_Specific`. Instead,
123/// we should use `m_Add(m_Value(X), m_Deferred(X))`.
125 return DeferredValue_match(V);
126}
127
129 unsigned Opcode;
130
131 explicit Opcode_match(unsigned Opc) : Opcode(Opc) {}
132
133 template <typename MatchContext>
134 bool match(const MatchContext &Ctx, SDValue N) {
135 return Ctx.match(N, Opcode);
136 }
137};
138
139inline Opcode_match m_Opc(unsigned Opcode) { return Opcode_match(Opcode); }
140
142
143template <unsigned NumUses, typename Pattern> struct NUses_match {
145
146 explicit NUses_match(const Pattern &P) : P(P) {}
147
148 template <typename MatchContext>
149 bool match(const MatchContext &Ctx, SDValue N) {
150 // SDNode::hasNUsesOfValue is pretty expensive when the SDNode produces
151 // multiple results, hence we check the subsequent pattern here before
152 // checking the number of value users.
153 return P.match(Ctx, N) && N->hasNUsesOfValue(NumUses, N.getResNo());
154 }
155};
156
157template <typename Pattern>
160}
161template <unsigned N, typename Pattern>
164}
165
168}
169template <unsigned N> inline NUses_match<N, Value_match> m_NUses() {
171}
172
175
176 explicit Value_bind(SDValue &N) : BindVal(N) {}
177
178 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
179 BindVal = N;
180 return true;
181 }
182};
183
184inline Value_bind m_Value(SDValue &N) { return Value_bind(N); }
185
186template <typename Pattern, typename PredFuncT> struct TLI_pred_match {
188 PredFuncT PredFunc;
189
190 TLI_pred_match(const PredFuncT &Pred, const Pattern &P)
191 : P(P), PredFunc(Pred) {}
192
193 template <typename MatchContext>
194 bool match(const MatchContext &Ctx, SDValue N) {
195 assert(Ctx.getTLI() && "TargetLowering is required for this pattern.");
196 return PredFunc(*Ctx.getTLI(), N) && P.match(Ctx, N);
197 }
198};
199
200// Explicit deduction guide.
201template <typename PredFuncT, typename Pattern>
202TLI_pred_match(const PredFuncT &Pred, const Pattern &P)
204
205/// Match legal SDNodes based on the information provided by TargetLowering.
206template <typename Pattern> inline auto m_LegalOp(const Pattern &P) {
207 return TLI_pred_match{[](const TargetLowering &TLI, SDValue N) {
208 return TLI.isOperationLegal(N->getOpcode(),
209 N.getValueType());
210 },
211 P};
212}
213
214/// Switch to a different MatchContext for subsequent patterns.
215template <typename NewMatchContext, typename Pattern> struct SwitchContext {
216 const NewMatchContext &Ctx;
218
219 template <typename OrigMatchContext>
220 bool match(const OrigMatchContext &, SDValue N) {
221 return P.match(Ctx, N);
222 }
223};
224
225template <typename MatchContext, typename Pattern>
226inline SwitchContext<MatchContext, Pattern> m_Context(const MatchContext &Ctx,
227 Pattern &&P) {
228 return SwitchContext<MatchContext, Pattern>{Ctx, std::move(P)};
229}
230
231// === Value type ===
234
235 explicit ValueType_bind(EVT &Bind) : BindVT(Bind) {}
236
237 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
238 BindVT = N.getValueType();
239 return true;
240 }
241};
242
243/// Retreive the ValueType of the current SDValue.
244inline ValueType_bind m_VT(EVT &VT) { return ValueType_bind(VT); }
245
246template <typename Pattern, typename PredFuncT> struct ValueType_match {
247 PredFuncT PredFunc;
249
250 ValueType_match(const PredFuncT &Pred, const Pattern &P)
251 : PredFunc(Pred), P(P) {}
252
253 template <typename MatchContext>
254 bool match(const MatchContext &Ctx, SDValue N) {
255 return PredFunc(N.getValueType()) && P.match(Ctx, N);
256 }
257};
258
259// Explicit deduction guide.
260template <typename PredFuncT, typename Pattern>
261ValueType_match(const PredFuncT &Pred, const Pattern &P)
263
264/// Match a specific ValueType.
265template <typename Pattern>
266inline auto m_SpecificVT(EVT RefVT, const Pattern &P) {
267 return ValueType_match{[=](EVT VT) { return VT == RefVT; }, P};
268}
269inline auto m_SpecificVT(EVT RefVT) {
270 return ValueType_match{[=](EVT VT) { return VT == RefVT; }, m_Value()};
271}
272
273inline auto m_Glue() { return m_SpecificVT(MVT::Glue); }
274inline auto m_OtherVT() { return m_SpecificVT(MVT::Other); }
275
276/// Match any integer ValueTypes.
277template <typename Pattern> inline auto m_IntegerVT(const Pattern &P) {
278 return ValueType_match{[](EVT VT) { return VT.isInteger(); }, P};
279}
280inline auto m_IntegerVT() {
281 return ValueType_match{[](EVT VT) { return VT.isInteger(); }, m_Value()};
282}
283
284/// Match any floating point ValueTypes.
285template <typename Pattern> inline auto m_FloatingPointVT(const Pattern &P) {
286 return ValueType_match{[](EVT VT) { return VT.isFloatingPoint(); }, P};
287}
288inline auto m_FloatingPointVT() {
289 return ValueType_match{[](EVT VT) { return VT.isFloatingPoint(); },
290 m_Value()};
291}
292
293/// Match any vector ValueTypes.
294template <typename Pattern> inline auto m_VectorVT(const Pattern &P) {
295 return ValueType_match{[](EVT VT) { return VT.isVector(); }, P};
296}
297inline auto m_VectorVT() {
298 return ValueType_match{[](EVT VT) { return VT.isVector(); }, m_Value()};
299}
300
301/// Match fixed-length vector ValueTypes.
302template <typename Pattern> inline auto m_FixedVectorVT(const Pattern &P) {
303 return ValueType_match{[](EVT VT) { return VT.isFixedLengthVector(); }, P};
304}
305inline auto m_FixedVectorVT() {
306 return ValueType_match{[](EVT VT) { return VT.isFixedLengthVector(); },
307 m_Value()};
308}
309
310/// Match scalable vector ValueTypes.
311template <typename Pattern> inline auto m_ScalableVectorVT(const Pattern &P) {
312 return ValueType_match{[](EVT VT) { return VT.isScalableVector(); }, P};
313}
314inline auto m_ScalableVectorVT() {
315 return ValueType_match{[](EVT VT) { return VT.isScalableVector(); },
316 m_Value()};
317}
318
319/// Match legal ValueTypes based on the information provided by TargetLowering.
320template <typename Pattern> inline auto m_LegalType(const Pattern &P) {
321 return TLI_pred_match{[](const TargetLowering &TLI, SDValue N) {
322 return TLI.isTypeLegal(N.getValueType());
323 },
324 P};
325}
326
327// === Patterns combinators ===
328template <typename... Preds> struct And {
329 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
330 return true;
331 }
332};
333
334template <typename Pred, typename... Preds>
335struct And<Pred, Preds...> : And<Preds...> {
336 Pred P;
337 And(const Pred &p, const Preds &...preds) : And<Preds...>(preds...), P(p) {}
338
339 template <typename MatchContext>
340 bool match(const MatchContext &Ctx, SDValue N) {
341 return P.match(Ctx, N) && And<Preds...>::match(Ctx, N);
342 }
343};
344
345template <typename... Preds> struct Or {
346 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
347 return false;
348 }
349};
350
351template <typename Pred, typename... Preds>
352struct Or<Pred, Preds...> : Or<Preds...> {
353 Pred P;
354 Or(const Pred &p, const Preds &...preds) : Or<Preds...>(preds...), P(p) {}
355
356 template <typename MatchContext>
357 bool match(const MatchContext &Ctx, SDValue N) {
358 return P.match(Ctx, N) || Or<Preds...>::match(Ctx, N);
359 }
360};
361
362template <typename Pred> struct Not {
363 Pred P;
364
365 explicit Not(const Pred &P) : P(P) {}
366
367 template <typename MatchContext>
368 bool match(const MatchContext &Ctx, SDValue N) {
369 return !P.match(Ctx, N);
370 }
371};
372// Explicit deduction guide.
373template <typename Pred> Not(const Pred &P) -> Not<Pred>;
374
375/// Match if the inner pattern does NOT match.
376template <typename Pred> inline Not<Pred> m_Unless(const Pred &P) {
377 return Not{P};
378}
379
380template <typename... Preds> And<Preds...> m_AllOf(const Preds &...preds) {
381 return And<Preds...>(preds...);
382}
383
384template <typename... Preds> Or<Preds...> m_AnyOf(const Preds &...preds) {
385 return Or<Preds...>(preds...);
386}
387
388template <typename... Preds> auto m_NoneOf(const Preds &...preds) {
389 return m_Unless(m_AnyOf(preds...));
390}
391
392// === Generic node matching ===
393template <unsigned OpIdx, typename... OpndPreds> struct Operands_match {
394 template <typename MatchContext>
395 bool match(const MatchContext &Ctx, SDValue N) {
396 // Returns false if there are more operands than predicates;
397 // Ignores the last two operands if both the Context and the Node are VP
398 return Ctx.getNumOperands(N) == OpIdx;
399 }
400};
401
402template <unsigned OpIdx, typename OpndPred, typename... OpndPreds>
403struct Operands_match<OpIdx, OpndPred, OpndPreds...>
404 : Operands_match<OpIdx + 1, OpndPreds...> {
405 OpndPred P;
406
407 Operands_match(const OpndPred &p, const OpndPreds &...preds)
408 : Operands_match<OpIdx + 1, OpndPreds...>(preds...), P(p) {}
409
410 template <typename MatchContext>
411 bool match(const MatchContext &Ctx, SDValue N) {
412 if (OpIdx < N->getNumOperands())
413 return P.match(Ctx, N->getOperand(OpIdx)) &&
415
416 // This is the case where there are more predicates than operands.
417 return false;
418 }
419};
420
421template <typename... OpndPreds>
422auto m_Node(unsigned Opcode, const OpndPreds &...preds) {
423 return m_AllOf(m_Opc(Opcode), Operands_match<0, OpndPreds...>(preds...));
424}
425
426/// Provide number of operands that are not chain or glue, as well as the first
427/// index of such operand.
428template <bool ExcludeChain> struct EffectiveOperands {
429 unsigned Size = 0;
430 unsigned FirstIndex = 0;
431
432 template <typename MatchContext>
433 explicit EffectiveOperands(SDValue N, const MatchContext &Ctx) {
434 const unsigned TotalNumOps = Ctx.getNumOperands(N);
435 FirstIndex = TotalNumOps;
436 for (unsigned I = 0; I < TotalNumOps; ++I) {
437 // Count the number of non-chain and non-glue nodes (we ignore chain
438 // and glue by default) and retreive the operand index offset.
439 EVT VT = N->getOperand(I).getValueType();
440 if (VT != MVT::Glue && VT != MVT::Other) {
441 ++Size;
442 if (FirstIndex == TotalNumOps)
443 FirstIndex = I;
444 }
445 }
446 }
447};
448
449template <> struct EffectiveOperands<false> {
450 unsigned Size = 0;
451 unsigned FirstIndex = 0;
452
453 template <typename MatchContext>
454 explicit EffectiveOperands(SDValue N, const MatchContext &Ctx)
455 : Size(Ctx.getNumOperands(N)) {}
456};
457
458// === Ternary operations ===
459template <typename T0_P, typename T1_P, typename T2_P, bool Commutable = false,
460 bool ExcludeChain = false>
462 unsigned Opcode;
463 T0_P Op0;
464 T1_P Op1;
465 T2_P Op2;
466
467 TernaryOpc_match(unsigned Opc, const T0_P &Op0, const T1_P &Op1,
468 const T2_P &Op2)
469 : Opcode(Opc), Op0(Op0), Op1(Op1), Op2(Op2) {}
470
471 template <typename MatchContext>
472 bool match(const MatchContext &Ctx, SDValue N) {
473 if (sd_context_match(N, Ctx, m_Opc(Opcode))) {
475 assert(EO.Size == 3);
476 return ((Op0.match(Ctx, N->getOperand(EO.FirstIndex)) &&
477 Op1.match(Ctx, N->getOperand(EO.FirstIndex + 1))) ||
478 (Commutable && Op0.match(Ctx, N->getOperand(EO.FirstIndex + 1)) &&
479 Op1.match(Ctx, N->getOperand(EO.FirstIndex)))) &&
480 Op2.match(Ctx, N->getOperand(EO.FirstIndex + 2));
481 }
482
483 return false;
484 }
485};
486
487template <typename T0_P, typename T1_P, typename T2_P>
488inline TernaryOpc_match<T0_P, T1_P, T2_P>
489m_SetCC(const T0_P &LHS, const T1_P &RHS, const T2_P &CC) {
491}
492
493template <typename T0_P, typename T1_P, typename T2_P>
494inline TernaryOpc_match<T0_P, T1_P, T2_P, true, false>
495m_c_SetCC(const T0_P &LHS, const T1_P &RHS, const T2_P &CC) {
497 CC);
498}
499
500template <typename T0_P, typename T1_P, typename T2_P>
501inline TernaryOpc_match<T0_P, T1_P, T2_P>
502m_Select(const T0_P &Cond, const T1_P &T, const T2_P &F) {
504}
505
506template <typename T0_P, typename T1_P, typename T2_P>
507inline TernaryOpc_match<T0_P, T1_P, T2_P>
508m_VSelect(const T0_P &Cond, const T1_P &T, const T2_P &F) {
510}
511
512template <typename T0_P, typename T1_P, typename T2_P>
513inline TernaryOpc_match<T0_P, T1_P, T2_P>
514m_InsertElt(const T0_P &Vec, const T1_P &Val, const T2_P &Idx) {
516 Idx);
517}
518
519template <typename LHS, typename RHS, typename IDX>
520inline TernaryOpc_match<LHS, RHS, IDX>
521m_InsertSubvector(const LHS &Base, const RHS &Sub, const IDX &Idx) {
523}
524
525// === Binary operations ===
526template <typename LHS_P, typename RHS_P, bool Commutable = false,
527 bool ExcludeChain = false>
529 unsigned Opcode;
530 LHS_P LHS;
531 RHS_P RHS;
532 std::optional<SDNodeFlags> Flags;
533 BinaryOpc_match(unsigned Opc, const LHS_P &L, const RHS_P &R,
534 std::optional<SDNodeFlags> Flgs = std::nullopt)
535 : Opcode(Opc), LHS(L), RHS(R), Flags(Flgs) {}
536
537 template <typename MatchContext>
538 bool match(const MatchContext &Ctx, SDValue N) {
539 if (sd_context_match(N, Ctx, m_Opc(Opcode))) {
541 assert(EO.Size == 2);
542 if (!((LHS.match(Ctx, N->getOperand(EO.FirstIndex)) &&
543 RHS.match(Ctx, N->getOperand(EO.FirstIndex + 1))) ||
544 (Commutable && LHS.match(Ctx, N->getOperand(EO.FirstIndex + 1)) &&
545 RHS.match(Ctx, N->getOperand(EO.FirstIndex)))))
546 return false;
547
548 if (!Flags.has_value())
549 return true;
550
551 return (*Flags & N->getFlags()) == *Flags;
552 }
553
554 return false;
555 }
556};
557
558/// Matching while capturing mask
559template <typename T0, typename T1, typename T2> struct SDShuffle_match {
560 T0 Op1;
563
564 SDShuffle_match(const T0 &Op1, const T1 &Op2, const T2 &Mask)
565 : Op1(Op1), Op2(Op2), Mask(Mask) {}
566
567 template <typename MatchContext>
568 bool match(const MatchContext &Ctx, SDValue N) {
569 if (auto *I = dyn_cast<ShuffleVectorSDNode>(N)) {
570 return Op1.match(Ctx, I->getOperand(0)) &&
571 Op2.match(Ctx, I->getOperand(1)) && Mask.match(I->getMask());
572 }
573 return false;
574 }
575};
576struct m_Mask {
579 bool match(ArrayRef<int> Mask) {
580 MaskRef = Mask;
581 return true;
582 }
583};
584
588 bool match(ArrayRef<int> Mask) { return MaskRef == Mask; }
589};
590
591template <typename LHS_P, typename RHS_P, typename Pred_t,
592 bool Commutable = false, bool ExcludeChain = false>
594 using PredType = Pred_t;
595 LHS_P LHS;
596 RHS_P RHS;
597
598 MaxMin_match(const LHS_P &L, const RHS_P &R) : LHS(L), RHS(R) {}
599
600 template <typename MatchContext>
601 bool match(const MatchContext &Ctx, SDValue N) {
602 if (sd_context_match(N, Ctx, m_Opc(ISD::SELECT)) ||
604 EffectiveOperands<ExcludeChain> EO_SELECT(N, Ctx);
605 assert(EO_SELECT.Size == 3);
606 SDValue Cond = N->getOperand(EO_SELECT.FirstIndex);
607 SDValue TrueValue = N->getOperand(EO_SELECT.FirstIndex + 1);
608 SDValue FalseValue = N->getOperand(EO_SELECT.FirstIndex + 2);
609
612 assert(EO_SETCC.Size == 3);
613 SDValue L = Cond->getOperand(EO_SETCC.FirstIndex);
614 SDValue R = Cond->getOperand(EO_SETCC.FirstIndex + 1);
615 auto *CondNode =
616 cast<CondCodeSDNode>(Cond->getOperand(EO_SETCC.FirstIndex + 2));
617
618 if ((TrueValue != L || FalseValue != R) &&
619 (TrueValue != R || FalseValue != L)) {
620 return false;
621 }
622
624 TrueValue == L ? CondNode->get()
625 : getSetCCInverse(CondNode->get(), L.getValueType());
626 if (!Pred_t::match(Cond)) {
627 return false;
628 }
629 return (LHS.match(Ctx, L) && RHS.match(Ctx, R)) ||
630 (Commutable && LHS.match(Ctx, R) && RHS.match(Ctx, L));
631 }
632 }
633
634 return false;
635 }
636};
637
638// Helper class for identifying signed max predicates.
640 static bool match(ISD::CondCode Cond) {
642 }
643};
644
645// Helper class for identifying unsigned max predicates.
647 static bool match(ISD::CondCode Cond) {
649 }
650};
651
652// Helper class for identifying signed min predicates.
654 static bool match(ISD::CondCode Cond) {
656 }
657};
658
659// Helper class for identifying unsigned min predicates.
661 static bool match(ISD::CondCode Cond) {
663 }
664};
665
666template <typename LHS, typename RHS>
667inline BinaryOpc_match<LHS, RHS> m_BinOp(unsigned Opc, const LHS &L,
668 const RHS &R) {
669 return BinaryOpc_match<LHS, RHS>(Opc, L, R);
670}
671template <typename LHS, typename RHS>
672inline BinaryOpc_match<LHS, RHS, true> m_c_BinOp(unsigned Opc, const LHS &L,
673 const RHS &R) {
674 return BinaryOpc_match<LHS, RHS, true>(Opc, L, R);
675}
676
677template <typename LHS, typename RHS>
678inline BinaryOpc_match<LHS, RHS, false, true>
679m_ChainedBinOp(unsigned Opc, const LHS &L, const RHS &R) {
681}
682template <typename LHS, typename RHS>
683inline BinaryOpc_match<LHS, RHS, true, true>
684m_c_ChainedBinOp(unsigned Opc, const LHS &L, const RHS &R) {
686}
687
688// Common binary operations
689template <typename LHS, typename RHS>
690inline BinaryOpc_match<LHS, RHS, true> m_Add(const LHS &L, const RHS &R) {
692}
693
694template <typename LHS, typename RHS>
695inline BinaryOpc_match<LHS, RHS> m_Sub(const LHS &L, const RHS &R) {
697}
698
699template <typename LHS, typename RHS>
700inline BinaryOpc_match<LHS, RHS, true> m_Mul(const LHS &L, const RHS &R) {
702}
703
704template <typename LHS, typename RHS>
705inline BinaryOpc_match<LHS, RHS, true> m_And(const LHS &L, const RHS &R) {
707}
708
709template <typename LHS, typename RHS>
710inline BinaryOpc_match<LHS, RHS, true> m_Or(const LHS &L, const RHS &R) {
712}
713
714template <typename LHS, typename RHS>
716 const RHS &R) {
718}
719
720template <typename LHS, typename RHS>
721inline auto m_AddLike(const LHS &L, const RHS &R) {
722 return m_AnyOf(m_Add(L, R), m_DisjointOr(L, R));
723}
724
725template <typename LHS, typename RHS>
726inline BinaryOpc_match<LHS, RHS, true> m_Xor(const LHS &L, const RHS &R) {
728}
729
730template <typename LHS, typename RHS>
731inline BinaryOpc_match<LHS, RHS, true> m_SMin(const LHS &L, const RHS &R) {
733}
734
735template <typename LHS, typename RHS>
736inline auto m_SMinLike(const LHS &L, const RHS &R) {
739}
740
741template <typename LHS, typename RHS>
742inline BinaryOpc_match<LHS, RHS, true> m_SMax(const LHS &L, const RHS &R) {
744}
745
746template <typename LHS, typename RHS>
747inline auto m_SMaxLike(const LHS &L, const RHS &R) {
750}
751
752template <typename LHS, typename RHS>
753inline BinaryOpc_match<LHS, RHS, true> m_UMin(const LHS &L, const RHS &R) {
755}
756
757template <typename LHS, typename RHS>
758inline auto m_UMinLike(const LHS &L, const RHS &R) {
761}
762
763template <typename LHS, typename RHS>
764inline BinaryOpc_match<LHS, RHS, true> m_UMax(const LHS &L, const RHS &R) {
766}
767
768template <typename LHS, typename RHS>
769inline auto m_UMaxLike(const LHS &L, const RHS &R) {
772}
773
774template <typename LHS, typename RHS>
775inline BinaryOpc_match<LHS, RHS> m_UDiv(const LHS &L, const RHS &R) {
777}
778template <typename LHS, typename RHS>
779inline BinaryOpc_match<LHS, RHS> m_SDiv(const LHS &L, const RHS &R) {
781}
782
783template <typename LHS, typename RHS>
784inline BinaryOpc_match<LHS, RHS> m_URem(const LHS &L, const RHS &R) {
786}
787template <typename LHS, typename RHS>
788inline BinaryOpc_match<LHS, RHS> m_SRem(const LHS &L, const RHS &R) {
790}
791
792template <typename LHS, typename RHS>
793inline BinaryOpc_match<LHS, RHS> m_Shl(const LHS &L, const RHS &R) {
795}
796
797template <typename LHS, typename RHS>
798inline BinaryOpc_match<LHS, RHS> m_Sra(const LHS &L, const RHS &R) {
800}
801template <typename LHS, typename RHS>
802inline BinaryOpc_match<LHS, RHS> m_Srl(const LHS &L, const RHS &R) {
804}
805
806template <typename LHS, typename RHS>
807inline BinaryOpc_match<LHS, RHS> m_Rotl(const LHS &L, const RHS &R) {
809}
810
811template <typename LHS, typename RHS>
812inline BinaryOpc_match<LHS, RHS> m_Rotr(const LHS &L, const RHS &R) {
814}
815
816template <typename LHS, typename RHS>
817inline BinaryOpc_match<LHS, RHS, true> m_FAdd(const LHS &L, const RHS &R) {
819}
820
821template <typename LHS, typename RHS>
822inline BinaryOpc_match<LHS, RHS> m_FSub(const LHS &L, const RHS &R) {
824}
825
826template <typename LHS, typename RHS>
827inline BinaryOpc_match<LHS, RHS, true> m_FMul(const LHS &L, const RHS &R) {
829}
830
831template <typename LHS, typename RHS>
832inline BinaryOpc_match<LHS, RHS> m_FDiv(const LHS &L, const RHS &R) {
834}
835
836template <typename LHS, typename RHS>
837inline BinaryOpc_match<LHS, RHS> m_FRem(const LHS &L, const RHS &R) {
839}
840
841template <typename V1_t, typename V2_t>
842inline BinaryOpc_match<V1_t, V2_t> m_Shuffle(const V1_t &v1, const V2_t &v2) {
844}
845
846template <typename V1_t, typename V2_t, typename Mask_t>
847inline SDShuffle_match<V1_t, V2_t, Mask_t>
848m_Shuffle(const V1_t &v1, const V2_t &v2, const Mask_t &mask) {
849 return SDShuffle_match<V1_t, V2_t, Mask_t>(v1, v2, mask);
850}
851
852template <typename LHS, typename RHS>
855}
856
857template <typename LHS, typename RHS>
859 const RHS &Idx) {
861}
862
863// === Unary operations ===
864template <typename Opnd_P, bool ExcludeChain = false> struct UnaryOpc_match {
865 unsigned Opcode;
866 Opnd_P Opnd;
867 std::optional<SDNodeFlags> Flags;
868 UnaryOpc_match(unsigned Opc, const Opnd_P &Op,
869 std::optional<SDNodeFlags> Flgs = std::nullopt)
870 : Opcode(Opc), Opnd(Op), Flags(Flgs) {}
871
872 template <typename MatchContext>
873 bool match(const MatchContext &Ctx, SDValue N) {
874 if (sd_context_match(N, Ctx, m_Opc(Opcode))) {
876 assert(EO.Size == 1);
877 if (!Opnd.match(Ctx, N->getOperand(EO.FirstIndex)))
878 return false;
879 if (!Flags.has_value())
880 return true;
881
882 return (*Flags & N->getFlags()) == *Flags;
883 }
884
885 return false;
886 }
887};
888
889template <typename Opnd>
890inline UnaryOpc_match<Opnd> m_UnaryOp(unsigned Opc, const Opnd &Op) {
891 return UnaryOpc_match<Opnd>(Opc, Op);
892}
893template <typename Opnd>
895 const Opnd &Op) {
896 return UnaryOpc_match<Opnd, true>(Opc, Op);
897}
898
899template <typename Opnd>
900inline UnaryOpc_match<Opnd> m_BSwap(const Opnd &Op) {
902}
903
904template <typename Opnd>
907}
908
909template <typename Opnd> inline UnaryOpc_match<Opnd> m_ZExt(const Opnd &Op) {
911}
912
913template <typename Opnd>
914inline UnaryOpc_match<Opnd> m_NNegZExt(const Opnd &Op) {
916}
917
918template <typename Opnd> inline auto m_SExt(const Opnd &Op) {
920}
921
922template <typename Opnd> inline UnaryOpc_match<Opnd> m_AnyExt(const Opnd &Op) {
924}
925
926template <typename Opnd> inline UnaryOpc_match<Opnd> m_Trunc(const Opnd &Op) {
928}
929
930/// Match a zext or identity
931/// Allows to peek through optional extensions
932template <typename Opnd> inline auto m_ZExtOrSelf(const Opnd &Op) {
933 return m_AnyOf(m_ZExt(Op), Op);
934}
935
936/// Match a sext or identity
937/// Allows to peek through optional extensions
938template <typename Opnd> inline auto m_SExtOrSelf(const Opnd &Op) {
939 return m_AnyOf(m_SExt(Op), Op);
940}
941
942template <typename Opnd> inline auto m_SExtLike(const Opnd &Op) {
943 return m_AnyOf(m_SExt(Op), m_NNegZExt(Op));
944}
945
946/// Match a aext or identity
947/// Allows to peek through optional extensions
948template <typename Opnd>
949inline Or<UnaryOpc_match<Opnd>, Opnd> m_AExtOrSelf(const Opnd &Op) {
950 return Or<UnaryOpc_match<Opnd>, Opnd>(m_AnyExt(Op), Op);
951}
952
953/// Match a trunc or identity
954/// Allows to peek through optional truncations
955template <typename Opnd>
956inline Or<UnaryOpc_match<Opnd>, Opnd> m_TruncOrSelf(const Opnd &Op) {
957 return Or<UnaryOpc_match<Opnd>, Opnd>(m_Trunc(Op), Op);
958}
959
960template <typename Opnd> inline UnaryOpc_match<Opnd> m_VScale(const Opnd &Op) {
962}
963
964template <typename Opnd> inline UnaryOpc_match<Opnd> m_FPToUI(const Opnd &Op) {
966}
967
968template <typename Opnd> inline UnaryOpc_match<Opnd> m_FPToSI(const Opnd &Op) {
970}
971
972template <typename Opnd> inline UnaryOpc_match<Opnd> m_Ctpop(const Opnd &Op) {
974}
975
976template <typename Opnd> inline UnaryOpc_match<Opnd> m_Ctlz(const Opnd &Op) {
978}
979
980template <typename Opnd> inline UnaryOpc_match<Opnd> m_Cttz(const Opnd &Op) {
982}
983
984// === Constants ===
987
988 explicit ConstantInt_match(APInt *V) : BindVal(V) {}
989
990 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
991 // The logics here are similar to that in
992 // SelectionDAG::isConstantIntBuildVectorOrConstantInt, but the latter also
993 // treats GlobalAddressSDNode as a constant, which is difficult to turn into
994 // APInt.
995 if (auto *C = dyn_cast_or_null<ConstantSDNode>(N.getNode())) {
996 if (BindVal)
997 *BindVal = C->getAPIntValue();
998 return true;
999 }
1000
1001 APInt Discard;
1002 return ISD::isConstantSplatVector(N.getNode(),
1003 BindVal ? *BindVal : Discard);
1004 }
1005};
1006/// Match any interger constants or splat of an integer constant.
1008/// Match any interger constants or splat of an integer constant; return the
1009/// specific constant or constant splat value.
1011
1014
1015 explicit SpecificInt_match(APInt APV) : IntVal(std::move(APV)) {}
1016
1017 template <typename MatchContext>
1018 bool match(const MatchContext &Ctx, SDValue N) {
1019 APInt ConstInt;
1020 if (sd_context_match(N, Ctx, m_ConstInt(ConstInt)))
1021 return APInt::isSameValue(IntVal, ConstInt);
1022 return false;
1023 }
1024};
1025
1026/// Match a specific integer constant or constant splat value.
1028 return SpecificInt_match(std::move(V));
1029}
1031 return SpecificInt_match(APInt(64, V));
1032}
1033
1035inline SpecificInt_match m_One() { return m_SpecificInt(1U); }
1036
1038
1039 AllOnes_match() = default;
1040
1041 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
1042 return isAllOnesOrAllOnesSplat(N);
1043 }
1044};
1045
1047
1048/// Match true boolean value based on the information provided by
1049/// TargetLowering.
1050inline auto m_True() {
1051 return TLI_pred_match{
1052 [](const TargetLowering &TLI, SDValue N) {
1053 APInt ConstVal;
1054 if (sd_match(N, m_ConstInt(ConstVal)))
1055 switch (TLI.getBooleanContents(N.getValueType())) {
1057 return ConstVal.isOne();
1059 return ConstVal.isAllOnes();
1061 return (ConstVal & 0x01) == 1;
1062 }
1063
1064 return false;
1065 },
1066 m_Value()};
1067}
1068/// Match false boolean value based on the information provided by
1069/// TargetLowering.
1070inline auto m_False() {
1071 return TLI_pred_match{
1072 [](const TargetLowering &TLI, SDValue N) {
1073 APInt ConstVal;
1074 if (sd_match(N, m_ConstInt(ConstVal)))
1075 switch (TLI.getBooleanContents(N.getValueType())) {
1078 return ConstVal.isZero();
1080 return (ConstVal & 0x01) == 0;
1081 }
1082
1083 return false;
1084 },
1085 m_Value()};
1086}
1087
1089 std::optional<ISD::CondCode> CCToMatch;
1091
1093
1095
1096 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
1097 if (auto *CC = dyn_cast<CondCodeSDNode>(N.getNode())) {
1098 if (CCToMatch && *CCToMatch != CC->get())
1099 return false;
1100
1101 if (BindCC)
1102 *BindCC = CC->get();
1103 return true;
1104 }
1105
1106 return false;
1107 }
1108};
1109
1110/// Match any conditional code SDNode.
1111inline CondCode_match m_CondCode() { return CondCode_match(nullptr); }
1112/// Match any conditional code SDNode and return its ISD::CondCode value.
1114 return CondCode_match(&CC);
1115}
1116/// Match a conditional code SDNode with a specific ISD::CondCode.
1118 return CondCode_match(CC);
1119}
1120
1121/// Match a negate as a sub(0, v)
1122template <typename ValTy>
1124 return m_Sub(m_Zero(), V);
1125}
1126
1127/// Match a Not as a xor(v, -1) or xor(-1, v)
1128template <typename ValTy>
1130 return m_Xor(V, m_AllOnes());
1131}
1132
1133} // namespace SDPatternMatch
1134} // namespace llvm
1135#endif
This file implements a class to represent arbitrary precision integral constant values and operations...
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
#define T1
#define P(N)
const SmallVectorImpl< MachineOperand > & Cond
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file contains some templates that are useful if you are working with the STL at all.
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:371
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
Definition: APInt.h:380
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:553
bool isOne() const
Determine if this is a value of 1.
Definition: APInt.h:389
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
This class represents an Operation in the Expression.
MatchResult match(StringRef Buffer, const SourceMgr &SM) const
Matches the pattern string against the input buffer Buffer.
Definition: FileCheck.cpp:1077
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...
Definition: SelectionDAG.h:228
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:780
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
Definition: ISDOpcodes.h:574
@ BSWAP
Byte Swap and Counting operators.
Definition: ISDOpcodes.h:744
@ ADD
Simple integer binary arithmetic operators.
Definition: ISDOpcodes.h:246
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
Definition: ISDOpcodes.h:814
@ FADD
Simple binary floating point operators.
Definition: ISDOpcodes.h:397
@ SIGN_EXTEND
Conversion operators.
Definition: ISDOpcodes.h:805
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
Definition: ISDOpcodes.h:757
@ UNDEF
UNDEF - An undefined node.
Definition: ISDOpcodes.h:218
@ SHL
Shift and rotation operations.
Definition: ISDOpcodes.h:735
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
Definition: ISDOpcodes.h:615
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
Definition: ISDOpcodes.h:588
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
Definition: ISDOpcodes.h:550
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition: ISDOpcodes.h:811
@ VSCALE
VSCALE(IMM) - Returns the runtime scaling factor used to calculate the number of elements within a sc...
Definition: ISDOpcodes.h:1407
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
Definition: ISDOpcodes.h:697
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
Definition: ISDOpcodes.h:766
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition: ISDOpcodes.h:887
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition: ISDOpcodes.h:709
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
Definition: ISDOpcodes.h:539
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition: ISDOpcodes.h:817
bool isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
Definition: ISDOpcodes.h:1606
class_match< BinaryOperator > m_BinOp()
Match an arbitrary binary operation and ignore it.
Definition: PatternMatch.h:100
VScaleVal_match m_VScale()
Opcode_match m_Opc(unsigned Opcode)
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)
BinaryOpc_match< LHS, RHS, true > m_Mul(const LHS &L, const RHS &R)
auto m_UMinLike(const LHS &L, const RHS &R)
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_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)
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)
auto m_LegalType(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)
NUses_match< N, Value_match > m_NUses()
UnaryOpc_match< Opnd, true > m_ChainedUnaryOp(unsigned Opc, const Opnd &Op)
SpecificInt_match m_SpecificInt(APInt V)
Match a specific integer constant or constant splat value.
UnaryOpc_match< Opnd > m_FPToUI(const Opnd &Op)
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 > 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)
BinaryOpc_match< LHS, RHS > m_Rotr(const LHS &L, const RHS &R)
SpecificInt_match m_One()
SpecificInt_match m_Zero()
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)
BinaryOpc_match< SpecificInt_match, ValTy > m_Neg(const ValTy &V)
Match a negate as a sub(0, v)
BinaryOpc_match< LHS, RHS > m_SDiv(const LHS &L, const RHS &R)
SwitchContext< MatchContext, Pattern > m_Context(const MatchContext &Ctx, Pattern &&P)
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)
BinaryOpc_match< LHS, RHS, true > m_Xor(const LHS &L, const RHS &R)
Opcode_match m_Undef()
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)
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_True()
Match true boolean value based on the information provided by TargetLowering.
UnaryOpc_match< Opnd > m_Ctpop(const Opnd &Op)
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.
BinaryOpc_match< LHS, RHS, true > m_c_BinOp(unsigned Opc, const LHS &L, const RHS &R)
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)
AllOnes_match m_AllOnes()
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 interger 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: AddressRanges.h:18
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:1565
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:1873
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858
#define N
Extended Value Type.
Definition: ValueTypes.h:35
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)
std::optional< SDNodeFlags > Flags
BinaryOpc_match(unsigned Opc, const LHS_P &L, const RHS_P &R, std::optional< SDNodeFlags > Flgs=std::nullopt)
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)
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)
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 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)
std::optional< SDNodeFlags > Flags
UnaryOpc_match(unsigned Opc, const Opnd_P &Op, std::optional< SDNodeFlags > Flgs=std::nullopt)
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(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)