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
225inline auto m_Undef() {
227}
228
230
231template <unsigned NumUses, typename Pattern> struct NUses_match {
233
234 explicit NUses_match(const Pattern &P) : P(P) {}
235
236 template <typename MatchContext>
237 bool match(const MatchContext &Ctx, SDValue N) {
238 // SDNode::hasNUsesOfValue is pretty expensive when the SDNode produces
239 // multiple results, hence we check the subsequent pattern here before
240 // checking the number of value users.
241 return P.match(Ctx, N) && N->hasNUsesOfValue(NumUses, N.getResNo());
242 }
243};
244
245template <typename Pattern>
249template <unsigned N, typename Pattern>
253
257template <unsigned N> inline NUses_match<N, Value_match> m_NUses() {
259}
260
263
264 explicit Value_bind(SDValue &N) : BindVal(N) {}
265
266 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
267 BindVal = N;
268 return true;
269 }
270};
271
272inline Value_bind m_Value(SDValue &N) { return Value_bind(N); }
273
274template <typename Pattern, typename PredFuncT> struct TLI_pred_match {
276 PredFuncT PredFunc;
277
278 TLI_pred_match(const PredFuncT &Pred, const Pattern &P)
279 : P(P), PredFunc(Pred) {}
280
281 template <typename MatchContext>
282 bool match(const MatchContext &Ctx, SDValue N) {
283 assert(Ctx.getTLI() && "TargetLowering is required for this pattern.");
284 return PredFunc(*Ctx.getTLI(), N) && P.match(Ctx, N);
285 }
286};
287
288// Explicit deduction guide.
289template <typename PredFuncT, typename Pattern>
290TLI_pred_match(const PredFuncT &Pred, const Pattern &P)
292
293/// Match legal SDNodes based on the information provided by TargetLowering.
294template <typename Pattern> inline auto m_LegalOp(const Pattern &P) {
295 return TLI_pred_match{[](const TargetLowering &TLI, SDValue N) {
296 return TLI.isOperationLegal(N->getOpcode(),
297 N.getValueType());
298 },
299 P};
300}
301
302/// Switch to a different MatchContext for subsequent patterns.
303template <typename NewMatchContext, typename Pattern> struct SwitchContext {
304 const NewMatchContext &Ctx;
306
307 template <typename OrigMatchContext>
308 bool match(const OrigMatchContext &, SDValue N) {
309 return P.match(Ctx, N);
310 }
311};
312
313template <typename MatchContext, typename Pattern>
314inline SwitchContext<MatchContext, Pattern> m_Context(const MatchContext &Ctx,
315 Pattern &&P) {
316 return SwitchContext<MatchContext, Pattern>{Ctx, std::move(P)};
317}
318
319// === Value type ===
322
323 explicit ValueType_bind(EVT &Bind) : BindVT(Bind) {}
324
325 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
326 BindVT = N.getValueType();
327 return true;
328 }
329};
330
331/// Retreive the ValueType of the current SDValue.
332inline ValueType_bind m_VT(EVT &VT) { return ValueType_bind(VT); }
333
334template <typename Pattern, typename PredFuncT> struct ValueType_match {
335 PredFuncT PredFunc;
337
338 ValueType_match(const PredFuncT &Pred, const Pattern &P)
339 : PredFunc(Pred), P(P) {}
340
341 template <typename MatchContext>
342 bool match(const MatchContext &Ctx, SDValue N) {
343 return PredFunc(N.getValueType()) && P.match(Ctx, N);
344 }
345};
346
347// Explicit deduction guide.
348template <typename PredFuncT, typename Pattern>
349ValueType_match(const PredFuncT &Pred, const Pattern &P)
351
352/// Match a specific ValueType.
353template <typename Pattern>
354inline auto m_SpecificVT(EVT RefVT, const Pattern &P) {
355 return ValueType_match{[=](EVT VT) { return VT == RefVT; }, P};
356}
357inline auto m_SpecificVT(EVT RefVT) {
358 return ValueType_match{[=](EVT VT) { return VT == RefVT; }, m_Value()};
359}
360
361inline auto m_Glue() { return m_SpecificVT(MVT::Glue); }
362inline auto m_OtherVT() { return m_SpecificVT(MVT::Other); }
363
364/// Match a scalar ValueType.
365template <typename Pattern>
366inline auto m_SpecificScalarVT(EVT RefVT, const Pattern &P) {
367 return ValueType_match{[=](EVT VT) { return VT.getScalarType() == RefVT; },
368 P};
369}
370inline auto m_SpecificScalarVT(EVT RefVT) {
371 return ValueType_match{[=](EVT VT) { return VT.getScalarType() == RefVT; },
372 m_Value()};
373}
374
375/// Match a vector ValueType.
376template <typename Pattern>
377inline auto m_SpecificVectorElementVT(EVT RefVT, const Pattern &P) {
378 return ValueType_match{[=](EVT VT) {
379 return VT.isVector() &&
380 VT.getVectorElementType() == RefVT;
381 },
382 P};
383}
384inline auto m_SpecificVectorElementVT(EVT RefVT) {
385 return ValueType_match{[=](EVT VT) {
386 return VT.isVector() &&
387 VT.getVectorElementType() == RefVT;
388 },
389 m_Value()};
390}
391
392/// Match any integer ValueTypes.
393template <typename Pattern> inline auto m_IntegerVT(const Pattern &P) {
394 return ValueType_match{[](EVT VT) { return VT.isInteger(); }, P};
395}
396inline auto m_IntegerVT() {
397 return ValueType_match{[](EVT VT) { return VT.isInteger(); }, m_Value()};
398}
399
400/// Match any floating point ValueTypes.
401template <typename Pattern> inline auto m_FloatingPointVT(const Pattern &P) {
402 return ValueType_match{[](EVT VT) { return VT.isFloatingPoint(); }, P};
403}
404inline auto m_FloatingPointVT() {
405 return ValueType_match{[](EVT VT) { return VT.isFloatingPoint(); },
406 m_Value()};
407}
408
409/// Match any vector ValueTypes.
410template <typename Pattern> inline auto m_VectorVT(const Pattern &P) {
411 return ValueType_match{[](EVT VT) { return VT.isVector(); }, P};
412}
413inline auto m_VectorVT() {
414 return ValueType_match{[](EVT VT) { return VT.isVector(); }, m_Value()};
415}
416
417/// Match fixed-length vector ValueTypes.
418template <typename Pattern> inline auto m_FixedVectorVT(const Pattern &P) {
419 return ValueType_match{[](EVT VT) { return VT.isFixedLengthVector(); }, P};
420}
421inline auto m_FixedVectorVT() {
422 return ValueType_match{[](EVT VT) { return VT.isFixedLengthVector(); },
423 m_Value()};
424}
425
426/// Match scalable vector ValueTypes.
427template <typename Pattern> inline auto m_ScalableVectorVT(const Pattern &P) {
428 return ValueType_match{[](EVT VT) { return VT.isScalableVector(); }, P};
429}
430inline auto m_ScalableVectorVT() {
431 return ValueType_match{[](EVT VT) { return VT.isScalableVector(); },
432 m_Value()};
433}
434
435/// Match legal ValueTypes based on the information provided by TargetLowering.
436template <typename Pattern> inline auto m_LegalType(const Pattern &P) {
437 return TLI_pred_match{[](const TargetLowering &TLI, SDValue N) {
438 return TLI.isTypeLegal(N.getValueType());
439 },
440 P};
441}
442
443// === Generic node matching ===
444template <unsigned OpIdx, typename... OpndPreds> struct Operands_match {
445 template <typename MatchContext>
446 bool match(const MatchContext &Ctx, SDValue N) {
447 // Returns false if there are more operands than predicates;
448 // Ignores the last two operands if both the Context and the Node are VP
449 return Ctx.getNumOperands(N) == OpIdx;
450 }
451};
452
453template <unsigned OpIdx, typename OpndPred, typename... OpndPreds>
454struct Operands_match<OpIdx, OpndPred, OpndPreds...>
455 : Operands_match<OpIdx + 1, OpndPreds...> {
456 OpndPred P;
457
458 Operands_match(const OpndPred &p, const OpndPreds &...preds)
459 : Operands_match<OpIdx + 1, OpndPreds...>(preds...), P(p) {}
460
461 template <typename MatchContext>
462 bool match(const MatchContext &Ctx, SDValue N) {
463 if (OpIdx < N->getNumOperands())
464 return P.match(Ctx, N->getOperand(OpIdx)) &&
466
467 // This is the case where there are more predicates than operands.
468 return false;
469 }
470};
471
472template <typename... OpndPreds>
473auto m_Node(unsigned Opcode, const OpndPreds &...preds) {
474 return m_AllOf(m_Opc(Opcode), Operands_match<0, OpndPreds...>(preds...));
475}
476
477/// Provide number of operands that are not chain or glue, as well as the first
478/// index of such operand.
479template <bool ExcludeChain> struct EffectiveOperands {
480 unsigned Size = 0;
481 unsigned FirstIndex = 0;
482
483 template <typename MatchContext>
484 explicit EffectiveOperands(SDValue N, const MatchContext &Ctx) {
485 const unsigned TotalNumOps = Ctx.getNumOperands(N);
486 FirstIndex = TotalNumOps;
487 for (unsigned I = 0; I < TotalNumOps; ++I) {
488 // Count the number of non-chain and non-glue nodes (we ignore chain
489 // and glue by default) and retreive the operand index offset.
490 EVT VT = N->getOperand(I).getValueType();
491 if (VT != MVT::Glue && VT != MVT::Other) {
492 ++Size;
493 if (FirstIndex == TotalNumOps)
494 FirstIndex = I;
495 }
496 }
497 }
498};
499
500template <> struct EffectiveOperands<false> {
501 unsigned Size = 0;
502 unsigned FirstIndex = 0;
503
504 template <typename MatchContext>
505 explicit EffectiveOperands(SDValue N, const MatchContext &Ctx)
506 : Size(Ctx.getNumOperands(N)) {}
507};
508
509// === Ternary operations ===
510template <typename T0_P, typename T1_P, typename T2_P, bool Commutable = false,
511 bool ExcludeChain = false>
513 unsigned Opcode;
514 T0_P Op0;
515 T1_P Op1;
516 T2_P Op2;
517
518 TernaryOpc_match(unsigned Opc, const T0_P &Op0, const T1_P &Op1,
519 const T2_P &Op2)
520 : Opcode(Opc), Op0(Op0), Op1(Op1), Op2(Op2) {}
521
522 template <typename MatchContext>
523 bool match(const MatchContext &Ctx, SDValue N) {
524 if (sd_context_match(N, Ctx, m_Opc(Opcode))) {
526 assert(EO.Size == 3);
527 return ((Op0.match(Ctx, N->getOperand(EO.FirstIndex)) &&
528 Op1.match(Ctx, N->getOperand(EO.FirstIndex + 1))) ||
529 (Commutable && Op0.match(Ctx, N->getOperand(EO.FirstIndex + 1)) &&
530 Op1.match(Ctx, N->getOperand(EO.FirstIndex)))) &&
531 Op2.match(Ctx, N->getOperand(EO.FirstIndex + 2));
532 }
533
534 return false;
535 }
536};
537
538template <typename T0_P, typename T1_P, typename T2_P>
539inline TernaryOpc_match<T0_P, T1_P, T2_P>
540m_SetCC(const T0_P &LHS, const T1_P &RHS, const T2_P &CC) {
542}
543
544template <typename T0_P, typename T1_P, typename T2_P>
545inline TernaryOpc_match<T0_P, T1_P, T2_P, true, false>
546m_c_SetCC(const T0_P &LHS, const T1_P &RHS, const T2_P &CC) {
548 CC);
549}
550
551template <typename T0_P, typename T1_P, typename T2_P>
552inline TernaryOpc_match<T0_P, T1_P, T2_P>
553m_Select(const T0_P &Cond, const T1_P &T, const T2_P &F) {
555}
556
557template <typename T0_P, typename T1_P, typename T2_P>
558inline TernaryOpc_match<T0_P, T1_P, T2_P>
559m_VSelect(const T0_P &Cond, const T1_P &T, const T2_P &F) {
561}
562
563template <typename T0_P, typename T1_P, typename T2_P>
564inline auto m_SelectLike(const T0_P &Cond, const T1_P &T, const T2_P &F) {
565 return m_AnyOf(m_Select(Cond, T, F), m_VSelect(Cond, T, F));
566}
567
568template <typename T0_P, typename T1_P, typename T2_P>
569inline Result_match<0, TernaryOpc_match<T0_P, T1_P, T2_P>>
570m_Load(const T0_P &Ch, const T1_P &Ptr, const T2_P &Offset) {
571 return m_Result<0>(
573}
574
575template <typename T0_P, typename T1_P, typename T2_P>
576inline TernaryOpc_match<T0_P, T1_P, T2_P>
577m_InsertElt(const T0_P &Vec, const T1_P &Val, const T2_P &Idx) {
579 Idx);
580}
581
582template <typename LHS, typename RHS, typename IDX>
583inline TernaryOpc_match<LHS, RHS, IDX>
584m_InsertSubvector(const LHS &Base, const RHS &Sub, const IDX &Idx) {
586}
587
588template <typename T0_P, typename T1_P, typename T2_P>
589inline TernaryOpc_match<T0_P, T1_P, T2_P>
590m_TernaryOp(unsigned Opc, const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
591 return TernaryOpc_match<T0_P, T1_P, T2_P>(Opc, Op0, Op1, Op2);
592}
593
594template <typename T0_P, typename T1_P, typename T2_P>
595inline TernaryOpc_match<T0_P, T1_P, T2_P, true>
596m_c_TernaryOp(unsigned Opc, const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
597 return TernaryOpc_match<T0_P, T1_P, T2_P, true>(Opc, Op0, Op1, Op2);
598}
599
600template <typename LTy, typename RTy, typename TTy, typename FTy, typename CCTy>
601inline auto m_SelectCC(const LTy &L, const RTy &R, const TTy &T, const FTy &F,
602 const CCTy &CC) {
603 return m_Node(ISD::SELECT_CC, L, R, T, F, CC);
604}
605
606template <typename LTy, typename RTy, typename TTy, typename FTy, typename CCTy>
607inline auto m_SelectCCLike(const LTy &L, const RTy &R, const TTy &T,
608 const FTy &F, const CCTy &CC) {
609 return m_AnyOf(m_Select(m_SetCC(L, R, CC), T, F), m_SelectCC(L, R, T, F, CC));
610}
611
612// === Binary operations ===
613template <typename LHS_P, typename RHS_P, bool Commutable = false,
614 bool ExcludeChain = false>
616 unsigned Opcode;
617 LHS_P LHS;
618 RHS_P RHS;
620 BinaryOpc_match(unsigned Opc, const LHS_P &L, const RHS_P &R,
621 SDNodeFlags Flgs = SDNodeFlags())
622 : Opcode(Opc), LHS(L), RHS(R), Flags(Flgs) {}
623
624 template <typename MatchContext>
625 bool match(const MatchContext &Ctx, SDValue N) {
626 if (sd_context_match(N, Ctx, m_Opc(Opcode))) {
628 assert(EO.Size == 2);
629 if (!((LHS.match(Ctx, N->getOperand(EO.FirstIndex)) &&
630 RHS.match(Ctx, N->getOperand(EO.FirstIndex + 1))) ||
631 (Commutable && LHS.match(Ctx, N->getOperand(EO.FirstIndex + 1)) &&
632 RHS.match(Ctx, N->getOperand(EO.FirstIndex)))))
633 return false;
634
635 return (Flags & N->getFlags()) == Flags;
636 }
637
638 return false;
639 }
640};
641
642/// Matching while capturing mask
643template <typename T0, typename T1, typename T2> struct SDShuffle_match {
644 T0 Op1;
647
648 SDShuffle_match(const T0 &Op1, const T1 &Op2, const T2 &Mask)
649 : Op1(Op1), Op2(Op2), Mask(Mask) {}
650
651 template <typename MatchContext>
652 bool match(const MatchContext &Ctx, SDValue N) {
653 if (auto *I = dyn_cast<ShuffleVectorSDNode>(N)) {
654 return Op1.match(Ctx, I->getOperand(0)) &&
655 Op2.match(Ctx, I->getOperand(1)) && Mask.match(I->getMask());
656 }
657 return false;
658 }
659};
660struct m_Mask {
663 bool match(ArrayRef<int> Mask) {
664 MaskRef = Mask;
665 return true;
666 }
667};
668
674
675template <typename LHS_P, typename RHS_P, typename Pred_t,
676 bool Commutable = false, bool ExcludeChain = false>
678 using PredType = Pred_t;
679 LHS_P LHS;
680 RHS_P RHS;
681
682 MaxMin_match(const LHS_P &L, const RHS_P &R) : LHS(L), RHS(R) {}
683
684 template <typename MatchContext>
685 bool match(const MatchContext &Ctx, SDValue N) {
686 auto MatchMinMax = [&](SDValue L, SDValue R, SDValue TrueValue,
687 SDValue FalseValue, ISD::CondCode CC) {
688 if ((TrueValue != L || FalseValue != R) &&
689 (TrueValue != R || FalseValue != L))
690 return false;
691
693 TrueValue == L ? CC : getSetCCInverse(CC, L.getValueType());
694 if (!Pred_t::match(Cond))
695 return false;
696
697 return (LHS.match(Ctx, L) && RHS.match(Ctx, R)) ||
698 (Commutable && LHS.match(Ctx, R) && RHS.match(Ctx, L));
699 };
700
701 if (sd_context_match(N, Ctx, m_Opc(ISD::SELECT)) ||
703 EffectiveOperands<ExcludeChain> EO_SELECT(N, Ctx);
704 assert(EO_SELECT.Size == 3);
705 SDValue Cond = N->getOperand(EO_SELECT.FirstIndex);
706 SDValue TrueValue = N->getOperand(EO_SELECT.FirstIndex + 1);
707 SDValue FalseValue = N->getOperand(EO_SELECT.FirstIndex + 2);
708
711 assert(EO_SETCC.Size == 3);
712 SDValue L = Cond->getOperand(EO_SETCC.FirstIndex);
713 SDValue R = Cond->getOperand(EO_SETCC.FirstIndex + 1);
714 auto *CondNode =
715 cast<CondCodeSDNode>(Cond->getOperand(EO_SETCC.FirstIndex + 2));
716 return MatchMinMax(L, R, TrueValue, FalseValue, CondNode->get());
717 }
718 }
719
721 EffectiveOperands<ExcludeChain> EO_SELECT(N, Ctx);
722 assert(EO_SELECT.Size == 5);
723 SDValue L = N->getOperand(EO_SELECT.FirstIndex);
724 SDValue R = N->getOperand(EO_SELECT.FirstIndex + 1);
725 SDValue TrueValue = N->getOperand(EO_SELECT.FirstIndex + 2);
726 SDValue FalseValue = N->getOperand(EO_SELECT.FirstIndex + 3);
727 auto *CondNode =
728 cast<CondCodeSDNode>(N->getOperand(EO_SELECT.FirstIndex + 4));
729 return MatchMinMax(L, R, TrueValue, FalseValue, CondNode->get());
730 }
731
732 return false;
733 }
734};
735
736// Helper class for identifying signed max predicates.
738 static bool match(ISD::CondCode Cond) {
740 }
741};
742
743// Helper class for identifying unsigned max predicates.
748};
749
750// Helper class for identifying signed min predicates.
752 static bool match(ISD::CondCode Cond) {
754 }
755};
756
757// Helper class for identifying unsigned min predicates.
762};
763
764template <typename LHS, typename RHS>
765inline BinaryOpc_match<LHS, RHS> m_BinOp(unsigned Opc, const LHS &L,
766 const RHS &R) {
767 return BinaryOpc_match<LHS, RHS>(Opc, L, R);
768}
769template <typename LHS, typename RHS>
771 const RHS &R) {
773}
774
775template <typename LHS, typename RHS>
777m_ChainedBinOp(unsigned Opc, const LHS &L, const RHS &R) {
779}
780template <typename LHS, typename RHS>
782m_c_ChainedBinOp(unsigned Opc, const LHS &L, const RHS &R) {
784}
785
786// Common binary operations
787template <typename LHS, typename RHS>
788inline BinaryOpc_match<LHS, RHS, true> m_Add(const LHS &L, const RHS &R) {
790}
791
792template <typename LHS, typename RHS>
793inline BinaryOpc_match<LHS, RHS> m_Sub(const LHS &L, const RHS &R) {
795}
796
797template <typename LHS, typename RHS>
798inline BinaryOpc_match<LHS, RHS, true> m_Mul(const LHS &L, const RHS &R) {
800}
801
802template <typename LHS, typename RHS>
803inline BinaryOpc_match<LHS, RHS, true> m_And(const LHS &L, const RHS &R) {
805}
806
807template <typename LHS, typename RHS>
808inline BinaryOpc_match<LHS, RHS, true> m_Or(const LHS &L, const RHS &R) {
810}
811
812template <typename LHS, typename RHS>
817
818template <typename LHS, typename RHS>
819inline auto m_AddLike(const LHS &L, const RHS &R) {
820 return m_AnyOf(m_Add(L, R), m_DisjointOr(L, R));
821}
822
823template <typename LHS, typename RHS>
824inline BinaryOpc_match<LHS, RHS, true> m_Xor(const LHS &L, const RHS &R) {
826}
827
828template <typename LHS, typename RHS>
829inline auto m_BitwiseLogic(const LHS &L, const RHS &R) {
830 return m_AnyOf(m_And(L, R), m_Or(L, R), m_Xor(L, R));
831}
832
833template <typename LHS, typename RHS>
834inline BinaryOpc_match<LHS, RHS, true> m_SMin(const LHS &L, const RHS &R) {
836}
837
838template <typename LHS, typename RHS>
839inline auto m_SMinLike(const LHS &L, const RHS &R) {
842}
843
844template <typename LHS, typename RHS>
845inline BinaryOpc_match<LHS, RHS, true> m_SMax(const LHS &L, const RHS &R) {
847}
848
849template <typename LHS, typename RHS>
850inline auto m_SMaxLike(const LHS &L, const RHS &R) {
853}
854
855template <typename LHS, typename RHS>
856inline BinaryOpc_match<LHS, RHS, true> m_UMin(const LHS &L, const RHS &R) {
858}
859
860template <typename LHS, typename RHS>
861inline auto m_UMinLike(const LHS &L, const RHS &R) {
864}
865
866template <typename LHS, typename RHS>
867inline BinaryOpc_match<LHS, RHS, true> m_UMax(const LHS &L, const RHS &R) {
869}
870
871template <typename LHS, typename RHS>
872inline auto m_UMaxLike(const LHS &L, const RHS &R) {
875}
876
877template <typename LHS, typename RHS>
878inline BinaryOpc_match<LHS, RHS> m_UDiv(const LHS &L, const RHS &R) {
880}
881template <typename LHS, typename RHS>
882inline BinaryOpc_match<LHS, RHS> m_SDiv(const LHS &L, const RHS &R) {
884}
885
886template <typename LHS, typename RHS>
887inline BinaryOpc_match<LHS, RHS> m_URem(const LHS &L, const RHS &R) {
889}
890template <typename LHS, typename RHS>
891inline BinaryOpc_match<LHS, RHS> m_SRem(const LHS &L, const RHS &R) {
893}
894
895template <typename LHS, typename RHS>
896inline BinaryOpc_match<LHS, RHS> m_Shl(const LHS &L, const RHS &R) {
898}
899
900template <typename LHS, typename RHS>
901inline BinaryOpc_match<LHS, RHS> m_Sra(const LHS &L, const RHS &R) {
903}
904template <typename LHS, typename RHS>
905inline BinaryOpc_match<LHS, RHS> m_Srl(const LHS &L, const RHS &R) {
907}
908template <typename LHS, typename RHS>
913
914template <typename LHS, typename RHS>
915inline BinaryOpc_match<LHS, RHS> m_Rotl(const LHS &L, const RHS &R) {
917}
918
919template <typename LHS, typename RHS>
920inline BinaryOpc_match<LHS, RHS> m_Rotr(const LHS &L, const RHS &R) {
922}
923
924template <typename LHS, typename RHS>
928
929template <typename LHS, typename RHS>
930inline BinaryOpc_match<LHS, RHS, true> m_FAdd(const LHS &L, const RHS &R) {
932}
933
934template <typename LHS, typename RHS>
935inline BinaryOpc_match<LHS, RHS> m_FSub(const LHS &L, const RHS &R) {
937}
938
939template <typename LHS, typename RHS>
940inline BinaryOpc_match<LHS, RHS, true> m_FMul(const LHS &L, const RHS &R) {
942}
943
944template <typename LHS, typename RHS>
945inline BinaryOpc_match<LHS, RHS> m_FDiv(const LHS &L, const RHS &R) {
947}
948
949template <typename LHS, typename RHS>
950inline BinaryOpc_match<LHS, RHS> m_FRem(const LHS &L, const RHS &R) {
952}
953
954template <typename V1_t, typename V2_t>
955inline BinaryOpc_match<V1_t, V2_t> m_Shuffle(const V1_t &v1, const V2_t &v2) {
957}
958
959template <typename V1_t, typename V2_t, typename Mask_t>
960inline SDShuffle_match<V1_t, V2_t, Mask_t>
961m_Shuffle(const V1_t &v1, const V2_t &v2, const Mask_t &mask) {
963}
964
965template <typename LHS, typename RHS>
966inline BinaryOpc_match<LHS, RHS> m_ExtractElt(const LHS &Vec, const RHS &Idx) {
968}
969
970template <typename LHS, typename RHS>
972 const RHS &Idx) {
974}
975
976// === Unary operations ===
977template <typename Opnd_P, bool ExcludeChain = false> struct UnaryOpc_match {
978 unsigned Opcode;
979 Opnd_P Opnd;
980 std::optional<SDNodeFlags> Flags;
981 UnaryOpc_match(unsigned Opc, const Opnd_P &Op,
982 std::optional<SDNodeFlags> Flgs = std::nullopt)
983 : Opcode(Opc), Opnd(Op), Flags(Flgs) {}
984
985 template <typename MatchContext>
986 bool match(const MatchContext &Ctx, SDValue N) {
987 if (sd_context_match(N, Ctx, m_Opc(Opcode))) {
989 assert(EO.Size == 1);
990 if (!Opnd.match(Ctx, N->getOperand(EO.FirstIndex)))
991 return false;
992 if (!Flags.has_value())
993 return true;
994
995 return (*Flags & N->getFlags()) == *Flags;
996 }
997
998 return false;
999 }
1000};
1001
1002template <typename Opnd>
1003inline UnaryOpc_match<Opnd> m_UnaryOp(unsigned Opc, const Opnd &Op) {
1004 return UnaryOpc_match<Opnd>(Opc, Op);
1005}
1006template <typename Opnd>
1008 const Opnd &Op) {
1010}
1011
1012template <typename Opnd> inline UnaryOpc_match<Opnd> m_BitCast(const Opnd &Op) {
1014}
1015
1016template <typename Opnd>
1017inline UnaryOpc_match<Opnd> m_BSwap(const Opnd &Op) {
1019}
1020
1021template <typename Opnd>
1025
1026template <typename Opnd> inline UnaryOpc_match<Opnd> m_ZExt(const Opnd &Op) {
1028}
1029
1030template <typename Opnd>
1034
1035template <typename Opnd> inline auto m_SExt(const Opnd &Op) {
1037}
1038
1039template <typename Opnd> inline UnaryOpc_match<Opnd> m_AnyExt(const Opnd &Op) {
1041}
1042
1043template <typename Opnd> inline UnaryOpc_match<Opnd> m_Trunc(const Opnd &Op) {
1045}
1046
1047template <typename Opnd> inline UnaryOpc_match<Opnd> m_Abs(const Opnd &Op) {
1049}
1050
1051template <typename Opnd> inline UnaryOpc_match<Opnd> m_FAbs(const Opnd &Op) {
1053}
1054
1055/// Match a zext or identity
1056/// Allows to peek through optional extensions
1057template <typename Opnd> inline auto m_ZExtOrSelf(const Opnd &Op) {
1058 return m_AnyOf(m_ZExt(Op), Op);
1059}
1060
1061/// Match a sext or identity
1062/// Allows to peek through optional extensions
1063template <typename Opnd> inline auto m_SExtOrSelf(const Opnd &Op) {
1064 return m_AnyOf(m_SExt(Op), Op);
1065}
1066
1067template <typename Opnd> inline auto m_SExtLike(const Opnd &Op) {
1068 return m_AnyOf(m_SExt(Op), m_NNegZExt(Op));
1069}
1070
1071/// Match a aext or identity
1072/// Allows to peek through optional extensions
1073template <typename Opnd>
1074inline Or<UnaryOpc_match<Opnd>, Opnd> m_AExtOrSelf(const Opnd &Op) {
1075 return Or<UnaryOpc_match<Opnd>, Opnd>(m_AnyExt(Op), Op);
1076}
1077
1078/// Match a trunc or identity
1079/// Allows to peek through optional truncations
1080template <typename Opnd>
1081inline Or<UnaryOpc_match<Opnd>, Opnd> m_TruncOrSelf(const Opnd &Op) {
1082 return Or<UnaryOpc_match<Opnd>, Opnd>(m_Trunc(Op), Op);
1083}
1084
1085template <typename Opnd> inline UnaryOpc_match<Opnd> m_VScale(const Opnd &Op) {
1087}
1088
1089template <typename Opnd> inline UnaryOpc_match<Opnd> m_FPToUI(const Opnd &Op) {
1091}
1092
1093template <typename Opnd> inline UnaryOpc_match<Opnd> m_FPToSI(const Opnd &Op) {
1095}
1096
1097template <typename Opnd> inline UnaryOpc_match<Opnd> m_Ctpop(const Opnd &Op) {
1099}
1100
1101template <typename Opnd> inline UnaryOpc_match<Opnd> m_Ctlz(const Opnd &Op) {
1103}
1104
1105template <typename Opnd> inline UnaryOpc_match<Opnd> m_Cttz(const Opnd &Op) {
1107}
1108
1109template <typename Opnd> inline UnaryOpc_match<Opnd> m_FNeg(const Opnd &Op) {
1111}
1112
1113// === Constants ===
1116
1117 explicit ConstantInt_match(APInt *V) : BindVal(V) {}
1118
1119 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
1120 // The logics here are similar to that in
1121 // SelectionDAG::isConstantIntBuildVectorOrConstantInt, but the latter also
1122 // treats GlobalAddressSDNode as a constant, which is difficult to turn into
1123 // APInt.
1124 if (auto *C = dyn_cast_or_null<ConstantSDNode>(N.getNode())) {
1125 if (BindVal)
1126 *BindVal = C->getAPIntValue();
1127 return true;
1128 }
1129
1130 APInt Discard;
1131 return ISD::isConstantSplatVector(N.getNode(),
1132 BindVal ? *BindVal : Discard);
1133 }
1134};
1135/// Match any integer constants or splat of an integer constant.
1137/// Match any integer constants or splat of an integer constant; return the
1138/// specific constant or constant splat value.
1140
1143
1144 explicit SpecificInt_match(APInt APV) : IntVal(std::move(APV)) {}
1145
1146 template <typename MatchContext>
1147 bool match(const MatchContext &Ctx, SDValue N) {
1148 APInt ConstInt;
1149 if (sd_context_match(N, Ctx, m_ConstInt(ConstInt)))
1150 return APInt::isSameValue(IntVal, ConstInt);
1151 return false;
1152 }
1153};
1154
1155/// Match a specific integer constant or constant splat value.
1157 return SpecificInt_match(std::move(V));
1158}
1160 return SpecificInt_match(APInt(64, V));
1161}
1162
1165
1166 explicit SpecificFP_match(APFloat V) : Val(V) {}
1167
1168 template <typename MatchContext>
1169 bool match(const MatchContext &Ctx, SDValue V) {
1170 if (const auto *CFP = dyn_cast<ConstantFPSDNode>(V.getNode()))
1171 return CFP->isExactlyValue(Val);
1172 if (ConstantFPSDNode *C = isConstOrConstSplatFP(V, /*AllowUndefs=*/true))
1173 return C->getValueAPF().compare(Val) == APFloat::cmpEqual;
1174 return false;
1175 }
1176};
1177
1178/// Match a specific float constant.
1180
1182 return SpecificFP_match(APFloat(V));
1183}
1184
1187
1189
1190 template <typename MatchContext>
1191 bool match(const MatchContext &, SDValue N) const {
1193 }
1194};
1195
1198
1200
1201 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
1203 }
1204};
1205
1208
1210
1211 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
1213 }
1214};
1215
1216inline Ones_match m_One(bool AllowUndefs = false) {
1217 return Ones_match(AllowUndefs);
1218}
1219inline Zero_match m_Zero(bool AllowUndefs = false) {
1220 return Zero_match(AllowUndefs);
1221}
1222inline AllOnes_match m_AllOnes(bool AllowUndefs = false) {
1223 return AllOnes_match(AllowUndefs);
1224}
1225
1226/// Match true boolean value based on the information provided by
1227/// TargetLowering.
1228inline auto m_True() {
1229 return TLI_pred_match{
1230 [](const TargetLowering &TLI, SDValue N) {
1231 APInt ConstVal;
1232 if (sd_match(N, m_ConstInt(ConstVal)))
1233 switch (TLI.getBooleanContents(N.getValueType())) {
1235 return ConstVal.isOne();
1237 return ConstVal.isAllOnes();
1239 return (ConstVal & 0x01) == 1;
1240 }
1241
1242 return false;
1243 },
1244 m_Value()};
1245}
1246/// Match false boolean value based on the information provided by
1247/// TargetLowering.
1248inline auto m_False() {
1249 return TLI_pred_match{
1250 [](const TargetLowering &TLI, SDValue N) {
1251 APInt ConstVal;
1252 if (sd_match(N, m_ConstInt(ConstVal)))
1253 switch (TLI.getBooleanContents(N.getValueType())) {
1256 return ConstVal.isZero();
1258 return (ConstVal & 0x01) == 0;
1259 }
1260
1261 return false;
1262 },
1263 m_Value()};
1264}
1265
1267 std::optional<ISD::CondCode> CCToMatch;
1269
1271
1272 explicit CondCode_match(ISD::CondCode *CC) : BindCC(CC) {}
1273
1274 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
1275 if (auto *CC = dyn_cast<CondCodeSDNode>(N.getNode())) {
1276 if (CCToMatch && *CCToMatch != CC->get())
1277 return false;
1278
1279 if (BindCC)
1280 *BindCC = CC->get();
1281 return true;
1282 }
1283
1284 return false;
1285 }
1286};
1287
1288/// Match any conditional code SDNode.
1289inline CondCode_match m_CondCode() { return CondCode_match(nullptr); }
1290/// Match any conditional code SDNode and return its ISD::CondCode value.
1292 return CondCode_match(&CC);
1293}
1294/// Match a conditional code SDNode with a specific ISD::CondCode.
1298
1299/// Match a negate as a sub(0, v)
1300template <typename ValTy>
1302 return m_Sub(m_Zero(), V);
1303}
1304
1305/// Match a Not as a xor(v, -1) or xor(-1, v)
1306template <typename ValTy>
1308 return m_Xor(V, m_AllOnes());
1309}
1310
1313
1315
1316 template <typename MatchContext>
1317 bool match(const MatchContext &Ctx, SDValue N) {
1318 if (sd_context_match(N, Ctx, m_Neg(m_Specific(V))))
1319 return true;
1320
1323 return LHS->getAPIntValue() == -RHS->getAPIntValue();
1324 });
1325 }
1326};
1327
1328/// Match a negation of a specific value V, either as sub(0, V) or as
1329/// constant(s) that are the negation of V's constant(s).
1333
1334template <typename... PatternTs> struct ReassociatableOpc_match {
1335 unsigned Opcode;
1336 std::tuple<PatternTs...> Patterns;
1337 constexpr static size_t NumPatterns =
1338 std::tuple_size_v<std::tuple<PatternTs...>>;
1339
1340 ReassociatableOpc_match(unsigned Opcode, const PatternTs &...Patterns)
1341 : Opcode(Opcode), Patterns(Patterns...) {}
1342
1343 template <typename MatchContext>
1344 bool match(const MatchContext &Ctx, SDValue N) {
1345 std::array<SDValue, NumPatterns> Leaves;
1346 size_t LeavesIdx = 0;
1347 if (!(collectLeaves(N, Leaves, LeavesIdx) && (LeavesIdx == NumPatterns)))
1348 return false;
1349
1351 return std::apply(
1352 [&](auto &...P) -> bool {
1353 return reassociatableMatchHelper(Ctx, Leaves, Used, P...);
1354 },
1355 Patterns);
1356 }
1357
1358 bool collectLeaves(SDValue V, std::array<SDValue, NumPatterns> &Leaves,
1359 std::size_t &LeafIdx) {
1360 if (V->getOpcode() == Opcode) {
1361 for (size_t I = 0, N = V->getNumOperands(); I < N; I++)
1362 if ((LeafIdx == NumPatterns) ||
1363 !collectLeaves(V->getOperand(I), Leaves, LeafIdx))
1364 return false;
1365 } else {
1366 Leaves[LeafIdx] = V;
1367 LeafIdx++;
1368 }
1369 return true;
1370 }
1371
1372 // Searchs for a matching leaf for every sub-pattern.
1373 template <typename MatchContext, typename PatternHd, typename... PatternTl>
1374 [[nodiscard]] inline bool
1375 reassociatableMatchHelper(const MatchContext &Ctx, ArrayRef<SDValue> Leaves,
1376 Bitset<NumPatterns> &Used, PatternHd &HeadPattern,
1377 PatternTl &...TailPatterns) {
1378 for (size_t Match = 0, N = Used.size(); Match < N; Match++) {
1379 if (Used[Match] || !(sd_context_match(Leaves[Match], Ctx, HeadPattern)))
1380 continue;
1381 Used.set(Match);
1382 if (reassociatableMatchHelper(Ctx, Leaves, Used, TailPatterns...))
1383 return true;
1384 Used.reset(Match);
1385 }
1386 return false;
1387 }
1388
1389 template <typename MatchContext>
1390 [[nodiscard]] inline bool
1391 reassociatableMatchHelper(const MatchContext &Ctx, ArrayRef<SDValue> Leaves,
1392 Bitset<NumPatterns> &Used) {
1393 return true;
1394 }
1395};
1396
1397template <typename... PatternTs>
1398inline ReassociatableOpc_match<PatternTs...>
1399m_ReassociatableAdd(const PatternTs &...Patterns) {
1400 return ReassociatableOpc_match<PatternTs...>(ISD::ADD, Patterns...);
1401}
1402
1403template <typename... PatternTs>
1404inline ReassociatableOpc_match<PatternTs...>
1405m_ReassociatableOr(const PatternTs &...Patterns) {
1406 return ReassociatableOpc_match<PatternTs...>(ISD::OR, Patterns...);
1407}
1408
1409template <typename... PatternTs>
1410inline ReassociatableOpc_match<PatternTs...>
1411m_ReassociatableAnd(const PatternTs &...Patterns) {
1412 return ReassociatableOpc_match<PatternTs...>(ISD::AND, Patterns...);
1413}
1414
1415template <typename... PatternTs>
1416inline ReassociatableOpc_match<PatternTs...>
1417m_ReassociatableMul(const PatternTs &...Patterns) {
1418 return ReassociatableOpc_match<PatternTs...>(ISD::MUL, Patterns...);
1419}
1420
1421} // namespace SDPatternMatch
1422} // namespace llvm
1423#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
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...
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:813
@ 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:595
@ BSWAP
Byte Swap and Counting operators.
Definition ISDOpcodes.h:773
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:259
@ 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:847
@ FADD
Simple binary floating point operators.
Definition ISDOpcodes.h:412
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
Definition ISDOpcodes.h:741
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
Definition ISDOpcodes.h:987
@ CLMUL
Carry-less multiplication operations.
Definition ISDOpcodes.h:768
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:838
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
Definition ISDOpcodes.h:790
@ UNDEF
UNDEF - An undefined node.
Definition ISDOpcodes.h:228
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:759
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
Definition ISDOpcodes.h:644
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
Definition ISDOpcodes.h:609
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
Definition ISDOpcodes.h:571
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition ISDOpcodes.h:844
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
Definition ISDOpcodes.h:805
@ 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:721
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
Definition ISDOpcodes.h:799
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition ISDOpcodes.h:920
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:733
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
Definition ISDOpcodes.h:560
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition ISDOpcodes.h:850
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.
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)
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)
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)
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)
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)
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)
BinaryOpc_match< LHS, RHS, true > m_FAdd(const LHS &L, const RHS &R)
Or< UnaryOpc_match< Opnd >, Opnd > m_AExtOrSelf(const Opnd &Op)
Match a aext or identity Allows to peek through optional extensions.
BinaryOpc_match< LHS, RHS, true > m_UMax(const LHS &L, const RHS &R)
TernaryOpc_match< T0_P, T1_P, T2_P > m_VSelect(const T0_P &Cond, const T1_P &T, const T2_P &F)
bool sd_match(SDNode *N, const SelectionDAG *DAG, Pattern &&P)
UnaryOpc_match< Opnd > m_UnaryOp(unsigned Opc, const Opnd &Op)
auto m_SExt(const Opnd &Op)
BinaryOpc_match< LHS, RHS, true > m_Xor(const LHS &L, const RHS &R)
auto m_SMinLike(const LHS &L, const RHS &R)
BinaryOpc_match< LHS, RHS > m_SRem(const LHS &L, const RHS &R)
auto m_NoneOf(const Preds &...preds)
CondCode_match m_SpecificCondCode(ISD::CondCode CC)
Match a conditional code SDNode with a specific ISD::CondCode.
UnaryOpc_match< Opnd > m_ZExt(const Opnd &Op)
Value_match m_Value()
Match any valid SDValue.
BinaryOpc_match< LHS, RHS, true > m_Add(const LHS &L, const RHS &R)
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.
UnaryOpc_match< Opnd > m_FAbs(const Opnd &Op)
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.
Definition Types.h:26
@ Offset
Definition DWP.cpp:532
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:1613
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
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
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:1915
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:870
#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)
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)
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)
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)