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.
36 const SelectionDAG *DAG;
37 const TargetLowering *TLI;
38
39public:
40 explicit BasicMatchContext(const SelectionDAG *DAG)
41 : DAG(DAG), TLI(DAG ? &DAG->getTargetLoweringInfo() : nullptr) {}
42
43 explicit BasicMatchContext(const TargetLowering *TLI)
44 : DAG(nullptr), TLI(TLI) {}
45
46 // A valid MatchContext has to implement the following functions.
47
48 const SelectionDAG *getDAG() const { return DAG; }
49
50 const TargetLowering *getTLI() const { return TLI; }
51
52 /// Return true if N effectively has opcode Opcode.
53 bool match(SDValue N, unsigned Opcode) const {
54 return N->getOpcode() == Opcode;
55 }
56
57 unsigned getNumOperands(SDValue N) const { return N->getNumOperands(); }
58};
59
60template <typename Pattern, typename MatchContext>
61[[nodiscard]] bool sd_context_match(SDValue N, const MatchContext &Ctx,
62 Pattern &&P) {
63 return P.match(Ctx, N);
64}
65
66template <typename Pattern, typename MatchContext>
67[[nodiscard]] bool sd_context_match(SDNode *N, const MatchContext &Ctx,
68 Pattern &&P) {
69 return sd_context_match(SDValue(N, 0), Ctx, P);
70}
71
72template <typename Pattern>
73[[nodiscard]] bool sd_match(SDNode *N, const SelectionDAG *DAG, Pattern &&P) {
75}
76
77template <typename Pattern>
78[[nodiscard]] bool sd_match(SDValue N, const SelectionDAG *DAG, Pattern &&P) {
80}
81
82template <typename Pattern>
83[[nodiscard]] bool sd_match(SDNode *N, Pattern &&P) {
84 return sd_match(N, nullptr, P);
85}
86
87template <typename Pattern>
88[[nodiscard]] bool sd_match(SDValue N, Pattern &&P) {
89 return sd_match(N, nullptr, P);
90}
91
92// === Utilities ===
95
96 Value_match() = default;
97
98 explicit Value_match(SDValue Match) : MatchVal(Match) {}
99
100 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
101 if (MatchVal)
102 return MatchVal == N;
103 return N.getNode();
104 }
105};
106
107/// Match any valid SDValue.
108inline Value_match m_Value() { return Value_match(); }
109
111 assert(N);
112 return Value_match(N);
113}
114
115template <unsigned ResNo, typename Pattern> struct Result_match {
117
118 explicit Result_match(const Pattern &P) : P(P) {}
119
120 template <typename MatchContext>
121 bool match(const MatchContext &Ctx, SDValue N) {
122 return N.getResNo() == ResNo && P.match(Ctx, N);
123 }
124};
125
126/// Match only if the SDValue is a certain result at ResNo.
127template <unsigned ResNo, typename Pattern>
131
134
135 explicit DeferredValue_match(SDValue &Match) : MatchVal(Match) {}
136
137 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
138 return N == MatchVal;
139 }
140};
141
142/// Similar to m_Specific, but the specific value to match is determined by
143/// another sub-pattern in the same sd_match() expression. For instance,
144/// We cannot match `(add V, V)` with `m_Add(m_Value(X), m_Specific(X))` since
145/// `X` is not initialized at the time it got copied into `m_Specific`. Instead,
146/// we should use `m_Add(m_Value(X), m_Deferred(X))`.
150
152 unsigned Opcode;
153
154 explicit Opcode_match(unsigned Opc) : Opcode(Opc) {}
155
156 template <typename MatchContext>
157 bool match(const MatchContext &Ctx, SDValue N) {
158 return Ctx.match(N, Opcode);
159 }
160};
161
162// === Patterns combinators ===
163template <typename... Preds> struct And {
164 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
165 return true;
166 }
167};
168
169template <typename Pred, typename... Preds>
170struct And<Pred, Preds...> : And<Preds...> {
171 Pred P;
172 And(const Pred &p, const Preds &...preds) : And<Preds...>(preds...), P(p) {}
173
174 template <typename MatchContext>
175 bool match(const MatchContext &Ctx, SDValue N) {
176 return P.match(Ctx, N) && And<Preds...>::match(Ctx, N);
177 }
178};
179
180template <typename... Preds> struct Or {
181 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
182 return false;
183 }
184};
185
186template <typename Pred, typename... Preds>
187struct Or<Pred, Preds...> : Or<Preds...> {
188 Pred P;
189 Or(const Pred &p, const Preds &...preds) : Or<Preds...>(preds...), P(p) {}
190
191 template <typename MatchContext>
192 bool match(const MatchContext &Ctx, SDValue N) {
193 return P.match(Ctx, N) || Or<Preds...>::match(Ctx, N);
194 }
195};
196
197template <typename Pred> struct Not {
198 Pred P;
199
200 explicit Not(const Pred &P) : P(P) {}
201
202 template <typename MatchContext>
203 bool match(const MatchContext &Ctx, SDValue N) {
204 return !P.match(Ctx, N);
205 }
206};
207// Explicit deduction guide.
208template <typename Pred> Not(const Pred &P) -> Not<Pred>;
209
210/// Match if the inner pattern does NOT match.
211template <typename Pred> inline Not<Pred> m_Unless(const Pred &P) {
212 return Not{P};
213}
214
215template <typename... Preds> And<Preds...> m_AllOf(const Preds &...preds) {
216 return And<Preds...>(preds...);
217}
218
219template <typename... Preds> Or<Preds...> m_AnyOf(const Preds &...preds) {
220 return Or<Preds...>(preds...);
221}
222
223template <typename... Preds> auto m_NoneOf(const Preds &...preds) {
224 return m_Unless(m_AnyOf(preds...));
225}
226
227inline Opcode_match m_SpecificOpc(unsigned Opcode) {
228 return Opcode_match(Opcode);
229}
230
231inline auto m_Undef() {
233}
234
236
237template <unsigned NumUses, typename Pattern> struct NUses_match {
239
240 explicit NUses_match(const Pattern &P) : P(P) {}
241
242 template <typename MatchContext>
243 bool match(const MatchContext &Ctx, SDValue N) {
244 // SDNode::hasNUsesOfValue is pretty expensive when the SDNode produces
245 // multiple results, hence we check the subsequent pattern here before
246 // checking the number of value users.
247 return P.match(Ctx, N) && N->hasNUsesOfValue(NumUses, N.getResNo());
248 }
249};
250
251template <typename Pattern>
255template <unsigned N, typename Pattern>
259
263template <unsigned N> inline NUses_match<N, Value_match> m_NUses() {
265}
266
267template <typename PredPattern> struct Value_bind {
269 PredPattern Pred;
270
271 Value_bind(SDValue &N, const PredPattern &P) : BindVal(N), Pred(P) {}
272
273 template <typename MatchContext>
274 bool match(const MatchContext &Ctx, SDValue N) {
275 if (!Pred.match(Ctx, N))
276 return false;
277
278 BindVal = N;
279 return true;
280 }
281};
282
283inline auto m_Value(SDValue &N) {
285}
286/// Conditionally bind an SDValue based on the predicate.
287template <typename PredPattern>
288inline auto m_Value(SDValue &N, const PredPattern &P) {
289 return Value_bind<PredPattern>(N, P);
290}
291
292template <typename Pattern, typename PredFuncT> struct TLI_pred_match {
294 PredFuncT PredFunc;
295
296 TLI_pred_match(const PredFuncT &Pred, const Pattern &P)
297 : P(P), PredFunc(Pred) {}
298
299 template <typename MatchContext>
300 bool match(const MatchContext &Ctx, SDValue N) {
301 assert(Ctx.getTLI() && "TargetLowering is required for this pattern.");
302 return PredFunc(*Ctx.getTLI(), N) && P.match(Ctx, N);
303 }
304};
305
306// Explicit deduction guide.
307template <typename PredFuncT, typename Pattern>
308TLI_pred_match(const PredFuncT &Pred, const Pattern &P)
310
311/// Match legal SDNodes based on the information provided by TargetLowering.
312template <typename Pattern> inline auto m_LegalOp(const Pattern &P) {
313 return TLI_pred_match{[](const TargetLowering &TLI, SDValue N) {
314 return TLI.isOperationLegal(N->getOpcode(),
315 N.getValueType());
316 },
317 P};
318}
319
320/// Switch to a different MatchContext for subsequent patterns.
321template <typename NewMatchContext, typename Pattern> struct SwitchContext {
322 const NewMatchContext &Ctx;
324
325 template <typename OrigMatchContext>
326 bool match(const OrigMatchContext &, SDValue N) {
327 return P.match(Ctx, N);
328 }
329};
330
331template <typename MatchContext, typename Pattern>
332inline SwitchContext<MatchContext, Pattern> m_Context(const MatchContext &Ctx,
333 Pattern &&P) {
334 return SwitchContext<MatchContext, Pattern>{Ctx, std::move(P)};
335}
336
337// === Value type ===
338
339template <typename Pattern> struct ValueType_bind {
342
343 explicit ValueType_bind(EVT &Bind, const Pattern &P) : BindVT(Bind), P(P) {}
344
345 template <typename MatchContext>
346 bool match(const MatchContext &Ctx, SDValue N) {
347 BindVT = N.getValueType();
348 return P.match(Ctx, N);
349 }
350};
351
352template <typename Pattern>
354
355/// Retreive the ValueType of the current SDValue.
356inline auto m_VT(EVT &VT) { return ValueType_bind(VT, m_Value()); }
357
358template <typename Pattern> inline auto m_VT(EVT &VT, const Pattern &P) {
359 return ValueType_bind(VT, P);
360}
361
362template <typename Pattern, typename PredFuncT> struct ValueType_match {
363 PredFuncT PredFunc;
365
366 ValueType_match(const PredFuncT &Pred, const Pattern &P)
367 : PredFunc(Pred), P(P) {}
368
369 template <typename MatchContext>
370 bool match(const MatchContext &Ctx, SDValue N) {
371 return PredFunc(N.getValueType()) && P.match(Ctx, N);
372 }
373};
374
375// Explicit deduction guide.
376template <typename PredFuncT, typename Pattern>
377ValueType_match(const PredFuncT &Pred, const Pattern &P)
379
380/// Match a specific ValueType.
381template <typename Pattern>
382inline auto m_SpecificVT(EVT RefVT, const Pattern &P) {
383 return ValueType_match{[=](EVT VT) { return VT == RefVT; }, P};
384}
385inline auto m_SpecificVT(EVT RefVT) {
386 return ValueType_match{[=](EVT VT) { return VT == RefVT; }, m_Value()};
387}
388
389inline auto m_Glue() { return m_SpecificVT(MVT::Glue); }
390inline auto m_OtherVT() { return m_SpecificVT(MVT::Other); }
391
392/// Match a scalar ValueType.
393template <typename Pattern>
394inline auto m_SpecificScalarVT(EVT RefVT, const Pattern &P) {
395 return ValueType_match{[=](EVT VT) { return VT.getScalarType() == RefVT; },
396 P};
397}
398inline auto m_SpecificScalarVT(EVT RefVT) {
399 return ValueType_match{[=](EVT VT) { return VT.getScalarType() == RefVT; },
400 m_Value()};
401}
402
403/// Match a vector ValueType.
404template <typename Pattern>
405inline auto m_SpecificVectorElementVT(EVT RefVT, const Pattern &P) {
406 return ValueType_match{[=](EVT VT) {
407 return VT.isVector() &&
408 VT.getVectorElementType() == RefVT;
409 },
410 P};
411}
412inline auto m_SpecificVectorElementVT(EVT RefVT) {
413 return ValueType_match{[=](EVT VT) {
414 return VT.isVector() &&
415 VT.getVectorElementType() == RefVT;
416 },
417 m_Value()};
418}
419
420/// Match any integer ValueTypes.
421template <typename Pattern> inline auto m_IntegerVT(const Pattern &P) {
422 return ValueType_match{[](EVT VT) { return VT.isInteger(); }, P};
423}
424inline auto m_IntegerVT() {
425 return ValueType_match{[](EVT VT) { return VT.isInteger(); }, m_Value()};
426}
427
428/// Match any floating point ValueTypes.
429template <typename Pattern> inline auto m_FloatingPointVT(const Pattern &P) {
430 return ValueType_match{[](EVT VT) { return VT.isFloatingPoint(); }, P};
431}
432inline auto m_FloatingPointVT() {
433 return ValueType_match{[](EVT VT) { return VT.isFloatingPoint(); },
434 m_Value()};
435}
436
437/// Match any vector ValueTypes.
438template <typename Pattern> inline auto m_VectorVT(const Pattern &P) {
439 return ValueType_match{[](EVT VT) { return VT.isVector(); }, P};
440}
441inline auto m_VectorVT() {
442 return ValueType_match{[](EVT VT) { return VT.isVector(); }, m_Value()};
443}
444
445/// Match fixed-length vector ValueTypes.
446template <typename Pattern> inline auto m_FixedVectorVT(const Pattern &P) {
447 return ValueType_match{[](EVT VT) { return VT.isFixedLengthVector(); }, P};
448}
449inline auto m_FixedVectorVT() {
450 return ValueType_match{[](EVT VT) { return VT.isFixedLengthVector(); },
451 m_Value()};
452}
453
454/// Match scalable vector ValueTypes.
455template <typename Pattern> inline auto m_ScalableVectorVT(const Pattern &P) {
456 return ValueType_match{[](EVT VT) { return VT.isScalableVector(); }, P};
457}
458inline auto m_ScalableVectorVT() {
459 return ValueType_match{[](EVT VT) { return VT.isScalableVector(); },
460 m_Value()};
461}
462
463/// Match legal ValueTypes based on the information provided by TargetLowering.
464template <typename Pattern> inline auto m_LegalType(const Pattern &P) {
465 return TLI_pred_match{[](const TargetLowering &TLI, SDValue N) {
466 return TLI.isTypeLegal(N.getValueType());
467 },
468 P};
469}
470
471// === Generic node matching ===
472template <unsigned OpIdx, typename... OpndPreds> struct Operands_match {
473 template <typename MatchContext>
474 bool match(const MatchContext &Ctx, SDValue N) {
475 // Returns false if there are more operands than predicates;
476 // Ignores the last two operands if both the Context and the Node are VP
477 return Ctx.getNumOperands(N) == OpIdx;
478 }
479};
480
481template <unsigned OpIdx, typename OpndPred, typename... OpndPreds>
482struct Operands_match<OpIdx, OpndPred, OpndPreds...>
483 : Operands_match<OpIdx + 1, OpndPreds...> {
484 OpndPred P;
485
486 Operands_match(const OpndPred &p, const OpndPreds &...preds)
487 : Operands_match<OpIdx + 1, OpndPreds...>(preds...), P(p) {}
488
489 template <typename MatchContext>
490 bool match(const MatchContext &Ctx, SDValue N) {
491 if (OpIdx < N->getNumOperands())
492 return P.match(Ctx, N->getOperand(OpIdx)) &&
494
495 // This is the case where there are more predicates than operands.
496 return false;
497 }
498};
499
500template <typename... OpndPreds>
501auto m_Node(unsigned Opcode, const OpndPreds &...preds) {
502 return m_AllOf(m_SpecificOpc(Opcode),
504}
505
506/// Provide number of operands that are not chain or glue, as well as the first
507/// index of such operand.
508template <bool ExcludeChain> struct EffectiveOperands {
509 unsigned Size = 0;
510 unsigned FirstIndex = 0;
511
512 template <typename MatchContext>
513 explicit EffectiveOperands(SDValue N, const MatchContext &Ctx) {
514 const unsigned TotalNumOps = Ctx.getNumOperands(N);
515 FirstIndex = TotalNumOps;
516 for (unsigned I = 0; I < TotalNumOps; ++I) {
517 // Count the number of non-chain and non-glue nodes (we ignore chain
518 // and glue by default) and retreive the operand index offset.
519 EVT VT = N->getOperand(I).getValueType();
520 if (VT != MVT::Glue && VT != MVT::Other) {
521 ++Size;
522 if (FirstIndex == TotalNumOps)
523 FirstIndex = I;
524 }
525 }
526 }
527};
528
529template <> struct EffectiveOperands<false> {
530 unsigned Size = 0;
531 unsigned FirstIndex = 0;
532
533 template <typename MatchContext>
534 explicit EffectiveOperands(SDValue N, const MatchContext &Ctx)
535 : Size(Ctx.getNumOperands(N)) {}
536};
537
538// === Ternary operations ===
539template <typename T0_P, typename T1_P, typename T2_P, bool Commutable = false,
540 bool ExcludeChain = false>
542 unsigned Opcode;
543 T0_P Op0;
544 T1_P Op1;
545 T2_P Op2;
546
547 TernaryOpc_match(unsigned Opc, const T0_P &Op0, const T1_P &Op1,
548 const T2_P &Op2)
549 : Opcode(Opc), Op0(Op0), Op1(Op1), Op2(Op2) {}
550
551 template <typename MatchContext>
552 bool match(const MatchContext &Ctx, SDValue N) {
555 assert(EO.Size == 3);
556 return ((Op0.match(Ctx, N->getOperand(EO.FirstIndex)) &&
557 Op1.match(Ctx, N->getOperand(EO.FirstIndex + 1))) ||
558 (Commutable && Op0.match(Ctx, N->getOperand(EO.FirstIndex + 1)) &&
559 Op1.match(Ctx, N->getOperand(EO.FirstIndex)))) &&
560 Op2.match(Ctx, N->getOperand(EO.FirstIndex + 2));
561 }
562
563 return false;
564 }
565};
566
567template <typename T0_P, typename T1_P, typename T2_P>
568inline TernaryOpc_match<T0_P, T1_P, T2_P>
569m_SetCC(const T0_P &LHS, const T1_P &RHS, const T2_P &CC) {
571}
572
573template <typename T0_P, typename T1_P, typename T2_P>
574inline TernaryOpc_match<T0_P, T1_P, T2_P, true, false>
575m_c_SetCC(const T0_P &LHS, const T1_P &RHS, const T2_P &CC) {
577 CC);
578}
579
580template <typename T0_P, typename T1_P, typename T2_P>
581inline TernaryOpc_match<T0_P, T1_P, T2_P>
582m_Select(const T0_P &Cond, const T1_P &T, const T2_P &F) {
584}
585
586template <typename T0_P, typename T1_P, typename T2_P>
587inline TernaryOpc_match<T0_P, T1_P, T2_P>
588m_VSelect(const T0_P &Cond, const T1_P &T, const T2_P &F) {
590}
591
592template <typename T0_P, typename T1_P, typename T2_P>
593inline auto m_SelectLike(const T0_P &Cond, const T1_P &T, const T2_P &F) {
594 return m_AnyOf(m_Select(Cond, T, F), m_VSelect(Cond, T, F));
595}
596
597template <typename T0_P, typename T1_P, typename T2_P>
598inline Result_match<0, TernaryOpc_match<T0_P, T1_P, T2_P>>
599m_Load(const T0_P &Ch, const T1_P &Ptr, const T2_P &Offset) {
600 return m_Result<0>(
602}
603
604template <typename T0_P, typename T1_P, typename T2_P>
605inline TernaryOpc_match<T0_P, T1_P, T2_P>
606m_InsertElt(const T0_P &Vec, const T1_P &Val, const T2_P &Idx) {
608 Idx);
609}
610
611template <typename LHS, typename RHS, typename IDX>
612inline TernaryOpc_match<LHS, RHS, IDX>
613m_InsertSubvector(const LHS &Base, const RHS &Sub, const IDX &Idx) {
615}
616
617template <typename T0_P, typename T1_P, typename T2_P>
618inline TernaryOpc_match<T0_P, T1_P, T2_P>
619m_SpliceRight(const T0_P &V1, const T1_P &V2, const T2_P &Offset) {
621 Offset);
622}
623
624template <typename T0_P, typename T1_P, typename T2_P>
625inline TernaryOpc_match<T0_P, T1_P, T2_P>
626m_TernaryOp(unsigned Opc, const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
627 return TernaryOpc_match<T0_P, T1_P, T2_P>(Opc, Op0, Op1, Op2);
628}
629
630template <typename T0_P, typename T1_P, typename T2_P>
631inline TernaryOpc_match<T0_P, T1_P, T2_P, true>
632m_c_TernaryOp(unsigned Opc, const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
633 return TernaryOpc_match<T0_P, T1_P, T2_P, true>(Opc, Op0, Op1, Op2);
634}
635
636template <typename LTy, typename RTy, typename TTy, typename FTy, typename CCTy>
637inline auto m_SelectCC(const LTy &L, const RTy &R, const TTy &T, const FTy &F,
638 const CCTy &CC) {
639 return m_Node(ISD::SELECT_CC, L, R, T, F, CC);
640}
641
642template <typename LTy, typename RTy, typename TTy, typename FTy, typename CCTy>
643inline auto m_SelectCCLike(const LTy &L, const RTy &R, const TTy &T,
644 const FTy &F, const CCTy &CC) {
645 return m_AnyOf(m_Select(m_SetCC(L, R, CC), T, F), m_SelectCC(L, R, T, F, CC));
646}
647
648// === Binary operations ===
649template <typename LHS_P, typename RHS_P, bool Commutable = false,
650 bool ExcludeChain = false>
652 unsigned Opcode;
653 LHS_P LHS;
654 RHS_P RHS;
656 BinaryOpc_match(unsigned Opc, const LHS_P &L, const RHS_P &R,
657 SDNodeFlags Flgs = SDNodeFlags())
658 : Opcode(Opc), LHS(L), RHS(R), Flags(Flgs) {}
659
660 template <typename MatchContext>
661 bool match(const MatchContext &Ctx, SDValue N) {
664 assert(EO.Size == 2);
665 if (!((LHS.match(Ctx, N->getOperand(EO.FirstIndex)) &&
666 RHS.match(Ctx, N->getOperand(EO.FirstIndex + 1))) ||
667 (Commutable && LHS.match(Ctx, N->getOperand(EO.FirstIndex + 1)) &&
668 RHS.match(Ctx, N->getOperand(EO.FirstIndex)))))
669 return false;
670
671 return (Flags & N->getFlags()) == Flags;
672 }
673
674 return false;
675 }
676};
677
678/// Matching while capturing mask
679template <typename T0, typename T1, typename T2> struct SDShuffle_match {
680 T0 Op1;
683
684 SDShuffle_match(const T0 &Op1, const T1 &Op2, const T2 &Mask)
685 : Op1(Op1), Op2(Op2), Mask(Mask) {}
686
687 template <typename MatchContext>
688 bool match(const MatchContext &Ctx, SDValue N) {
689 if (auto *I = dyn_cast<ShuffleVectorSDNode>(N)) {
690 return Op1.match(Ctx, I->getOperand(0)) &&
691 Op2.match(Ctx, I->getOperand(1)) && Mask.match(I->getMask());
692 }
693 return false;
694 }
695};
696struct m_Mask {
699 bool match(ArrayRef<int> Mask) {
700 MaskRef = Mask;
701 return true;
702 }
703};
704
710
711template <typename LHS_P, typename RHS_P, typename Pred_t,
712 bool Commutable = false, bool ExcludeChain = false>
714 using PredType = Pred_t;
715 LHS_P LHS;
716 RHS_P RHS;
717
718 MaxMin_match(const LHS_P &L, const RHS_P &R) : LHS(L), RHS(R) {}
719
720 template <typename MatchContext>
721 bool match(const MatchContext &Ctx, SDValue N) {
722 auto MatchMinMax = [&](SDValue L, SDValue R, SDValue TrueValue,
723 SDValue FalseValue, ISD::CondCode CC) {
724 if ((TrueValue != L || FalseValue != R) &&
725 (TrueValue != R || FalseValue != L))
726 return false;
727
729 TrueValue == L ? CC : getSetCCInverse(CC, L.getValueType());
730 if (!Pred_t::match(Cond))
731 return false;
732
733 return (LHS.match(Ctx, L) && RHS.match(Ctx, R)) ||
734 (Commutable && LHS.match(Ctx, R) && RHS.match(Ctx, L));
735 };
736
739 EffectiveOperands<ExcludeChain> EO_SELECT(N, Ctx);
740 assert(EO_SELECT.Size == 3);
741 SDValue Cond = N->getOperand(EO_SELECT.FirstIndex);
742 SDValue TrueValue = N->getOperand(EO_SELECT.FirstIndex + 1);
743 SDValue FalseValue = N->getOperand(EO_SELECT.FirstIndex + 2);
744
747 assert(EO_SETCC.Size == 3);
748 SDValue L = Cond->getOperand(EO_SETCC.FirstIndex);
749 SDValue R = Cond->getOperand(EO_SETCC.FirstIndex + 1);
750 auto *CondNode =
751 cast<CondCodeSDNode>(Cond->getOperand(EO_SETCC.FirstIndex + 2));
752 return MatchMinMax(L, R, TrueValue, FalseValue, CondNode->get());
753 }
754 }
755
757 EffectiveOperands<ExcludeChain> EO_SELECT(N, Ctx);
758 assert(EO_SELECT.Size == 5);
759 SDValue L = N->getOperand(EO_SELECT.FirstIndex);
760 SDValue R = N->getOperand(EO_SELECT.FirstIndex + 1);
761 SDValue TrueValue = N->getOperand(EO_SELECT.FirstIndex + 2);
762 SDValue FalseValue = N->getOperand(EO_SELECT.FirstIndex + 3);
763 auto *CondNode =
764 cast<CondCodeSDNode>(N->getOperand(EO_SELECT.FirstIndex + 4));
765 return MatchMinMax(L, R, TrueValue, FalseValue, CondNode->get());
766 }
767
768 return false;
769 }
770};
771
772// Helper class for identifying signed max predicates.
774 static bool match(ISD::CondCode Cond) {
776 }
777};
778
779// Helper class for identifying unsigned max predicates.
784};
785
786// Helper class for identifying signed min predicates.
788 static bool match(ISD::CondCode Cond) {
790 }
791};
792
793// Helper class for identifying unsigned min predicates.
798};
799
800template <typename LHS, typename RHS>
801inline BinaryOpc_match<LHS, RHS> m_BinOp(unsigned Opc, const LHS &L,
802 const RHS &R,
803 SDNodeFlags Flgs = SDNodeFlags()) {
804 return BinaryOpc_match<LHS, RHS>(Opc, L, R, Flgs);
805}
806template <typename LHS, typename RHS>
808m_c_BinOp(unsigned Opc, const LHS &L, const RHS &R,
809 SDNodeFlags Flgs = SDNodeFlags()) {
810 return BinaryOpc_match<LHS, RHS, true>(Opc, L, R, Flgs);
811}
812
813template <typename LHS, typename RHS>
815m_ChainedBinOp(unsigned Opc, const LHS &L, const RHS &R) {
817}
818template <typename LHS, typename RHS>
820m_c_ChainedBinOp(unsigned Opc, const LHS &L, const RHS &R) {
822}
823
824// Common binary operations
825template <typename LHS, typename RHS>
826inline BinaryOpc_match<LHS, RHS, true> m_Add(const LHS &L, const RHS &R) {
828}
829
830template <typename LHS, typename RHS>
831inline auto m_NUWAdd(const LHS &L, const RHS &R) {
834}
835
836template <typename LHS, typename RHS>
837inline auto m_NSWAdd(const LHS &L, const RHS &R) {
840}
841
842template <typename LHS, typename RHS>
843inline BinaryOpc_match<LHS, RHS> m_Sub(const LHS &L, const RHS &R) {
845}
846
847template <typename LHS, typename RHS>
848inline BinaryOpc_match<LHS, RHS, true> m_Mul(const LHS &L, const RHS &R) {
850}
851
852template <typename LHS, typename RHS>
853inline BinaryOpc_match<LHS, RHS, true> m_And(const LHS &L, const RHS &R) {
855}
856
857template <typename LHS, typename RHS>
858inline BinaryOpc_match<LHS, RHS, true> m_Or(const LHS &L, const RHS &R) {
860}
861
862template <typename LHS, typename RHS>
867
868template <typename LHS, typename RHS>
869inline auto m_AddLike(const LHS &L, const RHS &R) {
870 return m_AnyOf(m_Add(L, R), m_DisjointOr(L, R));
871}
872
873template <typename LHS, typename RHS>
874inline auto m_NSWAddLike(const LHS &L, const RHS &R) {
875 return m_AnyOf(m_NSWAdd(L, R), m_DisjointOr(L, R));
876}
877
878template <typename LHS, typename RHS>
879inline auto m_NUWAddLike(const LHS &L, const RHS &R) {
880 return m_AnyOf(m_NUWAdd(L, R), m_DisjointOr(L, R));
881}
882
883template <typename LHS, typename RHS>
884inline BinaryOpc_match<LHS, RHS, true> m_Xor(const LHS &L, const RHS &R) {
886}
887
888template <typename LHS, typename RHS>
889inline auto m_BitwiseLogic(const LHS &L, const RHS &R) {
890 return m_AnyOf(m_And(L, R), m_Or(L, R), m_Xor(L, R));
891}
892
893template <unsigned Opc, typename Pred, typename LHS, typename RHS>
894inline auto m_MaxMinLike(const LHS &L, const RHS &R) {
897}
898
899template <typename LHS, typename RHS>
900inline BinaryOpc_match<LHS, RHS, true> m_SMin(const LHS &L, const RHS &R) {
902}
903
904template <typename LHS, typename RHS>
911
912template <typename LHS, typename RHS>
913inline BinaryOpc_match<LHS, RHS, true> m_SMax(const LHS &L, const RHS &R) {
915}
916
917template <typename LHS, typename RHS>
924
925template <typename LHS, typename RHS>
926inline BinaryOpc_match<LHS, RHS, true> m_UMin(const LHS &L, const RHS &R) {
928}
929
930template <typename LHS, typename RHS>
937
938template <typename LHS, typename RHS>
939inline BinaryOpc_match<LHS, RHS, true> m_UMax(const LHS &L, const RHS &R) {
941}
942
943template <typename LHS, typename RHS>
950
951template <typename LHS, typename RHS>
952inline BinaryOpc_match<LHS, RHS> m_UDiv(const LHS &L, const RHS &R) {
954}
955template <typename LHS, typename RHS>
956inline BinaryOpc_match<LHS, RHS> m_SDiv(const LHS &L, const RHS &R) {
958}
959
960template <typename LHS, typename RHS>
961inline BinaryOpc_match<LHS, RHS> m_URem(const LHS &L, const RHS &R) {
963}
964template <typename LHS, typename RHS>
965inline BinaryOpc_match<LHS, RHS> m_SRem(const LHS &L, const RHS &R) {
967}
968
969template <typename LHS, typename RHS>
970inline BinaryOpc_match<LHS, RHS> m_Shl(const LHS &L, const RHS &R) {
972}
973
974template <typename LHS, typename RHS>
975inline BinaryOpc_match<LHS, RHS> m_Sra(const LHS &L, const RHS &R) {
977}
978template <typename LHS, typename RHS>
979inline BinaryOpc_match<LHS, RHS> m_Srl(const LHS &L, const RHS &R) {
981}
982template <typename LHS, typename RHS>
987
988template <typename LHS, typename RHS>
989inline BinaryOpc_match<LHS, RHS> m_Rotl(const LHS &L, const RHS &R) {
991}
992
993template <typename LHS, typename RHS>
994inline BinaryOpc_match<LHS, RHS> m_Rotr(const LHS &L, const RHS &R) {
996}
997
998template <typename T0_P, typename T1_P, typename T2_P>
999inline TernaryOpc_match<T0_P, T1_P, T2_P>
1000m_FShL(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
1001 return m_TernaryOp(ISD::FSHL, Op0, Op1, Op2);
1002}
1003
1004template <typename T0_P, typename T1_P, typename T2_P>
1005inline TernaryOpc_match<T0_P, T1_P, T2_P>
1006m_FShR(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
1007 return m_TernaryOp(ISD::FSHR, Op0, Op1, Op2);
1008}
1009
1010template <typename T0_P, typename T1_P, typename T2_P, bool Left>
1012 T0_P Op0;
1013 T1_P Op1;
1014 T2_P Op2;
1015
1016 FunnelShiftLike_match(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2)
1017 : Op0(Op0), Op1(Op1), Op2(Op2) {}
1018
1019 static bool hasComplementaryConstantShifts(const APInt &ShlV,
1020 const APInt &SrlV,
1021 unsigned BitWidth) {
1022 unsigned SumWidth = std::max(ShlV.getBitWidth(), SrlV.getBitWidth()) + 1;
1023 unsigned BitWidthBits = llvm::bit_width(BitWidth);
1024 if (BitWidthBits > SumWidth)
1025 return false;
1026
1027 return ShlV.zext(SumWidth) + SrlV.zext(SumWidth) ==
1028 APInt(SumWidth, BitWidth);
1029 }
1030
1031 template <typename MatchContext>
1032 bool matchOperands(const MatchContext &Ctx, SDValue X, SDValue Y, SDValue Z) {
1033 return Op0.match(Ctx, X) && Op1.match(Ctx, Y) && Op2.match(Ctx, Z);
1034 }
1035
1036 template <typename MatchContext>
1037 bool matchShiftOr(const MatchContext &Ctx, SDValue N, unsigned BitWidth);
1038
1039 template <typename MatchContext>
1040 bool match(const MatchContext &Ctx, SDValue N) {
1041 if (sd_context_match(N, Ctx,
1042 Left ? m_FShL(Op0, Op1, Op2) : m_FShR(Op0, Op1, Op2)))
1043 return true;
1044
1045 SDValue X, Z;
1046 if (sd_context_match(N, Ctx,
1047 Left ? m_Rotl(m_Value(X), m_Value(Z))
1048 : m_Rotr(m_Value(X), m_Value(Z))))
1049 return matchOperands(Ctx, X, X, Z);
1050
1051 return matchShiftOr(Ctx, N, N.getValueType().getScalarSizeInBits());
1052 }
1053};
1054
1055template <typename T0_P, typename T1_P, typename T2_P>
1056inline FunnelShiftLike_match<T0_P, T1_P, T2_P, true>
1057m_FShLLike(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
1059}
1060
1061template <typename T0_P, typename T1_P, typename T2_P>
1062inline FunnelShiftLike_match<T0_P, T1_P, T2_P, false>
1063m_FShRLike(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
1065}
1066
1067template <typename LHS, typename RHS>
1070}
1071
1072template <typename LHS, typename RHS>
1073inline BinaryOpc_match<LHS, RHS, true> m_FAdd(const LHS &L, const RHS &R) {
1075}
1076
1077template <typename LHS, typename RHS>
1078inline BinaryOpc_match<LHS, RHS> m_FSub(const LHS &L, const RHS &R) {
1080}
1081
1082template <typename LHS, typename RHS>
1083inline BinaryOpc_match<LHS, RHS, true> m_FMul(const LHS &L, const RHS &R) {
1085}
1086
1087template <typename LHS, typename RHS>
1088inline BinaryOpc_match<LHS, RHS> m_FDiv(const LHS &L, const RHS &R) {
1090}
1091
1092template <typename LHS, typename RHS>
1093inline BinaryOpc_match<LHS, RHS> m_FRem(const LHS &L, const RHS &R) {
1095}
1096
1097template <typename V1_t, typename V2_t>
1098inline BinaryOpc_match<V1_t, V2_t> m_Shuffle(const V1_t &v1, const V2_t &v2) {
1100}
1101
1102template <typename V1_t, typename V2_t, typename Mask_t>
1103inline SDShuffle_match<V1_t, V2_t, Mask_t>
1104m_Shuffle(const V1_t &v1, const V2_t &v2, const Mask_t &mask) {
1106}
1107
1108template <typename LHS, typename RHS>
1109inline BinaryOpc_match<LHS, RHS> m_ExtractElt(const LHS &Vec, const RHS &Idx) {
1111}
1112
1113template <typename LHS, typename RHS>
1115 const RHS &Idx) {
1117}
1118
1119// === Unary operations ===
1120template <typename Opnd_P, bool ExcludeChain = false> struct UnaryOpc_match {
1121 unsigned Opcode;
1122 Opnd_P Opnd;
1124 UnaryOpc_match(unsigned Opc, const Opnd_P &Op,
1125 SDNodeFlags Flgs = SDNodeFlags())
1126 : Opcode(Opc), Opnd(Op), Flags(Flgs) {}
1127
1128 template <typename MatchContext>
1129 bool match(const MatchContext &Ctx, SDValue N) {
1130 if (sd_context_match(N, Ctx, m_SpecificOpc(Opcode))) {
1132 assert(EO.Size == 1);
1133 if (!Opnd.match(Ctx, N->getOperand(EO.FirstIndex)))
1134 return false;
1135
1136 return (Flags & N->getFlags()) == Flags;
1137 }
1138
1139 return false;
1140 }
1141};
1142
1143template <typename Opnd>
1144inline UnaryOpc_match<Opnd> m_UnaryOp(unsigned Opc, const Opnd &Op) {
1145 return UnaryOpc_match<Opnd>(Opc, Op);
1146}
1147template <typename Opnd>
1149 const Opnd &Op) {
1151}
1152
1153template <typename Opnd> inline UnaryOpc_match<Opnd> m_BitCast(const Opnd &Op) {
1155}
1156
1157template <typename Opnd>
1158inline UnaryOpc_match<Opnd> m_BSwap(const Opnd &Op) {
1160}
1161
1162template <typename Opnd>
1166
1167template <typename Opnd> inline UnaryOpc_match<Opnd> m_ZExt(const Opnd &Op) {
1169}
1170
1171template <typename Opnd>
1175
1176template <typename Opnd> inline auto m_SExt(const Opnd &Op) {
1178}
1179
1180template <typename Opnd> inline UnaryOpc_match<Opnd> m_AnyExt(const Opnd &Op) {
1182}
1183
1184template <typename Opnd> inline UnaryOpc_match<Opnd> m_Trunc(const Opnd &Op) {
1186}
1187
1188template <typename Opnd> inline auto m_Abs(const Opnd &Op) {
1191}
1192
1193template <typename Opnd> inline UnaryOpc_match<Opnd> m_FAbs(const Opnd &Op) {
1195}
1196
1197/// Match a zext or identity
1198/// Allows to peek through optional extensions
1199template <typename Opnd> inline auto m_ZExtOrSelf(const Opnd &Op) {
1200 return m_AnyOf(m_ZExt(Op), Op);
1201}
1202
1203/// Match a sext or identity
1204/// Allows to peek through optional extensions
1205template <typename Opnd> inline auto m_SExtOrSelf(const Opnd &Op) {
1206 return m_AnyOf(m_SExt(Op), Op);
1207}
1208
1209template <typename Opnd> inline auto m_SExtLike(const Opnd &Op) {
1210 return m_AnyOf(m_SExt(Op), m_NNegZExt(Op));
1211}
1212
1213/// Match a aext or identity
1214/// Allows to peek through optional extensions
1215template <typename Opnd>
1216inline Or<UnaryOpc_match<Opnd>, Opnd> m_AExtOrSelf(const Opnd &Op) {
1217 return Or<UnaryOpc_match<Opnd>, Opnd>(m_AnyExt(Op), Op);
1218}
1219
1220/// Match a trunc or identity
1221/// Allows to peek through optional truncations
1222template <typename Opnd>
1223inline Or<UnaryOpc_match<Opnd>, Opnd> m_TruncOrSelf(const Opnd &Op) {
1224 return Or<UnaryOpc_match<Opnd>, Opnd>(m_Trunc(Op), Op);
1225}
1226
1227template <typename Opnd> inline UnaryOpc_match<Opnd> m_VScale(const Opnd &Op) {
1229}
1230
1231template <typename Opnd> inline UnaryOpc_match<Opnd> m_FPToUI(const Opnd &Op) {
1233}
1234
1235template <typename Opnd> inline UnaryOpc_match<Opnd> m_FPToSI(const Opnd &Op) {
1237}
1238
1239template <typename Opnd> inline UnaryOpc_match<Opnd> m_Ctpop(const Opnd &Op) {
1241}
1242
1243template <typename Opnd> inline UnaryOpc_match<Opnd> m_Ctlz(const Opnd &Op) {
1245}
1246
1247template <typename Opnd> inline UnaryOpc_match<Opnd> m_Cttz(const Opnd &Op) {
1249}
1250
1251template <typename Opnd> inline UnaryOpc_match<Opnd> m_FNeg(const Opnd &Op) {
1253}
1254
1255template <typename Opnd>
1259
1260// === Constants ===
1263
1264 explicit ConstantInt_match(APInt *V) : BindVal(V) {}
1265
1266 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
1267 // The logics here are similar to that in
1268 // SelectionDAG::isConstantIntBuildVectorOrConstantInt, but the latter also
1269 // treats GlobalAddressSDNode as a constant, which is difficult to turn into
1270 // APInt.
1271 if (auto *C = dyn_cast_or_null<ConstantSDNode>(N.getNode())) {
1272 if (BindVal)
1273 *BindVal = C->getAPIntValue();
1274 return true;
1275 }
1276
1277 APInt Discard;
1278 return ISD::isConstantSplatVector(N.getNode(),
1279 BindVal ? *BindVal : Discard);
1280 }
1281};
1282
1283template <typename T> struct Constant64_match {
1284 static_assert(sizeof(T) == 8, "T must be 64 bits wide");
1285
1287
1288 explicit Constant64_match(T &V) : BindVal(V) {}
1289
1290 template <typename MatchContext>
1291 bool match(const MatchContext &Ctx, SDValue N) {
1292 APInt V;
1293 if (!ConstantInt_match(&V).match(Ctx, N))
1294 return false;
1295
1296 if constexpr (std::is_signed_v<T>) {
1297 if (std::optional<int64_t> TrySExt = V.trySExtValue()) {
1298 BindVal = *TrySExt;
1299 return true;
1300 }
1301 }
1302
1303 if constexpr (std::is_unsigned_v<T>) {
1304 if (std::optional<uint64_t> TryZExt = V.tryZExtValue()) {
1305 BindVal = *TryZExt;
1306 return true;
1307 }
1308 }
1309
1310 return false;
1311 }
1312};
1313
1314/// Match any integer constants or splat of an integer constant.
1316/// Match any integer constants or splat of an integer constant; return the
1317/// specific constant or constant splat value.
1319/// Match any integer constants or splat of an integer constant that can fit in
1320/// 64 bits; return the specific constant or constant splat value, zero-extended
1321/// to 64 bits.
1325/// Match any integer constants or splat of an integer constant that can fit in
1326/// 64 bits; return the specific constant or constant splat value, sign-extended
1327/// to 64 bits.
1329 return Constant64_match<int64_t>(V);
1330}
1331
1332template <typename T0_P, typename T1_P, typename T2_P, bool Left>
1333template <typename MatchContext>
1335 const MatchContext &Ctx, SDValue N, unsigned BitWidth) {
1336 SDValue X, Y, ShlAmt, SrlAmt;
1337 APInt ShlConst, SrlConst;
1338 if (!sd_context_match(
1339 N, Ctx,
1340 m_Or(m_Shl(m_Value(X), m_Value(ShlAmt, m_ConstInt(ShlConst))),
1341 m_Srl(m_Value(Y), m_Value(SrlAmt, m_ConstInt(SrlConst))))) ||
1342 !hasComplementaryConstantShifts(ShlConst, SrlConst, BitWidth))
1343 return false;
1344
1345 return matchOperands(Ctx, X, Y, Left ? ShlAmt : SrlAmt);
1346}
1347
1350
1351 explicit SpecificInt_match(APInt APV) : IntVal(std::move(APV)) {}
1352
1353 template <typename MatchContext>
1354 bool match(const MatchContext &Ctx, SDValue N) {
1355 APInt ConstInt;
1356 if (sd_context_match(N, Ctx, m_ConstInt(ConstInt)))
1357 return APInt::isSameValue(IntVal, ConstInt);
1358 return false;
1359 }
1360};
1361
1362/// Match a specific integer constant or constant splat value.
1364 return SpecificInt_match(std::move(V));
1365}
1367 return SpecificInt_match(APInt(64, V));
1368}
1369
1372
1373 explicit SpecificFP_match(APFloat V) : Val(V) {}
1374
1375 template <typename MatchContext>
1376 bool match(const MatchContext &Ctx, SDValue V) {
1377 if (const auto *CFP = dyn_cast<ConstantFPSDNode>(V.getNode()))
1378 return CFP->isExactlyValue(Val);
1379 if (ConstantFPSDNode *C = isConstOrConstSplatFP(V, /*AllowUndefs=*/true))
1380 return C->getValueAPF().compare(Val) == APFloat::cmpEqual;
1381 return false;
1382 }
1383};
1384
1385/// Match a specific float constant.
1387
1389 return SpecificFP_match(APFloat(V));
1390}
1391
1393 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
1395 return C->isZero();
1396 return false;
1397 }
1398};
1399
1400/// Match a floating-point +0.0 or -0.0 constant or splat.
1402
1404 template <typename MatchContext>
1405 bool match(const MatchContext &Ctx, SDValue N) {
1406 const SelectionDAG *DAG = Ctx.getDAG();
1407 return DAG && DAG->computeKnownBits(N).isNegative();
1408 }
1409};
1410
1412 template <typename MatchContext>
1413 bool match(const MatchContext &Ctx, SDValue N) {
1414 const SelectionDAG *DAG = Ctx.getDAG();
1415 return DAG && DAG->computeKnownBits(N).isNonNegative();
1416 }
1417};
1418
1420 template <typename MatchContext>
1421 bool match(const MatchContext &Ctx, SDValue N) {
1422 const SelectionDAG *DAG = Ctx.getDAG();
1423 return DAG && DAG->computeKnownBits(N).isStrictlyPositive();
1424 }
1425};
1426
1428 template <typename MatchContext>
1429 bool match(const MatchContext &Ctx, SDValue N) {
1430 const SelectionDAG *DAG = Ctx.getDAG();
1431 return DAG && DAG->computeKnownBits(N).isNonPositive();
1432 }
1433};
1434
1436 template <typename MatchContext>
1437 bool match(const MatchContext &Ctx, SDValue N) {
1438 const SelectionDAG *DAG = Ctx.getDAG();
1439 return DAG && DAG->computeKnownBits(N).isNonZero();
1440 }
1441};
1442
1445
1447
1448 template <typename MatchContext>
1449 bool match(const MatchContext &, SDValue N) const {
1451 }
1452};
1453
1456
1458
1459 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
1461 }
1462};
1463
1466
1468
1469 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
1471 }
1472};
1473
1475template <typename Pattern> inline auto m_Negative(const Pattern &P) {
1476 return m_AllOf(m_Negative(), P);
1477}
1479template <typename Pattern> inline auto m_NonNegative(const Pattern &P) {
1480 return m_AllOf(m_NonNegative(), P);
1481}
1485template <typename Pattern> inline auto m_StrictlyPositive(const Pattern &P) {
1486 return m_AllOf(m_StrictlyPositive(), P);
1487}
1489template <typename Pattern> inline auto m_NonPositive(const Pattern &P) {
1490 return m_AllOf(m_NonPositive(), P);
1491}
1493template <typename Pattern> inline auto m_NonZero(const Pattern &P) {
1494 return m_AllOf(m_NonZero(), P);
1495}
1496inline Ones_match m_One(bool AllowUndefs = false) {
1497 return Ones_match(AllowUndefs);
1498}
1499inline Zero_match m_Zero(bool AllowUndefs = false) {
1500 return Zero_match(AllowUndefs);
1501}
1502inline AllOnes_match m_AllOnes(bool AllowUndefs = false) {
1503 return AllOnes_match(AllowUndefs);
1504}
1505
1506/// Match true boolean value based on the information provided by
1507/// TargetLowering.
1508inline auto m_True() {
1509 return TLI_pred_match{
1510 [](const TargetLowering &TLI, SDValue N) {
1511 APInt ConstVal;
1512 if (sd_match(N, m_ConstInt(ConstVal)))
1513 switch (TLI.getBooleanContents(N.getValueType())) {
1515 return ConstVal.isOne();
1517 return ConstVal.isAllOnes();
1519 return (ConstVal & 0x01) == 1;
1520 }
1521
1522 return false;
1523 },
1524 m_Value()};
1525}
1526/// Match false boolean value based on the information provided by
1527/// TargetLowering.
1528inline auto m_False() {
1529 return TLI_pred_match{
1530 [](const TargetLowering &TLI, SDValue N) {
1531 APInt ConstVal;
1532 if (sd_match(N, m_ConstInt(ConstVal)))
1533 switch (TLI.getBooleanContents(N.getValueType())) {
1536 return ConstVal.isZero();
1538 return (ConstVal & 0x01) == 0;
1539 }
1540
1541 return false;
1542 },
1543 m_Value()};
1544}
1545
1547 std::optional<ISD::CondCode> CCToMatch;
1549
1551
1552 explicit CondCode_match(ISD::CondCode *CC) : BindCC(CC) {}
1553
1554 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
1555 if (auto *CC = dyn_cast<CondCodeSDNode>(N.getNode())) {
1556 if (CCToMatch && *CCToMatch != CC->get())
1557 return false;
1558
1559 if (BindCC)
1560 *BindCC = CC->get();
1561 return true;
1562 }
1563
1564 return false;
1565 }
1566};
1567
1568/// Match any conditional code SDNode.
1569inline CondCode_match m_CondCode() { return CondCode_match(nullptr); }
1570/// Match any conditional code SDNode and return its ISD::CondCode value.
1572 return CondCode_match(&CC);
1573}
1574/// Match a conditional code SDNode with a specific ISD::CondCode.
1578
1579/// Match a negate as a sub(0, v)
1580template <typename ValTy>
1582 return m_Sub(m_Zero(), V);
1583}
1584
1585/// Match a Not as a xor(v, -1) or xor(-1, v)
1586template <typename ValTy>
1588 return m_Xor(V, m_AllOnes());
1589}
1590
1591template <unsigned IntrinsicId, typename... OpndPreds>
1592inline auto m_IntrinsicWOChain(const OpndPreds &...Opnds) {
1593 return m_Node(ISD::INTRINSIC_WO_CHAIN, m_SpecificInt(IntrinsicId), Opnds...);
1594}
1595
1598
1600
1601 template <typename MatchContext>
1602 bool match(const MatchContext &Ctx, SDValue N) {
1603 if (sd_context_match(N, Ctx, m_Neg(m_Specific(V))))
1604 return true;
1605
1608 return LHS->getAPIntValue() == -RHS->getAPIntValue();
1609 });
1610 }
1611};
1612
1613/// Match a negation of a specific value V, either as sub(0, V) or as
1614/// constant(s) that are the negation of V's constant(s).
1618
1619template <typename... PatternTs> struct ReassociatableOpc_match {
1620 unsigned Opcode;
1621 std::tuple<PatternTs...> Patterns;
1622 constexpr static size_t NumPatterns =
1623 std::tuple_size_v<std::tuple<PatternTs...>>;
1624
1626
1627 ReassociatableOpc_match(unsigned Opcode, const PatternTs &...Patterns)
1628 : Opcode(Opcode), Patterns(Patterns...) {}
1629
1631 const PatternTs &...Patterns)
1633
1634 template <typename MatchContext>
1635 bool match(const MatchContext &Ctx, SDValue N) {
1636 std::array<SDValue, NumPatterns> Leaves;
1637 size_t LeavesIdx = 0;
1638 if (!(collectLeaves(N, Leaves, LeavesIdx) && (LeavesIdx == NumPatterns)))
1639 return false;
1640
1642 return std::apply(
1643 [&](auto &...P) -> bool {
1644 return reassociatableMatchHelper(Ctx, Leaves, Used, P...);
1645 },
1646 Patterns);
1647 }
1648
1649 bool collectLeaves(SDValue V, std::array<SDValue, NumPatterns> &Leaves,
1650 std::size_t &LeafIdx) {
1651 if (V->getOpcode() == Opcode && (Flags & V->getFlags()) == Flags) {
1652 for (size_t I = 0, N = V->getNumOperands(); I < N; I++)
1653 if ((LeafIdx == NumPatterns) ||
1654 !collectLeaves(V->getOperand(I), Leaves, LeafIdx))
1655 return false;
1656 } else {
1657 Leaves[LeafIdx] = V;
1658 LeafIdx++;
1659 }
1660 return true;
1661 }
1662
1663 // Searchs for a matching leaf for every sub-pattern.
1664 template <typename MatchContext, typename PatternHd, typename... PatternTl>
1665 [[nodiscard]] inline bool
1666 reassociatableMatchHelper(const MatchContext &Ctx, ArrayRef<SDValue> Leaves,
1667 Bitset<NumPatterns> &Used, PatternHd &HeadPattern,
1668 PatternTl &...TailPatterns) {
1669 for (size_t Match = 0, N = Used.size(); Match < N; Match++) {
1670 if (Used[Match] || !(sd_context_match(Leaves[Match], Ctx, HeadPattern)))
1671 continue;
1672 Used.set(Match);
1673 if (reassociatableMatchHelper(Ctx, Leaves, Used, TailPatterns...))
1674 return true;
1675 Used.reset(Match);
1676 }
1677 return false;
1678 }
1679
1680 template <typename MatchContext>
1681 [[nodiscard]] inline bool
1682 reassociatableMatchHelper(const MatchContext &Ctx, ArrayRef<SDValue> Leaves,
1683 Bitset<NumPatterns> &Used) {
1684 return true;
1685 }
1686};
1687
1688template <typename... PatternTs>
1689inline ReassociatableOpc_match<PatternTs...>
1690m_ReassociatableAdd(const PatternTs &...Patterns) {
1691 return ReassociatableOpc_match<PatternTs...>(ISD::ADD, Patterns...);
1692}
1693
1694template <typename... PatternTs>
1695inline ReassociatableOpc_match<PatternTs...>
1696m_ReassociatableOr(const PatternTs &...Patterns) {
1697 return ReassociatableOpc_match<PatternTs...>(ISD::OR, Patterns...);
1698}
1699
1700template <typename... PatternTs>
1701inline ReassociatableOpc_match<PatternTs...>
1702m_ReassociatableAnd(const PatternTs &...Patterns) {
1703 return ReassociatableOpc_match<PatternTs...>(ISD::AND, Patterns...);
1704}
1705
1706template <typename... PatternTs>
1707inline ReassociatableOpc_match<PatternTs...>
1708m_ReassociatableMul(const PatternTs &...Patterns) {
1709 return ReassociatableOpc_match<PatternTs...>(ISD::MUL, Patterns...);
1710}
1711
1712template <typename... PatternTs>
1713inline ReassociatableOpc_match<PatternTs...>
1714m_ReassociatableNSWAdd(const PatternTs &...Patterns) {
1715 return ReassociatableOpc_match<PatternTs...>(
1716 ISD::ADD, SDNodeFlags::NoSignedWrap, Patterns...);
1717}
1718
1719template <typename... PatternTs>
1720inline ReassociatableOpc_match<PatternTs...>
1721m_ReassociatableNUWAdd(const PatternTs &...Patterns) {
1722 return ReassociatableOpc_match<PatternTs...>(
1724}
1725
1726} // namespace SDPatternMatch
1727} // namespace llvm
1728#endif
return SDValue()
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements a class to represent arbitrary precision integral constant values and operations...
#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
MachineInstr unsigned OpIdx
#define P(N)
const SmallVectorImpl< MachineOperand > & Cond
This file contains some templates that are useful if you are working with the STL at all.
This file implements the SmallBitVector class.
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:1055
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
Definition APInt.h:372
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
Definition APInt.h:381
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition APInt.h:1513
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:555
bool isOne() const
Determine if this is a value of 1.
Definition APInt.h:390
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 isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
LLVM_ABI bool matchBinaryPredicate(SDValue LHS, SDValue RHS, std::function< bool(ConstantSDNode *, ConstantSDNode *)> Match, bool AllowUndefs=false, bool AllowTypeMismatch=false)
Attempt to match a binary predicate against a pair of scalar/splat constants or every element of a pa...
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
cst_pred_ty< is_all_ones > m_AllOnes()
Match an integer or vector with all bits set.
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)