LLVM 24.0.0git
SDPatternMatch.h
Go to the documentation of this file.
1//==--------------- llvm/CodeGen/SDPatternMatch.h ---------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8/// \file
9/// Contains matchers for matching SelectionDAG nodes and values.
10///
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_CODEGEN_SDPATTERNMATCH_H
14#define LLVM_CODEGEN_SDPATTERNMATCH_H
15
16#include "llvm/ADT/APInt.h"
17#include "llvm/ADT/ArrayRef.h"
18#include "llvm/ADT/STLExtras.h"
20#include "llvm/ADT/bit.h"
25
26#include <type_traits>
27
28namespace llvm {
29namespace SDPatternMatch {
30
31/// MatchContext can repurpose existing patterns to behave differently under
32/// a certain context. For instance, `m_SpecificOpc(ISD::ADD)` matches plain ADD
33/// nodes in normal circumstances, but matches VP_ADD nodes under a custom
34/// VPMatchContext. This design is meant to facilitate code / pattern reusing.
35/// TODO: Remove now that we don't need to match over VP nodes.
36
38 const SelectionDAG *DAG;
39 const TargetLowering *TLI;
40
41public:
42 explicit BasicMatchContext(const SelectionDAG *DAG)
43 : DAG(DAG), TLI(DAG ? &DAG->getTargetLoweringInfo() : nullptr) {}
44
45 explicit BasicMatchContext(const TargetLowering *TLI)
46 : DAG(nullptr), TLI(TLI) {}
47
48 // A valid MatchContext has to implement the following functions.
49
50 const SelectionDAG *getDAG() const { return DAG; }
51
52 const TargetLowering *getTLI() const { return TLI; }
53
54 /// Return true if N effectively has opcode Opcode.
55 bool match(SDValue N, unsigned Opcode) const {
56 return N->getOpcode() == Opcode;
57 }
58
59 unsigned getNumOperands(SDValue N) const { return N->getNumOperands(); }
60};
61
62template <typename Pattern, typename MatchContext>
63[[nodiscard]] bool sd_context_match(SDValue N, const MatchContext &Ctx,
64 Pattern &&P) {
65 return P.match(Ctx, N);
66}
67
68template <typename Pattern, typename MatchContext>
69[[nodiscard]] bool sd_context_match(SDNode *N, const MatchContext &Ctx,
70 Pattern &&P) {
71 return sd_context_match(SDValue(N, 0), Ctx, P);
72}
73
74template <typename Pattern>
75[[nodiscard]] bool sd_match(SDNode *N, const SelectionDAG *DAG, Pattern &&P) {
77}
78
79template <typename Pattern>
80[[nodiscard]] bool sd_match(SDValue N, const SelectionDAG *DAG, Pattern &&P) {
82}
83
84template <typename Pattern>
85[[nodiscard]] bool sd_match(SDNode *N, Pattern &&P) {
86 return sd_match(N, nullptr, P);
87}
88
89template <typename Pattern>
90[[nodiscard]] bool sd_match(SDValue N, Pattern &&P) {
91 return sd_match(N, nullptr, P);
92}
93
94// === Utilities ===
97
98 Value_match() = default;
99
100 explicit Value_match(SDValue Match) : MatchVal(Match) {}
101
102 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
103 if (MatchVal)
104 return MatchVal == N;
105 return N.getNode();
106 }
107};
108
109/// Match any valid SDValue.
110inline Value_match m_Value() { return Value_match(); }
111
113 assert(N);
114 return Value_match(N);
115}
116
117template <unsigned ResNo, typename Pattern> struct Result_match {
119
120 explicit Result_match(const Pattern &P) : P(P) {}
121
122 template <typename MatchContext>
123 bool match(const MatchContext &Ctx, SDValue N) {
124 return N.getResNo() == ResNo && P.match(Ctx, N);
125 }
126};
127
128/// Match only if the SDValue is a certain result at ResNo.
129template <unsigned ResNo, typename Pattern>
133
136
137 explicit DeferredValue_match(SDValue &Match) : MatchVal(Match) {}
138
139 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
140 return N == MatchVal;
141 }
142};
143
144/// Similar to m_Specific, but the specific value to match is determined by
145/// another sub-pattern in the same sd_match() expression. For instance,
146/// We cannot match `(add V, V)` with `m_Add(m_Value(X), m_Specific(X))` since
147/// `X` is not initialized at the time it got copied into `m_Specific`. Instead,
148/// we should use `m_Add(m_Value(X), m_Deferred(X))`.
152
154 unsigned Opcode;
155
156 explicit Opcode_match(unsigned Opc) : Opcode(Opc) {}
157
158 template <typename MatchContext>
159 bool match(const MatchContext &Ctx, SDValue N) {
160 return Ctx.match(N, Opcode);
161 }
162};
163
164// === Patterns combinators ===
165template <typename... Preds> struct And {
166 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
167 return true;
168 }
169};
170
171template <typename Pred, typename... Preds>
172struct And<Pred, Preds...> : And<Preds...> {
173 Pred P;
174 And(const Pred &p, const Preds &...preds) : And<Preds...>(preds...), P(p) {}
175
176 template <typename MatchContext>
177 bool match(const MatchContext &Ctx, SDValue N) {
178 return P.match(Ctx, N) && And<Preds...>::match(Ctx, N);
179 }
180};
181
182template <typename... Preds> struct Or {
183 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
184 return false;
185 }
186};
187
188template <typename Pred, typename... Preds>
189struct Or<Pred, Preds...> : Or<Preds...> {
190 Pred P;
191 Or(const Pred &p, const Preds &...preds) : Or<Preds...>(preds...), P(p) {}
192
193 template <typename MatchContext>
194 bool match(const MatchContext &Ctx, SDValue N) {
195 return P.match(Ctx, N) || Or<Preds...>::match(Ctx, N);
196 }
197};
198
199template <typename Pred> struct Not {
200 Pred P;
201
202 explicit Not(const Pred &P) : P(P) {}
203
204 template <typename MatchContext>
205 bool match(const MatchContext &Ctx, SDValue N) {
206 return !P.match(Ctx, N);
207 }
208};
209// Explicit deduction guide.
210template <typename Pred> Not(const Pred &P) -> Not<Pred>;
211
212/// Match if the inner pattern does NOT match.
213template <typename Pred> inline Not<Pred> m_Unless(const Pred &P) {
214 return Not{P};
215}
216
217template <typename... Preds> And<Preds...> m_AllOf(const Preds &...preds) {
218 return And<Preds...>(preds...);
219}
220
221template <typename... Preds> Or<Preds...> m_AnyOf(const Preds &...preds) {
222 return Or<Preds...>(preds...);
223}
224
225template <typename... Preds> auto m_NoneOf(const Preds &...preds) {
226 return m_Unless(m_AnyOf(preds...));
227}
228
229inline Opcode_match m_SpecificOpc(unsigned Opcode) {
230 return Opcode_match(Opcode);
231}
232
233inline auto m_Undef() {
235}
236
238
239template <unsigned NumUses, typename Pattern> struct NUses_match {
241
242 explicit NUses_match(const Pattern &P) : P(P) {}
243
244 template <typename MatchContext>
245 bool match(const MatchContext &Ctx, SDValue N) {
246 // SDNode::hasNUsesOfValue is pretty expensive when the SDNode produces
247 // multiple results, hence we check the subsequent pattern here before
248 // checking the number of value users.
249 return P.match(Ctx, N) && N->hasNUsesOfValue(NumUses, N.getResNo());
250 }
251};
252
253template <typename Pattern>
257template <unsigned N, typename Pattern>
261
265template <unsigned N> inline NUses_match<N, Value_match> m_NUses() {
267}
268
269template <typename PredPattern> struct Value_bind {
271 PredPattern Pred;
272
273 Value_bind(SDValue &N, const PredPattern &P) : BindVal(N), Pred(P) {}
274
275 template <typename MatchContext>
276 bool match(const MatchContext &Ctx, SDValue N) {
277 if (!Pred.match(Ctx, N))
278 return false;
279
280 BindVal = N;
281 return true;
282 }
283};
284
285inline auto m_Value(SDValue &N) {
287}
288/// Conditionally bind an SDValue based on the predicate.
289template <typename PredPattern>
290inline auto m_Value(SDValue &N, const PredPattern &P) {
291 return Value_bind<PredPattern>(N, P);
292}
293
294template <typename Pattern, typename PredFuncT> struct TLI_pred_match {
296 PredFuncT PredFunc;
297
298 TLI_pred_match(const PredFuncT &Pred, const Pattern &P)
299 : P(P), PredFunc(Pred) {}
300
301 template <typename MatchContext>
302 bool match(const MatchContext &Ctx, SDValue N) {
303 assert(Ctx.getTLI() && "TargetLowering is required for this pattern.");
304 return PredFunc(*Ctx.getTLI(), N) && P.match(Ctx, N);
305 }
306};
307
308// Explicit deduction guide.
309template <typename PredFuncT, typename Pattern>
310TLI_pred_match(const PredFuncT &Pred, const Pattern &P)
312
313/// Match legal SDNodes based on the information provided by TargetLowering.
314template <typename Pattern> inline auto m_LegalOp(const Pattern &P) {
315 return TLI_pred_match{[](const TargetLowering &TLI, SDValue N) {
316 return TLI.isOperationLegal(N->getOpcode(),
317 N.getValueType());
318 },
319 P};
320}
321
322/// Switch to a different MatchContext for subsequent patterns.
323template <typename NewMatchContext, typename Pattern> struct SwitchContext {
324 const NewMatchContext &Ctx;
326
327 template <typename OrigMatchContext>
328 bool match(const OrigMatchContext &, SDValue N) {
329 return P.match(Ctx, N);
330 }
331};
332
333template <typename MatchContext, typename Pattern>
334inline SwitchContext<MatchContext, Pattern> m_Context(const MatchContext &Ctx,
335 Pattern &&P) {
336 return SwitchContext<MatchContext, Pattern>{Ctx, std::move(P)};
337}
338
339// === Value type ===
340
341template <typename Pattern> struct ValueType_bind {
344
345 explicit ValueType_bind(EVT &Bind, const Pattern &P) : BindVT(Bind), P(P) {}
346
347 template <typename MatchContext>
348 bool match(const MatchContext &Ctx, SDValue N) {
349 BindVT = N.getValueType();
350 return P.match(Ctx, N);
351 }
352};
353
354template <typename Pattern>
356
357/// Retreive the ValueType of the current SDValue.
358inline auto m_VT(EVT &VT) { return ValueType_bind(VT, m_Value()); }
359
360template <typename Pattern> inline auto m_VT(EVT &VT, const Pattern &P) {
361 return ValueType_bind(VT, P);
362}
363
364template <typename Pattern, typename PredFuncT> struct ValueType_match {
365 PredFuncT PredFunc;
367
368 ValueType_match(const PredFuncT &Pred, const Pattern &P)
369 : PredFunc(Pred), P(P) {}
370
371 template <typename MatchContext>
372 bool match(const MatchContext &Ctx, SDValue N) {
373 return PredFunc(N.getValueType()) && P.match(Ctx, N);
374 }
375};
376
377// Explicit deduction guide.
378template <typename PredFuncT, typename Pattern>
379ValueType_match(const PredFuncT &Pred, const Pattern &P)
381
382/// Match a specific ValueType.
383template <typename Pattern>
384inline auto m_SpecificVT(EVT RefVT, const Pattern &P) {
385 return ValueType_match{[=](EVT VT) { return VT == RefVT; }, P};
386}
387inline auto m_SpecificVT(EVT RefVT) {
388 return ValueType_match{[=](EVT VT) { return VT == RefVT; }, m_Value()};
389}
390
391inline auto m_Glue() { return m_SpecificVT(MVT::Glue); }
392inline auto m_OtherVT() { return m_SpecificVT(MVT::Other); }
393
394/// Match a scalar ValueType.
395template <typename Pattern>
396inline auto m_SpecificScalarVT(EVT RefVT, const Pattern &P) {
397 return ValueType_match{[=](EVT VT) { return VT.getScalarType() == RefVT; },
398 P};
399}
400inline auto m_SpecificScalarVT(EVT RefVT) {
401 return ValueType_match{[=](EVT VT) { return VT.getScalarType() == RefVT; },
402 m_Value()};
403}
404
405/// Match a vector ValueType.
406template <typename Pattern>
407inline auto m_SpecificVectorElementVT(EVT RefVT, const Pattern &P) {
408 return ValueType_match{[=](EVT VT) {
409 return VT.isVector() &&
410 VT.getVectorElementType() == RefVT;
411 },
412 P};
413}
414inline auto m_SpecificVectorElementVT(EVT RefVT) {
415 return ValueType_match{[=](EVT VT) {
416 return VT.isVector() &&
417 VT.getVectorElementType() == RefVT;
418 },
419 m_Value()};
420}
421
422/// Match any integer ValueTypes.
423template <typename Pattern> inline auto m_IntegerVT(const Pattern &P) {
424 return ValueType_match{[](EVT VT) { return VT.isInteger(); }, P};
425}
426inline auto m_IntegerVT() {
427 return ValueType_match{[](EVT VT) { return VT.isInteger(); }, m_Value()};
428}
429
430/// Match any floating point ValueTypes.
431template <typename Pattern> inline auto m_FloatingPointVT(const Pattern &P) {
432 return ValueType_match{[](EVT VT) { return VT.isFloatingPoint(); }, P};
433}
434inline auto m_FloatingPointVT() {
435 return ValueType_match{[](EVT VT) { return VT.isFloatingPoint(); },
436 m_Value()};
437}
438
439/// Match any vector ValueTypes.
440template <typename Pattern> inline auto m_VectorVT(const Pattern &P) {
441 return ValueType_match{[](EVT VT) { return VT.isVector(); }, P};
442}
443inline auto m_VectorVT() {
444 return ValueType_match{[](EVT VT) { return VT.isVector(); }, m_Value()};
445}
446
447/// Match fixed-length vector ValueTypes.
448template <typename Pattern> inline auto m_FixedVectorVT(const Pattern &P) {
449 return ValueType_match{[](EVT VT) { return VT.isFixedLengthVector(); }, P};
450}
451inline auto m_FixedVectorVT() {
452 return ValueType_match{[](EVT VT) { return VT.isFixedLengthVector(); },
453 m_Value()};
454}
455
456/// Match scalable vector ValueTypes.
457template <typename Pattern> inline auto m_ScalableVectorVT(const Pattern &P) {
458 return ValueType_match{[](EVT VT) { return VT.isScalableVector(); }, P};
459}
460inline auto m_ScalableVectorVT() {
461 return ValueType_match{[](EVT VT) { return VT.isScalableVector(); },
462 m_Value()};
463}
464
465/// Match legal ValueTypes based on the information provided by TargetLowering.
466template <typename Pattern> inline auto m_LegalType(const Pattern &P) {
467 return TLI_pred_match{[](const TargetLowering &TLI, SDValue N) {
468 return TLI.isTypeLegal(N.getValueType());
469 },
470 P};
471}
472
473// === Generic node matching ===
474template <unsigned OpIdx, typename... OpndPreds> struct Operands_match {
475 template <typename MatchContext>
476 bool match(const MatchContext &Ctx, SDValue N) {
477 // Returns false if there are more operands than predicates;
478 // Ignores the last two operands if both the Context and the Node are VP
479 return Ctx.getNumOperands(N) == OpIdx;
480 }
481};
482
483template <unsigned OpIdx, typename OpndPred, typename... OpndPreds>
484struct Operands_match<OpIdx, OpndPred, OpndPreds...>
485 : Operands_match<OpIdx + 1, OpndPreds...> {
486 OpndPred P;
487
488 Operands_match(const OpndPred &p, const OpndPreds &...preds)
489 : Operands_match<OpIdx + 1, OpndPreds...>(preds...), P(p) {}
490
491 template <typename MatchContext>
492 bool match(const MatchContext &Ctx, SDValue N) {
493 if (OpIdx < N->getNumOperands())
494 return P.match(Ctx, N->getOperand(OpIdx)) &&
496
497 // This is the case where there are more predicates than operands.
498 return false;
499 }
500};
501
502template <typename... OpndPreds>
503auto m_Node(unsigned Opcode, const OpndPreds &...preds) {
504 return m_AllOf(m_SpecificOpc(Opcode),
506}
507
508/// Provide number of operands that are not chain or glue, as well as the first
509/// index of such operand.
510template <bool ExcludeChain> struct EffectiveOperands {
511 unsigned Size = 0;
512 unsigned FirstIndex = 0;
513
514 template <typename MatchContext>
515 explicit EffectiveOperands(SDValue N, const MatchContext &Ctx) {
516 const unsigned TotalNumOps = Ctx.getNumOperands(N);
517 FirstIndex = TotalNumOps;
518 for (unsigned I = 0; I < TotalNumOps; ++I) {
519 // Count the number of non-chain and non-glue nodes (we ignore chain
520 // and glue by default) and retreive the operand index offset.
521 EVT VT = N->getOperand(I).getValueType();
522 if (VT != MVT::Glue && VT != MVT::Other) {
523 ++Size;
524 if (FirstIndex == TotalNumOps)
525 FirstIndex = I;
526 }
527 }
528 }
529};
530
531template <> struct EffectiveOperands<false> {
532 unsigned Size = 0;
533 unsigned FirstIndex = 0;
534
535 template <typename MatchContext>
536 explicit EffectiveOperands(SDValue N, const MatchContext &Ctx)
537 : Size(Ctx.getNumOperands(N)) {}
538};
539
540// === Ternary operations ===
541template <typename T0_P, typename T1_P, typename T2_P, bool Commutable = false,
542 bool ExcludeChain = false>
544 unsigned Opcode;
545 T0_P Op0;
546 T1_P Op1;
547 T2_P Op2;
548
549 TernaryOpc_match(unsigned Opc, const T0_P &Op0, const T1_P &Op1,
550 const T2_P &Op2)
551 : Opcode(Opc), Op0(Op0), Op1(Op1), Op2(Op2) {}
552
553 template <typename MatchContext>
554 bool match(const MatchContext &Ctx, SDValue N) {
557 assert(EO.Size == 3);
558 return ((Op0.match(Ctx, N->getOperand(EO.FirstIndex)) &&
559 Op1.match(Ctx, N->getOperand(EO.FirstIndex + 1))) ||
560 (Commutable && Op0.match(Ctx, N->getOperand(EO.FirstIndex + 1)) &&
561 Op1.match(Ctx, N->getOperand(EO.FirstIndex)))) &&
562 Op2.match(Ctx, N->getOperand(EO.FirstIndex + 2));
563 }
564
565 return false;
566 }
567};
568
569template <typename T0_P, typename T1_P, typename T2_P>
570inline TernaryOpc_match<T0_P, T1_P, T2_P>
571m_SetCC(const T0_P &LHS, const T1_P &RHS, const T2_P &CC) {
573}
574
575template <typename T0_P, typename T1_P, typename T2_P>
576inline TernaryOpc_match<T0_P, T1_P, T2_P, true, false>
577m_c_SetCC(const T0_P &LHS, const T1_P &RHS, const T2_P &CC) {
579 CC);
580}
581
582template <typename T0_P, typename T1_P, typename T2_P>
583inline TernaryOpc_match<T0_P, T1_P, T2_P>
584m_Select(const T0_P &Cond, const T1_P &T, const T2_P &F) {
586}
587
588template <typename T0_P, typename T1_P, typename T2_P>
589inline TernaryOpc_match<T0_P, T1_P, T2_P>
590m_VSelect(const T0_P &Cond, const T1_P &T, const T2_P &F) {
592}
593
594template <typename T0_P, typename T1_P, typename T2_P>
595inline auto m_SelectLike(const T0_P &Cond, const T1_P &T, const T2_P &F) {
596 return m_AnyOf(m_Select(Cond, T, F), m_VSelect(Cond, T, F));
597}
598
599template <typename T0_P, typename T1_P, typename T2_P>
600inline Result_match<0, TernaryOpc_match<T0_P, T1_P, T2_P>>
601m_Load(const T0_P &Ch, const T1_P &Ptr, const T2_P &Offset) {
602 return m_Result<0>(
604}
605
606template <typename T0_P, typename T1_P, typename T2_P>
607inline TernaryOpc_match<T0_P, T1_P, T2_P>
608m_InsertElt(const T0_P &Vec, const T1_P &Val, const T2_P &Idx) {
610 Idx);
611}
612
613template <typename LHS, typename RHS, typename IDX>
614inline TernaryOpc_match<LHS, RHS, IDX>
615m_InsertSubvector(const LHS &Base, const RHS &Sub, const IDX &Idx) {
617}
618
619template <typename T0_P, typename T1_P, typename T2_P>
620inline TernaryOpc_match<T0_P, T1_P, T2_P>
621m_SpliceRight(const T0_P &V1, const T1_P &V2, const T2_P &Offset) {
623 Offset);
624}
625
626template <typename T0_P, typename T1_P, typename T2_P>
627inline TernaryOpc_match<T0_P, T1_P, T2_P>
628m_TernaryOp(unsigned Opc, const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
629 return TernaryOpc_match<T0_P, T1_P, T2_P>(Opc, Op0, Op1, Op2);
630}
631
632template <typename T0_P, typename T1_P, typename T2_P>
633inline TernaryOpc_match<T0_P, T1_P, T2_P, true>
634m_c_TernaryOp(unsigned Opc, const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
635 return TernaryOpc_match<T0_P, T1_P, T2_P, true>(Opc, Op0, Op1, Op2);
636}
637
638template <typename LTy, typename RTy, typename TTy, typename FTy, typename CCTy>
639inline auto m_SelectCC(const LTy &L, const RTy &R, const TTy &T, const FTy &F,
640 const CCTy &CC) {
641 return m_Node(ISD::SELECT_CC, L, R, T, F, CC);
642}
643
644template <typename LTy, typename RTy, typename TTy, typename FTy, typename CCTy>
645inline auto m_SelectCCLike(const LTy &L, const RTy &R, const TTy &T,
646 const FTy &F, const CCTy &CC) {
647 return m_AnyOf(m_Select(m_SetCC(L, R, CC), T, F), m_SelectCC(L, R, T, F, CC));
648}
649
650// === Binary operations ===
651template <typename LHS_P, typename RHS_P, bool Commutable = false,
652 bool ExcludeChain = false>
654 unsigned Opcode;
655 LHS_P LHS;
656 RHS_P RHS;
658 BinaryOpc_match(unsigned Opc, const LHS_P &L, const RHS_P &R,
659 SDNodeFlags Flgs = SDNodeFlags())
660 : Opcode(Opc), LHS(L), RHS(R), Flags(Flgs) {}
661
662 template <typename MatchContext>
663 bool match(const MatchContext &Ctx, SDValue N) {
666 assert(EO.Size == 2);
667 if (!((LHS.match(Ctx, N->getOperand(EO.FirstIndex)) &&
668 RHS.match(Ctx, N->getOperand(EO.FirstIndex + 1))) ||
669 (Commutable && LHS.match(Ctx, N->getOperand(EO.FirstIndex + 1)) &&
670 RHS.match(Ctx, N->getOperand(EO.FirstIndex)))))
671 return false;
672
673 return (Flags & N->getFlags()) == Flags;
674 }
675
676 return false;
677 }
678};
679
680/// Matching while capturing mask
681template <typename T0, typename T1, typename T2> struct SDShuffle_match {
682 T0 Op1;
685
686 SDShuffle_match(const T0 &Op1, const T1 &Op2, const T2 &Mask)
687 : Op1(Op1), Op2(Op2), Mask(Mask) {}
688
689 template <typename MatchContext>
690 bool match(const MatchContext &Ctx, SDValue N) {
691 if (auto *I = dyn_cast<ShuffleVectorSDNode>(N)) {
692 return Op1.match(Ctx, I->getOperand(0)) &&
693 Op2.match(Ctx, I->getOperand(1)) && Mask.match(I->getMask());
694 }
695 return false;
696 }
697};
698struct m_Mask {
701 bool match(ArrayRef<int> Mask) {
702 MaskRef = Mask;
703 return true;
704 }
705};
706
712
713template <typename LHS_P, typename RHS_P, typename Pred_t,
714 bool Commutable = false, bool ExcludeChain = false>
716 using PredType = Pred_t;
717 LHS_P LHS;
718 RHS_P RHS;
719
720 MaxMin_match(const LHS_P &L, const RHS_P &R) : LHS(L), RHS(R) {}
721
722 template <typename MatchContext>
723 bool match(const MatchContext &Ctx, SDValue N) {
724 auto MatchMinMax = [&](SDValue L, SDValue R, SDValue TrueValue,
725 SDValue FalseValue, ISD::CondCode CC) {
726 if ((TrueValue != L || FalseValue != R) &&
727 (TrueValue != R || FalseValue != L))
728 return false;
729
731 TrueValue == L ? CC : getSetCCInverse(CC, L.getValueType());
732 if (!Pred_t::match(Cond))
733 return false;
734
735 return (LHS.match(Ctx, L) && RHS.match(Ctx, R)) ||
736 (Commutable && LHS.match(Ctx, R) && RHS.match(Ctx, L));
737 };
738
741 EffectiveOperands<ExcludeChain> EO_SELECT(N, Ctx);
742 assert(EO_SELECT.Size == 3);
743 SDValue Cond = N->getOperand(EO_SELECT.FirstIndex);
744 SDValue TrueValue = N->getOperand(EO_SELECT.FirstIndex + 1);
745 SDValue FalseValue = N->getOperand(EO_SELECT.FirstIndex + 2);
746
749 assert(EO_SETCC.Size == 3);
750 SDValue L = Cond->getOperand(EO_SETCC.FirstIndex);
751 SDValue R = Cond->getOperand(EO_SETCC.FirstIndex + 1);
752 auto *CondNode =
753 cast<CondCodeSDNode>(Cond->getOperand(EO_SETCC.FirstIndex + 2));
754 return MatchMinMax(L, R, TrueValue, FalseValue, CondNode->get());
755 }
756 }
757
759 EffectiveOperands<ExcludeChain> EO_SELECT(N, Ctx);
760 assert(EO_SELECT.Size == 5);
761 SDValue L = N->getOperand(EO_SELECT.FirstIndex);
762 SDValue R = N->getOperand(EO_SELECT.FirstIndex + 1);
763 SDValue TrueValue = N->getOperand(EO_SELECT.FirstIndex + 2);
764 SDValue FalseValue = N->getOperand(EO_SELECT.FirstIndex + 3);
765 auto *CondNode =
766 cast<CondCodeSDNode>(N->getOperand(EO_SELECT.FirstIndex + 4));
767 return MatchMinMax(L, R, TrueValue, FalseValue, CondNode->get());
768 }
769
770 return false;
771 }
772};
773
774// Helper class for identifying signed max predicates.
776 static bool match(ISD::CondCode Cond) {
778 }
779};
780
781// Helper class for identifying unsigned max predicates.
786};
787
788// Helper class for identifying signed min predicates.
790 static bool match(ISD::CondCode Cond) {
792 }
793};
794
795// Helper class for identifying unsigned min predicates.
800};
801
802template <typename LHS, typename RHS>
803inline BinaryOpc_match<LHS, RHS> m_BinOp(unsigned Opc, const LHS &L,
804 const RHS &R,
805 SDNodeFlags Flgs = SDNodeFlags()) {
806 return BinaryOpc_match<LHS, RHS>(Opc, L, R, Flgs);
807}
808template <typename LHS, typename RHS>
810m_c_BinOp(unsigned Opc, const LHS &L, const RHS &R,
811 SDNodeFlags Flgs = SDNodeFlags()) {
812 return BinaryOpc_match<LHS, RHS, true>(Opc, L, R, Flgs);
813}
814
815template <typename LHS, typename RHS>
817m_ChainedBinOp(unsigned Opc, const LHS &L, const RHS &R) {
819}
820template <typename LHS, typename RHS>
822m_c_ChainedBinOp(unsigned Opc, const LHS &L, const RHS &R) {
824}
825
826// Common binary operations
827template <typename LHS, typename RHS>
828inline BinaryOpc_match<LHS, RHS, true> m_Add(const LHS &L, const RHS &R) {
830}
831
832template <typename LHS, typename RHS>
833inline auto m_NUWAdd(const LHS &L, const RHS &R) {
836}
837
838template <typename LHS, typename RHS>
839inline auto m_NSWAdd(const LHS &L, const RHS &R) {
842}
843
844template <typename LHS, typename RHS>
845inline BinaryOpc_match<LHS, RHS> m_Sub(const LHS &L, const RHS &R) {
847}
848
849template <typename LHS, typename RHS>
850inline BinaryOpc_match<LHS, RHS, true> m_Mul(const LHS &L, const RHS &R) {
852}
853
854template <typename LHS, typename RHS>
855inline BinaryOpc_match<LHS, RHS, true> m_And(const LHS &L, const RHS &R) {
857}
858
859template <typename LHS, typename RHS>
860inline BinaryOpc_match<LHS, RHS, true> m_Or(const LHS &L, const RHS &R) {
862}
863
864template <typename LHS, typename RHS>
869
870template <typename LHS, typename RHS>
871inline auto m_AddLike(const LHS &L, const RHS &R) {
872 return m_AnyOf(m_Add(L, R), m_DisjointOr(L, R));
873}
874
875template <typename LHS, typename RHS>
876inline auto m_NSWAddLike(const LHS &L, const RHS &R) {
877 return m_AnyOf(m_NSWAdd(L, R), m_DisjointOr(L, R));
878}
879
880template <typename LHS, typename RHS>
881inline auto m_NUWAddLike(const LHS &L, const RHS &R) {
882 return m_AnyOf(m_NUWAdd(L, R), m_DisjointOr(L, R));
883}
884
885template <typename LHS, typename RHS>
886inline BinaryOpc_match<LHS, RHS, true> m_Xor(const LHS &L, const RHS &R) {
888}
889
890template <typename LHS, typename RHS>
891inline auto m_BitwiseLogic(const LHS &L, const RHS &R) {
892 return m_AnyOf(m_And(L, R), m_Or(L, R), m_Xor(L, R));
893}
894
895template <unsigned Opc, typename Pred, typename LHS, typename RHS>
896inline auto m_MaxMinLike(const LHS &L, const RHS &R) {
899}
900
901template <typename LHS, typename RHS>
902inline BinaryOpc_match<LHS, RHS, true> m_SMin(const LHS &L, const RHS &R) {
904}
905
906template <typename LHS, typename RHS>
913
914template <typename LHS, typename RHS>
915inline BinaryOpc_match<LHS, RHS, true> m_SMax(const LHS &L, const RHS &R) {
917}
918
919template <typename LHS, typename RHS>
926
927template <typename LHS, typename RHS>
928inline BinaryOpc_match<LHS, RHS, true> m_UMin(const LHS &L, const RHS &R) {
930}
931
932template <typename LHS, typename RHS>
939
940template <typename LHS, typename RHS>
941inline BinaryOpc_match<LHS, RHS, true> m_UMax(const LHS &L, const RHS &R) {
943}
944
945template <typename LHS, typename RHS>
952
953template <typename LHS, typename RHS>
954inline BinaryOpc_match<LHS, RHS> m_UDiv(const LHS &L, const RHS &R) {
956}
957template <typename LHS, typename RHS>
958inline BinaryOpc_match<LHS, RHS> m_SDiv(const LHS &L, const RHS &R) {
960}
961
962template <typename LHS, typename RHS>
963inline BinaryOpc_match<LHS, RHS> m_URem(const LHS &L, const RHS &R) {
965}
966template <typename LHS, typename RHS>
967inline BinaryOpc_match<LHS, RHS> m_SRem(const LHS &L, const RHS &R) {
969}
970
971template <typename LHS, typename RHS>
972inline BinaryOpc_match<LHS, RHS> m_Shl(const LHS &L, const RHS &R) {
974}
975
976template <typename LHS, typename RHS>
977inline BinaryOpc_match<LHS, RHS> m_Sra(const LHS &L, const RHS &R) {
979}
980template <typename LHS, typename RHS>
981inline BinaryOpc_match<LHS, RHS> m_Srl(const LHS &L, const RHS &R) {
983}
984template <typename LHS, typename RHS>
989
990template <typename LHS, typename RHS>
991inline BinaryOpc_match<LHS, RHS> m_Rotl(const LHS &L, const RHS &R) {
993}
994
995template <typename LHS, typename RHS>
996inline BinaryOpc_match<LHS, RHS> m_Rotr(const LHS &L, const RHS &R) {
998}
999
1000template <typename T0_P, typename T1_P, typename T2_P>
1001inline TernaryOpc_match<T0_P, T1_P, T2_P>
1002m_FShL(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
1003 return m_TernaryOp(ISD::FSHL, Op0, Op1, Op2);
1004}
1005
1006template <typename T0_P, typename T1_P, typename T2_P>
1007inline TernaryOpc_match<T0_P, T1_P, T2_P>
1008m_FShR(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
1009 return m_TernaryOp(ISD::FSHR, Op0, Op1, Op2);
1010}
1011
1012template <typename T0_P, typename T1_P, typename T2_P, bool Left>
1014 T0_P Op0;
1015 T1_P Op1;
1016 T2_P Op2;
1017
1018 FunnelShiftLike_match(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2)
1019 : Op0(Op0), Op1(Op1), Op2(Op2) {}
1020
1021 static bool hasComplementaryConstantShifts(const APInt &ShlV,
1022 const APInt &SrlV,
1023 unsigned BitWidth) {
1024 unsigned SumWidth = std::max(ShlV.getBitWidth(), SrlV.getBitWidth()) + 1;
1025 unsigned BitWidthBits = llvm::bit_width(BitWidth);
1026 if (BitWidthBits > SumWidth)
1027 return false;
1028
1029 return ShlV.zext(SumWidth) + SrlV.zext(SumWidth) ==
1030 APInt(SumWidth, BitWidth);
1031 }
1032
1033 template <typename MatchContext>
1034 bool matchOperands(const MatchContext &Ctx, SDValue X, SDValue Y, SDValue Z) {
1035 return Op0.match(Ctx, X) && Op1.match(Ctx, Y) && Op2.match(Ctx, Z);
1036 }
1037
1038 template <typename MatchContext>
1039 bool matchShiftOr(const MatchContext &Ctx, SDValue N, unsigned BitWidth);
1040
1041 template <typename MatchContext>
1042 bool match(const MatchContext &Ctx, SDValue N) {
1043 if (sd_context_match(N, Ctx,
1044 Left ? m_FShL(Op0, Op1, Op2) : m_FShR(Op0, Op1, Op2)))
1045 return true;
1046
1047 SDValue X, Z;
1048 if (sd_context_match(N, Ctx,
1049 Left ? m_Rotl(m_Value(X), m_Value(Z))
1050 : m_Rotr(m_Value(X), m_Value(Z))))
1051 return matchOperands(Ctx, X, X, Z);
1052
1053 return matchShiftOr(Ctx, N, N.getValueType().getScalarSizeInBits());
1054 }
1055};
1056
1057template <typename T0_P, typename T1_P, typename T2_P>
1058inline FunnelShiftLike_match<T0_P, T1_P, T2_P, true>
1059m_FShLLike(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
1061}
1062
1063template <typename T0_P, typename T1_P, typename T2_P>
1064inline FunnelShiftLike_match<T0_P, T1_P, T2_P, false>
1065m_FShRLike(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
1067}
1068
1069template <typename LHS, typename RHS>
1072}
1073
1074template <typename LHS, typename RHS>
1075inline BinaryOpc_match<LHS, RHS, true> m_FAdd(const LHS &L, const RHS &R) {
1077}
1078
1079template <typename LHS, typename RHS>
1080inline BinaryOpc_match<LHS, RHS> m_FSub(const LHS &L, const RHS &R) {
1082}
1083
1084template <typename LHS, typename RHS>
1085inline BinaryOpc_match<LHS, RHS, true> m_FMul(const LHS &L, const RHS &R) {
1087}
1088
1089template <typename LHS, typename RHS>
1090inline BinaryOpc_match<LHS, RHS> m_FDiv(const LHS &L, const RHS &R) {
1092}
1093
1094template <typename LHS, typename RHS>
1095inline BinaryOpc_match<LHS, RHS> m_FRem(const LHS &L, const RHS &R) {
1097}
1098
1099template <typename V1_t, typename V2_t>
1100inline BinaryOpc_match<V1_t, V2_t> m_Shuffle(const V1_t &v1, const V2_t &v2) {
1102}
1103
1104template <typename V1_t, typename V2_t, typename Mask_t>
1105inline SDShuffle_match<V1_t, V2_t, Mask_t>
1106m_Shuffle(const V1_t &v1, const V2_t &v2, const Mask_t &mask) {
1108}
1109
1110template <typename LHS, typename RHS>
1111inline BinaryOpc_match<LHS, RHS> m_ExtractElt(const LHS &Vec, const RHS &Idx) {
1113}
1114
1115template <typename LHS, typename RHS>
1117 const RHS &Idx) {
1119}
1120
1121// === Unary operations ===
1122template <typename Opnd_P, bool ExcludeChain = false> struct UnaryOpc_match {
1123 unsigned Opcode;
1124 Opnd_P Opnd;
1126 UnaryOpc_match(unsigned Opc, const Opnd_P &Op,
1127 SDNodeFlags Flgs = SDNodeFlags())
1128 : Opcode(Opc), Opnd(Op), Flags(Flgs) {}
1129
1130 template <typename MatchContext>
1131 bool match(const MatchContext &Ctx, SDValue N) {
1132 if (sd_context_match(N, Ctx, m_SpecificOpc(Opcode))) {
1134 assert(EO.Size == 1);
1135 if (!Opnd.match(Ctx, N->getOperand(EO.FirstIndex)))
1136 return false;
1137
1138 return (Flags & N->getFlags()) == Flags;
1139 }
1140
1141 return false;
1142 }
1143};
1144
1145template <typename Opnd>
1146inline UnaryOpc_match<Opnd> m_UnaryOp(unsigned Opc, const Opnd &Op) {
1147 return UnaryOpc_match<Opnd>(Opc, Op);
1148}
1149template <typename Opnd>
1151 const Opnd &Op) {
1153}
1154
1155template <typename Opnd> inline UnaryOpc_match<Opnd> m_BitCast(const Opnd &Op) {
1157}
1158
1159template <typename Opnd>
1160inline UnaryOpc_match<Opnd> m_BSwap(const Opnd &Op) {
1162}
1163
1164template <typename Opnd>
1168
1169template <typename Opnd> inline UnaryOpc_match<Opnd> m_ZExt(const Opnd &Op) {
1171}
1172
1173template <typename Opnd>
1177
1178template <typename Opnd> inline auto m_SExt(const Opnd &Op) {
1180}
1181
1182template <typename Opnd> inline UnaryOpc_match<Opnd> m_AnyExt(const Opnd &Op) {
1184}
1185
1186template <typename Opnd> inline UnaryOpc_match<Opnd> m_Trunc(const Opnd &Op) {
1188}
1189
1190template <typename Opnd> inline auto m_Abs(const Opnd &Op) {
1193}
1194
1195template <typename Opnd> inline UnaryOpc_match<Opnd> m_FAbs(const Opnd &Op) {
1197}
1198
1199/// Match a zext or identity
1200/// Allows to peek through optional extensions
1201template <typename Opnd> inline auto m_ZExtOrSelf(const Opnd &Op) {
1202 return m_AnyOf(m_ZExt(Op), Op);
1203}
1204
1205/// Match a sext or identity
1206/// Allows to peek through optional extensions
1207template <typename Opnd> inline auto m_SExtOrSelf(const Opnd &Op) {
1208 return m_AnyOf(m_SExt(Op), Op);
1209}
1210
1211template <typename Opnd> inline auto m_SExtLike(const Opnd &Op) {
1212 return m_AnyOf(m_SExt(Op), m_NNegZExt(Op));
1213}
1214
1215/// Match a aext or identity
1216/// Allows to peek through optional extensions
1217template <typename Opnd>
1218inline Or<UnaryOpc_match<Opnd>, Opnd> m_AExtOrSelf(const Opnd &Op) {
1219 return Or<UnaryOpc_match<Opnd>, Opnd>(m_AnyExt(Op), Op);
1220}
1221
1222/// Match a trunc or identity
1223/// Allows to peek through optional truncations
1224template <typename Opnd>
1225inline Or<UnaryOpc_match<Opnd>, Opnd> m_TruncOrSelf(const Opnd &Op) {
1226 return Or<UnaryOpc_match<Opnd>, Opnd>(m_Trunc(Op), Op);
1227}
1228
1229template <typename Opnd> inline UnaryOpc_match<Opnd> m_VScale(const Opnd &Op) {
1231}
1232
1233template <typename Opnd> inline UnaryOpc_match<Opnd> m_FPToUI(const Opnd &Op) {
1235}
1236
1237template <typename Opnd> inline UnaryOpc_match<Opnd> m_FPToSI(const Opnd &Op) {
1239}
1240
1241template <typename Opnd> inline UnaryOpc_match<Opnd> m_Ctpop(const Opnd &Op) {
1243}
1244
1245template <typename Opnd> inline UnaryOpc_match<Opnd> m_Ctlz(const Opnd &Op) {
1247}
1248
1249template <typename Opnd> inline UnaryOpc_match<Opnd> m_Cttz(const Opnd &Op) {
1251}
1252
1253template <typename Opnd> inline UnaryOpc_match<Opnd> m_FNeg(const Opnd &Op) {
1255}
1256
1257template <typename Opnd>
1261
1262// === Constants ===
1265
1266 explicit ConstantInt_match(APInt *V) : BindVal(V) {}
1267
1268 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
1269 // The logics here are similar to that in
1270 // SelectionDAG::isConstantIntBuildVectorOrConstantInt, but the latter also
1271 // treats GlobalAddressSDNode as a constant, which is difficult to turn into
1272 // APInt.
1273 if (auto *C = dyn_cast_or_null<ConstantSDNode>(N.getNode())) {
1274 if (BindVal)
1275 *BindVal = C->getAPIntValue();
1276 return true;
1277 }
1278
1279 APInt Discard;
1280 return ISD::isConstantSplatVector(N.getNode(),
1281 BindVal ? *BindVal : Discard);
1282 }
1283};
1284
1285template <typename T> struct Constant64_match {
1286 static_assert(sizeof(T) == 8, "T must be 64 bits wide");
1287
1289
1290 explicit Constant64_match(T &V) : BindVal(V) {}
1291
1292 template <typename MatchContext>
1293 bool match(const MatchContext &Ctx, SDValue N) {
1294 APInt V;
1295 if (!ConstantInt_match(&V).match(Ctx, N))
1296 return false;
1297
1298 if constexpr (std::is_signed_v<T>) {
1299 if (std::optional<int64_t> TrySExt = V.trySExtValue()) {
1300 BindVal = *TrySExt;
1301 return true;
1302 }
1303 }
1304
1305 if constexpr (std::is_unsigned_v<T>) {
1306 if (std::optional<uint64_t> TryZExt = V.tryZExtValue()) {
1307 BindVal = *TryZExt;
1308 return true;
1309 }
1310 }
1311
1312 return false;
1313 }
1314};
1315
1316/// Match any integer constants or splat of an integer constant.
1318/// Match any integer constants or splat of an integer constant; return the
1319/// specific constant or constant splat value.
1321/// Match any integer constants or splat of an integer constant that can fit in
1322/// 64 bits; return the specific constant or constant splat value, zero-extended
1323/// to 64 bits.
1327/// Match any integer constants or splat of an integer constant that can fit in
1328/// 64 bits; return the specific constant or constant splat value, sign-extended
1329/// to 64 bits.
1331 return Constant64_match<int64_t>(V);
1332}
1333
1334template <typename T0_P, typename T1_P, typename T2_P, bool Left>
1335template <typename MatchContext>
1337 const MatchContext &Ctx, SDValue N, unsigned BitWidth) {
1338 SDValue X, Y, ShlAmt, SrlAmt;
1339 APInt ShlConst, SrlConst;
1340 if (!sd_context_match(
1341 N, Ctx,
1342 m_Or(m_Shl(m_Value(X), m_Value(ShlAmt, m_ConstInt(ShlConst))),
1343 m_Srl(m_Value(Y), m_Value(SrlAmt, m_ConstInt(SrlConst))))) ||
1344 !hasComplementaryConstantShifts(ShlConst, SrlConst, BitWidth))
1345 return false;
1346
1347 return matchOperands(Ctx, X, Y, Left ? ShlAmt : SrlAmt);
1348}
1349
1352
1353 explicit SpecificInt_match(APInt APV) : IntVal(std::move(APV)) {}
1354
1355 template <typename MatchContext>
1356 bool match(const MatchContext &Ctx, SDValue N) {
1357 APInt ConstInt;
1358 if (sd_context_match(N, Ctx, m_ConstInt(ConstInt)))
1359 return APInt::isSameValue(IntVal, ConstInt);
1360 return false;
1361 }
1362};
1363
1364/// Match a specific integer constant or constant splat value.
1366 return SpecificInt_match(std::move(V));
1367}
1369 return SpecificInt_match(APInt(64, V));
1370}
1371
1374
1375 explicit SpecificFP_match(APFloat V) : Val(V) {}
1376
1377 template <typename MatchContext>
1378 bool match(const MatchContext &Ctx, SDValue V) {
1379 if (const auto *CFP = dyn_cast<ConstantFPSDNode>(V.getNode()))
1380 return CFP->isExactlyValue(Val);
1381 if (ConstantFPSDNode *C = isConstOrConstSplatFP(V, /*AllowUndefs=*/true))
1382 return C->getValueAPF().compare(Val) == APFloat::cmpEqual;
1383 return false;
1384 }
1385};
1386
1387/// Match a specific float constant.
1389
1391 return SpecificFP_match(APFloat(V));
1392}
1393
1395 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
1397 return C->isZero();
1398 return false;
1399 }
1400};
1401
1402/// Match a floating-point +0.0 or -0.0 constant or splat.
1404
1406 template <typename MatchContext>
1407 bool match(const MatchContext &Ctx, SDValue N) {
1408 const SelectionDAG *DAG = Ctx.getDAG();
1409 return DAG && DAG->computeKnownBits(N).isNegative();
1410 }
1411};
1412
1414 template <typename MatchContext>
1415 bool match(const MatchContext &Ctx, SDValue N) {
1416 const SelectionDAG *DAG = Ctx.getDAG();
1417 return DAG && DAG->computeKnownBits(N).isNonNegative();
1418 }
1419};
1420
1422 template <typename MatchContext>
1423 bool match(const MatchContext &Ctx, SDValue N) {
1424 const SelectionDAG *DAG = Ctx.getDAG();
1425 return DAG && DAG->computeKnownBits(N).isStrictlyPositive();
1426 }
1427};
1428
1430 template <typename MatchContext>
1431 bool match(const MatchContext &Ctx, SDValue N) {
1432 const SelectionDAG *DAG = Ctx.getDAG();
1433 return DAG && DAG->computeKnownBits(N).isNonPositive();
1434 }
1435};
1436
1438 template <typename MatchContext>
1439 bool match(const MatchContext &Ctx, SDValue N) {
1440 const SelectionDAG *DAG = Ctx.getDAG();
1441 return DAG && DAG->computeKnownBits(N).isNonZero();
1442 }
1443};
1444
1447
1449
1450 template <typename MatchContext>
1451 bool match(const MatchContext &, SDValue N) const {
1453 }
1454};
1455
1458
1460
1461 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
1463 }
1464};
1465
1468
1470
1471 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
1473 }
1474};
1475
1477template <typename Pattern> inline auto m_Negative(const Pattern &P) {
1478 return m_AllOf(m_Negative(), P);
1479}
1481template <typename Pattern> inline auto m_NonNegative(const Pattern &P) {
1482 return m_AllOf(m_NonNegative(), P);
1483}
1487template <typename Pattern> inline auto m_StrictlyPositive(const Pattern &P) {
1488 return m_AllOf(m_StrictlyPositive(), P);
1489}
1491template <typename Pattern> inline auto m_NonPositive(const Pattern &P) {
1492 return m_AllOf(m_NonPositive(), P);
1493}
1495template <typename Pattern> inline auto m_NonZero(const Pattern &P) {
1496 return m_AllOf(m_NonZero(), P);
1497}
1498inline Ones_match m_One(bool AllowUndefs = false) {
1499 return Ones_match(AllowUndefs);
1500}
1501inline Zero_match m_Zero(bool AllowUndefs = false) {
1502 return Zero_match(AllowUndefs);
1503}
1504inline AllOnes_match m_AllOnes(bool AllowUndefs = false) {
1505 return AllOnes_match(AllowUndefs);
1506}
1507
1508/// Match true boolean value based on the information provided by
1509/// TargetLowering.
1510inline auto m_True() {
1511 return TLI_pred_match{
1512 [](const TargetLowering &TLI, SDValue N) {
1513 APInt ConstVal;
1514 if (sd_match(N, m_ConstInt(ConstVal)))
1515 switch (TLI.getBooleanContents(N.getValueType())) {
1517 return ConstVal.isOne();
1519 return ConstVal.isAllOnes();
1521 return (ConstVal & 0x01) == 1;
1522 }
1523
1524 return false;
1525 },
1526 m_Value()};
1527}
1528/// Match false boolean value based on the information provided by
1529/// TargetLowering.
1530inline auto m_False() {
1531 return TLI_pred_match{
1532 [](const TargetLowering &TLI, SDValue N) {
1533 APInt ConstVal;
1534 if (sd_match(N, m_ConstInt(ConstVal)))
1535 switch (TLI.getBooleanContents(N.getValueType())) {
1538 return ConstVal.isZero();
1540 return (ConstVal & 0x01) == 0;
1541 }
1542
1543 return false;
1544 },
1545 m_Value()};
1546}
1547
1549 std::optional<ISD::CondCode> CCToMatch;
1551
1553
1554 explicit CondCode_match(ISD::CondCode *CC) : BindCC(CC) {}
1555
1556 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
1557 if (auto *CC = dyn_cast<CondCodeSDNode>(N.getNode())) {
1558 if (CCToMatch && *CCToMatch != CC->get())
1559 return false;
1560
1561 if (BindCC)
1562 *BindCC = CC->get();
1563 return true;
1564 }
1565
1566 return false;
1567 }
1568};
1569
1570/// Match any conditional code SDNode.
1571inline CondCode_match m_CondCode() { return CondCode_match(nullptr); }
1572/// Match any conditional code SDNode and return its ISD::CondCode value.
1574 return CondCode_match(&CC);
1575}
1576/// Match a conditional code SDNode with a specific ISD::CondCode.
1580
1581/// Match a negate as a sub(0, v)
1582template <typename ValTy>
1584 return m_Sub(m_Zero(), V);
1585}
1586
1587/// Match a Not as a xor(v, -1) or xor(-1, v)
1588template <typename ValTy>
1590 return m_Xor(V, m_AllOnes());
1591}
1592
1593template <unsigned IntrinsicId, typename... OpndPreds>
1594inline auto m_IntrinsicWOChain(const OpndPreds &...Opnds) {
1595 return m_Node(ISD::INTRINSIC_WO_CHAIN, m_SpecificInt(IntrinsicId), Opnds...);
1596}
1597
1600
1602
1603 template <typename MatchContext>
1604 bool match(const MatchContext &Ctx, SDValue N) {
1605 if (sd_context_match(N, Ctx, m_Neg(m_Specific(V))))
1606 return true;
1607
1610 return LHS->getAPIntValue() == -RHS->getAPIntValue();
1611 });
1612 }
1613};
1614
1615/// Match a negation of a specific value V, either as sub(0, V) or as
1616/// constant(s) that are the negation of V's constant(s).
1620
1621template <typename... PatternTs> struct ReassociatableOpc_match {
1622 unsigned Opcode;
1623 std::tuple<PatternTs...> Patterns;
1624 constexpr static size_t NumPatterns =
1625 std::tuple_size_v<std::tuple<PatternTs...>>;
1626
1628
1629 ReassociatableOpc_match(unsigned Opcode, const PatternTs &...Patterns)
1630 : Opcode(Opcode), Patterns(Patterns...) {}
1631
1633 const PatternTs &...Patterns)
1635
1636 template <typename MatchContext>
1637 bool match(const MatchContext &Ctx, SDValue N) {
1638 std::array<SDValue, NumPatterns> Leaves;
1639 size_t LeavesIdx = 0;
1640 if (!(collectLeaves(N, Leaves, LeavesIdx) && (LeavesIdx == NumPatterns)))
1641 return false;
1642
1644 return std::apply(
1645 [&](auto &...P) -> bool {
1646 return reassociatableMatchHelper(Ctx, Leaves, Used, P...);
1647 },
1648 Patterns);
1649 }
1650
1651 bool collectLeaves(SDValue V, std::array<SDValue, NumPatterns> &Leaves,
1652 std::size_t &LeafIdx) {
1653 if (V->getOpcode() == Opcode && (Flags & V->getFlags()) == Flags) {
1654 for (size_t I = 0, N = V->getNumOperands(); I < N; I++)
1655 if ((LeafIdx == NumPatterns) ||
1656 !collectLeaves(V->getOperand(I), Leaves, LeafIdx))
1657 return false;
1658 } else {
1659 Leaves[LeafIdx] = V;
1660 LeafIdx++;
1661 }
1662 return true;
1663 }
1664
1665 // Searchs for a matching leaf for every sub-pattern.
1666 template <typename MatchContext, typename PatternHd, typename... PatternTl>
1667 [[nodiscard]] inline bool
1668 reassociatableMatchHelper(const MatchContext &Ctx, ArrayRef<SDValue> Leaves,
1669 Bitset<NumPatterns> &Used, PatternHd &HeadPattern,
1670 PatternTl &...TailPatterns) {
1671 for (size_t Match = 0, N = Used.size(); Match < N; Match++) {
1672 if (Used[Match] || !(sd_context_match(Leaves[Match], Ctx, HeadPattern)))
1673 continue;
1674 Used.set(Match);
1675 if (reassociatableMatchHelper(Ctx, Leaves, Used, TailPatterns...))
1676 return true;
1677 Used.reset(Match);
1678 }
1679 return false;
1680 }
1681
1682 template <typename MatchContext>
1683 [[nodiscard]] inline bool
1684 reassociatableMatchHelper(const MatchContext &Ctx, ArrayRef<SDValue> Leaves,
1685 Bitset<NumPatterns> &Used) {
1686 return true;
1687 }
1688};
1689
1690template <typename... PatternTs>
1691inline ReassociatableOpc_match<PatternTs...>
1692m_ReassociatableAdd(const PatternTs &...Patterns) {
1693 return ReassociatableOpc_match<PatternTs...>(ISD::ADD, Patterns...);
1694}
1695
1696template <typename... PatternTs>
1697inline ReassociatableOpc_match<PatternTs...>
1698m_ReassociatableOr(const PatternTs &...Patterns) {
1699 return ReassociatableOpc_match<PatternTs...>(ISD::OR, Patterns...);
1700}
1701
1702template <typename... PatternTs>
1703inline ReassociatableOpc_match<PatternTs...>
1704m_ReassociatableAnd(const PatternTs &...Patterns) {
1705 return ReassociatableOpc_match<PatternTs...>(ISD::AND, Patterns...);
1706}
1707
1708template <typename... PatternTs>
1709inline ReassociatableOpc_match<PatternTs...>
1710m_ReassociatableMul(const PatternTs &...Patterns) {
1711 return ReassociatableOpc_match<PatternTs...>(ISD::MUL, Patterns...);
1712}
1713
1714template <typename... PatternTs>
1715inline ReassociatableOpc_match<PatternTs...>
1716m_ReassociatableNSWAdd(const PatternTs &...Patterns) {
1717 return ReassociatableOpc_match<PatternTs...>(
1718 ISD::ADD, SDNodeFlags::NoSignedWrap, Patterns...);
1719}
1720
1721template <typename... PatternTs>
1722inline ReassociatableOpc_match<PatternTs...>
1723m_ReassociatableNUWAdd(const PatternTs &...Patterns) {
1724 return ReassociatableOpc_match<PatternTs...>(
1726}
1727
1728} // namespace SDPatternMatch
1729} // namespace llvm
1730#endif
return SDValue()
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned uint64_t
This file implements a class to represent arbitrary precision integral constant values and operations...
#define X(NUM, ENUM, NAME)
Definition ELF.h:856
static constexpr unsigned long long mask(BlockVerifier::State S)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define T
#define T1
#define P(N)
const SmallVectorImpl< MachineOperand > & Cond
This file contains some templates that are useful if you are working with the STL at all.
This file implements the SmallBitVector class.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
This file describes how to lower LLVM code to machine code.
Value * RHS
Value * LHS
This file implements the C++20 <bit> header.
Class for arbitrary precision integers.
Definition APInt.h:78
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
Definition APInt.cpp:1056
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
Definition APInt.h:368
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
Definition APInt.h:377
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition APInt.h:1509
static bool isSameValue(const APInt &I1, const APInt &I2, bool SignedCompare=false)
Determine if two APInts have the same value, after zero-extending or sign-extending (if SignedCompare...
Definition APInt.h:551
bool isOne() const
Determine if this is a value of 1.
Definition APInt.h:386
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...
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
Definition ISDOpcodes.h:829
@ 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:602
@ BSWAP
Byte Swap and Counting operators.
Definition ISDOpcodes.h:789
@ 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:863
@ 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:749
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ CLMUL
Carry-less multiplication operations.
Definition ISDOpcodes.h:780
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:854
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
Definition ISDOpcodes.h:806
@ UNDEF
UNDEF - An undefined node.
Definition ISDOpcodes.h:233
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:771
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
Definition ISDOpcodes.h:651
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
Definition ISDOpcodes.h:616
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
Definition ISDOpcodes.h:578
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition ISDOpcodes.h:860
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
Definition ISDOpcodes.h:821
@ 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:729
@ VECTOR_REVERSE
VECTOR_REVERSE(VECTOR) - Returns a vector, of the same type as VECTOR, whose elements are shuffled us...
Definition ISDOpcodes.h:642
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
Definition ISDOpcodes.h:815
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition ISDOpcodes.h:936
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:741
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
Definition ISDOpcodes.h:205
@ VECTOR_SPLICE_RIGHT
VECTOR_SPLICE_RIGHT(VEC1, VEC2, OFFSET) - Shifts CONCAT_VECTORS(VEC1,VEC2) right by OFFSET elements a...
Definition ISDOpcodes.h:659
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
Definition ISDOpcodes.h:567
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition ISDOpcodes.h:866
@ ABS_MIN_POISON
ABS with a poison result for INT_MIN.
Definition ISDOpcodes.h:753
LLVM_ABI bool matchBinaryPredicate(SDValue LHS, SDValue RHS, const APInt &DemandedElts, std::function< bool(ConstantSDNode *, ConstantSDNode *)> Match, bool AllowUndefs=false, bool AllowTypeMismatch=false)
Attempt to match a binary predicate against a pair of scalar/splat constants or every element of a pa...
LLVM_ABI bool isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
AllOnesConstantMatch m_AllOnes()
cst_pred_ty< is_one > m_One()
Match an integer 1 or a vector with all elements equal to 1.
auto m_BinOp()
Match an arbitrary binary operation and ignore it.
auto m_VScale()
Matches a call to llvm.vscale().
is_zero m_Zero()
Match any null constant or a vector with all elements equal to 0.
BinaryOpc_match< Zero_match, ValTy, false > m_Neg(const ValTy &V)
Match a negate as a sub(0, v)
Result_match< 0, TernaryOpc_match< T0_P, T1_P, T2_P > > m_Load(const T0_P &Ch, const T1_P &Ptr, const T2_P &Offset)
ReassociatableOpc_match< PatternTs... > m_ReassociatableMul(const PatternTs &...Patterns)
auto m_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)
Opcode_match m_SpecificOpc(unsigned Opcode)
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 >
auto m_Abs(const Opnd &Op)
Result_match< ResNo, Pattern > m_Result(const Pattern &P)
Match only if the SDValue is a certain result at ResNo.
auto m_MaxMinLike(const LHS &L, const RHS &R)
BinaryOpc_match< LHS, RHS, true > m_c_BinOp(unsigned Opc, const LHS &L, const RHS &R, SDNodeFlags Flgs=SDNodeFlags())
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)
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)
AnyZeroFP_match m_AnyZeroFP()
Match a floating-point +0.0 or -0.0 constant or splat.
UnaryOpc_match< Opnd > m_BSwap(const Opnd &Op)
Or< Preds... > m_AnyOf(const Preds &...preds)
BinaryOpc_match< LHS, RHS, true, true > m_c_ChainedBinOp(unsigned Opc, const LHS &L, const RHS &R)
Or< UnaryOpc_match< Opnd >, Opnd > m_TruncOrSelf(const Opnd &Op)
Match a trunc or identity Allows to peek through optional truncations.
UnaryOpc_match< Opnd > m_NNegZExt(const Opnd &Op)
TernaryOpc_match< T0_P, T1_P, T2_P > m_FShR(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2)
And< Preds... > m_AllOf(const Preds &...preds)
UnaryOpc_match< Opnd > m_VectorReverse(const Opnd &Op)
BinaryOpc_match< LHS, RHS > m_FDiv(const LHS &L, const RHS &R)
auto m_NSWAdd(const LHS &L, const RHS &R)
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)
FunnelShiftLike_match< T0_P, T1_P, T2_P, false > m_FShRLike(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2)
Opcode_match m_Poison()
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)
auto m_NUWAddLike(const LHS &L, const RHS &R)
SpecificFP_match m_SpecificFP(APFloat V)
Match a specific float constant.
Value_match m_Specific(SDValue N)
BinaryOpc_match< LHS, RHS > m_ExtractElt(const LHS &Vec, const RHS &Idx)
BinaryOpc_match< LHS, RHS > m_ExtractSubvector(const LHS &Vec, const RHS &Idx)
UnaryOpc_match< Opnd > m_BitReverse(const Opnd &Op)
BinaryOpc_match< LHS, RHS, true > m_And(const LHS &L, const RHS &R)
BinaryOpc_match< LHS, RHS > m_Sub(const LHS &L, const RHS &R)
TernaryOpc_match< T0_P, T1_P, 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)
auto m_NSWAddLike(const LHS &L, const RHS &R)
auto m_VT(EVT &VT)
Retreive the ValueType of the current SDValue.
BinaryOpc_match< ValTy, AllOnes_match, true > m_Not(const ValTy &V)
Match a Not as a xor(v, -1) or xor(-1, v)
ReassociatableOpc_match< PatternTs... > m_ReassociatableOr(const PatternTs &...Patterns)
BinaryOpc_match< LHS, RHS > m_Rotr(const LHS &L, const RHS &R)
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)
TernaryOpc_match< T0_P, T1_P, T2_P > m_FShL(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2)
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)
TernaryOpc_match< T0_P, T1_P, T2_P > m_SpliceRight(const T0_P &V1, const T1_P &V2, const T2_P &Offset)
UnaryOpc_match< Opnd > m_FPToSI(const Opnd &Op)
NUses_match< 1, Value_match > m_OneUse()
auto m_False()
Match false boolean value based on the information provided by TargetLowering.
auto m_NUWAdd(const LHS &L, const RHS &R)
auto m_SExtOrSelf(const Opnd &Op)
Match a sext or identity Allows to peek through optional extensions.
CondCode_match m_CondCode()
Match any conditional code SDNode.
UnaryOpc_match< Opnd > m_FAbs(const Opnd &Op)
Not(const Pred &P) -> Not< Pred >
DeferredValue_match m_Deferred(SDValue &V)
Similar to m_Specific, but the specific value to match is determined by another sub-pattern in the sa...
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)
ValueType_bind(const Pattern &P) -> ValueType_bind< Pattern >
ConstantInt_match m_ConstInt()
Match any integer constants or splat of an integer constant.
FunnelShiftLike_match< T0_P, T1_P, T2_P, true > m_FShLLike(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2)
auto m_ZExtOrSelf(const Opnd &Op)
Match a zext or identity Allows to peek through optional extensions.
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:578
LLVM_ABI bool isAllOnesOrAllOnesSplat(const MachineInstr &MI, const MachineRegisterInfo &MRI, bool AllowUndefs=false)
Return true if the value is a constant -1 integer or a splatted vector of a constant -1 integer (with...
Definition Utils.cpp:1557
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
Definition bit.h:325
LLVM_ABI ConstantFPSDNode * isConstOrConstSplatFP(SDValue N, bool AllowUndefs=false)
Returns the SDNode if it is a constant splat BuildVector or constant float.
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
@ Sub
Subtraction of integers.
DWARFExpression::Operation Op
constexpr unsigned BitWidth
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1917
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
LLVM_ABI bool isZeroOrZeroSplat(SDValue N, bool AllowUndefs=false)
Return true if the value is a constant 0 integer or a splatted vector of a constant 0 integer (with n...
LLVM_ABI bool isOnesOrOnesSplat(SDValue N, bool AllowUndefs=false)
Return true if the value is a constant 1 integer or a splatted vector of a constant 1 integer (with n...
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
#define N
Extended Value Type.
Definition ValueTypes.h:35
bool isNonNegative() const
Returns true if this value is known to be non-negative.
Definition KnownBits.h:106
bool isNonZero() const
Returns true if this value is known to be non-zero.
Definition KnownBits.h:109
bool isStrictlyPositive() const
Returns true if this value is known to be positive.
Definition KnownBits.h:112
bool isNegative() const
Returns true if this value is known to be negative.
Definition KnownBits.h:103
bool isNonPositive() const
Returns true if this value is known to be non-positive.
Definition KnownBits.h:117
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 &, 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 &Ctx, SDValue N)
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)
bool match(const MatchContext &Ctx, SDValue N)
bool matchShiftOr(const MatchContext &Ctx, SDValue N, unsigned BitWidth)
static bool hasComplementaryConstantShifts(const APInt &ShlV, const APInt &SrlV, unsigned BitWidth)
FunnelShiftLike_match(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2)
bool matchOperands(const MatchContext &Ctx, SDValue X, SDValue Y, SDValue Z)
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)
ValueType_bind(EVT &Bind, const Pattern &P)
bool match(const MatchContext &Ctx, SDValue N)
ValueType_match(const PredFuncT &Pred, const Pattern &P)
bool match(const MatchContext &Ctx, SDValue N)
Value_bind(SDValue &N, const PredPattern &P)
bool match(const MatchContext &Ctx, 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)