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>
126}
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))`.
144 return DeferredValue_match(V);
145}
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
158inline Opcode_match m_Opc(unsigned Opcode) { return Opcode_match(Opcode); }
159
161
163
164template <unsigned NumUses, typename Pattern> struct NUses_match {
166
167 explicit NUses_match(const Pattern &P) : P(P) {}
168
169 template <typename MatchContext>
170 bool match(const MatchContext &Ctx, SDValue N) {
171 // SDNode::hasNUsesOfValue is pretty expensive when the SDNode produces
172 // multiple results, hence we check the subsequent pattern here before
173 // checking the number of value users.
174 return P.match(Ctx, N) && N->hasNUsesOfValue(NumUses, N.getResNo());
175 }
176};
177
178template <typename Pattern>
181}
182template <unsigned N, typename Pattern>
185}
186
189}
190template <unsigned N> inline NUses_match<N, Value_match> m_NUses() {
192}
193
196
197 explicit Value_bind(SDValue &N) : BindVal(N) {}
198
199 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
200 BindVal = N;
201 return true;
202 }
203};
204
205inline Value_bind m_Value(SDValue &N) { return Value_bind(N); }
206
207template <typename Pattern, typename PredFuncT> struct TLI_pred_match {
209 PredFuncT PredFunc;
210
211 TLI_pred_match(const PredFuncT &Pred, const Pattern &P)
212 : P(P), PredFunc(Pred) {}
213
214 template <typename MatchContext>
215 bool match(const MatchContext &Ctx, SDValue N) {
216 assert(Ctx.getTLI() && "TargetLowering is required for this pattern.");
217 return PredFunc(*Ctx.getTLI(), N) && P.match(Ctx, N);
218 }
219};
220
221// Explicit deduction guide.
222template <typename PredFuncT, typename Pattern>
223TLI_pred_match(const PredFuncT &Pred, const Pattern &P)
225
226/// Match legal SDNodes based on the information provided by TargetLowering.
227template <typename Pattern> inline auto m_LegalOp(const Pattern &P) {
228 return TLI_pred_match{[](const TargetLowering &TLI, SDValue N) {
229 return TLI.isOperationLegal(N->getOpcode(),
230 N.getValueType());
231 },
232 P};
233}
234
235/// Switch to a different MatchContext for subsequent patterns.
236template <typename NewMatchContext, typename Pattern> struct SwitchContext {
237 const NewMatchContext &Ctx;
239
240 template <typename OrigMatchContext>
241 bool match(const OrigMatchContext &, SDValue N) {
242 return P.match(Ctx, N);
243 }
244};
245
246template <typename MatchContext, typename Pattern>
247inline SwitchContext<MatchContext, Pattern> m_Context(const MatchContext &Ctx,
248 Pattern &&P) {
249 return SwitchContext<MatchContext, Pattern>{Ctx, std::move(P)};
250}
251
252// === Value type ===
255
256 explicit ValueType_bind(EVT &Bind) : BindVT(Bind) {}
257
258 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
259 BindVT = N.getValueType();
260 return true;
261 }
262};
263
264/// Retreive the ValueType of the current SDValue.
265inline ValueType_bind m_VT(EVT &VT) { return ValueType_bind(VT); }
266
267template <typename Pattern, typename PredFuncT> struct ValueType_match {
268 PredFuncT PredFunc;
270
271 ValueType_match(const PredFuncT &Pred, const Pattern &P)
272 : PredFunc(Pred), P(P) {}
273
274 template <typename MatchContext>
275 bool match(const MatchContext &Ctx, SDValue N) {
276 return PredFunc(N.getValueType()) && P.match(Ctx, N);
277 }
278};
279
280// Explicit deduction guide.
281template <typename PredFuncT, typename Pattern>
282ValueType_match(const PredFuncT &Pred, const Pattern &P)
284
285/// Match a specific ValueType.
286template <typename Pattern>
287inline auto m_SpecificVT(EVT RefVT, const Pattern &P) {
288 return ValueType_match{[=](EVT VT) { return VT == RefVT; }, P};
289}
290inline auto m_SpecificVT(EVT RefVT) {
291 return ValueType_match{[=](EVT VT) { return VT == RefVT; }, m_Value()};
292}
293
294inline auto m_Glue() { return m_SpecificVT(MVT::Glue); }
295inline auto m_OtherVT() { return m_SpecificVT(MVT::Other); }
296
297/// Match a scalar ValueType.
298template <typename Pattern>
299inline auto m_SpecificScalarVT(EVT RefVT, const Pattern &P) {
300 return ValueType_match{[=](EVT VT) { return VT.getScalarType() == RefVT; },
301 P};
302}
303inline auto m_SpecificScalarVT(EVT RefVT) {
304 return ValueType_match{[=](EVT VT) { return VT.getScalarType() == RefVT; },
305 m_Value()};
306}
307
308/// Match a vector ValueType.
309template <typename Pattern>
310inline auto m_SpecificVectorElementVT(EVT RefVT, const Pattern &P) {
311 return ValueType_match{[=](EVT VT) {
312 return VT.isVector() &&
313 VT.getVectorElementType() == RefVT;
314 },
315 P};
316}
317inline auto m_SpecificVectorElementVT(EVT RefVT) {
318 return ValueType_match{[=](EVT VT) {
319 return VT.isVector() &&
320 VT.getVectorElementType() == RefVT;
321 },
322 m_Value()};
323}
324
325/// Match any integer ValueTypes.
326template <typename Pattern> inline auto m_IntegerVT(const Pattern &P) {
327 return ValueType_match{[](EVT VT) { return VT.isInteger(); }, P};
328}
329inline auto m_IntegerVT() {
330 return ValueType_match{[](EVT VT) { return VT.isInteger(); }, m_Value()};
331}
332
333/// Match any floating point ValueTypes.
334template <typename Pattern> inline auto m_FloatingPointVT(const Pattern &P) {
335 return ValueType_match{[](EVT VT) { return VT.isFloatingPoint(); }, P};
336}
337inline auto m_FloatingPointVT() {
338 return ValueType_match{[](EVT VT) { return VT.isFloatingPoint(); },
339 m_Value()};
340}
341
342/// Match any vector ValueTypes.
343template <typename Pattern> inline auto m_VectorVT(const Pattern &P) {
344 return ValueType_match{[](EVT VT) { return VT.isVector(); }, P};
345}
346inline auto m_VectorVT() {
347 return ValueType_match{[](EVT VT) { return VT.isVector(); }, m_Value()};
348}
349
350/// Match fixed-length vector ValueTypes.
351template <typename Pattern> inline auto m_FixedVectorVT(const Pattern &P) {
352 return ValueType_match{[](EVT VT) { return VT.isFixedLengthVector(); }, P};
353}
354inline auto m_FixedVectorVT() {
355 return ValueType_match{[](EVT VT) { return VT.isFixedLengthVector(); },
356 m_Value()};
357}
358
359/// Match scalable vector ValueTypes.
360template <typename Pattern> inline auto m_ScalableVectorVT(const Pattern &P) {
361 return ValueType_match{[](EVT VT) { return VT.isScalableVector(); }, P};
362}
363inline auto m_ScalableVectorVT() {
364 return ValueType_match{[](EVT VT) { return VT.isScalableVector(); },
365 m_Value()};
366}
367
368/// Match legal ValueTypes based on the information provided by TargetLowering.
369template <typename Pattern> inline auto m_LegalType(const Pattern &P) {
370 return TLI_pred_match{[](const TargetLowering &TLI, SDValue N) {
371 return TLI.isTypeLegal(N.getValueType());
372 },
373 P};
374}
375
376// === Patterns combinators ===
377template <typename... Preds> struct And {
378 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
379 return true;
380 }
381};
382
383template <typename Pred, typename... Preds>
384struct And<Pred, Preds...> : And<Preds...> {
385 Pred P;
386 And(const Pred &p, const Preds &...preds) : And<Preds...>(preds...), P(p) {}
387
388 template <typename MatchContext>
389 bool match(const MatchContext &Ctx, SDValue N) {
390 return P.match(Ctx, N) && And<Preds...>::match(Ctx, N);
391 }
392};
393
394template <typename... Preds> struct Or {
395 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
396 return false;
397 }
398};
399
400template <typename Pred, typename... Preds>
401struct Or<Pred, Preds...> : Or<Preds...> {
402 Pred P;
403 Or(const Pred &p, const Preds &...preds) : Or<Preds...>(preds...), P(p) {}
404
405 template <typename MatchContext>
406 bool match(const MatchContext &Ctx, SDValue N) {
407 return P.match(Ctx, N) || Or<Preds...>::match(Ctx, N);
408 }
409};
410
411template <typename Pred> struct Not {
412 Pred P;
413
414 explicit Not(const Pred &P) : P(P) {}
415
416 template <typename MatchContext>
417 bool match(const MatchContext &Ctx, SDValue N) {
418 return !P.match(Ctx, N);
419 }
420};
421// Explicit deduction guide.
422template <typename Pred> Not(const Pred &P) -> Not<Pred>;
423
424/// Match if the inner pattern does NOT match.
425template <typename Pred> inline Not<Pred> m_Unless(const Pred &P) {
426 return Not{P};
427}
428
429template <typename... Preds> And<Preds...> m_AllOf(const Preds &...preds) {
430 return And<Preds...>(preds...);
431}
432
433template <typename... Preds> Or<Preds...> m_AnyOf(const Preds &...preds) {
434 return Or<Preds...>(preds...);
435}
436
437template <typename... Preds> auto m_NoneOf(const Preds &...preds) {
438 return m_Unless(m_AnyOf(preds...));
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 Result_match<0, TernaryOpc_match<T0_P, T1_P, T2_P>>
563m_Load(const T0_P &Ch, const T1_P &Ptr, const T2_P &Offset) {
564 return m_Result<0>(
566}
567
568template <typename T0_P, typename T1_P, typename T2_P>
569inline TernaryOpc_match<T0_P, T1_P, T2_P>
570m_InsertElt(const T0_P &Vec, const T1_P &Val, const T2_P &Idx) {
572 Idx);
573}
574
575template <typename LHS, typename RHS, typename IDX>
576inline TernaryOpc_match<LHS, RHS, IDX>
577m_InsertSubvector(const LHS &Base, const RHS &Sub, const IDX &Idx) {
579}
580
581template <typename LTy, typename RTy, typename TTy, typename FTy, typename CCTy>
582inline auto m_SelectCC(const LTy &L, const RTy &R, const TTy &T, const FTy &F,
583 const CCTy &CC) {
584 return m_Node(ISD::SELECT_CC, L, R, T, F, CC);
585}
586
587template <typename LTy, typename RTy, typename TTy, typename FTy, typename CCTy>
588inline auto m_SelectCCLike(const LTy &L, const RTy &R, const TTy &T,
589 const FTy &F, const CCTy &CC) {
590 return m_AnyOf(m_Select(m_SetCC(L, R, CC), T, F), m_SelectCC(L, R, T, F, CC));
591}
592
593// === Binary operations ===
594template <typename LHS_P, typename RHS_P, bool Commutable = false,
595 bool ExcludeChain = false>
597 unsigned Opcode;
598 LHS_P LHS;
599 RHS_P RHS;
600 std::optional<SDNodeFlags> Flags;
601 BinaryOpc_match(unsigned Opc, const LHS_P &L, const RHS_P &R,
602 std::optional<SDNodeFlags> Flgs = std::nullopt)
603 : Opcode(Opc), LHS(L), RHS(R), Flags(Flgs) {}
604
605 template <typename MatchContext>
606 bool match(const MatchContext &Ctx, SDValue N) {
607 if (sd_context_match(N, Ctx, m_Opc(Opcode))) {
609 assert(EO.Size == 2);
610 if (!((LHS.match(Ctx, N->getOperand(EO.FirstIndex)) &&
611 RHS.match(Ctx, N->getOperand(EO.FirstIndex + 1))) ||
612 (Commutable && LHS.match(Ctx, N->getOperand(EO.FirstIndex + 1)) &&
613 RHS.match(Ctx, N->getOperand(EO.FirstIndex)))))
614 return false;
615
616 if (!Flags.has_value())
617 return true;
618
619 return (*Flags & N->getFlags()) == *Flags;
620 }
621
622 return false;
623 }
624};
625
626/// Matching while capturing mask
627template <typename T0, typename T1, typename T2> struct SDShuffle_match {
628 T0 Op1;
631
632 SDShuffle_match(const T0 &Op1, const T1 &Op2, const T2 &Mask)
633 : Op1(Op1), Op2(Op2), Mask(Mask) {}
634
635 template <typename MatchContext>
636 bool match(const MatchContext &Ctx, SDValue N) {
637 if (auto *I = dyn_cast<ShuffleVectorSDNode>(N)) {
638 return Op1.match(Ctx, I->getOperand(0)) &&
639 Op2.match(Ctx, I->getOperand(1)) && Mask.match(I->getMask());
640 }
641 return false;
642 }
643};
644struct m_Mask {
647 bool match(ArrayRef<int> Mask) {
648 MaskRef = Mask;
649 return true;
650 }
651};
652
656 bool match(ArrayRef<int> Mask) { return MaskRef == Mask; }
657};
658
659template <typename LHS_P, typename RHS_P, typename Pred_t,
660 bool Commutable = false, bool ExcludeChain = false>
662 using PredType = Pred_t;
663 LHS_P LHS;
664 RHS_P RHS;
665
666 MaxMin_match(const LHS_P &L, const RHS_P &R) : LHS(L), RHS(R) {}
667
668 template <typename MatchContext>
669 bool match(const MatchContext &Ctx, SDValue N) {
670 auto MatchMinMax = [&](SDValue L, SDValue R, SDValue TrueValue,
671 SDValue FalseValue, ISD::CondCode CC) {
672 if ((TrueValue != L || FalseValue != R) &&
673 (TrueValue != R || FalseValue != L))
674 return false;
675
677 TrueValue == L ? CC : getSetCCInverse(CC, L.getValueType());
678 if (!Pred_t::match(Cond))
679 return false;
680
681 return (LHS.match(Ctx, L) && RHS.match(Ctx, R)) ||
682 (Commutable && LHS.match(Ctx, R) && RHS.match(Ctx, L));
683 };
684
685 if (sd_context_match(N, Ctx, m_Opc(ISD::SELECT)) ||
687 EffectiveOperands<ExcludeChain> EO_SELECT(N, Ctx);
688 assert(EO_SELECT.Size == 3);
689 SDValue Cond = N->getOperand(EO_SELECT.FirstIndex);
690 SDValue TrueValue = N->getOperand(EO_SELECT.FirstIndex + 1);
691 SDValue FalseValue = N->getOperand(EO_SELECT.FirstIndex + 2);
692
695 assert(EO_SETCC.Size == 3);
696 SDValue L = Cond->getOperand(EO_SETCC.FirstIndex);
697 SDValue R = Cond->getOperand(EO_SETCC.FirstIndex + 1);
698 auto *CondNode =
699 cast<CondCodeSDNode>(Cond->getOperand(EO_SETCC.FirstIndex + 2));
700 return MatchMinMax(L, R, TrueValue, FalseValue, CondNode->get());
701 }
702 }
703
705 EffectiveOperands<ExcludeChain> EO_SELECT(N, Ctx);
706 assert(EO_SELECT.Size == 5);
707 SDValue L = N->getOperand(EO_SELECT.FirstIndex);
708 SDValue R = N->getOperand(EO_SELECT.FirstIndex + 1);
709 SDValue TrueValue = N->getOperand(EO_SELECT.FirstIndex + 2);
710 SDValue FalseValue = N->getOperand(EO_SELECT.FirstIndex + 3);
711 auto *CondNode =
712 cast<CondCodeSDNode>(N->getOperand(EO_SELECT.FirstIndex + 4));
713 return MatchMinMax(L, R, TrueValue, FalseValue, CondNode->get());
714 }
715
716 return false;
717 }
718};
719
720// Helper class for identifying signed max predicates.
722 static bool match(ISD::CondCode Cond) {
724 }
725};
726
727// Helper class for identifying unsigned max predicates.
729 static bool match(ISD::CondCode Cond) {
731 }
732};
733
734// Helper class for identifying signed min predicates.
736 static bool match(ISD::CondCode Cond) {
738 }
739};
740
741// Helper class for identifying unsigned min predicates.
743 static bool match(ISD::CondCode Cond) {
745 }
746};
747
748template <typename LHS, typename RHS>
749inline BinaryOpc_match<LHS, RHS> m_BinOp(unsigned Opc, const LHS &L,
750 const RHS &R) {
751 return BinaryOpc_match<LHS, RHS>(Opc, L, R);
752}
753template <typename LHS, typename RHS>
755 const RHS &R) {
757}
758
759template <typename LHS, typename RHS>
761m_ChainedBinOp(unsigned Opc, const LHS &L, const RHS &R) {
763}
764template <typename LHS, typename RHS>
766m_c_ChainedBinOp(unsigned Opc, const LHS &L, const RHS &R) {
768}
769
770// Common binary operations
771template <typename LHS, typename RHS>
772inline BinaryOpc_match<LHS, RHS, true> m_Add(const LHS &L, const RHS &R) {
774}
775
776template <typename LHS, typename RHS>
777inline BinaryOpc_match<LHS, RHS> m_Sub(const LHS &L, const RHS &R) {
779}
780
781template <typename LHS, typename RHS>
782inline BinaryOpc_match<LHS, RHS, true> m_Mul(const LHS &L, const RHS &R) {
784}
785
786template <typename LHS, typename RHS>
787inline BinaryOpc_match<LHS, RHS, true> m_And(const LHS &L, const RHS &R) {
789}
790
791template <typename LHS, typename RHS>
792inline BinaryOpc_match<LHS, RHS, true> m_Or(const LHS &L, const RHS &R) {
794}
795
796template <typename LHS, typename RHS>
798 const RHS &R) {
800}
801
802template <typename LHS, typename RHS>
803inline auto m_AddLike(const LHS &L, const RHS &R) {
804 return m_AnyOf(m_Add(L, R), m_DisjointOr(L, R));
805}
806
807template <typename LHS, typename RHS>
808inline BinaryOpc_match<LHS, RHS, true> m_Xor(const LHS &L, const RHS &R) {
810}
811
812template <typename LHS, typename RHS>
813inline auto m_BitwiseLogic(const LHS &L, const RHS &R) {
814 return m_AnyOf(m_And(L, R), m_Or(L, R), m_Xor(L, R));
815}
816
817template <typename LHS, typename RHS>
818inline BinaryOpc_match<LHS, RHS, true> m_SMin(const LHS &L, const RHS &R) {
820}
821
822template <typename LHS, typename RHS>
823inline auto m_SMinLike(const LHS &L, const RHS &R) {
826}
827
828template <typename LHS, typename RHS>
829inline BinaryOpc_match<LHS, RHS, true> m_SMax(const LHS &L, const RHS &R) {
831}
832
833template <typename LHS, typename RHS>
834inline auto m_SMaxLike(const LHS &L, const RHS &R) {
837}
838
839template <typename LHS, typename RHS>
840inline BinaryOpc_match<LHS, RHS, true> m_UMin(const LHS &L, const RHS &R) {
842}
843
844template <typename LHS, typename RHS>
845inline auto m_UMinLike(const LHS &L, const RHS &R) {
848}
849
850template <typename LHS, typename RHS>
851inline BinaryOpc_match<LHS, RHS, true> m_UMax(const LHS &L, const RHS &R) {
853}
854
855template <typename LHS, typename RHS>
856inline auto m_UMaxLike(const LHS &L, const RHS &R) {
859}
860
861template <typename LHS, typename RHS>
862inline BinaryOpc_match<LHS, RHS> m_UDiv(const LHS &L, const RHS &R) {
864}
865template <typename LHS, typename RHS>
866inline BinaryOpc_match<LHS, RHS> m_SDiv(const LHS &L, const RHS &R) {
868}
869
870template <typename LHS, typename RHS>
871inline BinaryOpc_match<LHS, RHS> m_URem(const LHS &L, const RHS &R) {
873}
874template <typename LHS, typename RHS>
875inline BinaryOpc_match<LHS, RHS> m_SRem(const LHS &L, const RHS &R) {
877}
878
879template <typename LHS, typename RHS>
880inline BinaryOpc_match<LHS, RHS> m_Shl(const LHS &L, const RHS &R) {
882}
883
884template <typename LHS, typename RHS>
885inline BinaryOpc_match<LHS, RHS> m_Sra(const LHS &L, const RHS &R) {
887}
888template <typename LHS, typename RHS>
889inline BinaryOpc_match<LHS, RHS> m_Srl(const LHS &L, const RHS &R) {
891}
892
893template <typename LHS, typename RHS>
894inline BinaryOpc_match<LHS, RHS> m_Rotl(const LHS &L, const RHS &R) {
896}
897
898template <typename LHS, typename RHS>
899inline BinaryOpc_match<LHS, RHS> m_Rotr(const LHS &L, const RHS &R) {
901}
902
903template <typename LHS, typename RHS>
904inline BinaryOpc_match<LHS, RHS, true> m_FAdd(const LHS &L, const RHS &R) {
906}
907
908template <typename LHS, typename RHS>
909inline BinaryOpc_match<LHS, RHS> m_FSub(const LHS &L, const RHS &R) {
911}
912
913template <typename LHS, typename RHS>
914inline BinaryOpc_match<LHS, RHS, true> m_FMul(const LHS &L, const RHS &R) {
916}
917
918template <typename LHS, typename RHS>
919inline BinaryOpc_match<LHS, RHS> m_FDiv(const LHS &L, const RHS &R) {
921}
922
923template <typename LHS, typename RHS>
924inline BinaryOpc_match<LHS, RHS> m_FRem(const LHS &L, const RHS &R) {
926}
927
928template <typename V1_t, typename V2_t>
929inline BinaryOpc_match<V1_t, V2_t> m_Shuffle(const V1_t &v1, const V2_t &v2) {
931}
932
933template <typename V1_t, typename V2_t, typename Mask_t>
934inline SDShuffle_match<V1_t, V2_t, Mask_t>
935m_Shuffle(const V1_t &v1, const V2_t &v2, const Mask_t &mask) {
936 return SDShuffle_match<V1_t, V2_t, Mask_t>(v1, v2, mask);
937}
938
939template <typename LHS, typename RHS>
942}
943
944template <typename LHS, typename RHS>
946 const RHS &Idx) {
948}
949
950// === Unary operations ===
951template <typename Opnd_P, bool ExcludeChain = false> struct UnaryOpc_match {
952 unsigned Opcode;
953 Opnd_P Opnd;
954 std::optional<SDNodeFlags> Flags;
955 UnaryOpc_match(unsigned Opc, const Opnd_P &Op,
956 std::optional<SDNodeFlags> Flgs = std::nullopt)
957 : Opcode(Opc), Opnd(Op), Flags(Flgs) {}
958
959 template <typename MatchContext>
960 bool match(const MatchContext &Ctx, SDValue N) {
961 if (sd_context_match(N, Ctx, m_Opc(Opcode))) {
963 assert(EO.Size == 1);
964 if (!Opnd.match(Ctx, N->getOperand(EO.FirstIndex)))
965 return false;
966 if (!Flags.has_value())
967 return true;
968
969 return (*Flags & N->getFlags()) == *Flags;
970 }
971
972 return false;
973 }
974};
975
976template <typename Opnd>
977inline UnaryOpc_match<Opnd> m_UnaryOp(unsigned Opc, const Opnd &Op) {
978 return UnaryOpc_match<Opnd>(Opc, Op);
979}
980template <typename Opnd>
982 const Opnd &Op) {
984}
985
986template <typename Opnd> inline UnaryOpc_match<Opnd> m_BitCast(const Opnd &Op) {
988}
989
990template <typename Opnd>
991inline UnaryOpc_match<Opnd> m_BSwap(const Opnd &Op) {
993}
994
995template <typename Opnd>
998}
999
1000template <typename Opnd> inline UnaryOpc_match<Opnd> m_ZExt(const Opnd &Op) {
1002}
1003
1004template <typename Opnd>
1007}
1008
1009template <typename Opnd> inline auto m_SExt(const Opnd &Op) {
1011}
1012
1013template <typename Opnd> inline UnaryOpc_match<Opnd> m_AnyExt(const Opnd &Op) {
1015}
1016
1017template <typename Opnd> inline UnaryOpc_match<Opnd> m_Trunc(const Opnd &Op) {
1019}
1020
1021template <typename Opnd> inline UnaryOpc_match<Opnd> m_Abs(const Opnd &Op) {
1023}
1024
1025/// Match a zext or identity
1026/// Allows to peek through optional extensions
1027template <typename Opnd> inline auto m_ZExtOrSelf(const Opnd &Op) {
1028 return m_AnyOf(m_ZExt(Op), Op);
1029}
1030
1031/// Match a sext or identity
1032/// Allows to peek through optional extensions
1033template <typename Opnd> inline auto m_SExtOrSelf(const Opnd &Op) {
1034 return m_AnyOf(m_SExt(Op), Op);
1035}
1036
1037template <typename Opnd> inline auto m_SExtLike(const Opnd &Op) {
1038 return m_AnyOf(m_SExt(Op), m_NNegZExt(Op));
1039}
1040
1041/// Match a aext or identity
1042/// Allows to peek through optional extensions
1043template <typename Opnd>
1044inline Or<UnaryOpc_match<Opnd>, Opnd> m_AExtOrSelf(const Opnd &Op) {
1045 return Or<UnaryOpc_match<Opnd>, Opnd>(m_AnyExt(Op), Op);
1046}
1047
1048/// Match a trunc or identity
1049/// Allows to peek through optional truncations
1050template <typename Opnd>
1051inline Or<UnaryOpc_match<Opnd>, Opnd> m_TruncOrSelf(const Opnd &Op) {
1052 return Or<UnaryOpc_match<Opnd>, Opnd>(m_Trunc(Op), Op);
1053}
1054
1055template <typename Opnd> inline UnaryOpc_match<Opnd> m_VScale(const Opnd &Op) {
1057}
1058
1059template <typename Opnd> inline UnaryOpc_match<Opnd> m_FPToUI(const Opnd &Op) {
1061}
1062
1063template <typename Opnd> inline UnaryOpc_match<Opnd> m_FPToSI(const Opnd &Op) {
1065}
1066
1067template <typename Opnd> inline UnaryOpc_match<Opnd> m_Ctpop(const Opnd &Op) {
1069}
1070
1071template <typename Opnd> inline UnaryOpc_match<Opnd> m_Ctlz(const Opnd &Op) {
1073}
1074
1075template <typename Opnd> inline UnaryOpc_match<Opnd> m_Cttz(const Opnd &Op) {
1077}
1078
1079// === Constants ===
1082
1083 explicit ConstantInt_match(APInt *V) : BindVal(V) {}
1084
1085 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
1086 // The logics here are similar to that in
1087 // SelectionDAG::isConstantIntBuildVectorOrConstantInt, but the latter also
1088 // treats GlobalAddressSDNode as a constant, which is difficult to turn into
1089 // APInt.
1090 if (auto *C = dyn_cast_or_null<ConstantSDNode>(N.getNode())) {
1091 if (BindVal)
1092 *BindVal = C->getAPIntValue();
1093 return true;
1094 }
1095
1096 APInt Discard;
1097 return ISD::isConstantSplatVector(N.getNode(),
1098 BindVal ? *BindVal : Discard);
1099 }
1100};
1101/// Match any integer constants or splat of an integer constant.
1103/// Match any integer constants or splat of an integer constant; return the
1104/// specific constant or constant splat value.
1106
1109
1110 explicit SpecificInt_match(APInt APV) : IntVal(std::move(APV)) {}
1111
1112 template <typename MatchContext>
1113 bool match(const MatchContext &Ctx, SDValue N) {
1114 APInt ConstInt;
1115 if (sd_context_match(N, Ctx, m_ConstInt(ConstInt)))
1116 return APInt::isSameValue(IntVal, ConstInt);
1117 return false;
1118 }
1119};
1120
1121/// Match a specific integer constant or constant splat value.
1123 return SpecificInt_match(std::move(V));
1124}
1126 return SpecificInt_match(APInt(64, V));
1127}
1128
1131
1133
1134 template <typename MatchContext>
1135 bool match(const MatchContext &, SDValue N) const {
1137 }
1138};
1139
1142
1144
1145 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
1147 }
1148};
1149
1152
1154
1155 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
1157 }
1158};
1159
1160inline Ones_match m_One(bool AllowUndefs = false) {
1161 return Ones_match(AllowUndefs);
1162}
1163inline Zero_match m_Zero(bool AllowUndefs = false) {
1164 return Zero_match(AllowUndefs);
1165}
1166inline AllOnes_match m_AllOnes(bool AllowUndefs = false) {
1167 return AllOnes_match(AllowUndefs);
1168}
1169
1170/// Match true boolean value based on the information provided by
1171/// TargetLowering.
1172inline auto m_True() {
1173 return TLI_pred_match{
1174 [](const TargetLowering &TLI, SDValue N) {
1175 APInt ConstVal;
1176 if (sd_match(N, m_ConstInt(ConstVal)))
1177 switch (TLI.getBooleanContents(N.getValueType())) {
1179 return ConstVal.isOne();
1181 return ConstVal.isAllOnes();
1183 return (ConstVal & 0x01) == 1;
1184 }
1185
1186 return false;
1187 },
1188 m_Value()};
1189}
1190/// Match false boolean value based on the information provided by
1191/// TargetLowering.
1192inline auto m_False() {
1193 return TLI_pred_match{
1194 [](const TargetLowering &TLI, SDValue N) {
1195 APInt ConstVal;
1196 if (sd_match(N, m_ConstInt(ConstVal)))
1197 switch (TLI.getBooleanContents(N.getValueType())) {
1200 return ConstVal.isZero();
1202 return (ConstVal & 0x01) == 0;
1203 }
1204
1205 return false;
1206 },
1207 m_Value()};
1208}
1209
1211 std::optional<ISD::CondCode> CCToMatch;
1213
1215
1216 explicit CondCode_match(ISD::CondCode *CC) : BindCC(CC) {}
1217
1218 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
1219 if (auto *CC = dyn_cast<CondCodeSDNode>(N.getNode())) {
1220 if (CCToMatch && *CCToMatch != CC->get())
1221 return false;
1222
1223 if (BindCC)
1224 *BindCC = CC->get();
1225 return true;
1226 }
1227
1228 return false;
1229 }
1230};
1231
1232/// Match any conditional code SDNode.
1233inline CondCode_match m_CondCode() { return CondCode_match(nullptr); }
1234/// Match any conditional code SDNode and return its ISD::CondCode value.
1236 return CondCode_match(&CC);
1237}
1238/// Match a conditional code SDNode with a specific ISD::CondCode.
1240 return CondCode_match(CC);
1241}
1242
1243/// Match a negate as a sub(0, v)
1244template <typename ValTy>
1246 return m_Sub(m_Zero(), V);
1247}
1248
1249/// Match a Not as a xor(v, -1) or xor(-1, v)
1250template <typename ValTy>
1252 return m_Xor(V, m_AllOnes());
1253}
1254
1255template <typename... PatternTs> struct ReassociatableOpc_match {
1256 unsigned Opcode;
1257 std::tuple<PatternTs...> Patterns;
1258
1259 ReassociatableOpc_match(unsigned Opcode, const PatternTs &...Patterns)
1260 : Opcode(Opcode), Patterns(Patterns...) {}
1261
1262 template <typename MatchContext>
1263 bool match(const MatchContext &Ctx, SDValue N) {
1264 constexpr size_t NumPatterns = std::tuple_size_v<std::tuple<PatternTs...>>;
1265
1266 SmallVector<SDValue> Leaves;
1267 collectLeaves(N, Leaves);
1268 if (Leaves.size() != NumPatterns)
1269 return false;
1270
1271 // Matches[I][J] == true iff sd_context_match(Leaves[I], Ctx,
1272 // std::get<J>(Patterns)) == true
1273 std::array<SmallBitVector, NumPatterns> Matches;
1274 for (size_t I = 0; I != NumPatterns; I++) {
1275 std::apply(
1276 [&](auto &...P) {
1277 (Matches[I].push_back(sd_context_match(Leaves[I], Ctx, P)), ...);
1278 },
1279 Patterns);
1280 }
1281
1282 SmallBitVector Used(NumPatterns);
1283 return reassociatableMatchHelper(Matches, Used);
1284 }
1285
1287 if (V->getOpcode() == Opcode) {
1288 for (size_t I = 0, N = V->getNumOperands(); I < N; I++)
1289 collectLeaves(V->getOperand(I), Leaves);
1290 } else {
1291 Leaves.emplace_back(V);
1292 }
1293 }
1294
1295 [[nodiscard]] inline bool
1297 SmallBitVector &Used, size_t Curr = 0) {
1298 if (Curr == Matches.size())
1299 return true;
1300 for (size_t Match = 0, N = Matches[Curr].size(); Match < N; Match++) {
1301 if (!Matches[Curr][Match] || Used[Match])
1302 continue;
1303 Used[Match] = true;
1304 if (reassociatableMatchHelper(Matches, Used, Curr + 1))
1305 return true;
1306 Used[Match] = false;
1307 }
1308 return false;
1309 }
1310};
1311
1312template <typename... PatternTs>
1313inline ReassociatableOpc_match<PatternTs...>
1314m_ReassociatableAdd(const PatternTs &...Patterns) {
1315 return ReassociatableOpc_match<PatternTs...>(ISD::ADD, Patterns...);
1316}
1317
1318template <typename... PatternTs>
1319inline ReassociatableOpc_match<PatternTs...>
1320m_ReassociatableOr(const PatternTs &...Patterns) {
1321 return ReassociatableOpc_match<PatternTs...>(ISD::OR, Patterns...);
1322}
1323
1324template <typename... PatternTs>
1325inline ReassociatableOpc_match<PatternTs...>
1326m_ReassociatableAnd(const PatternTs &...Patterns) {
1327 return ReassociatableOpc_match<PatternTs...>(ISD::AND, Patterns...);
1328}
1329
1330template <typename... PatternTs>
1331inline ReassociatableOpc_match<PatternTs...>
1332m_ReassociatableMul(const PatternTs &...Patterns) {
1333 return ReassociatableOpc_match<PatternTs...>(ISD::MUL, Patterns...);
1334}
1335
1336} // namespace SDPatternMatch
1337} // namespace llvm
1338#endif
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements a class to represent arbitrary precision integral constant values and operations...
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
#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:371
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
Definition: APInt.h:380
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:553
bool isOne() const
Determine if this is a value of 1.
Definition: APInt.h:389
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:147
This class represents an Operation in the Expression.
LLVM_ABI_FOR_TEST MatchResult match(StringRef Buffer, const SourceMgr &SM) const
Matches the pattern string against the input buffer Buffer.
Definition: FileCheck.cpp:1116
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...
Definition: SelectionDAG.h:229
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
size_t size() const
Definition: SmallVector.h:79
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:938
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1197
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:801
@ 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:587
@ BSWAP
Byte Swap and Counting operators.
Definition: ISDOpcodes.h:765
@ 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...
Definition: ISDOpcodes.h:1141
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
Definition: ISDOpcodes.h:835
@ 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:738
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
Definition: ISDOpcodes.h:975
@ SIGN_EXTEND
Conversion operators.
Definition: ISDOpcodes.h:826
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
Definition: ISDOpcodes.h:778
@ UNDEF
UNDEF - An undefined node.
Definition: ISDOpcodes.h:228
@ SHL
Shift and rotation operations.
Definition: ISDOpcodes.h:756
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
Definition: ISDOpcodes.h:636
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
Definition: ISDOpcodes.h:601
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
Definition: ISDOpcodes.h:563
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition: ISDOpcodes.h:832
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
Definition: ISDOpcodes.h:793
@ VSCALE
VSCALE(IMM) - Returns the runtime scaling factor used to calculate the number of elements within a sc...
Definition: ISDOpcodes.h:1448
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
Definition: ISDOpcodes.h:718
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
Definition: ISDOpcodes.h:787
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition: ISDOpcodes.h:908
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition: ISDOpcodes.h:730
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
Definition: ISDOpcodes.h:552
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition: ISDOpcodes.h:838
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,...
Definition: ISDOpcodes.h:1685
cst_pred_ty< is_all_ones > m_AllOnes()
Match an integer or vector with all bits set.
Definition: PatternMatch.h:524
class_match< BinaryOperator > m_BinOp()
Match an arbitrary binary operation and ignore it.
Definition: PatternMatch.h:100
cst_pred_ty< is_one > m_One()
Match an integer 1 or a vector with all elements equal to 1.
Definition: PatternMatch.h:592
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.
Definition: PatternMatch.h:612
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)
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)
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)
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_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)
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)
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 > 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)
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: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:477
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:1702
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:1605
@ 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:1886
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:856
#define N
Extended Value Type.
Definition: ValueTypes.h:35
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)
std::optional< SDNodeFlags > Flags
BinaryOpc_match(unsigned Opc, const LHS_P &L, const RHS_P &R, std::optional< SDNodeFlags > Flgs=std::nullopt)
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 ArrayRef< SmallBitVector > Matches, SmallBitVector &Used, size_t Curr=0)
void collectLeaves(SDValue V, SmallVector< SDValue > &Leaves)
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 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)