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 BinaryOpc_match<LHS, RHS> m_Sub(const LHS &L, const RHS &R) {
833}
834
835template <typename LHS, typename RHS>
836inline BinaryOpc_match<LHS, RHS, true> m_Mul(const LHS &L, const RHS &R) {
838}
839
840template <typename LHS, typename RHS>
841inline BinaryOpc_match<LHS, RHS, true> m_And(const LHS &L, const RHS &R) {
843}
844
845template <typename LHS, typename RHS>
846inline BinaryOpc_match<LHS, RHS, true> m_Or(const LHS &L, const RHS &R) {
848}
849
850template <typename LHS, typename RHS>
855
856template <typename LHS, typename RHS>
857inline auto m_AddLike(const LHS &L, const RHS &R) {
858 return m_AnyOf(m_Add(L, R), m_DisjointOr(L, R));
859}
860
861template <typename LHS, typename RHS>
862inline BinaryOpc_match<LHS, RHS, true> m_Xor(const LHS &L, const RHS &R) {
864}
865
866template <typename LHS, typename RHS>
867inline auto m_BitwiseLogic(const LHS &L, const RHS &R) {
868 return m_AnyOf(m_And(L, R), m_Or(L, R), m_Xor(L, R));
869}
870
871template <unsigned Opc, typename Pred, typename LHS, typename RHS>
872inline auto m_MaxMinLike(const LHS &L, const RHS &R) {
875}
876
877template <typename LHS, typename RHS>
878inline BinaryOpc_match<LHS, RHS, true> m_SMin(const LHS &L, const RHS &R) {
880}
881
882template <typename LHS, typename RHS>
889
890template <typename LHS, typename RHS>
891inline BinaryOpc_match<LHS, RHS, true> m_SMax(const LHS &L, const RHS &R) {
893}
894
895template <typename LHS, typename RHS>
902
903template <typename LHS, typename RHS>
904inline BinaryOpc_match<LHS, RHS, true> m_UMin(const LHS &L, const RHS &R) {
906}
907
908template <typename LHS, typename RHS>
915
916template <typename LHS, typename RHS>
917inline BinaryOpc_match<LHS, RHS, true> m_UMax(const LHS &L, const RHS &R) {
919}
920
921template <typename LHS, typename RHS>
928
929template <typename LHS, typename RHS>
930inline BinaryOpc_match<LHS, RHS> m_UDiv(const LHS &L, const RHS &R) {
932}
933template <typename LHS, typename RHS>
934inline BinaryOpc_match<LHS, RHS> m_SDiv(const LHS &L, const RHS &R) {
936}
937
938template <typename LHS, typename RHS>
939inline BinaryOpc_match<LHS, RHS> m_URem(const LHS &L, const RHS &R) {
941}
942template <typename LHS, typename RHS>
943inline BinaryOpc_match<LHS, RHS> m_SRem(const LHS &L, const RHS &R) {
945}
946
947template <typename LHS, typename RHS>
948inline BinaryOpc_match<LHS, RHS> m_Shl(const LHS &L, const RHS &R) {
950}
951
952template <typename LHS, typename RHS>
953inline BinaryOpc_match<LHS, RHS> m_Sra(const LHS &L, const RHS &R) {
955}
956template <typename LHS, typename RHS>
957inline BinaryOpc_match<LHS, RHS> m_Srl(const LHS &L, const RHS &R) {
959}
960template <typename LHS, typename RHS>
965
966template <typename LHS, typename RHS>
967inline BinaryOpc_match<LHS, RHS> m_Rotl(const LHS &L, const RHS &R) {
969}
970
971template <typename LHS, typename RHS>
972inline BinaryOpc_match<LHS, RHS> m_Rotr(const LHS &L, const RHS &R) {
974}
975
976template <typename T0_P, typename T1_P, typename T2_P>
977inline TernaryOpc_match<T0_P, T1_P, T2_P>
978m_FShL(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
979 return m_TernaryOp(ISD::FSHL, Op0, Op1, Op2);
980}
981
982template <typename T0_P, typename T1_P, typename T2_P>
983inline TernaryOpc_match<T0_P, T1_P, T2_P>
984m_FShR(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
985 return m_TernaryOp(ISD::FSHR, Op0, Op1, Op2);
986}
987
988template <typename T0_P, typename T1_P, typename T2_P, bool Left>
990 T0_P Op0;
991 T1_P Op1;
992 T2_P Op2;
993
994 FunnelShiftLike_match(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2)
995 : Op0(Op0), Op1(Op1), Op2(Op2) {}
996
997 static bool hasComplementaryConstantShifts(const APInt &ShlV,
998 const APInt &SrlV,
999 unsigned BitWidth) {
1000 unsigned SumWidth = std::max(ShlV.getBitWidth(), SrlV.getBitWidth()) + 1;
1001 unsigned BitWidthBits = llvm::bit_width(BitWidth);
1002 if (BitWidthBits > SumWidth)
1003 return false;
1004
1005 return ShlV.zext(SumWidth) + SrlV.zext(SumWidth) ==
1006 APInt(SumWidth, BitWidth);
1007 }
1008
1009 template <typename MatchContext>
1010 bool matchOperands(const MatchContext &Ctx, SDValue X, SDValue Y, SDValue Z) {
1011 return Op0.match(Ctx, X) && Op1.match(Ctx, Y) && Op2.match(Ctx, Z);
1012 }
1013
1014 template <typename MatchContext>
1015 bool matchShiftOr(const MatchContext &Ctx, SDValue N, unsigned BitWidth);
1016
1017 template <typename MatchContext>
1018 bool match(const MatchContext &Ctx, SDValue N) {
1019 if (sd_context_match(N, Ctx,
1020 Left ? m_FShL(Op0, Op1, Op2) : m_FShR(Op0, Op1, Op2)))
1021 return true;
1022
1023 SDValue X, Z;
1024 if (sd_context_match(N, Ctx,
1025 Left ? m_Rotl(m_Value(X), m_Value(Z))
1026 : m_Rotr(m_Value(X), m_Value(Z))))
1027 return matchOperands(Ctx, X, X, Z);
1028
1029 return matchShiftOr(Ctx, N, N.getValueType().getScalarSizeInBits());
1030 }
1031};
1032
1033template <typename T0_P, typename T1_P, typename T2_P>
1034inline FunnelShiftLike_match<T0_P, T1_P, T2_P, true>
1035m_FShLLike(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
1037}
1038
1039template <typename T0_P, typename T1_P, typename T2_P>
1040inline FunnelShiftLike_match<T0_P, T1_P, T2_P, false>
1041m_FShRLike(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
1043}
1044
1045template <typename LHS, typename RHS>
1048}
1049
1050template <typename LHS, typename RHS>
1051inline BinaryOpc_match<LHS, RHS, true> m_FAdd(const LHS &L, const RHS &R) {
1053}
1054
1055template <typename LHS, typename RHS>
1056inline BinaryOpc_match<LHS, RHS> m_FSub(const LHS &L, const RHS &R) {
1058}
1059
1060template <typename LHS, typename RHS>
1061inline BinaryOpc_match<LHS, RHS, true> m_FMul(const LHS &L, const RHS &R) {
1063}
1064
1065template <typename LHS, typename RHS>
1066inline BinaryOpc_match<LHS, RHS> m_FDiv(const LHS &L, const RHS &R) {
1068}
1069
1070template <typename LHS, typename RHS>
1071inline BinaryOpc_match<LHS, RHS> m_FRem(const LHS &L, const RHS &R) {
1073}
1074
1075template <typename V1_t, typename V2_t>
1076inline BinaryOpc_match<V1_t, V2_t> m_Shuffle(const V1_t &v1, const V2_t &v2) {
1078}
1079
1080template <typename V1_t, typename V2_t, typename Mask_t>
1081inline SDShuffle_match<V1_t, V2_t, Mask_t>
1082m_Shuffle(const V1_t &v1, const V2_t &v2, const Mask_t &mask) {
1084}
1085
1086template <typename LHS, typename RHS>
1087inline BinaryOpc_match<LHS, RHS> m_ExtractElt(const LHS &Vec, const RHS &Idx) {
1089}
1090
1091template <typename LHS, typename RHS>
1093 const RHS &Idx) {
1095}
1096
1097// === Unary operations ===
1098template <typename Opnd_P, bool ExcludeChain = false> struct UnaryOpc_match {
1099 unsigned Opcode;
1100 Opnd_P Opnd;
1102 UnaryOpc_match(unsigned Opc, const Opnd_P &Op,
1103 SDNodeFlags Flgs = SDNodeFlags())
1104 : Opcode(Opc), Opnd(Op), Flags(Flgs) {}
1105
1106 template <typename MatchContext>
1107 bool match(const MatchContext &Ctx, SDValue N) {
1108 if (sd_context_match(N, Ctx, m_SpecificOpc(Opcode))) {
1110 assert(EO.Size == 1);
1111 if (!Opnd.match(Ctx, N->getOperand(EO.FirstIndex)))
1112 return false;
1113
1114 return (Flags & N->getFlags()) == Flags;
1115 }
1116
1117 return false;
1118 }
1119};
1120
1121template <typename Opnd>
1122inline UnaryOpc_match<Opnd> m_UnaryOp(unsigned Opc, const Opnd &Op) {
1123 return UnaryOpc_match<Opnd>(Opc, Op);
1124}
1125template <typename Opnd>
1127 const Opnd &Op) {
1129}
1130
1131template <typename Opnd> inline UnaryOpc_match<Opnd> m_BitCast(const Opnd &Op) {
1133}
1134
1135template <typename Opnd>
1136inline UnaryOpc_match<Opnd> m_BSwap(const Opnd &Op) {
1138}
1139
1140template <typename Opnd>
1144
1145template <typename Opnd> inline UnaryOpc_match<Opnd> m_ZExt(const Opnd &Op) {
1147}
1148
1149template <typename Opnd>
1153
1154template <typename Opnd> inline auto m_SExt(const Opnd &Op) {
1156}
1157
1158template <typename Opnd> inline UnaryOpc_match<Opnd> m_AnyExt(const Opnd &Op) {
1160}
1161
1162template <typename Opnd> inline UnaryOpc_match<Opnd> m_Trunc(const Opnd &Op) {
1164}
1165
1166template <typename Opnd> inline auto m_Abs(const Opnd &Op) {
1169}
1170
1171template <typename Opnd> inline UnaryOpc_match<Opnd> m_FAbs(const Opnd &Op) {
1173}
1174
1175/// Match a zext or identity
1176/// Allows to peek through optional extensions
1177template <typename Opnd> inline auto m_ZExtOrSelf(const Opnd &Op) {
1178 return m_AnyOf(m_ZExt(Op), Op);
1179}
1180
1181/// Match a sext or identity
1182/// Allows to peek through optional extensions
1183template <typename Opnd> inline auto m_SExtOrSelf(const Opnd &Op) {
1184 return m_AnyOf(m_SExt(Op), Op);
1185}
1186
1187template <typename Opnd> inline auto m_SExtLike(const Opnd &Op) {
1188 return m_AnyOf(m_SExt(Op), m_NNegZExt(Op));
1189}
1190
1191/// Match a aext or identity
1192/// Allows to peek through optional extensions
1193template <typename Opnd>
1194inline Or<UnaryOpc_match<Opnd>, Opnd> m_AExtOrSelf(const Opnd &Op) {
1195 return Or<UnaryOpc_match<Opnd>, Opnd>(m_AnyExt(Op), Op);
1196}
1197
1198/// Match a trunc or identity
1199/// Allows to peek through optional truncations
1200template <typename Opnd>
1201inline Or<UnaryOpc_match<Opnd>, Opnd> m_TruncOrSelf(const Opnd &Op) {
1202 return Or<UnaryOpc_match<Opnd>, Opnd>(m_Trunc(Op), Op);
1203}
1204
1205template <typename Opnd> inline UnaryOpc_match<Opnd> m_VScale(const Opnd &Op) {
1207}
1208
1209template <typename Opnd> inline UnaryOpc_match<Opnd> m_FPToUI(const Opnd &Op) {
1211}
1212
1213template <typename Opnd> inline UnaryOpc_match<Opnd> m_FPToSI(const Opnd &Op) {
1215}
1216
1217template <typename Opnd> inline UnaryOpc_match<Opnd> m_Ctpop(const Opnd &Op) {
1219}
1220
1221template <typename Opnd> inline UnaryOpc_match<Opnd> m_Ctlz(const Opnd &Op) {
1223}
1224
1225template <typename Opnd> inline UnaryOpc_match<Opnd> m_Cttz(const Opnd &Op) {
1227}
1228
1229template <typename Opnd> inline UnaryOpc_match<Opnd> m_FNeg(const Opnd &Op) {
1231}
1232
1233template <typename Opnd>
1237
1238// === Constants ===
1241
1242 explicit ConstantInt_match(APInt *V) : BindVal(V) {}
1243
1244 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
1245 // The logics here are similar to that in
1246 // SelectionDAG::isConstantIntBuildVectorOrConstantInt, but the latter also
1247 // treats GlobalAddressSDNode as a constant, which is difficult to turn into
1248 // APInt.
1249 if (auto *C = dyn_cast_or_null<ConstantSDNode>(N.getNode())) {
1250 if (BindVal)
1251 *BindVal = C->getAPIntValue();
1252 return true;
1253 }
1254
1255 APInt Discard;
1256 return ISD::isConstantSplatVector(N.getNode(),
1257 BindVal ? *BindVal : Discard);
1258 }
1259};
1260
1261template <typename T> struct Constant64_match {
1262 static_assert(sizeof(T) == 8, "T must be 64 bits wide");
1263
1265
1266 explicit Constant64_match(T &V) : BindVal(V) {}
1267
1268 template <typename MatchContext>
1269 bool match(const MatchContext &Ctx, SDValue N) {
1270 APInt V;
1271 if (!ConstantInt_match(&V).match(Ctx, N))
1272 return false;
1273
1274 if constexpr (std::is_signed_v<T>) {
1275 if (std::optional<int64_t> TrySExt = V.trySExtValue()) {
1276 BindVal = *TrySExt;
1277 return true;
1278 }
1279 }
1280
1281 if constexpr (std::is_unsigned_v<T>) {
1282 if (std::optional<uint64_t> TryZExt = V.tryZExtValue()) {
1283 BindVal = *TryZExt;
1284 return true;
1285 }
1286 }
1287
1288 return false;
1289 }
1290};
1291
1292/// Match any integer constants or splat of an integer constant.
1294/// Match any integer constants or splat of an integer constant; return the
1295/// specific constant or constant splat value.
1297/// Match any integer constants or splat of an integer constant that can fit in
1298/// 64 bits; return the specific constant or constant splat value, zero-extended
1299/// to 64 bits.
1303/// Match any integer constants or splat of an integer constant that can fit in
1304/// 64 bits; return the specific constant or constant splat value, sign-extended
1305/// to 64 bits.
1307 return Constant64_match<int64_t>(V);
1308}
1309
1310template <typename T0_P, typename T1_P, typename T2_P, bool Left>
1311template <typename MatchContext>
1313 const MatchContext &Ctx, SDValue N, unsigned BitWidth) {
1314 SDValue X, Y, ShlAmt, SrlAmt;
1315 APInt ShlConst, SrlConst;
1316 if (!sd_context_match(
1317 N, Ctx,
1318 m_Or(m_Shl(m_Value(X), m_Value(ShlAmt, m_ConstInt(ShlConst))),
1319 m_Srl(m_Value(Y), m_Value(SrlAmt, m_ConstInt(SrlConst))))) ||
1320 !hasComplementaryConstantShifts(ShlConst, SrlConst, BitWidth))
1321 return false;
1322
1323 return matchOperands(Ctx, X, Y, Left ? ShlAmt : SrlAmt);
1324}
1325
1328
1329 explicit SpecificInt_match(APInt APV) : IntVal(std::move(APV)) {}
1330
1331 template <typename MatchContext>
1332 bool match(const MatchContext &Ctx, SDValue N) {
1333 APInt ConstInt;
1334 if (sd_context_match(N, Ctx, m_ConstInt(ConstInt)))
1335 return APInt::isSameValue(IntVal, ConstInt);
1336 return false;
1337 }
1338};
1339
1340/// Match a specific integer constant or constant splat value.
1342 return SpecificInt_match(std::move(V));
1343}
1345 return SpecificInt_match(APInt(64, V));
1346}
1347
1350
1351 explicit SpecificFP_match(APFloat V) : Val(V) {}
1352
1353 template <typename MatchContext>
1354 bool match(const MatchContext &Ctx, SDValue V) {
1355 if (const auto *CFP = dyn_cast<ConstantFPSDNode>(V.getNode()))
1356 return CFP->isExactlyValue(Val);
1357 if (ConstantFPSDNode *C = isConstOrConstSplatFP(V, /*AllowUndefs=*/true))
1358 return C->getValueAPF().compare(Val) == APFloat::cmpEqual;
1359 return false;
1360 }
1361};
1362
1363/// Match a specific float constant.
1365
1367 return SpecificFP_match(APFloat(V));
1368}
1369
1371 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
1373 return C->isZero();
1374 return false;
1375 }
1376};
1377
1378/// Match a floating-point +0.0 or -0.0 constant or splat.
1380
1382 template <typename MatchContext>
1383 bool match(const MatchContext &Ctx, SDValue N) {
1384 const SelectionDAG *DAG = Ctx.getDAG();
1385 return DAG && DAG->computeKnownBits(N).isNegative();
1386 }
1387};
1388
1390 template <typename MatchContext>
1391 bool match(const MatchContext &Ctx, SDValue N) {
1392 const SelectionDAG *DAG = Ctx.getDAG();
1393 return DAG && DAG->computeKnownBits(N).isNonNegative();
1394 }
1395};
1396
1398 template <typename MatchContext>
1399 bool match(const MatchContext &Ctx, SDValue N) {
1400 const SelectionDAG *DAG = Ctx.getDAG();
1401 return DAG && DAG->computeKnownBits(N).isStrictlyPositive();
1402 }
1403};
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).isNonPositive();
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).isNonZero();
1418 }
1419};
1420
1423
1425
1426 template <typename MatchContext>
1427 bool match(const MatchContext &, SDValue N) const {
1429 }
1430};
1431
1434
1436
1437 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
1439 }
1440};
1441
1444
1446
1447 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
1449 }
1450};
1451
1453template <typename Pattern> inline auto m_Negative(const Pattern &P) {
1454 return m_AllOf(m_Negative(), P);
1455}
1457template <typename Pattern> inline auto m_NonNegative(const Pattern &P) {
1458 return m_AllOf(m_NonNegative(), P);
1459}
1463template <typename Pattern> inline auto m_StrictlyPositive(const Pattern &P) {
1464 return m_AllOf(m_StrictlyPositive(), P);
1465}
1467template <typename Pattern> inline auto m_NonPositive(const Pattern &P) {
1468 return m_AllOf(m_NonPositive(), P);
1469}
1471template <typename Pattern> inline auto m_NonZero(const Pattern &P) {
1472 return m_AllOf(m_NonZero(), P);
1473}
1474inline Ones_match m_One(bool AllowUndefs = false) {
1475 return Ones_match(AllowUndefs);
1476}
1477inline Zero_match m_Zero(bool AllowUndefs = false) {
1478 return Zero_match(AllowUndefs);
1479}
1480inline AllOnes_match m_AllOnes(bool AllowUndefs = false) {
1481 return AllOnes_match(AllowUndefs);
1482}
1483
1484/// Match true boolean value based on the information provided by
1485/// TargetLowering.
1486inline auto m_True() {
1487 return TLI_pred_match{
1488 [](const TargetLowering &TLI, SDValue N) {
1489 APInt ConstVal;
1490 if (sd_match(N, m_ConstInt(ConstVal)))
1491 switch (TLI.getBooleanContents(N.getValueType())) {
1493 return ConstVal.isOne();
1495 return ConstVal.isAllOnes();
1497 return (ConstVal & 0x01) == 1;
1498 }
1499
1500 return false;
1501 },
1502 m_Value()};
1503}
1504/// Match false boolean value based on the information provided by
1505/// TargetLowering.
1506inline auto m_False() {
1507 return TLI_pred_match{
1508 [](const TargetLowering &TLI, SDValue N) {
1509 APInt ConstVal;
1510 if (sd_match(N, m_ConstInt(ConstVal)))
1511 switch (TLI.getBooleanContents(N.getValueType())) {
1514 return ConstVal.isZero();
1516 return (ConstVal & 0x01) == 0;
1517 }
1518
1519 return false;
1520 },
1521 m_Value()};
1522}
1523
1525 std::optional<ISD::CondCode> CCToMatch;
1527
1529
1530 explicit CondCode_match(ISD::CondCode *CC) : BindCC(CC) {}
1531
1532 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
1533 if (auto *CC = dyn_cast<CondCodeSDNode>(N.getNode())) {
1534 if (CCToMatch && *CCToMatch != CC->get())
1535 return false;
1536
1537 if (BindCC)
1538 *BindCC = CC->get();
1539 return true;
1540 }
1541
1542 return false;
1543 }
1544};
1545
1546/// Match any conditional code SDNode.
1547inline CondCode_match m_CondCode() { return CondCode_match(nullptr); }
1548/// Match any conditional code SDNode and return its ISD::CondCode value.
1550 return CondCode_match(&CC);
1551}
1552/// Match a conditional code SDNode with a specific ISD::CondCode.
1556
1557/// Match a negate as a sub(0, v)
1558template <typename ValTy>
1560 return m_Sub(m_Zero(), V);
1561}
1562
1563/// Match a Not as a xor(v, -1) or xor(-1, v)
1564template <typename ValTy>
1566 return m_Xor(V, m_AllOnes());
1567}
1568
1569template <unsigned IntrinsicId, typename... OpndPreds>
1570inline auto m_IntrinsicWOChain(const OpndPreds &...Opnds) {
1571 return m_Node(ISD::INTRINSIC_WO_CHAIN, m_SpecificInt(IntrinsicId), Opnds...);
1572}
1573
1576
1578
1579 template <typename MatchContext>
1580 bool match(const MatchContext &Ctx, SDValue N) {
1581 if (sd_context_match(N, Ctx, m_Neg(m_Specific(V))))
1582 return true;
1583
1586 return LHS->getAPIntValue() == -RHS->getAPIntValue();
1587 });
1588 }
1589};
1590
1591/// Match a negation of a specific value V, either as sub(0, V) or as
1592/// constant(s) that are the negation of V's constant(s).
1596
1597template <typename... PatternTs> struct ReassociatableOpc_match {
1598 unsigned Opcode;
1599 std::tuple<PatternTs...> Patterns;
1600 constexpr static size_t NumPatterns =
1601 std::tuple_size_v<std::tuple<PatternTs...>>;
1602
1604
1605 ReassociatableOpc_match(unsigned Opcode, const PatternTs &...Patterns)
1606 : Opcode(Opcode), Patterns(Patterns...) {}
1607
1609 const PatternTs &...Patterns)
1611
1612 template <typename MatchContext>
1613 bool match(const MatchContext &Ctx, SDValue N) {
1614 std::array<SDValue, NumPatterns> Leaves;
1615 size_t LeavesIdx = 0;
1616 if (!(collectLeaves(N, Leaves, LeavesIdx) && (LeavesIdx == NumPatterns)))
1617 return false;
1618
1620 return std::apply(
1621 [&](auto &...P) -> bool {
1622 return reassociatableMatchHelper(Ctx, Leaves, Used, P...);
1623 },
1624 Patterns);
1625 }
1626
1627 bool collectLeaves(SDValue V, std::array<SDValue, NumPatterns> &Leaves,
1628 std::size_t &LeafIdx) {
1629 if (V->getOpcode() == Opcode && (Flags & V->getFlags()) == Flags) {
1630 for (size_t I = 0, N = V->getNumOperands(); I < N; I++)
1631 if ((LeafIdx == NumPatterns) ||
1632 !collectLeaves(V->getOperand(I), Leaves, LeafIdx))
1633 return false;
1634 } else {
1635 Leaves[LeafIdx] = V;
1636 LeafIdx++;
1637 }
1638 return true;
1639 }
1640
1641 // Searchs for a matching leaf for every sub-pattern.
1642 template <typename MatchContext, typename PatternHd, typename... PatternTl>
1643 [[nodiscard]] inline bool
1644 reassociatableMatchHelper(const MatchContext &Ctx, ArrayRef<SDValue> Leaves,
1645 Bitset<NumPatterns> &Used, PatternHd &HeadPattern,
1646 PatternTl &...TailPatterns) {
1647 for (size_t Match = 0, N = Used.size(); Match < N; Match++) {
1648 if (Used[Match] || !(sd_context_match(Leaves[Match], Ctx, HeadPattern)))
1649 continue;
1650 Used.set(Match);
1651 if (reassociatableMatchHelper(Ctx, Leaves, Used, TailPatterns...))
1652 return true;
1653 Used.reset(Match);
1654 }
1655 return false;
1656 }
1657
1658 template <typename MatchContext>
1659 [[nodiscard]] inline bool
1660 reassociatableMatchHelper(const MatchContext &Ctx, ArrayRef<SDValue> Leaves,
1661 Bitset<NumPatterns> &Used) {
1662 return true;
1663 }
1664};
1665
1666template <typename... PatternTs>
1667inline ReassociatableOpc_match<PatternTs...>
1668m_ReassociatableAdd(const PatternTs &...Patterns) {
1669 return ReassociatableOpc_match<PatternTs...>(ISD::ADD, Patterns...);
1670}
1671
1672template <typename... PatternTs>
1673inline ReassociatableOpc_match<PatternTs...>
1674m_ReassociatableOr(const PatternTs &...Patterns) {
1675 return ReassociatableOpc_match<PatternTs...>(ISD::OR, Patterns...);
1676}
1677
1678template <typename... PatternTs>
1679inline ReassociatableOpc_match<PatternTs...>
1680m_ReassociatableAnd(const PatternTs &...Patterns) {
1681 return ReassociatableOpc_match<PatternTs...>(ISD::AND, Patterns...);
1682}
1683
1684template <typename... PatternTs>
1685inline ReassociatableOpc_match<PatternTs...>
1686m_ReassociatableMul(const PatternTs &...Patterns) {
1687 return ReassociatableOpc_match<PatternTs...>(ISD::MUL, Patterns...);
1688}
1689
1690template <typename... PatternTs>
1691inline ReassociatableOpc_match<PatternTs...>
1692m_ReassociatableNSWAdd(const PatternTs &...Patterns) {
1693 return ReassociatableOpc_match<PatternTs...>(
1694 ISD::ADD, SDNodeFlags::NoSignedWrap, Patterns...);
1695}
1696
1697template <typename... PatternTs>
1698inline ReassociatableOpc_match<PatternTs...>
1699m_ReassociatableNUWAdd(const PatternTs &...Patterns) {
1700 return ReassociatableOpc_match<PatternTs...>(
1702}
1703
1704} // namespace SDPatternMatch
1705} // namespace llvm
1706#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)
#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...
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
Definition ISDOpcodes.h: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)
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)
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_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_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)