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
141template <unsigned NumUses, typename Pattern> struct NUses_match {
143
144 explicit NUses_match(const Pattern &P) : P(P) {}
145
146 template <typename MatchContext>
147 bool match(const MatchContext &Ctx, SDValue N) {
148 // SDNode::hasNUsesOfValue is pretty expensive when the SDNode produces
149 // multiple results, hence we check the subsequent pattern here before
150 // checking the number of value users.
151 return P.match(Ctx, N) && N->hasNUsesOfValue(NumUses, N.getResNo());
152 }
153};
154
155template <typename Pattern>
158}
159template <unsigned N, typename Pattern>
162}
163
166}
167template <unsigned N> inline NUses_match<N, Value_match> m_NUses() {
169}
170
173
174 explicit Value_bind(SDValue &N) : BindVal(N) {}
175
176 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
177 BindVal = N;
178 return true;
179 }
180};
181
182inline Value_bind m_Value(SDValue &N) { return Value_bind(N); }
183
184template <typename Pattern, typename PredFuncT> struct TLI_pred_match {
186 PredFuncT PredFunc;
187
188 TLI_pred_match(const PredFuncT &Pred, const Pattern &P)
189 : P(P), PredFunc(Pred) {}
190
191 template <typename MatchContext>
192 bool match(const MatchContext &Ctx, SDValue N) {
193 assert(Ctx.getTLI() && "TargetLowering is required for this pattern.");
194 return PredFunc(*Ctx.getTLI(), N) && P.match(Ctx, N);
195 }
196};
197
198// Explicit deduction guide.
199template <typename PredFuncT, typename Pattern>
200TLI_pred_match(const PredFuncT &Pred, const Pattern &P)
202
203/// Match legal SDNodes based on the information provided by TargetLowering.
204template <typename Pattern> inline auto m_LegalOp(const Pattern &P) {
205 return TLI_pred_match{[](const TargetLowering &TLI, SDValue N) {
206 return TLI.isOperationLegal(N->getOpcode(),
207 N.getValueType());
208 },
209 P};
210}
211
212/// Switch to a different MatchContext for subsequent patterns.
213template <typename NewMatchContext, typename Pattern> struct SwitchContext {
214 const NewMatchContext &Ctx;
216
217 template <typename OrigMatchContext>
218 bool match(const OrigMatchContext &, SDValue N) {
219 return P.match(Ctx, N);
220 }
221};
222
223template <typename MatchContext, typename Pattern>
224inline SwitchContext<MatchContext, Pattern> m_Context(const MatchContext &Ctx,
225 Pattern &&P) {
226 return SwitchContext<MatchContext, Pattern>{Ctx, std::move(P)};
227}
228
229// === Value type ===
232
233 explicit ValueType_bind(EVT &Bind) : BindVT(Bind) {}
234
235 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
236 BindVT = N.getValueType();
237 return true;
238 }
239};
240
241/// Retreive the ValueType of the current SDValue.
242inline ValueType_bind m_VT(EVT &VT) { return ValueType_bind(VT); }
243
244template <typename Pattern, typename PredFuncT> struct ValueType_match {
245 PredFuncT PredFunc;
247
248 ValueType_match(const PredFuncT &Pred, const Pattern &P)
249 : PredFunc(Pred), P(P) {}
250
251 template <typename MatchContext>
252 bool match(const MatchContext &Ctx, SDValue N) {
253 return PredFunc(N.getValueType()) && P.match(Ctx, N);
254 }
255};
256
257// Explicit deduction guide.
258template <typename PredFuncT, typename Pattern>
259ValueType_match(const PredFuncT &Pred, const Pattern &P)
261
262/// Match a specific ValueType.
263template <typename Pattern>
264inline auto m_SpecificVT(EVT RefVT, const Pattern &P) {
265 return ValueType_match{[=](EVT VT) { return VT == RefVT; }, P};
266}
267inline auto m_SpecificVT(EVT RefVT) {
268 return ValueType_match{[=](EVT VT) { return VT == RefVT; }, m_Value()};
269}
270
271inline auto m_Glue() { return m_SpecificVT(MVT::Glue); }
272inline auto m_OtherVT() { return m_SpecificVT(MVT::Other); }
273
274/// Match any integer ValueTypes.
275template <typename Pattern> inline auto m_IntegerVT(const Pattern &P) {
276 return ValueType_match{[](EVT VT) { return VT.isInteger(); }, P};
277}
278inline auto m_IntegerVT() {
279 return ValueType_match{[](EVT VT) { return VT.isInteger(); }, m_Value()};
280}
281
282/// Match any floating point ValueTypes.
283template <typename Pattern> inline auto m_FloatingPointVT(const Pattern &P) {
284 return ValueType_match{[](EVT VT) { return VT.isFloatingPoint(); }, P};
285}
286inline auto m_FloatingPointVT() {
287 return ValueType_match{[](EVT VT) { return VT.isFloatingPoint(); },
288 m_Value()};
289}
290
291/// Match any vector ValueTypes.
292template <typename Pattern> inline auto m_VectorVT(const Pattern &P) {
293 return ValueType_match{[](EVT VT) { return VT.isVector(); }, P};
294}
295inline auto m_VectorVT() {
296 return ValueType_match{[](EVT VT) { return VT.isVector(); }, m_Value()};
297}
298
299/// Match fixed-length vector ValueTypes.
300template <typename Pattern> inline auto m_FixedVectorVT(const Pattern &P) {
301 return ValueType_match{[](EVT VT) { return VT.isFixedLengthVector(); }, P};
302}
303inline auto m_FixedVectorVT() {
304 return ValueType_match{[](EVT VT) { return VT.isFixedLengthVector(); },
305 m_Value()};
306}
307
308/// Match scalable vector ValueTypes.
309template <typename Pattern> inline auto m_ScalableVectorVT(const Pattern &P) {
310 return ValueType_match{[](EVT VT) { return VT.isScalableVector(); }, P};
311}
312inline auto m_ScalableVectorVT() {
313 return ValueType_match{[](EVT VT) { return VT.isScalableVector(); },
314 m_Value()};
315}
316
317/// Match legal ValueTypes based on the information provided by TargetLowering.
318template <typename Pattern> inline auto m_LegalType(const Pattern &P) {
319 return TLI_pred_match{[](const TargetLowering &TLI, SDValue N) {
320 return TLI.isTypeLegal(N.getValueType());
321 },
322 P};
323}
324
325// === Patterns combinators ===
326template <typename... Preds> struct And {
327 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
328 return true;
329 }
330};
331
332template <typename Pred, typename... Preds>
333struct And<Pred, Preds...> : And<Preds...> {
334 Pred P;
335 And(const Pred &p, const Preds &...preds) : And<Preds...>(preds...), P(p) {}
336
337 template <typename MatchContext>
338 bool match(const MatchContext &Ctx, SDValue N) {
339 return P.match(Ctx, N) && And<Preds...>::match(Ctx, N);
340 }
341};
342
343template <typename... Preds> struct Or {
344 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
345 return false;
346 }
347};
348
349template <typename Pred, typename... Preds>
350struct Or<Pred, Preds...> : Or<Preds...> {
351 Pred P;
352 Or(const Pred &p, const Preds &...preds) : Or<Preds...>(preds...), P(p) {}
353
354 template <typename MatchContext>
355 bool match(const MatchContext &Ctx, SDValue N) {
356 return P.match(Ctx, N) || Or<Preds...>::match(Ctx, N);
357 }
358};
359
360template <typename Pred> struct Not {
361 Pred P;
362
363 explicit Not(const Pred &P) : P(P) {}
364
365 template <typename MatchContext>
366 bool match(const MatchContext &Ctx, SDValue N) {
367 return !P.match(Ctx, N);
368 }
369};
370// Explicit deduction guide.
371template <typename Pred> Not(const Pred &P) -> Not<Pred>;
372
373/// Match if the inner pattern does NOT match.
374template <typename Pred> inline Not<Pred> m_Unless(const Pred &P) {
375 return Not{P};
376}
377
378template <typename... Preds> And<Preds...> m_AllOf(const Preds &...preds) {
379 return And<Preds...>(preds...);
380}
381
382template <typename... Preds> Or<Preds...> m_AnyOf(const Preds &...preds) {
383 return Or<Preds...>(preds...);
384}
385
386template <typename... Preds> auto m_NoneOf(const Preds &...preds) {
387 return m_Unless(m_AnyOf(preds...));
388}
389
390// === Generic node matching ===
391template <unsigned OpIdx, typename... OpndPreds> struct Operands_match {
392 template <typename MatchContext>
393 bool match(const MatchContext &Ctx, SDValue N) {
394 // Returns false if there are more operands than predicates;
395 // Ignores the last two operands if both the Context and the Node are VP
396 return Ctx.getNumOperands(N) == OpIdx;
397 }
398};
399
400template <unsigned OpIdx, typename OpndPred, typename... OpndPreds>
401struct Operands_match<OpIdx, OpndPred, OpndPreds...>
402 : Operands_match<OpIdx + 1, OpndPreds...> {
403 OpndPred P;
404
405 Operands_match(const OpndPred &p, const OpndPreds &...preds)
406 : Operands_match<OpIdx + 1, OpndPreds...>(preds...), P(p) {}
407
408 template <typename MatchContext>
409 bool match(const MatchContext &Ctx, SDValue N) {
410 if (OpIdx < N->getNumOperands())
411 return P.match(Ctx, N->getOperand(OpIdx)) &&
413
414 // This is the case where there are more predicates than operands.
415 return false;
416 }
417};
418
419template <typename... OpndPreds>
420auto m_Node(unsigned Opcode, const OpndPreds &...preds) {
421 return m_AllOf(m_Opc(Opcode), Operands_match<0, OpndPreds...>(preds...));
422}
423
424/// Provide number of operands that are not chain or glue, as well as the first
425/// index of such operand.
426template <bool ExcludeChain> struct EffectiveOperands {
427 unsigned Size = 0;
428 unsigned FirstIndex = 0;
429
430 template <typename MatchContext>
431 explicit EffectiveOperands(SDValue N, const MatchContext &Ctx) {
432 const unsigned TotalNumOps = Ctx.getNumOperands(N);
433 FirstIndex = TotalNumOps;
434 for (unsigned I = 0; I < TotalNumOps; ++I) {
435 // Count the number of non-chain and non-glue nodes (we ignore chain
436 // and glue by default) and retreive the operand index offset.
437 EVT VT = N->getOperand(I).getValueType();
438 if (VT != MVT::Glue && VT != MVT::Other) {
439 ++Size;
440 if (FirstIndex == TotalNumOps)
441 FirstIndex = I;
442 }
443 }
444 }
445};
446
447template <> struct EffectiveOperands<false> {
448 unsigned Size = 0;
449 unsigned FirstIndex = 0;
450
451 template <typename MatchContext>
452 explicit EffectiveOperands(SDValue N, const MatchContext &Ctx)
453 : Size(Ctx.getNumOperands(N)) {}
454};
455
456// === Ternary operations ===
457template <typename T0_P, typename T1_P, typename T2_P, bool Commutable = false,
458 bool ExcludeChain = false>
460 unsigned Opcode;
461 T0_P Op0;
462 T1_P Op1;
463 T2_P Op2;
464
465 TernaryOpc_match(unsigned Opc, const T0_P &Op0, const T1_P &Op1,
466 const T2_P &Op2)
467 : Opcode(Opc), Op0(Op0), Op1(Op1), Op2(Op2) {}
468
469 template <typename MatchContext>
470 bool match(const MatchContext &Ctx, SDValue N) {
471 if (sd_context_match(N, Ctx, m_Opc(Opcode))) {
473 assert(EO.Size == 3);
474 return ((Op0.match(Ctx, N->getOperand(EO.FirstIndex)) &&
475 Op1.match(Ctx, N->getOperand(EO.FirstIndex + 1))) ||
476 (Commutable && Op0.match(Ctx, N->getOperand(EO.FirstIndex + 1)) &&
477 Op1.match(Ctx, N->getOperand(EO.FirstIndex)))) &&
478 Op2.match(Ctx, N->getOperand(EO.FirstIndex + 2));
479 }
480
481 return false;
482 }
483};
484
485template <typename T0_P, typename T1_P, typename T2_P>
486inline TernaryOpc_match<T0_P, T1_P, T2_P>
487m_SetCC(const T0_P &LHS, const T1_P &RHS, const T2_P &CC) {
489}
490
491template <typename T0_P, typename T1_P, typename T2_P>
492inline TernaryOpc_match<T0_P, T1_P, T2_P, true, false>
493m_c_SetCC(const T0_P &LHS, const T1_P &RHS, const T2_P &CC) {
495 CC);
496}
497
498template <typename T0_P, typename T1_P, typename T2_P>
499inline TernaryOpc_match<T0_P, T1_P, T2_P>
500m_Select(const T0_P &Cond, const T1_P &T, const T2_P &F) {
502}
503
504template <typename T0_P, typename T1_P, typename T2_P>
505inline TernaryOpc_match<T0_P, T1_P, T2_P>
506m_VSelect(const T0_P &Cond, const T1_P &T, const T2_P &F) {
508}
509
510template <typename T0_P, typename T1_P, typename T2_P>
511inline TernaryOpc_match<T0_P, T1_P, T2_P>
512m_InsertElt(const T0_P &Vec, const T1_P &Val, const T2_P &Idx) {
514 Idx);
515}
516
517// === Binary operations ===
518template <typename LHS_P, typename RHS_P, bool Commutable = false,
519 bool ExcludeChain = false>
521 unsigned Opcode;
522 LHS_P LHS;
523 RHS_P RHS;
524 std::optional<SDNodeFlags> Flags;
525 BinaryOpc_match(unsigned Opc, const LHS_P &L, const RHS_P &R,
526 std::optional<SDNodeFlags> Flgs = std::nullopt)
527 : Opcode(Opc), LHS(L), RHS(R), Flags(Flgs) {}
528
529 template <typename MatchContext>
530 bool match(const MatchContext &Ctx, SDValue N) {
531 if (sd_context_match(N, Ctx, m_Opc(Opcode))) {
533 assert(EO.Size == 2);
534 if (!((LHS.match(Ctx, N->getOperand(EO.FirstIndex)) &&
535 RHS.match(Ctx, N->getOperand(EO.FirstIndex + 1))) ||
536 (Commutable && LHS.match(Ctx, N->getOperand(EO.FirstIndex + 1)) &&
537 RHS.match(Ctx, N->getOperand(EO.FirstIndex)))))
538 return false;
539
540 if (!Flags.has_value())
541 return true;
542
543 return (*Flags & N->getFlags()) == *Flags;
544 }
545
546 return false;
547 }
548};
549
550/// Matching while capturing mask
551template <typename T0, typename T1, typename T2> struct SDShuffle_match {
552 T0 Op1;
555
556 SDShuffle_match(const T0 &Op1, const T1 &Op2, const T2 &Mask)
557 : Op1(Op1), Op2(Op2), Mask(Mask) {}
558
559 template <typename MatchContext>
560 bool match(const MatchContext &Ctx, SDValue N) {
561 if (auto *I = dyn_cast<ShuffleVectorSDNode>(N)) {
562 return Op1.match(Ctx, I->getOperand(0)) &&
563 Op2.match(Ctx, I->getOperand(1)) && Mask.match(I->getMask());
564 }
565 return false;
566 }
567};
568struct m_Mask {
571 bool match(ArrayRef<int> Mask) {
572 MaskRef = Mask;
573 return true;
574 }
575};
576
580 bool match(ArrayRef<int> Mask) { return MaskRef == Mask; }
581};
582
583template <typename LHS_P, typename RHS_P, typename Pred_t,
584 bool Commutable = false, bool ExcludeChain = false>
586 using PredType = Pred_t;
587 LHS_P LHS;
588 RHS_P RHS;
589
590 MaxMin_match(const LHS_P &L, const RHS_P &R) : LHS(L), RHS(R) {}
591
592 template <typename MatchContext>
593 bool match(const MatchContext &Ctx, SDValue N) {
594 if (sd_context_match(N, Ctx, m_Opc(ISD::SELECT)) ||
596 EffectiveOperands<ExcludeChain> EO_SELECT(N, Ctx);
597 assert(EO_SELECT.Size == 3);
598 SDValue Cond = N->getOperand(EO_SELECT.FirstIndex);
599 SDValue TrueValue = N->getOperand(EO_SELECT.FirstIndex + 1);
600 SDValue FalseValue = N->getOperand(EO_SELECT.FirstIndex + 2);
601
604 assert(EO_SETCC.Size == 3);
605 SDValue L = Cond->getOperand(EO_SETCC.FirstIndex);
606 SDValue R = Cond->getOperand(EO_SETCC.FirstIndex + 1);
607 auto *CondNode =
608 cast<CondCodeSDNode>(Cond->getOperand(EO_SETCC.FirstIndex + 2));
609
610 if ((TrueValue != L || FalseValue != R) &&
611 (TrueValue != R || FalseValue != L)) {
612 return false;
613 }
614
616 TrueValue == L ? CondNode->get()
617 : getSetCCInverse(CondNode->get(), L.getValueType());
618 if (!Pred_t::match(Cond)) {
619 return false;
620 }
621 return (LHS.match(Ctx, L) && RHS.match(Ctx, R)) ||
622 (Commutable && LHS.match(Ctx, R) && RHS.match(Ctx, L));
623 }
624 }
625
626 return false;
627 }
628};
629
630// Helper class for identifying signed max predicates.
632 static bool match(ISD::CondCode Cond) {
634 }
635};
636
637// Helper class for identifying unsigned max predicates.
639 static bool match(ISD::CondCode Cond) {
641 }
642};
643
644// Helper class for identifying signed min predicates.
646 static bool match(ISD::CondCode Cond) {
648 }
649};
650
651// Helper class for identifying unsigned min predicates.
653 static bool match(ISD::CondCode Cond) {
655 }
656};
657
658template <typename LHS, typename RHS>
659inline BinaryOpc_match<LHS, RHS> m_BinOp(unsigned Opc, const LHS &L,
660 const RHS &R) {
661 return BinaryOpc_match<LHS, RHS>(Opc, L, R);
662}
663template <typename LHS, typename RHS>
664inline BinaryOpc_match<LHS, RHS, true> m_c_BinOp(unsigned Opc, const LHS &L,
665 const RHS &R) {
666 return BinaryOpc_match<LHS, RHS, true>(Opc, L, R);
667}
668
669template <typename LHS, typename RHS>
670inline BinaryOpc_match<LHS, RHS, false, true>
671m_ChainedBinOp(unsigned Opc, const LHS &L, const RHS &R) {
673}
674template <typename LHS, typename RHS>
675inline BinaryOpc_match<LHS, RHS, true, true>
676m_c_ChainedBinOp(unsigned Opc, const LHS &L, const RHS &R) {
678}
679
680// Common binary operations
681template <typename LHS, typename RHS>
682inline BinaryOpc_match<LHS, RHS, true> m_Add(const LHS &L, const RHS &R) {
684}
685
686template <typename LHS, typename RHS>
687inline BinaryOpc_match<LHS, RHS> m_Sub(const LHS &L, const RHS &R) {
689}
690
691template <typename LHS, typename RHS>
692inline BinaryOpc_match<LHS, RHS, true> m_Mul(const LHS &L, const RHS &R) {
694}
695
696template <typename LHS, typename RHS>
697inline BinaryOpc_match<LHS, RHS, true> m_And(const LHS &L, const RHS &R) {
699}
700
701template <typename LHS, typename RHS>
702inline BinaryOpc_match<LHS, RHS, true> m_Or(const LHS &L, const RHS &R) {
704}
705
706template <typename LHS, typename RHS>
708 const RHS &R) {
710}
711
712template <typename LHS, typename RHS>
713inline auto m_AddLike(const LHS &L, const RHS &R) {
714 return m_AnyOf(m_Add(L, R), m_DisjointOr(L, R));
715}
716
717template <typename LHS, typename RHS>
718inline BinaryOpc_match<LHS, RHS, true> m_Xor(const LHS &L, const RHS &R) {
720}
721
722template <typename LHS, typename RHS>
723inline BinaryOpc_match<LHS, RHS, true> m_SMin(const LHS &L, const RHS &R) {
725}
726
727template <typename LHS, typename RHS>
728inline auto m_SMinLike(const LHS &L, const RHS &R) {
731}
732
733template <typename LHS, typename RHS>
734inline BinaryOpc_match<LHS, RHS, true> m_SMax(const LHS &L, const RHS &R) {
736}
737
738template <typename LHS, typename RHS>
739inline auto m_SMaxLike(const LHS &L, const RHS &R) {
742}
743
744template <typename LHS, typename RHS>
745inline BinaryOpc_match<LHS, RHS, true> m_UMin(const LHS &L, const RHS &R) {
747}
748
749template <typename LHS, typename RHS>
750inline auto m_UMinLike(const LHS &L, const RHS &R) {
753}
754
755template <typename LHS, typename RHS>
756inline BinaryOpc_match<LHS, RHS, true> m_UMax(const LHS &L, const RHS &R) {
758}
759
760template <typename LHS, typename RHS>
761inline auto m_UMaxLike(const LHS &L, const RHS &R) {
764}
765
766template <typename LHS, typename RHS>
767inline BinaryOpc_match<LHS, RHS> m_UDiv(const LHS &L, const RHS &R) {
769}
770template <typename LHS, typename RHS>
771inline BinaryOpc_match<LHS, RHS> m_SDiv(const LHS &L, const RHS &R) {
773}
774
775template <typename LHS, typename RHS>
776inline BinaryOpc_match<LHS, RHS> m_URem(const LHS &L, const RHS &R) {
778}
779template <typename LHS, typename RHS>
780inline BinaryOpc_match<LHS, RHS> m_SRem(const LHS &L, const RHS &R) {
782}
783
784template <typename LHS, typename RHS>
785inline BinaryOpc_match<LHS, RHS> m_Shl(const LHS &L, const RHS &R) {
787}
788
789template <typename LHS, typename RHS>
790inline BinaryOpc_match<LHS, RHS> m_Sra(const LHS &L, const RHS &R) {
792}
793template <typename LHS, typename RHS>
794inline BinaryOpc_match<LHS, RHS> m_Srl(const LHS &L, const RHS &R) {
796}
797
798template <typename LHS, typename RHS>
799inline BinaryOpc_match<LHS, RHS> m_Rotl(const LHS &L, const RHS &R) {
801}
802
803template <typename LHS, typename RHS>
804inline BinaryOpc_match<LHS, RHS> m_Rotr(const LHS &L, const RHS &R) {
806}
807
808template <typename LHS, typename RHS>
809inline BinaryOpc_match<LHS, RHS, true> m_FAdd(const LHS &L, const RHS &R) {
811}
812
813template <typename LHS, typename RHS>
814inline BinaryOpc_match<LHS, RHS> m_FSub(const LHS &L, const RHS &R) {
816}
817
818template <typename LHS, typename RHS>
819inline BinaryOpc_match<LHS, RHS, true> m_FMul(const LHS &L, const RHS &R) {
821}
822
823template <typename LHS, typename RHS>
824inline BinaryOpc_match<LHS, RHS> m_FDiv(const LHS &L, const RHS &R) {
826}
827
828template <typename LHS, typename RHS>
829inline BinaryOpc_match<LHS, RHS> m_FRem(const LHS &L, const RHS &R) {
831}
832
833template <typename V1_t, typename V2_t>
834inline BinaryOpc_match<V1_t, V2_t> m_Shuffle(const V1_t &v1, const V2_t &v2) {
836}
837
838template <typename V1_t, typename V2_t, typename Mask_t>
839inline SDShuffle_match<V1_t, V2_t, Mask_t>
840m_Shuffle(const V1_t &v1, const V2_t &v2, const Mask_t &mask) {
841 return SDShuffle_match<V1_t, V2_t, Mask_t>(v1, v2, mask);
842}
843
844template <typename LHS, typename RHS>
847}
848
849// === Unary operations ===
850template <typename Opnd_P, bool ExcludeChain = false> struct UnaryOpc_match {
851 unsigned Opcode;
852 Opnd_P Opnd;
853 std::optional<SDNodeFlags> Flags;
854 UnaryOpc_match(unsigned Opc, const Opnd_P &Op,
855 std::optional<SDNodeFlags> Flgs = std::nullopt)
856 : Opcode(Opc), Opnd(Op), Flags(Flgs) {}
857
858 template <typename MatchContext>
859 bool match(const MatchContext &Ctx, SDValue N) {
860 if (sd_context_match(N, Ctx, m_Opc(Opcode))) {
862 assert(EO.Size == 1);
863 if (!Opnd.match(Ctx, N->getOperand(EO.FirstIndex)))
864 return false;
865 if (!Flags.has_value())
866 return true;
867
868 return (*Flags & N->getFlags()) == *Flags;
869 }
870
871 return false;
872 }
873};
874
875template <typename Opnd>
876inline UnaryOpc_match<Opnd> m_UnaryOp(unsigned Opc, const Opnd &Op) {
877 return UnaryOpc_match<Opnd>(Opc, Op);
878}
879template <typename Opnd>
881 const Opnd &Op) {
882 return UnaryOpc_match<Opnd, true>(Opc, Op);
883}
884
885template <typename Opnd>
886inline UnaryOpc_match<Opnd> m_BSwap(const Opnd &Op) {
888}
889
890template <typename Opnd>
893}
894
895template <typename Opnd> inline UnaryOpc_match<Opnd> m_ZExt(const Opnd &Op) {
897}
898
899template <typename Opnd>
900inline UnaryOpc_match<Opnd> m_NNegZExt(const Opnd &Op) {
902}
903
904template <typename Opnd> inline auto m_SExt(const Opnd &Op) {
906}
907
908template <typename Opnd> inline UnaryOpc_match<Opnd> m_AnyExt(const Opnd &Op) {
910}
911
912template <typename Opnd> inline UnaryOpc_match<Opnd> m_Trunc(const Opnd &Op) {
914}
915
916/// Match a zext or identity
917/// Allows to peek through optional extensions
918template <typename Opnd> inline auto m_ZExtOrSelf(const Opnd &Op) {
919 return m_AnyOf(m_ZExt(Op), Op);
920}
921
922/// Match a sext or identity
923/// Allows to peek through optional extensions
924template <typename Opnd> inline auto m_SExtOrSelf(const Opnd &Op) {
925 return m_AnyOf(m_SExt(Op), Op);
926}
927
928template <typename Opnd> inline auto m_SExtLike(const Opnd &Op) {
929 return m_AnyOf(m_SExt(Op), m_NNegZExt(Op));
930}
931
932/// Match a aext or identity
933/// Allows to peek through optional extensions
934template <typename Opnd>
935inline Or<UnaryOpc_match<Opnd>, Opnd> m_AExtOrSelf(const Opnd &Op) {
936 return Or<UnaryOpc_match<Opnd>, Opnd>(m_AnyExt(Op), Op);
937}
938
939/// Match a trunc or identity
940/// Allows to peek through optional truncations
941template <typename Opnd>
942inline Or<UnaryOpc_match<Opnd>, Opnd> m_TruncOrSelf(const Opnd &Op) {
943 return Or<UnaryOpc_match<Opnd>, Opnd>(m_Trunc(Op), Op);
944}
945
946template <typename Opnd> inline UnaryOpc_match<Opnd> m_VScale(const Opnd &Op) {
948}
949
950template <typename Opnd> inline UnaryOpc_match<Opnd> m_FPToUI(const Opnd &Op) {
952}
953
954template <typename Opnd> inline UnaryOpc_match<Opnd> m_FPToSI(const Opnd &Op) {
956}
957
958template <typename Opnd> inline UnaryOpc_match<Opnd> m_Ctpop(const Opnd &Op) {
960}
961
962template <typename Opnd> inline UnaryOpc_match<Opnd> m_Ctlz(const Opnd &Op) {
964}
965
966template <typename Opnd> inline UnaryOpc_match<Opnd> m_Cttz(const Opnd &Op) {
968}
969
970// === Constants ===
973
974 explicit ConstantInt_match(APInt *V) : BindVal(V) {}
975
976 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
977 // The logics here are similar to that in
978 // SelectionDAG::isConstantIntBuildVectorOrConstantInt, but the latter also
979 // treats GlobalAddressSDNode as a constant, which is difficult to turn into
980 // APInt.
981 if (auto *C = dyn_cast_or_null<ConstantSDNode>(N.getNode())) {
982 if (BindVal)
983 *BindVal = C->getAPIntValue();
984 return true;
985 }
986
987 APInt Discard;
988 return ISD::isConstantSplatVector(N.getNode(),
989 BindVal ? *BindVal : Discard);
990 }
991};
992/// Match any interger constants or splat of an integer constant.
993inline ConstantInt_match m_ConstInt() { return ConstantInt_match(nullptr); }
994/// Match any interger constants or splat of an integer constant; return the
995/// specific constant or constant splat value.
997
1000
1001 explicit SpecificInt_match(APInt APV) : IntVal(std::move(APV)) {}
1002
1003 template <typename MatchContext>
1004 bool match(const MatchContext &Ctx, SDValue N) {
1005 APInt ConstInt;
1006 if (sd_context_match(N, Ctx, m_ConstInt(ConstInt)))
1007 return APInt::isSameValue(IntVal, ConstInt);
1008 return false;
1009 }
1010};
1011
1012/// Match a specific integer constant or constant splat value.
1014 return SpecificInt_match(std::move(V));
1015}
1017 return SpecificInt_match(APInt(64, V));
1018}
1019
1021inline SpecificInt_match m_One() { return m_SpecificInt(1U); }
1022
1024
1025 AllOnes_match() = default;
1026
1027 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
1028 return isAllOnesOrAllOnesSplat(N);
1029 }
1030};
1031
1033
1034/// Match true boolean value based on the information provided by
1035/// TargetLowering.
1036inline auto m_True() {
1037 return TLI_pred_match{
1038 [](const TargetLowering &TLI, SDValue N) {
1039 APInt ConstVal;
1040 if (sd_match(N, m_ConstInt(ConstVal)))
1041 switch (TLI.getBooleanContents(N.getValueType())) {
1043 return ConstVal.isOne();
1045 return ConstVal.isAllOnes();
1047 return (ConstVal & 0x01) == 1;
1048 }
1049
1050 return false;
1051 },
1052 m_Value()};
1053}
1054/// Match false boolean value based on the information provided by
1055/// TargetLowering.
1056inline auto m_False() {
1057 return TLI_pred_match{
1058 [](const TargetLowering &TLI, SDValue N) {
1059 APInt ConstVal;
1060 if (sd_match(N, m_ConstInt(ConstVal)))
1061 switch (TLI.getBooleanContents(N.getValueType())) {
1064 return ConstVal.isZero();
1066 return (ConstVal & 0x01) == 0;
1067 }
1068
1069 return false;
1070 },
1071 m_Value()};
1072}
1073
1075 std::optional<ISD::CondCode> CCToMatch;
1077
1079
1081
1082 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
1083 if (auto *CC = dyn_cast<CondCodeSDNode>(N.getNode())) {
1084 if (CCToMatch && *CCToMatch != CC->get())
1085 return false;
1086
1087 if (BindCC)
1088 *BindCC = CC->get();
1089 return true;
1090 }
1091
1092 return false;
1093 }
1094};
1095
1096/// Match any conditional code SDNode.
1097inline CondCode_match m_CondCode() { return CondCode_match(nullptr); }
1098/// Match any conditional code SDNode and return its ISD::CondCode value.
1100 return CondCode_match(&CC);
1101}
1102/// Match a conditional code SDNode with a specific ISD::CondCode.
1104 return CondCode_match(CC);
1105}
1106
1107/// Match a negate as a sub(0, v)
1108template <typename ValTy>
1110 return m_Sub(m_Zero(), V);
1111}
1112
1113/// Match a Not as a xor(v, -1) or xor(-1, v)
1114template <typename ValTy>
1116 return m_Xor(V, m_AllOnes());
1117}
1118
1119} // namespace SDPatternMatch
1120} // namespace llvm
1121#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
@ 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
@ 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_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)
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)
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)
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)