LLVM 22.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"
23
24namespace llvm {
25namespace SDPatternMatch {
26
27/// MatchContext can repurpose existing patterns to behave differently under
28/// a certain context. For instance, `m_Opc(ISD::ADD)` matches plain ADD nodes
29/// in normal circumstances, but matches VP_ADD nodes under a custom
30/// VPMatchContext. This design is meant to facilitate code / pattern reusing.
32 const SelectionDAG *DAG;
33 const TargetLowering *TLI;
34
35public:
36 explicit BasicMatchContext(const SelectionDAG *DAG)
37 : DAG(DAG), TLI(DAG ? &DAG->getTargetLoweringInfo() : nullptr) {}
38
39 explicit BasicMatchContext(const TargetLowering *TLI)
40 : DAG(nullptr), TLI(TLI) {}
41
42 // A valid MatchContext has to implement the following functions.
43
44 const SelectionDAG *getDAG() const { return DAG; }
45
46 const TargetLowering *getTLI() const { return TLI; }
47
48 /// Return true if N effectively has opcode Opcode.
49 bool match(SDValue N, unsigned Opcode) const {
50 return N->getOpcode() == Opcode;
51 }
52
53 unsigned getNumOperands(SDValue N) const { return N->getNumOperands(); }
54};
55
56template <typename Pattern, typename MatchContext>
57[[nodiscard]] bool sd_context_match(SDValue N, const MatchContext &Ctx,
58 Pattern &&P) {
59 return P.match(Ctx, N);
60}
61
62template <typename Pattern, typename MatchContext>
63[[nodiscard]] bool sd_context_match(SDNode *N, const MatchContext &Ctx,
64 Pattern &&P) {
65 return sd_context_match(SDValue(N, 0), Ctx, P);
66}
67
68template <typename Pattern>
69[[nodiscard]] bool sd_match(SDNode *N, const SelectionDAG *DAG, Pattern &&P) {
71}
72
73template <typename Pattern>
74[[nodiscard]] bool sd_match(SDValue N, const SelectionDAG *DAG, Pattern &&P) {
76}
77
78template <typename Pattern>
79[[nodiscard]] bool sd_match(SDNode *N, Pattern &&P) {
80 return sd_match(N, nullptr, P);
81}
82
83template <typename Pattern>
84[[nodiscard]] bool sd_match(SDValue N, Pattern &&P) {
85 return sd_match(N, nullptr, P);
86}
87
88// === Utilities ===
91
92 Value_match() = default;
93
94 explicit Value_match(SDValue Match) : MatchVal(Match) {}
95
96 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
97 if (MatchVal)
98 return MatchVal == N;
99 return N.getNode();
100 }
101};
102
103/// Match any valid SDValue.
104inline Value_match m_Value() { return Value_match(); }
105
107 assert(N);
108 return Value_match(N);
109}
110
111template <unsigned ResNo, typename Pattern> struct Result_match {
113
114 explicit Result_match(const Pattern &P) : P(P) {}
115
116 template <typename MatchContext>
117 bool match(const MatchContext &Ctx, SDValue N) {
118 return N.getResNo() == ResNo && P.match(Ctx, N);
119 }
120};
121
122/// Match only if the SDValue is a certain result at ResNo.
123template <unsigned ResNo, typename Pattern>
127
130
131 explicit DeferredValue_match(SDValue &Match) : MatchVal(Match) {}
132
133 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
134 return N == MatchVal;
135 }
136};
137
138/// Similar to m_Specific, but the specific value to match is determined by
139/// another sub-pattern in the same sd_match() expression. For instance,
140/// We cannot match `(add V, V)` with `m_Add(m_Value(X), m_Specific(X))` since
141/// `X` is not initialized at the time it got copied into `m_Specific`. Instead,
142/// we should use `m_Add(m_Value(X), m_Deferred(X))`.
146
148 unsigned Opcode;
149
150 explicit Opcode_match(unsigned Opc) : Opcode(Opc) {}
151
152 template <typename MatchContext>
153 bool match(const MatchContext &Ctx, SDValue N) {
154 return Ctx.match(N, Opcode);
155 }
156};
157
158// === Patterns combinators ===
159template <typename... Preds> struct And {
160 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
161 return true;
162 }
163};
164
165template <typename Pred, typename... Preds>
166struct And<Pred, Preds...> : And<Preds...> {
167 Pred P;
168 And(const Pred &p, const Preds &...preds) : And<Preds...>(preds...), P(p) {}
169
170 template <typename MatchContext>
171 bool match(const MatchContext &Ctx, SDValue N) {
172 return P.match(Ctx, N) && And<Preds...>::match(Ctx, N);
173 }
174};
175
176template <typename... Preds> struct Or {
177 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
178 return false;
179 }
180};
181
182template <typename Pred, typename... Preds>
183struct Or<Pred, Preds...> : Or<Preds...> {
184 Pred P;
185 Or(const Pred &p, const Preds &...preds) : Or<Preds...>(preds...), P(p) {}
186
187 template <typename MatchContext>
188 bool match(const MatchContext &Ctx, SDValue N) {
189 return P.match(Ctx, N) || Or<Preds...>::match(Ctx, N);
190 }
191};
192
193template <typename Pred> struct Not {
194 Pred P;
195
196 explicit Not(const Pred &P) : P(P) {}
197
198 template <typename MatchContext>
199 bool match(const MatchContext &Ctx, SDValue N) {
200 return !P.match(Ctx, N);
201 }
202};
203// Explicit deduction guide.
204template <typename Pred> Not(const Pred &P) -> Not<Pred>;
205
206/// Match if the inner pattern does NOT match.
207template <typename Pred> inline Not<Pred> m_Unless(const Pred &P) {
208 return Not{P};
209}
210
211template <typename... Preds> And<Preds...> m_AllOf(const Preds &...preds) {
212 return And<Preds...>(preds...);
213}
214
215template <typename... Preds> Or<Preds...> m_AnyOf(const Preds &...preds) {
216 return Or<Preds...>(preds...);
217}
218
219template <typename... Preds> auto m_NoneOf(const Preds &...preds) {
220 return m_Unless(m_AnyOf(preds...));
221}
222
223inline Opcode_match m_Opc(unsigned Opcode) { return Opcode_match(Opcode); }
224
226
228
229template <unsigned NumUses, typename Pattern> struct NUses_match {
231
232 explicit NUses_match(const Pattern &P) : P(P) {}
233
234 template <typename MatchContext>
235 bool match(const MatchContext &Ctx, SDValue N) {
236 // SDNode::hasNUsesOfValue is pretty expensive when the SDNode produces
237 // multiple results, hence we check the subsequent pattern here before
238 // checking the number of value users.
239 return P.match(Ctx, N) && N->hasNUsesOfValue(NumUses, N.getResNo());
240 }
241};
242
243template <typename Pattern>
247template <unsigned N, typename Pattern>
251
255template <unsigned N> inline NUses_match<N, Value_match> m_NUses() {
257}
258
261
262 explicit Value_bind(SDValue &N) : BindVal(N) {}
263
264 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
265 BindVal = N;
266 return true;
267 }
268};
269
270inline Value_bind m_Value(SDValue &N) { return Value_bind(N); }
271
272template <typename Pattern, typename PredFuncT> struct TLI_pred_match {
274 PredFuncT PredFunc;
275
276 TLI_pred_match(const PredFuncT &Pred, const Pattern &P)
277 : P(P), PredFunc(Pred) {}
278
279 template <typename MatchContext>
280 bool match(const MatchContext &Ctx, SDValue N) {
281 assert(Ctx.getTLI() && "TargetLowering is required for this pattern.");
282 return PredFunc(*Ctx.getTLI(), N) && P.match(Ctx, N);
283 }
284};
285
286// Explicit deduction guide.
287template <typename PredFuncT, typename Pattern>
288TLI_pred_match(const PredFuncT &Pred, const Pattern &P)
290
291/// Match legal SDNodes based on the information provided by TargetLowering.
292template <typename Pattern> inline auto m_LegalOp(const Pattern &P) {
293 return TLI_pred_match{[](const TargetLowering &TLI, SDValue N) {
294 return TLI.isOperationLegal(N->getOpcode(),
295 N.getValueType());
296 },
297 P};
298}
299
300/// Switch to a different MatchContext for subsequent patterns.
301template <typename NewMatchContext, typename Pattern> struct SwitchContext {
302 const NewMatchContext &Ctx;
304
305 template <typename OrigMatchContext>
306 bool match(const OrigMatchContext &, SDValue N) {
307 return P.match(Ctx, N);
308 }
309};
310
311template <typename MatchContext, typename Pattern>
312inline SwitchContext<MatchContext, Pattern> m_Context(const MatchContext &Ctx,
313 Pattern &&P) {
314 return SwitchContext<MatchContext, Pattern>{Ctx, std::move(P)};
315}
316
317// === Value type ===
320
321 explicit ValueType_bind(EVT &Bind) : BindVT(Bind) {}
322
323 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
324 BindVT = N.getValueType();
325 return true;
326 }
327};
328
329/// Retreive the ValueType of the current SDValue.
330inline ValueType_bind m_VT(EVT &VT) { return ValueType_bind(VT); }
331
332template <typename Pattern, typename PredFuncT> struct ValueType_match {
333 PredFuncT PredFunc;
335
336 ValueType_match(const PredFuncT &Pred, const Pattern &P)
337 : PredFunc(Pred), P(P) {}
338
339 template <typename MatchContext>
340 bool match(const MatchContext &Ctx, SDValue N) {
341 return PredFunc(N.getValueType()) && P.match(Ctx, N);
342 }
343};
344
345// Explicit deduction guide.
346template <typename PredFuncT, typename Pattern>
347ValueType_match(const PredFuncT &Pred, const Pattern &P)
349
350/// Match a specific ValueType.
351template <typename Pattern>
352inline auto m_SpecificVT(EVT RefVT, const Pattern &P) {
353 return ValueType_match{[=](EVT VT) { return VT == RefVT; }, P};
354}
355inline auto m_SpecificVT(EVT RefVT) {
356 return ValueType_match{[=](EVT VT) { return VT == RefVT; }, m_Value()};
357}
358
359inline auto m_Glue() { return m_SpecificVT(MVT::Glue); }
360inline auto m_OtherVT() { return m_SpecificVT(MVT::Other); }
361
362/// Match a scalar ValueType.
363template <typename Pattern>
364inline auto m_SpecificScalarVT(EVT RefVT, const Pattern &P) {
365 return ValueType_match{[=](EVT VT) { return VT.getScalarType() == RefVT; },
366 P};
367}
368inline auto m_SpecificScalarVT(EVT RefVT) {
369 return ValueType_match{[=](EVT VT) { return VT.getScalarType() == RefVT; },
370 m_Value()};
371}
372
373/// Match a vector ValueType.
374template <typename Pattern>
375inline auto m_SpecificVectorElementVT(EVT RefVT, const Pattern &P) {
376 return ValueType_match{[=](EVT VT) {
377 return VT.isVector() &&
378 VT.getVectorElementType() == RefVT;
379 },
380 P};
381}
382inline auto m_SpecificVectorElementVT(EVT RefVT) {
383 return ValueType_match{[=](EVT VT) {
384 return VT.isVector() &&
385 VT.getVectorElementType() == RefVT;
386 },
387 m_Value()};
388}
389
390/// Match any integer ValueTypes.
391template <typename Pattern> inline auto m_IntegerVT(const Pattern &P) {
392 return ValueType_match{[](EVT VT) { return VT.isInteger(); }, P};
393}
394inline auto m_IntegerVT() {
395 return ValueType_match{[](EVT VT) { return VT.isInteger(); }, m_Value()};
396}
397
398/// Match any floating point ValueTypes.
399template <typename Pattern> inline auto m_FloatingPointVT(const Pattern &P) {
400 return ValueType_match{[](EVT VT) { return VT.isFloatingPoint(); }, P};
401}
402inline auto m_FloatingPointVT() {
403 return ValueType_match{[](EVT VT) { return VT.isFloatingPoint(); },
404 m_Value()};
405}
406
407/// Match any vector ValueTypes.
408template <typename Pattern> inline auto m_VectorVT(const Pattern &P) {
409 return ValueType_match{[](EVT VT) { return VT.isVector(); }, P};
410}
411inline auto m_VectorVT() {
412 return ValueType_match{[](EVT VT) { return VT.isVector(); }, m_Value()};
413}
414
415/// Match fixed-length vector ValueTypes.
416template <typename Pattern> inline auto m_FixedVectorVT(const Pattern &P) {
417 return ValueType_match{[](EVT VT) { return VT.isFixedLengthVector(); }, P};
418}
419inline auto m_FixedVectorVT() {
420 return ValueType_match{[](EVT VT) { return VT.isFixedLengthVector(); },
421 m_Value()};
422}
423
424/// Match scalable vector ValueTypes.
425template <typename Pattern> inline auto m_ScalableVectorVT(const Pattern &P) {
426 return ValueType_match{[](EVT VT) { return VT.isScalableVector(); }, P};
427}
428inline auto m_ScalableVectorVT() {
429 return ValueType_match{[](EVT VT) { return VT.isScalableVector(); },
430 m_Value()};
431}
432
433/// Match legal ValueTypes based on the information provided by TargetLowering.
434template <typename Pattern> inline auto m_LegalType(const Pattern &P) {
435 return TLI_pred_match{[](const TargetLowering &TLI, SDValue N) {
436 return TLI.isTypeLegal(N.getValueType());
437 },
438 P};
439}
440
441// === Generic node matching ===
442template <unsigned OpIdx, typename... OpndPreds> struct Operands_match {
443 template <typename MatchContext>
444 bool match(const MatchContext &Ctx, SDValue N) {
445 // Returns false if there are more operands than predicates;
446 // Ignores the last two operands if both the Context and the Node are VP
447 return Ctx.getNumOperands(N) == OpIdx;
448 }
449};
450
451template <unsigned OpIdx, typename OpndPred, typename... OpndPreds>
452struct Operands_match<OpIdx, OpndPred, OpndPreds...>
453 : Operands_match<OpIdx + 1, OpndPreds...> {
454 OpndPred P;
455
456 Operands_match(const OpndPred &p, const OpndPreds &...preds)
457 : Operands_match<OpIdx + 1, OpndPreds...>(preds...), P(p) {}
458
459 template <typename MatchContext>
460 bool match(const MatchContext &Ctx, SDValue N) {
461 if (OpIdx < N->getNumOperands())
462 return P.match(Ctx, N->getOperand(OpIdx)) &&
464
465 // This is the case where there are more predicates than operands.
466 return false;
467 }
468};
469
470template <typename... OpndPreds>
471auto m_Node(unsigned Opcode, const OpndPreds &...preds) {
472 return m_AllOf(m_Opc(Opcode), Operands_match<0, OpndPreds...>(preds...));
473}
474
475/// Provide number of operands that are not chain or glue, as well as the first
476/// index of such operand.
477template <bool ExcludeChain> struct EffectiveOperands {
478 unsigned Size = 0;
479 unsigned FirstIndex = 0;
480
481 template <typename MatchContext>
482 explicit EffectiveOperands(SDValue N, const MatchContext &Ctx) {
483 const unsigned TotalNumOps = Ctx.getNumOperands(N);
484 FirstIndex = TotalNumOps;
485 for (unsigned I = 0; I < TotalNumOps; ++I) {
486 // Count the number of non-chain and non-glue nodes (we ignore chain
487 // and glue by default) and retreive the operand index offset.
488 EVT VT = N->getOperand(I).getValueType();
489 if (VT != MVT::Glue && VT != MVT::Other) {
490 ++Size;
491 if (FirstIndex == TotalNumOps)
492 FirstIndex = I;
493 }
494 }
495 }
496};
497
498template <> struct EffectiveOperands<false> {
499 unsigned Size = 0;
500 unsigned FirstIndex = 0;
501
502 template <typename MatchContext>
503 explicit EffectiveOperands(SDValue N, const MatchContext &Ctx)
504 : Size(Ctx.getNumOperands(N)) {}
505};
506
507// === Ternary operations ===
508template <typename T0_P, typename T1_P, typename T2_P, bool Commutable = false,
509 bool ExcludeChain = false>
511 unsigned Opcode;
512 T0_P Op0;
513 T1_P Op1;
514 T2_P Op2;
515
516 TernaryOpc_match(unsigned Opc, const T0_P &Op0, const T1_P &Op1,
517 const T2_P &Op2)
518 : Opcode(Opc), Op0(Op0), Op1(Op1), Op2(Op2) {}
519
520 template <typename MatchContext>
521 bool match(const MatchContext &Ctx, SDValue N) {
522 if (sd_context_match(N, Ctx, m_Opc(Opcode))) {
524 assert(EO.Size == 3);
525 return ((Op0.match(Ctx, N->getOperand(EO.FirstIndex)) &&
526 Op1.match(Ctx, N->getOperand(EO.FirstIndex + 1))) ||
527 (Commutable && Op0.match(Ctx, N->getOperand(EO.FirstIndex + 1)) &&
528 Op1.match(Ctx, N->getOperand(EO.FirstIndex)))) &&
529 Op2.match(Ctx, N->getOperand(EO.FirstIndex + 2));
530 }
531
532 return false;
533 }
534};
535
536template <typename T0_P, typename T1_P, typename T2_P>
537inline TernaryOpc_match<T0_P, T1_P, T2_P>
538m_SetCC(const T0_P &LHS, const T1_P &RHS, const T2_P &CC) {
540}
541
542template <typename T0_P, typename T1_P, typename T2_P>
543inline TernaryOpc_match<T0_P, T1_P, T2_P, true, false>
544m_c_SetCC(const T0_P &LHS, const T1_P &RHS, const T2_P &CC) {
546 CC);
547}
548
549template <typename T0_P, typename T1_P, typename T2_P>
550inline TernaryOpc_match<T0_P, T1_P, T2_P>
551m_Select(const T0_P &Cond, const T1_P &T, const T2_P &F) {
553}
554
555template <typename T0_P, typename T1_P, typename T2_P>
556inline TernaryOpc_match<T0_P, T1_P, T2_P>
557m_VSelect(const T0_P &Cond, const T1_P &T, const T2_P &F) {
559}
560
561template <typename T0_P, typename T1_P, typename T2_P>
562inline auto m_SelectLike(const T0_P &Cond, const T1_P &T, const T2_P &F) {
563 return m_AnyOf(m_Select(Cond, T, F), m_VSelect(Cond, T, F));
564}
565
566template <typename T0_P, typename T1_P, typename T2_P>
567inline Result_match<0, TernaryOpc_match<T0_P, T1_P, T2_P>>
568m_Load(const T0_P &Ch, const T1_P &Ptr, const T2_P &Offset) {
569 return m_Result<0>(
570 TernaryOpc_match<T0_P, T1_P, T2_P>(ISD::LOAD, Ch, Ptr, Offset));
571}
572
573template <typename T0_P, typename T1_P, typename T2_P>
574inline TernaryOpc_match<T0_P, T1_P, T2_P>
575m_InsertElt(const T0_P &Vec, const T1_P &Val, const T2_P &Idx) {
577 Idx);
578}
579
580template <typename LHS, typename RHS, typename IDX>
581inline TernaryOpc_match<LHS, RHS, IDX>
582m_InsertSubvector(const LHS &Base, const RHS &Sub, const IDX &Idx) {
584}
585
586template <typename T0_P, typename T1_P, typename T2_P>
587inline TernaryOpc_match<T0_P, T1_P, T2_P>
588m_TernaryOp(unsigned Opc, const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
589 return TernaryOpc_match<T0_P, T1_P, T2_P>(Opc, Op0, Op1, Op2);
590}
591
592template <typename T0_P, typename T1_P, typename T2_P>
593inline TernaryOpc_match<T0_P, T1_P, T2_P, true>
594m_c_TernaryOp(unsigned Opc, const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
595 return TernaryOpc_match<T0_P, T1_P, T2_P, true>(Opc, Op0, Op1, Op2);
596}
597
598template <typename LTy, typename RTy, typename TTy, typename FTy, typename CCTy>
599inline auto m_SelectCC(const LTy &L, const RTy &R, const TTy &T, const FTy &F,
600 const CCTy &CC) {
601 return m_Node(ISD::SELECT_CC, L, R, T, F, CC);
602}
603
604template <typename LTy, typename RTy, typename TTy, typename FTy, typename CCTy>
605inline auto m_SelectCCLike(const LTy &L, const RTy &R, const TTy &T,
606 const FTy &F, const CCTy &CC) {
607 return m_AnyOf(m_Select(m_SetCC(L, R, CC), T, F), m_SelectCC(L, R, T, F, CC));
608}
609
610// === Binary operations ===
611template <typename LHS_P, typename RHS_P, bool Commutable = false,
612 bool ExcludeChain = false>
614 unsigned Opcode;
615 LHS_P LHS;
616 RHS_P RHS;
618 BinaryOpc_match(unsigned Opc, const LHS_P &L, const RHS_P &R,
619 SDNodeFlags Flgs = SDNodeFlags())
620 : Opcode(Opc), LHS(L), RHS(R), Flags(Flgs) {}
621
622 template <typename MatchContext>
623 bool match(const MatchContext &Ctx, SDValue N) {
624 if (sd_context_match(N, Ctx, m_Opc(Opcode))) {
626 assert(EO.Size == 2);
627 if (!((LHS.match(Ctx, N->getOperand(EO.FirstIndex)) &&
628 RHS.match(Ctx, N->getOperand(EO.FirstIndex + 1))) ||
629 (Commutable && LHS.match(Ctx, N->getOperand(EO.FirstIndex + 1)) &&
630 RHS.match(Ctx, N->getOperand(EO.FirstIndex)))))
631 return false;
632
633 return (Flags & N->getFlags()) == Flags;
634 }
635
636 return false;
637 }
638};
639
640/// Matching while capturing mask
641template <typename T0, typename T1, typename T2> struct SDShuffle_match {
642 T0 Op1;
645
646 SDShuffle_match(const T0 &Op1, const T1 &Op2, const T2 &Mask)
647 : Op1(Op1), Op2(Op2), Mask(Mask) {}
648
649 template <typename MatchContext>
650 bool match(const MatchContext &Ctx, SDValue N) {
651 if (auto *I = dyn_cast<ShuffleVectorSDNode>(N)) {
652 return Op1.match(Ctx, I->getOperand(0)) &&
653 Op2.match(Ctx, I->getOperand(1)) && Mask.match(I->getMask());
654 }
655 return false;
656 }
657};
658struct m_Mask {
661 bool match(ArrayRef<int> Mask) {
662 MaskRef = Mask;
663 return true;
664 }
665};
666
672
673template <typename LHS_P, typename RHS_P, typename Pred_t,
674 bool Commutable = false, bool ExcludeChain = false>
676 using PredType = Pred_t;
677 LHS_P LHS;
678 RHS_P RHS;
679
680 MaxMin_match(const LHS_P &L, const RHS_P &R) : LHS(L), RHS(R) {}
681
682 template <typename MatchContext>
683 bool match(const MatchContext &Ctx, SDValue N) {
684 auto MatchMinMax = [&](SDValue L, SDValue R, SDValue TrueValue,
685 SDValue FalseValue, ISD::CondCode CC) {
686 if ((TrueValue != L || FalseValue != R) &&
687 (TrueValue != R || FalseValue != L))
688 return false;
689
691 TrueValue == L ? CC : getSetCCInverse(CC, L.getValueType());
692 if (!Pred_t::match(Cond))
693 return false;
694
695 return (LHS.match(Ctx, L) && RHS.match(Ctx, R)) ||
696 (Commutable && LHS.match(Ctx, R) && RHS.match(Ctx, L));
697 };
698
699 if (sd_context_match(N, Ctx, m_Opc(ISD::SELECT)) ||
701 EffectiveOperands<ExcludeChain> EO_SELECT(N, Ctx);
702 assert(EO_SELECT.Size == 3);
703 SDValue Cond = N->getOperand(EO_SELECT.FirstIndex);
704 SDValue TrueValue = N->getOperand(EO_SELECT.FirstIndex + 1);
705 SDValue FalseValue = N->getOperand(EO_SELECT.FirstIndex + 2);
706
709 assert(EO_SETCC.Size == 3);
710 SDValue L = Cond->getOperand(EO_SETCC.FirstIndex);
711 SDValue R = Cond->getOperand(EO_SETCC.FirstIndex + 1);
712 auto *CondNode =
713 cast<CondCodeSDNode>(Cond->getOperand(EO_SETCC.FirstIndex + 2));
714 return MatchMinMax(L, R, TrueValue, FalseValue, CondNode->get());
715 }
716 }
717
719 EffectiveOperands<ExcludeChain> EO_SELECT(N, Ctx);
720 assert(EO_SELECT.Size == 5);
721 SDValue L = N->getOperand(EO_SELECT.FirstIndex);
722 SDValue R = N->getOperand(EO_SELECT.FirstIndex + 1);
723 SDValue TrueValue = N->getOperand(EO_SELECT.FirstIndex + 2);
724 SDValue FalseValue = N->getOperand(EO_SELECT.FirstIndex + 3);
725 auto *CondNode =
726 cast<CondCodeSDNode>(N->getOperand(EO_SELECT.FirstIndex + 4));
727 return MatchMinMax(L, R, TrueValue, FalseValue, CondNode->get());
728 }
729
730 return false;
731 }
732};
733
734// Helper class for identifying signed max predicates.
736 static bool match(ISD::CondCode Cond) {
738 }
739};
740
741// Helper class for identifying unsigned max predicates.
746};
747
748// Helper class for identifying signed min predicates.
750 static bool match(ISD::CondCode Cond) {
752 }
753};
754
755// Helper class for identifying unsigned min predicates.
760};
761
762template <typename LHS, typename RHS>
763inline BinaryOpc_match<LHS, RHS> m_BinOp(unsigned Opc, const LHS &L,
764 const RHS &R) {
765 return BinaryOpc_match<LHS, RHS>(Opc, L, R);
766}
767template <typename LHS, typename RHS>
769 const RHS &R) {
771}
772
773template <typename LHS, typename RHS>
775m_ChainedBinOp(unsigned Opc, const LHS &L, const RHS &R) {
777}
778template <typename LHS, typename RHS>
780m_c_ChainedBinOp(unsigned Opc, const LHS &L, const RHS &R) {
782}
783
784// Common binary operations
785template <typename LHS, typename RHS>
786inline BinaryOpc_match<LHS, RHS, true> m_Add(const LHS &L, const RHS &R) {
788}
789
790template <typename LHS, typename RHS>
791inline BinaryOpc_match<LHS, RHS> m_Sub(const LHS &L, const RHS &R) {
793}
794
795template <typename LHS, typename RHS>
796inline BinaryOpc_match<LHS, RHS, true> m_Mul(const LHS &L, const RHS &R) {
798}
799
800template <typename LHS, typename RHS>
801inline BinaryOpc_match<LHS, RHS, true> m_And(const LHS &L, const RHS &R) {
803}
804
805template <typename LHS, typename RHS>
806inline BinaryOpc_match<LHS, RHS, true> m_Or(const LHS &L, const RHS &R) {
808}
809
810template <typename LHS, typename RHS>
815
816template <typename LHS, typename RHS>
817inline auto m_AddLike(const LHS &L, const RHS &R) {
818 return m_AnyOf(m_Add(L, R), m_DisjointOr(L, R));
819}
820
821template <typename LHS, typename RHS>
822inline BinaryOpc_match<LHS, RHS, true> m_Xor(const LHS &L, const RHS &R) {
824}
825
826template <typename LHS, typename RHS>
827inline auto m_BitwiseLogic(const LHS &L, const RHS &R) {
828 return m_AnyOf(m_And(L, R), m_Or(L, R), m_Xor(L, R));
829}
830
831template <typename LHS, typename RHS>
832inline BinaryOpc_match<LHS, RHS, true> m_SMin(const LHS &L, const RHS &R) {
834}
835
836template <typename LHS, typename RHS>
837inline auto m_SMinLike(const LHS &L, const RHS &R) {
840}
841
842template <typename LHS, typename RHS>
843inline BinaryOpc_match<LHS, RHS, true> m_SMax(const LHS &L, const RHS &R) {
845}
846
847template <typename LHS, typename RHS>
848inline auto m_SMaxLike(const LHS &L, const RHS &R) {
851}
852
853template <typename LHS, typename RHS>
854inline BinaryOpc_match<LHS, RHS, true> m_UMin(const LHS &L, const RHS &R) {
856}
857
858template <typename LHS, typename RHS>
859inline auto m_UMinLike(const LHS &L, const RHS &R) {
862}
863
864template <typename LHS, typename RHS>
865inline BinaryOpc_match<LHS, RHS, true> m_UMax(const LHS &L, const RHS &R) {
867}
868
869template <typename LHS, typename RHS>
870inline auto m_UMaxLike(const LHS &L, const RHS &R) {
873}
874
875template <typename LHS, typename RHS>
876inline BinaryOpc_match<LHS, RHS> m_UDiv(const LHS &L, const RHS &R) {
878}
879template <typename LHS, typename RHS>
880inline BinaryOpc_match<LHS, RHS> m_SDiv(const LHS &L, const RHS &R) {
882}
883
884template <typename LHS, typename RHS>
885inline BinaryOpc_match<LHS, RHS> m_URem(const LHS &L, const RHS &R) {
887}
888template <typename LHS, typename RHS>
889inline BinaryOpc_match<LHS, RHS> m_SRem(const LHS &L, const RHS &R) {
891}
892
893template <typename LHS, typename RHS>
894inline BinaryOpc_match<LHS, RHS> m_Shl(const LHS &L, const RHS &R) {
896}
897
898template <typename LHS, typename RHS>
899inline BinaryOpc_match<LHS, RHS> m_Sra(const LHS &L, const RHS &R) {
901}
902template <typename LHS, typename RHS>
903inline BinaryOpc_match<LHS, RHS> m_Srl(const LHS &L, const RHS &R) {
905}
906template <typename LHS, typename RHS>
911
912template <typename LHS, typename RHS>
913inline BinaryOpc_match<LHS, RHS> m_Rotl(const LHS &L, const RHS &R) {
915}
916
917template <typename LHS, typename RHS>
918inline BinaryOpc_match<LHS, RHS> m_Rotr(const LHS &L, const RHS &R) {
920}
921
922template <typename LHS, typename RHS>
923inline BinaryOpc_match<LHS, RHS, true> m_FAdd(const LHS &L, const RHS &R) {
925}
926
927template <typename LHS, typename RHS>
928inline BinaryOpc_match<LHS, RHS> m_FSub(const LHS &L, const RHS &R) {
930}
931
932template <typename LHS, typename RHS>
933inline BinaryOpc_match<LHS, RHS, true> m_FMul(const LHS &L, const RHS &R) {
935}
936
937template <typename LHS, typename RHS>
938inline BinaryOpc_match<LHS, RHS> m_FDiv(const LHS &L, const RHS &R) {
940}
941
942template <typename LHS, typename RHS>
943inline BinaryOpc_match<LHS, RHS> m_FRem(const LHS &L, const RHS &R) {
945}
946
947template <typename V1_t, typename V2_t>
948inline BinaryOpc_match<V1_t, V2_t> m_Shuffle(const V1_t &v1, const V2_t &v2) {
950}
951
952template <typename V1_t, typename V2_t, typename Mask_t>
953inline SDShuffle_match<V1_t, V2_t, Mask_t>
954m_Shuffle(const V1_t &v1, const V2_t &v2, const Mask_t &mask) {
956}
957
958template <typename LHS, typename RHS>
959inline BinaryOpc_match<LHS, RHS> m_ExtractElt(const LHS &Vec, const RHS &Idx) {
961}
962
963template <typename LHS, typename RHS>
965 const RHS &Idx) {
967}
968
969// === Unary operations ===
970template <typename Opnd_P, bool ExcludeChain = false> struct UnaryOpc_match {
971 unsigned Opcode;
972 Opnd_P Opnd;
973 std::optional<SDNodeFlags> Flags;
974 UnaryOpc_match(unsigned Opc, const Opnd_P &Op,
975 std::optional<SDNodeFlags> Flgs = std::nullopt)
976 : Opcode(Opc), Opnd(Op), Flags(Flgs) {}
977
978 template <typename MatchContext>
979 bool match(const MatchContext &Ctx, SDValue N) {
980 if (sd_context_match(N, Ctx, m_Opc(Opcode))) {
982 assert(EO.Size == 1);
983 if (!Opnd.match(Ctx, N->getOperand(EO.FirstIndex)))
984 return false;
985 if (!Flags.has_value())
986 return true;
987
988 return (*Flags & N->getFlags()) == *Flags;
989 }
990
991 return false;
992 }
993};
994
995template <typename Opnd>
996inline UnaryOpc_match<Opnd> m_UnaryOp(unsigned Opc, const Opnd &Op) {
997 return UnaryOpc_match<Opnd>(Opc, Op);
998}
999template <typename Opnd>
1001 const Opnd &Op) {
1003}
1004
1005template <typename Opnd> inline UnaryOpc_match<Opnd> m_BitCast(const Opnd &Op) {
1006 return UnaryOpc_match<Opnd>(ISD::BITCAST, Op);
1007}
1008
1009template <typename Opnd>
1010inline UnaryOpc_match<Opnd> m_BSwap(const Opnd &Op) {
1012}
1013
1014template <typename Opnd>
1018
1019template <typename Opnd> inline UnaryOpc_match<Opnd> m_ZExt(const Opnd &Op) {
1021}
1022
1023template <typename Opnd>
1027
1028template <typename Opnd> inline auto m_SExt(const Opnd &Op) {
1030}
1031
1032template <typename Opnd> inline UnaryOpc_match<Opnd> m_AnyExt(const Opnd &Op) {
1034}
1035
1036template <typename Opnd> inline UnaryOpc_match<Opnd> m_Trunc(const Opnd &Op) {
1038}
1039
1040template <typename Opnd> inline UnaryOpc_match<Opnd> m_Abs(const Opnd &Op) {
1042}
1043
1044/// Match a zext or identity
1045/// Allows to peek through optional extensions
1046template <typename Opnd> inline auto m_ZExtOrSelf(const Opnd &Op) {
1047 return m_AnyOf(m_ZExt(Op), Op);
1048}
1049
1050/// Match a sext or identity
1051/// Allows to peek through optional extensions
1052template <typename Opnd> inline auto m_SExtOrSelf(const Opnd &Op) {
1053 return m_AnyOf(m_SExt(Op), Op);
1054}
1055
1056template <typename Opnd> inline auto m_SExtLike(const Opnd &Op) {
1057 return m_AnyOf(m_SExt(Op), m_NNegZExt(Op));
1058}
1059
1060/// Match a aext or identity
1061/// Allows to peek through optional extensions
1062template <typename Opnd>
1063inline Or<UnaryOpc_match<Opnd>, Opnd> m_AExtOrSelf(const Opnd &Op) {
1064 return Or<UnaryOpc_match<Opnd>, Opnd>(m_AnyExt(Op), Op);
1065}
1066
1067/// Match a trunc or identity
1068/// Allows to peek through optional truncations
1069template <typename Opnd>
1070inline Or<UnaryOpc_match<Opnd>, Opnd> m_TruncOrSelf(const Opnd &Op) {
1071 return Or<UnaryOpc_match<Opnd>, Opnd>(m_Trunc(Op), Op);
1072}
1073
1074template <typename Opnd> inline UnaryOpc_match<Opnd> m_VScale(const Opnd &Op) {
1075 return UnaryOpc_match<Opnd>(ISD::VSCALE, Op);
1076}
1077
1078template <typename Opnd> inline UnaryOpc_match<Opnd> m_FPToUI(const Opnd &Op) {
1080}
1081
1082template <typename Opnd> inline UnaryOpc_match<Opnd> m_FPToSI(const Opnd &Op) {
1084}
1085
1086template <typename Opnd> inline UnaryOpc_match<Opnd> m_Ctpop(const Opnd &Op) {
1088}
1089
1090template <typename Opnd> inline UnaryOpc_match<Opnd> m_Ctlz(const Opnd &Op) {
1092}
1093
1094template <typename Opnd> inline UnaryOpc_match<Opnd> m_Cttz(const Opnd &Op) {
1096}
1097
1098template <typename Opnd> inline UnaryOpc_match<Opnd> m_FNeg(const Opnd &Op) {
1099 return UnaryOpc_match<Opnd>(ISD::FNEG, Op);
1100}
1101
1102// === Constants ===
1105
1106 explicit ConstantInt_match(APInt *V) : BindVal(V) {}
1107
1108 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
1109 // The logics here are similar to that in
1110 // SelectionDAG::isConstantIntBuildVectorOrConstantInt, but the latter also
1111 // treats GlobalAddressSDNode as a constant, which is difficult to turn into
1112 // APInt.
1113 if (auto *C = dyn_cast_or_null<ConstantSDNode>(N.getNode())) {
1114 if (BindVal)
1115 *BindVal = C->getAPIntValue();
1116 return true;
1117 }
1118
1119 APInt Discard;
1120 return ISD::isConstantSplatVector(N.getNode(),
1121 BindVal ? *BindVal : Discard);
1122 }
1123};
1124/// Match any integer constants or splat of an integer constant.
1126/// Match any integer constants or splat of an integer constant; return the
1127/// specific constant or constant splat value.
1129
1132
1133 explicit SpecificInt_match(APInt APV) : IntVal(std::move(APV)) {}
1134
1135 template <typename MatchContext>
1136 bool match(const MatchContext &Ctx, SDValue N) {
1137 APInt ConstInt;
1138 if (sd_context_match(N, Ctx, m_ConstInt(ConstInt)))
1139 return APInt::isSameValue(IntVal, ConstInt);
1140 return false;
1141 }
1142};
1143
1144/// Match a specific integer constant or constant splat value.
1146 return SpecificInt_match(std::move(V));
1147}
1149 return SpecificInt_match(APInt(64, V));
1150}
1151
1154
1156
1157 template <typename MatchContext>
1158 bool match(const MatchContext &, SDValue N) const {
1160 }
1161};
1162
1165
1167
1168 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
1170 }
1171};
1172
1175
1177
1178 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
1180 }
1181};
1182
1183inline Ones_match m_One(bool AllowUndefs = false) {
1184 return Ones_match(AllowUndefs);
1185}
1186inline Zero_match m_Zero(bool AllowUndefs = false) {
1187 return Zero_match(AllowUndefs);
1188}
1189inline AllOnes_match m_AllOnes(bool AllowUndefs = false) {
1190 return AllOnes_match(AllowUndefs);
1191}
1192
1193/// Match true boolean value based on the information provided by
1194/// TargetLowering.
1195inline auto m_True() {
1196 return TLI_pred_match{
1197 [](const TargetLowering &TLI, SDValue N) {
1198 APInt ConstVal;
1199 if (sd_match(N, m_ConstInt(ConstVal)))
1200 switch (TLI.getBooleanContents(N.getValueType())) {
1202 return ConstVal.isOne();
1204 return ConstVal.isAllOnes();
1206 return (ConstVal & 0x01) == 1;
1207 }
1208
1209 return false;
1210 },
1211 m_Value()};
1212}
1213/// Match false boolean value based on the information provided by
1214/// TargetLowering.
1215inline auto m_False() {
1216 return TLI_pred_match{
1217 [](const TargetLowering &TLI, SDValue N) {
1218 APInt ConstVal;
1219 if (sd_match(N, m_ConstInt(ConstVal)))
1220 switch (TLI.getBooleanContents(N.getValueType())) {
1223 return ConstVal.isZero();
1225 return (ConstVal & 0x01) == 0;
1226 }
1227
1228 return false;
1229 },
1230 m_Value()};
1231}
1232
1234 std::optional<ISD::CondCode> CCToMatch;
1236
1238
1239 explicit CondCode_match(ISD::CondCode *CC) : BindCC(CC) {}
1240
1241 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
1242 if (auto *CC = dyn_cast<CondCodeSDNode>(N.getNode())) {
1243 if (CCToMatch && *CCToMatch != CC->get())
1244 return false;
1245
1246 if (BindCC)
1247 *BindCC = CC->get();
1248 return true;
1249 }
1250
1251 return false;
1252 }
1253};
1254
1255/// Match any conditional code SDNode.
1256inline CondCode_match m_CondCode() { return CondCode_match(nullptr); }
1257/// Match any conditional code SDNode and return its ISD::CondCode value.
1259 return CondCode_match(&CC);
1260}
1261/// Match a conditional code SDNode with a specific ISD::CondCode.
1265
1266/// Match a negate as a sub(0, v)
1267template <typename ValTy>
1269 return m_Sub(m_Zero(), V);
1270}
1271
1272/// Match a Not as a xor(v, -1) or xor(-1, v)
1273template <typename ValTy>
1275 return m_Xor(V, m_AllOnes());
1276}
1277
1278template <typename... PatternTs> struct ReassociatableOpc_match {
1279 unsigned Opcode;
1280 std::tuple<PatternTs...> Patterns;
1281
1282 ReassociatableOpc_match(unsigned Opcode, const PatternTs &...Patterns)
1283 : Opcode(Opcode), Patterns(Patterns...) {}
1284
1285 template <typename MatchContext>
1286 bool match(const MatchContext &Ctx, SDValue N) {
1287 constexpr size_t NumPatterns = std::tuple_size_v<std::tuple<PatternTs...>>;
1288
1289 SmallVector<SDValue> Leaves;
1290 collectLeaves(N, Leaves);
1291 if (Leaves.size() != NumPatterns)
1292 return false;
1293
1294 // Matches[I][J] == true iff sd_context_match(Leaves[I], Ctx,
1295 // std::get<J>(Patterns)) == true
1296 std::array<SmallBitVector, NumPatterns> Matches;
1297 for (size_t I = 0; I != NumPatterns; I++) {
1298 std::apply(
1299 [&](auto &...P) {
1300 (Matches[I].push_back(sd_context_match(Leaves[I], Ctx, P)), ...);
1301 },
1302 Patterns);
1303 }
1304
1305 SmallBitVector Used(NumPatterns);
1306 return reassociatableMatchHelper(Matches, Used);
1307 }
1308
1310 if (V->getOpcode() == Opcode) {
1311 for (size_t I = 0, N = V->getNumOperands(); I < N; I++)
1312 collectLeaves(V->getOperand(I), Leaves);
1313 } else {
1314 Leaves.emplace_back(V);
1315 }
1316 }
1317
1318 [[nodiscard]] inline bool
1320 SmallBitVector &Used, size_t Curr = 0) {
1321 if (Curr == Matches.size())
1322 return true;
1323 for (size_t Match = 0, N = Matches[Curr].size(); Match < N; Match++) {
1324 if (!Matches[Curr][Match] || Used[Match])
1325 continue;
1326 Used[Match] = true;
1327 if (reassociatableMatchHelper(Matches, Used, Curr + 1))
1328 return true;
1329 Used[Match] = false;
1330 }
1331 return false;
1332 }
1333};
1334
1335template <typename... PatternTs>
1336inline ReassociatableOpc_match<PatternTs...>
1337m_ReassociatableAdd(const PatternTs &...Patterns) {
1338 return ReassociatableOpc_match<PatternTs...>(ISD::ADD, Patterns...);
1339}
1340
1341template <typename... PatternTs>
1342inline ReassociatableOpc_match<PatternTs...>
1343m_ReassociatableOr(const PatternTs &...Patterns) {
1344 return ReassociatableOpc_match<PatternTs...>(ISD::OR, Patterns...);
1345}
1346
1347template <typename... PatternTs>
1348inline ReassociatableOpc_match<PatternTs...>
1349m_ReassociatableAnd(const PatternTs &...Patterns) {
1350 return ReassociatableOpc_match<PatternTs...>(ISD::AND, Patterns...);
1351}
1352
1353template <typename... PatternTs>
1354inline ReassociatableOpc_match<PatternTs...>
1355m_ReassociatableMul(const PatternTs &...Patterns) {
1356 return ReassociatableOpc_match<PatternTs...>(ISD::MUL, Patterns...);
1357}
1358
1359} // namespace SDPatternMatch
1360} // namespace llvm
1361#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...
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.
This file describes how to lower LLVM code to machine code.
Value * RHS
Value * LHS
Class for arbitrary precision integers.
Definition APInt.h:78
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
Definition APInt.h:372
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
Definition APInt.h:381
static bool isSameValue(const APInt &I1, const APInt &I2)
Determine if two APInts have the same value, after zero-extending one of them (if needed!...
Definition APInt.h:554
bool isOne() const
Determine if this is a value of 1.
Definition APInt.h:390
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
size_t size() const
size - Get the array size.
Definition ArrayRef.h:142
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...
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
reference emplace_back(ArgTypes &&... Args)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
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:807
@ POISON
POISON - A poison node.
Definition ISDOpcodes.h:231
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
Definition ISDOpcodes.h:593
@ BSWAP
Byte Swap and Counting operators.
Definition ISDOpcodes.h:771
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:259
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
Definition ISDOpcodes.h:841
@ FADD
Simple binary floating point operators.
Definition ISDOpcodes.h:410
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
Definition ISDOpcodes.h:744
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:832
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
Definition ISDOpcodes.h:784
@ UNDEF
UNDEF - An undefined node.
Definition ISDOpcodes.h:228
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:762
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
Definition ISDOpcodes.h:642
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
Definition ISDOpcodes.h:607
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
Definition ISDOpcodes.h:569
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition ISDOpcodes.h:838
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
Definition ISDOpcodes.h:799
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
Definition ISDOpcodes.h:724
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
Definition ISDOpcodes.h:793
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition ISDOpcodes.h:914
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:736
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
Definition ISDOpcodes.h:558
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition ISDOpcodes.h:844
LLVM_ABI bool isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
cst_pred_ty< is_all_ones > m_AllOnes()
Match an integer or vector with all bits set.
class_match< BinaryOperator > m_BinOp()
Match an arbitrary binary operation and ignore it.
cst_pred_ty< is_one > m_One()
Match an integer 1 or a vector with all elements equal to 1.
IntrinsicID_match 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)
Opcode_match m_Opc(unsigned Opcode)
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)
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 >
Result_match< ResNo, Pattern > m_Result(const Pattern &P)
Match only if the SDValue is a certain result at ResNo.
BinaryOpc_match< LHS, RHS, true > m_Mul(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)
UnaryOpc_match< Opnd > m_Abs(const Opnd &Op)
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)
BinaryOpc_match< LHS, RHS, true > m_SMin(const LHS &L, const RHS &R)
UnaryOpc_match< Opnd > m_Trunc(const Opnd &Op)
BinaryOpc_match< LHS, RHS > m_FSub(const LHS &L, const RHS &R)
auto m_AddLike(const LHS &L, const RHS &R)
BinaryOpc_match< LHS, RHS > m_URem(const LHS &L, const RHS &R)
UnaryOpc_match< Opnd > m_BSwap(const Opnd &Op)
Or< Preds... > m_AnyOf(const Preds &...preds)
BinaryOpc_match< LHS, RHS, true, true > m_c_ChainedBinOp(unsigned Opc, const LHS &L, const RHS &R)
Or< UnaryOpc_match< Opnd >, Opnd > m_TruncOrSelf(const Opnd &Op)
Match a trunc or identity Allows to peek through optional truncations.
UnaryOpc_match< Opnd > m_NNegZExt(const Opnd &Op)
And< Preds... > m_AllOf(const Preds &...preds)
BinaryOpc_match< LHS, RHS > m_FDiv(const LHS &L, const RHS &R)
auto m_LegalType(const Pattern &P)
Match legal ValueTypes based on the information provided by TargetLowering.
UnaryOpc_match< Opnd > m_BitCast(const Opnd &Op)
UnaryOpc_match< Opnd > m_FNeg(const Opnd &Op)
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)
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)
Value_match m_Specific(SDValue N)
BinaryOpc_match< LHS, RHS > m_ExtractElt(const LHS &Vec, const RHS &Idx)
BinaryOpc_match< LHS, RHS > m_ExtractSubvector(const LHS &Vec, const RHS &Idx)
UnaryOpc_match< Opnd > m_BitReverse(const Opnd &Op)
BinaryOpc_match< LHS, RHS, true > m_And(const LHS &L, const RHS &R)
ValueType_bind m_VT(EVT &VT)
Retreive the ValueType of the current SDValue.
BinaryOpc_match< LHS, RHS > m_Sub(const LHS &L, const RHS &R)
TernaryOpc_match< T0_P, T1_P, T2_P, true > m_c_TernaryOp(unsigned Opc, const T0_P &Op0, const T1_P &Op1, const T2_P &Op2)
TernaryOpc_match< T0_P, T1_P, T2_P > m_SetCC(const T0_P &LHS, const T1_P &RHS, const T2_P &CC)
BinaryOpc_match< ValTy, AllOnes_match, true > m_Not(const ValTy &V)
Match a Not as a xor(v, -1) or xor(-1, v)
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)
BinaryOpc_match< LHS, RHS > m_SDiv(const LHS &L, const RHS &R)
SwitchContext< MatchContext, Pattern > m_Context(const MatchContext &Ctx, Pattern &&P)
BinaryOpc_match< LHS, RHS, true > m_FAdd(const LHS &L, const RHS &R)
Or< UnaryOpc_match< Opnd >, Opnd > m_AExtOrSelf(const Opnd &Op)
Match a aext or identity Allows to peek through optional extensions.
BinaryOpc_match< LHS, RHS, true > m_UMax(const LHS &L, const RHS &R)
TernaryOpc_match< T0_P, T1_P, T2_P > m_VSelect(const T0_P &Cond, const T1_P &T, const T2_P &F)
bool sd_match(SDNode *N, const SelectionDAG *DAG, Pattern &&P)
UnaryOpc_match< Opnd > m_UnaryOp(unsigned Opc, const Opnd &Op)
auto m_SExt(const Opnd &Op)
BinaryOpc_match< LHS, RHS, true > m_Xor(const LHS &L, const RHS &R)
Opcode_match m_Undef()
auto m_SMinLike(const LHS &L, const RHS &R)
BinaryOpc_match< LHS, RHS > m_SRem(const LHS &L, const RHS &R)
auto m_NoneOf(const Preds &...preds)
CondCode_match m_SpecificCondCode(ISD::CondCode CC)
Match a conditional code SDNode with a specific ISD::CondCode.
UnaryOpc_match< Opnd > m_ZExt(const Opnd &Op)
Value_match m_Value()
Match any valid SDValue.
BinaryOpc_match< LHS, RHS, true > m_Add(const LHS &L, const RHS &R)
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.
UnaryOpc_match< Opnd > m_Ctpop(const Opnd &Op)
ReassociatableOpc_match< PatternTs... > m_ReassociatableAnd(const PatternTs &...Patterns)
UnaryOpc_match< Opnd > m_FPToSI(const Opnd &Op)
NUses_match< 1, Value_match > m_OneUse()
auto m_False()
Match false boolean value based on the information provided by TargetLowering.
auto m_SExtOrSelf(const Opnd &Op)
Match a sext or identity Allows to peek through optional extensions.
CondCode_match m_CondCode()
Match any conditional code SDNode.
BinaryOpc_match< LHS, RHS, true > m_c_BinOp(unsigned Opc, const LHS &L, const RHS &R)
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)
ConstantInt_match m_ConstInt()
Match any integer constants or splat of an integer constant.
auto m_ZExtOrSelf(const Opnd &Op)
Match a zext or identity Allows to peek through optional extensions.
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:532
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition STLExtras.h:1655
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:1606
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
@ Sub
Subtraction of integers.
DWARFExpression::Operation Op
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1867
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:867
#define N
Extended Value Type.
Definition ValueTypes.h:35
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 &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 &, SDValue N)
bool match(const MatchContext &, SDValue N)
EffectiveOperands(SDValue N, const MatchContext &Ctx)
Provide number of operands that are not chain or glue, as well as the first index of such operand.
EffectiveOperands(SDValue N, const MatchContext &Ctx)
MaxMin_match(const LHS_P &L, const RHS_P &R)
bool match(const MatchContext &Ctx, SDValue N)
bool match(const MatchContext &Ctx, SDValue N)
bool match(const MatchContext &Ctx, SDValue N)
bool match(const MatchContext &, 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)
void collectLeaves(SDValue V, SmallVector< SDValue > &Leaves)
ReassociatableOpc_match(unsigned Opcode, const PatternTs &...Patterns)
bool reassociatableMatchHelper(ArrayRef< SmallBitVector > Matches, SmallBitVector &Used, size_t Curr=0)
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 N)
Switch to a different MatchContext for subsequent patterns.
bool match(const OrigMatchContext &, SDValue N)
bool match(const MatchContext &Ctx, SDValue N)
TLI_pred_match(const PredFuncT &Pred, const Pattern &P)
bool match(const MatchContext &Ctx, SDValue N)
TernaryOpc_match(unsigned Opc, const T0_P &Op0, const T1_P &Op1, const T2_P &Op2)
std::optional< SDNodeFlags > Flags
UnaryOpc_match(unsigned Opc, const Opnd_P &Op, std::optional< SDNodeFlags > Flgs=std::nullopt)
bool match(const MatchContext &Ctx, SDValue N)
bool match(const MatchContext &, SDValue N)
ValueType_match(const PredFuncT &Pred, const Pattern &P)
bool match(const MatchContext &Ctx, SDValue N)
bool match(const MatchContext &, SDValue N)
bool match(const MatchContext &, SDValue N)
bool match(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)