LLVM 24.0.0git
SDPatternMatch.h
Go to the documentation of this file.
1//==--------------- llvm/CodeGen/SDPatternMatch.h ---------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8/// \file
9/// Contains matchers for matching SelectionDAG nodes and values.
10///
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_CODEGEN_SDPATTERNMATCH_H
14#define LLVM_CODEGEN_SDPATTERNMATCH_H
15
16#include "llvm/ADT/APInt.h"
17#include "llvm/ADT/ArrayRef.h"
18#include "llvm/ADT/STLExtras.h"
20#include "llvm/ADT/bit.h"
25
26#include <type_traits>
27
28namespace llvm {
29namespace SDPatternMatch {
30
31template <typename Pattern>
32[[nodiscard]] bool sd_match(SDValue N, Pattern &&P) {
33 return P.match(N);
34}
35
36template <typename Pattern>
37[[nodiscard]] bool sd_match(SDNode *N, Pattern &&P) {
38 return sd_match(SDValue(N, 0), P);
39}
40
41// === Utilities ===
44
45 Value_match() = default;
46
47 explicit Value_match(SDValue Match) : MatchVal(Match) {}
48
49 bool match(SDValue N) {
50 if (MatchVal)
51 return MatchVal == N;
52 return N.getNode();
53 }
54};
55
56/// Match any valid SDValue.
57inline Value_match m_Value() { return Value_match(); }
58
60 assert(N);
61 return Value_match(N);
62}
63
64template <unsigned ResNo, typename Pattern> struct Result_match {
66
67 explicit Result_match(const Pattern &P) : P(P) {}
68
69 bool match(SDValue N) { return N.getResNo() == ResNo && P.match(N); }
70};
71
72/// Match only if the SDValue is a certain result at ResNo.
73template <unsigned ResNo, typename Pattern>
77
80
81 explicit DeferredValue_match(SDValue &Match) : MatchVal(Match) {}
82
83 bool match(SDValue N) { return N == MatchVal; }
84};
85
86/// Similar to m_Specific, but the specific value to match is determined by
87/// another sub-pattern in the same sd_match() expression. For instance,
88/// We cannot match `(add V, V)` with `m_Add(m_Value(X), m_Specific(X))` since
89/// `X` is not initialized at the time it got copied into `m_Specific`. Instead,
90/// we should use `m_Add(m_Value(X), m_Deferred(X))`.
94
96 unsigned Opcode;
97
98 explicit Opcode_match(unsigned Opc) : Opcode(Opc) {}
99
100 bool match(SDValue N) { return N->getOpcode() == Opcode; }
101};
102
103// === Patterns combinators ===
104template <typename... Preds> struct And {
105 bool match(SDValue N) { return true; }
106};
107
108template <typename Pred, typename... Preds>
109struct And<Pred, Preds...> : And<Preds...> {
110 Pred P;
111 And(const Pred &p, const Preds &...preds) : And<Preds...>(preds...), P(p) {}
112
113 bool match(SDValue N) { return P.match(N) && And<Preds...>::match(N); }
114};
115
116template <typename... Preds> struct Or {
117 bool match(SDValue N) { return false; }
118};
119
120template <typename Pred, typename... Preds>
121struct Or<Pred, Preds...> : Or<Preds...> {
122 Pred P;
123 Or(const Pred &p, const Preds &...preds) : Or<Preds...>(preds...), P(p) {}
124
125 bool match(SDValue N) { return P.match(N) || Or<Preds...>::match(N); }
126};
127
128template <typename Pred> struct Not {
129 Pred P;
130
131 explicit Not(const Pred &P) : P(P) {}
132
133 bool match(SDValue N) { return !P.match(N); }
134};
135// Explicit deduction guide.
136template <typename Pred> Not(const Pred &P) -> Not<Pred>;
137
138/// Match if the inner pattern does NOT match.
139template <typename Pred> inline Not<Pred> m_Unless(const Pred &P) {
140 return Not{P};
141}
142
143template <typename... Preds> And<Preds...> m_AllOf(const Preds &...preds) {
144 return And<Preds...>(preds...);
145}
146
147template <typename... Preds> Or<Preds...> m_AnyOf(const Preds &...preds) {
148 return Or<Preds...>(preds...);
149}
150
151template <typename... Preds> auto m_NoneOf(const Preds &...preds) {
152 return m_Unless(m_AnyOf(preds...));
153}
154
155inline Opcode_match m_SpecificOpc(unsigned Opcode) {
156 return Opcode_match(Opcode);
157}
158
159inline auto m_Undef() {
161}
162
164
165template <unsigned NumUses, typename Pattern> struct NUses_match {
167
168 explicit NUses_match(const Pattern &P) : P(P) {}
169
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(N) && N->hasNUsesOfValue(NumUses, N.getResNo());
175 }
176};
177
178template <typename Pattern>
182template <unsigned N, typename Pattern>
186
190template <unsigned N> inline NUses_match<N, Value_match> m_NUses() {
192}
193
196
198
200 BindVal = N;
201 return true;
202 }
203};
204
205inline auto m_Value(SDValue &N) { return Value_bind(N); }
206/// Conditionally bind an SDValue based on the predicate.
207template <typename PredPattern>
208inline auto m_Value(SDValue &N, const PredPattern &P) {
209 return m_AllOf(P, Value_bind(N));
210}
211
212template <typename Pattern, typename PredFuncT> struct TLI_pred_match {
214 PredFuncT PredFunc;
215
216 TLI_pred_match(const PredFuncT &Pred, const Pattern &P)
217 : P(P), PredFunc(Pred) {}
218
219 bool match(SDValue N) { return PredFunc(N) && P.match(N); }
220};
221
222// Explicit deduction guide.
223template <typename PredFuncT, typename Pattern>
224TLI_pred_match(const PredFuncT &Pred, const Pattern &P)
226
227/// Match legal SDNodes based on the information provided by TargetLowering.
228template <typename Pattern>
229inline auto m_LegalOp(const SelectionDAG &DAG, const Pattern &P) {
230 return TLI_pred_match{[&DAG](SDValue N) {
232 N->getOpcode(), N.getValueType());
233 },
234 P};
235}
236
237// === Value type ===
238
239template <typename Pattern> struct ValueType_bind {
242
243 explicit ValueType_bind(EVT &Bind, const Pattern &P) : BindVT(Bind), P(P) {}
244
246 BindVT = N.getValueType();
247 return P.match(N);
248 }
249};
250
251template <typename Pattern>
253
254/// Retreive the ValueType of the current SDValue.
255inline auto m_VT(EVT &VT) { return ValueType_bind(VT, m_Value()); }
256
257template <typename Pattern> inline auto m_VT(EVT &VT, const Pattern &P) {
258 return ValueType_bind(VT, P);
259}
260
261template <typename Pattern, typename PredFuncT> struct ValueType_match {
262 PredFuncT PredFunc;
264
265 ValueType_match(const PredFuncT &Pred, const Pattern &P)
266 : PredFunc(Pred), P(P) {}
267
268 bool match(SDValue N) { return PredFunc(N.getValueType()) && P.match(N); }
269};
270
271// Explicit deduction guide.
272template <typename PredFuncT, typename Pattern>
273ValueType_match(const PredFuncT &Pred, const Pattern &P)
275
276/// Match a specific ValueType.
277template <typename Pattern>
278inline auto m_SpecificVT(EVT RefVT, const Pattern &P) {
279 return ValueType_match{[=](EVT VT) { return VT == RefVT; }, P};
280}
281inline auto m_SpecificVT(EVT RefVT) {
282 return ValueType_match{[=](EVT VT) { return VT == RefVT; }, m_Value()};
283}
284
285inline auto m_Glue() { return m_SpecificVT(MVT::Glue); }
286inline auto m_OtherVT() { return m_SpecificVT(MVT::Other); }
287
288/// Match a scalar ValueType.
289template <typename Pattern>
290inline auto m_SpecificScalarVT(EVT RefVT, const Pattern &P) {
291 return ValueType_match{[=](EVT VT) { return VT.getScalarType() == RefVT; },
292 P};
293}
294inline auto m_SpecificScalarVT(EVT RefVT) {
295 return ValueType_match{[=](EVT VT) { return VT.getScalarType() == RefVT; },
296 m_Value()};
297}
298
299/// Match a vector ValueType.
300template <typename Pattern>
301inline auto m_SpecificVectorElementVT(EVT RefVT, const Pattern &P) {
302 return ValueType_match{[=](EVT VT) {
303 return VT.isVector() &&
304 VT.getVectorElementType() == RefVT;
305 },
306 P};
307}
308inline auto m_SpecificVectorElementVT(EVT RefVT) {
309 return ValueType_match{[=](EVT VT) {
310 return VT.isVector() &&
311 VT.getVectorElementType() == RefVT;
312 },
313 m_Value()};
314}
315
316/// Match any integer ValueTypes.
317template <typename Pattern> inline auto m_IntegerVT(const Pattern &P) {
318 return ValueType_match{[](EVT VT) { return VT.isInteger(); }, P};
319}
320inline auto m_IntegerVT() {
321 return ValueType_match{[](EVT VT) { return VT.isInteger(); }, m_Value()};
322}
323
324/// Match any floating point ValueTypes.
325template <typename Pattern> inline auto m_FloatingPointVT(const Pattern &P) {
326 return ValueType_match{[](EVT VT) { return VT.isFloatingPoint(); }, P};
327}
328inline auto m_FloatingPointVT() {
329 return ValueType_match{[](EVT VT) { return VT.isFloatingPoint(); },
330 m_Value()};
331}
332
333/// Match any vector ValueTypes.
334template <typename Pattern> inline auto m_VectorVT(const Pattern &P) {
335 return ValueType_match{[](EVT VT) { return VT.isVector(); }, P};
336}
337inline auto m_VectorVT() {
338 return ValueType_match{[](EVT VT) { return VT.isVector(); }, m_Value()};
339}
340
341/// Match fixed-length vector ValueTypes.
342template <typename Pattern> inline auto m_FixedVectorVT(const Pattern &P) {
343 return ValueType_match{[](EVT VT) { return VT.isFixedLengthVector(); }, P};
344}
345inline auto m_FixedVectorVT() {
346 return ValueType_match{[](EVT VT) { return VT.isFixedLengthVector(); },
347 m_Value()};
348}
349
350/// Match scalable vector ValueTypes.
351template <typename Pattern> inline auto m_ScalableVectorVT(const Pattern &P) {
352 return ValueType_match{[](EVT VT) { return VT.isScalableVector(); }, P};
353}
354inline auto m_ScalableVectorVT() {
355 return ValueType_match{[](EVT VT) { return VT.isScalableVector(); },
356 m_Value()};
357}
358
359/// Match legal ValueTypes based on the information provided by TargetLowering.
360template <typename Pattern>
361inline auto m_LegalType(const SelectionDAG &DAG, const Pattern &P) {
362 return TLI_pred_match{[&DAG](SDValue N) {
364 N.getValueType());
365 },
366 P};
367}
368
369// === Generic node matching ===
370template <unsigned OpIdx, typename... OpndPreds> struct Operands_match {
372 // Returns false if there are more operands than predicates;
373 return N->getNumOperands() == OpIdx;
374 }
375};
376
377template <unsigned OpIdx, typename OpndPred, typename... OpndPreds>
378struct Operands_match<OpIdx, OpndPred, OpndPreds...>
379 : Operands_match<OpIdx + 1, OpndPreds...> {
380 OpndPred P;
381
382 Operands_match(const OpndPred &p, const OpndPreds &...preds)
383 : Operands_match<OpIdx + 1, OpndPreds...>(preds...), P(p) {}
384
386 if (OpIdx < N->getNumOperands())
387 return P.match(N->getOperand(OpIdx)) &&
389
390 // This is the case where there are more predicates than operands.
391 return false;
392 }
393};
394
395template <typename... OpndPreds>
396auto m_Node(unsigned Opcode, const OpndPreds &...preds) {
397 return m_AllOf(m_SpecificOpc(Opcode),
399}
400
401/// Provide number of operands that are not chain or glue, as well as the first
402/// index of such operand.
403template <bool ExcludeChain> struct EffectiveOperands {
404 unsigned Size = 0;
405 unsigned FirstIndex = 0;
406
408 const unsigned TotalNumOps = N->getNumOperands();
409 FirstIndex = TotalNumOps;
410 for (unsigned I = 0; I < TotalNumOps; ++I) {
411 // Count the number of non-chain and non-glue nodes (we ignore chain
412 // and glue by default) and retreive the operand index offset.
413 EVT VT = N->getOperand(I).getValueType();
414 if (VT != MVT::Glue && VT != MVT::Other) {
415 ++Size;
416 if (FirstIndex == TotalNumOps)
417 FirstIndex = I;
418 }
419 }
420 }
421};
422
423template <> struct EffectiveOperands<false> {
424 unsigned Size = 0;
425 unsigned FirstIndex = 0;
426
427 explicit EffectiveOperands(SDValue N) : Size(N->getNumOperands()) {}
428};
429
430// === Ternary operations ===
431template <typename T0_P, typename T1_P, typename T2_P, bool Commutable = false,
432 bool ExcludeChain = false>
434 unsigned Opcode;
435 T0_P Op0;
436 T1_P Op1;
437 T2_P Op2;
438
439 TernaryOpc_match(unsigned Opc, const T0_P &Op0, const T1_P &Op1,
440 const T2_P &Op2)
441 : Opcode(Opc), Op0(Op0), Op1(Op1), Op2(Op2) {}
442
446 assert(EO.Size == 3);
447 return ((Op0.match(N->getOperand(EO.FirstIndex)) &&
448 Op1.match(N->getOperand(EO.FirstIndex + 1))) ||
449 (Commutable && Op0.match(N->getOperand(EO.FirstIndex + 1)) &&
450 Op1.match(N->getOperand(EO.FirstIndex)))) &&
451 Op2.match(N->getOperand(EO.FirstIndex + 2));
452 }
453
454 return false;
455 }
456};
457
458template <typename T0_P, typename T1_P, typename T2_P>
459inline TernaryOpc_match<T0_P, T1_P, T2_P>
460m_SetCC(const T0_P &LHS, const T1_P &RHS, const T2_P &CC) {
462}
463
464template <typename T0_P, typename T1_P, typename T2_P>
465inline TernaryOpc_match<T0_P, T1_P, T2_P, true, false>
466m_c_SetCC(const T0_P &LHS, const T1_P &RHS, const T2_P &CC) {
468 CC);
469}
470
471template <typename T0_P, typename T1_P, typename T2_P>
472inline TernaryOpc_match<T0_P, T1_P, T2_P>
473m_Select(const T0_P &Cond, const T1_P &T, const T2_P &F) {
475}
476
477template <typename T0_P, typename T1_P, typename T2_P>
478inline TernaryOpc_match<T0_P, T1_P, T2_P>
479m_VSelect(const T0_P &Cond, const T1_P &T, const T2_P &F) {
481}
482
483template <typename T0_P, typename T1_P, typename T2_P>
484inline auto m_SelectLike(const T0_P &Cond, const T1_P &T, const T2_P &F) {
485 return m_AnyOf(m_Select(Cond, T, F), m_VSelect(Cond, T, F));
486}
487
488template <typename T0_P, typename T1_P, typename T2_P>
489inline Result_match<0, TernaryOpc_match<T0_P, T1_P, T2_P>>
490m_Load(const T0_P &Ch, const T1_P &Ptr, const T2_P &Offset) {
491 return m_Result<0>(
493}
494
495template <typename T0_P, typename T1_P, typename T2_P>
496inline TernaryOpc_match<T0_P, T1_P, T2_P>
497m_InsertElt(const T0_P &Vec, const T1_P &Val, const T2_P &Idx) {
499 Idx);
500}
501
502template <typename LHS, typename RHS, typename IDX>
503inline TernaryOpc_match<LHS, RHS, IDX>
504m_InsertSubvector(const LHS &Base, const RHS &Sub, const IDX &Idx) {
506}
507
508template <typename T0_P, typename T1_P, typename T2_P>
509inline TernaryOpc_match<T0_P, T1_P, T2_P>
510m_SpliceRight(const T0_P &V1, const T1_P &V2, const T2_P &Offset) {
512 Offset);
513}
514
515template <typename T0_P, typename T1_P, typename T2_P>
516inline TernaryOpc_match<T0_P, T1_P, T2_P>
517m_TernaryOp(unsigned Opc, const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
518 return TernaryOpc_match<T0_P, T1_P, T2_P>(Opc, Op0, Op1, Op2);
519}
520
521template <typename T0_P, typename T1_P, typename T2_P>
522inline TernaryOpc_match<T0_P, T1_P, T2_P, true>
523m_c_TernaryOp(unsigned Opc, const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
524 return TernaryOpc_match<T0_P, T1_P, T2_P, true>(Opc, Op0, Op1, Op2);
525}
526
527template <typename LTy, typename RTy, typename TTy, typename FTy, typename CCTy>
528inline auto m_SelectCC(const LTy &L, const RTy &R, const TTy &T, const FTy &F,
529 const CCTy &CC) {
530 return m_Node(ISD::SELECT_CC, L, R, T, F, CC);
531}
532
533template <typename LTy, typename RTy, typename TTy, typename FTy, typename CCTy>
534inline auto m_SelectCCLike(const LTy &L, const RTy &R, const TTy &T,
535 const FTy &F, const CCTy &CC) {
536 return m_AnyOf(m_Select(m_SetCC(L, R, CC), T, F), m_SelectCC(L, R, T, F, CC));
537}
538
539// === Binary operations ===
540template <typename LHS_P, typename RHS_P, bool Commutable = false,
541 bool ExcludeChain = false>
543 unsigned Opcode;
544 LHS_P LHS;
545 RHS_P RHS;
547 BinaryOpc_match(unsigned Opc, const LHS_P &L, const RHS_P &R,
548 SDNodeFlags Flgs = SDNodeFlags())
549 : Opcode(Opc), LHS(L), RHS(R), Flags(Flgs) {}
550
554 assert(EO.Size == 2);
555 if (!((LHS.match(N->getOperand(EO.FirstIndex)) &&
556 RHS.match(N->getOperand(EO.FirstIndex + 1))) ||
557 (Commutable && LHS.match(N->getOperand(EO.FirstIndex + 1)) &&
558 RHS.match(N->getOperand(EO.FirstIndex)))))
559 return false;
560
561 return (Flags & N->getFlags()) == Flags;
562 }
563
564 return false;
565 }
566};
567
568/// Matching while capturing mask
569template <typename T0, typename T1, typename T2> struct SDShuffle_match {
570 T0 Op1;
573
574 SDShuffle_match(const T0 &Op1, const T1 &Op2, const T2 &Mask)
575 : Op1(Op1), Op2(Op2), Mask(Mask) {}
576
578 if (auto *I = dyn_cast<ShuffleVectorSDNode>(N)) {
579 return Op1.match(I->getOperand(0)) && Op2.match(I->getOperand(1)) &&
580 Mask.match(I->getMask());
581 }
582 return false;
583 }
584};
585struct m_Mask {
588 bool match(ArrayRef<int> Mask) {
589 MaskRef = Mask;
590 return true;
591 }
592};
593
599
600template <typename LHS_P, typename RHS_P, typename Pred_t,
601 bool Commutable = false, bool ExcludeChain = false>
603 using PredType = Pred_t;
604 LHS_P LHS;
605 RHS_P RHS;
606
607 MaxMin_match(const LHS_P &L, const RHS_P &R) : LHS(L), RHS(R) {}
608
610 auto MatchMinMax = [&](SDValue L, SDValue R, SDValue TrueValue,
611 SDValue FalseValue, ISD::CondCode CC) {
612 if ((TrueValue != L || FalseValue != R) &&
613 (TrueValue != R || FalseValue != L))
614 return false;
615
617 TrueValue == L ? CC : getSetCCInverse(CC, L.getValueType());
618 if (!Pred_t::match(Cond))
619 return false;
620
621 return (LHS.match(L) && RHS.match(R)) ||
622 (Commutable && LHS.match(R) && RHS.match(L));
623 };
624
628 assert(EO_SELECT.Size == 3);
629 SDValue Cond = N->getOperand(EO_SELECT.FirstIndex);
630 SDValue TrueValue = N->getOperand(EO_SELECT.FirstIndex + 1);
631 SDValue FalseValue = N->getOperand(EO_SELECT.FirstIndex + 2);
632
635 assert(EO_SETCC.Size == 3);
636 SDValue L = Cond->getOperand(EO_SETCC.FirstIndex);
637 SDValue R = Cond->getOperand(EO_SETCC.FirstIndex + 1);
638 auto *CondNode =
639 cast<CondCodeSDNode>(Cond->getOperand(EO_SETCC.FirstIndex + 2));
640 return MatchMinMax(L, R, TrueValue, FalseValue, CondNode->get());
641 }
642 }
643
646 assert(EO_SELECT.Size == 5);
647 SDValue L = N->getOperand(EO_SELECT.FirstIndex);
648 SDValue R = N->getOperand(EO_SELECT.FirstIndex + 1);
649 SDValue TrueValue = N->getOperand(EO_SELECT.FirstIndex + 2);
650 SDValue FalseValue = N->getOperand(EO_SELECT.FirstIndex + 3);
651 auto *CondNode =
652 cast<CondCodeSDNode>(N->getOperand(EO_SELECT.FirstIndex + 4));
653 return MatchMinMax(L, R, TrueValue, FalseValue, CondNode->get());
654 }
655
656 return false;
657 }
658};
659
660// Helper class for identifying signed max predicates.
662 static bool match(ISD::CondCode Cond) {
664 }
665};
666
667// Helper class for identifying unsigned max predicates.
672};
673
674// Helper class for identifying signed min predicates.
676 static bool match(ISD::CondCode Cond) {
678 }
679};
680
681// Helper class for identifying unsigned min predicates.
686};
687
688template <typename LHS, typename RHS>
689inline BinaryOpc_match<LHS, RHS> m_BinOp(unsigned Opc, const LHS &L,
690 const RHS &R,
691 SDNodeFlags Flgs = SDNodeFlags()) {
692 return BinaryOpc_match<LHS, RHS>(Opc, L, R, Flgs);
693}
694template <typename LHS, typename RHS>
696m_c_BinOp(unsigned Opc, const LHS &L, const RHS &R,
697 SDNodeFlags Flgs = SDNodeFlags()) {
698 return BinaryOpc_match<LHS, RHS, true>(Opc, L, R, Flgs);
699}
700
701template <typename LHS, typename RHS>
703m_ChainedBinOp(unsigned Opc, const LHS &L, const RHS &R) {
705}
706template <typename LHS, typename RHS>
708m_c_ChainedBinOp(unsigned Opc, const LHS &L, const RHS &R) {
710}
711
712// Common binary operations
713template <typename LHS, typename RHS>
714inline BinaryOpc_match<LHS, RHS, true> m_Add(const LHS &L, const RHS &R) {
716}
717
718template <typename LHS, typename RHS>
719inline auto m_NUWAdd(const LHS &L, const RHS &R) {
722}
723
724template <typename LHS, typename RHS>
725inline auto m_NSWAdd(const LHS &L, const RHS &R) {
728}
729
730template <typename LHS, typename RHS>
731inline BinaryOpc_match<LHS, RHS> m_Sub(const LHS &L, const RHS &R) {
733}
734
735template <typename LHS, typename RHS>
736inline BinaryOpc_match<LHS, RHS, true> m_Mul(const LHS &L, const RHS &R) {
738}
739
740template <typename LHS, typename RHS>
741inline BinaryOpc_match<LHS, RHS, true> m_And(const LHS &L, const RHS &R) {
743}
744
745template <typename LHS, typename RHS>
746inline BinaryOpc_match<LHS, RHS, true> m_Or(const LHS &L, const RHS &R) {
748}
749
750template <typename LHS, typename RHS>
755
756template <typename LHS, typename RHS>
757inline auto m_AddLike(const LHS &L, const RHS &R) {
758 return m_AnyOf(m_Add(L, R), m_DisjointOr(L, R));
759}
760
761template <typename LHS, typename RHS>
762inline auto m_NSWAddLike(const LHS &L, const RHS &R) {
763 return m_AnyOf(m_NSWAdd(L, R), m_DisjointOr(L, R));
764}
765
766template <typename LHS, typename RHS>
767inline auto m_NUWAddLike(const LHS &L, const RHS &R) {
768 return m_AnyOf(m_NUWAdd(L, R), m_DisjointOr(L, R));
769}
770
771template <typename LHS, typename RHS>
772inline BinaryOpc_match<LHS, RHS, true> m_Xor(const LHS &L, const RHS &R) {
774}
775
776template <typename LHS, typename RHS>
777inline auto m_BitwiseLogic(const LHS &L, const RHS &R) {
778 return m_AnyOf(m_And(L, R), m_Or(L, R), m_Xor(L, R));
779}
780
781template <unsigned Opc, typename Pred, typename LHS, typename RHS>
782inline auto m_MaxMinLike(const LHS &L, const RHS &R) {
785}
786
787template <typename LHS, typename RHS>
788inline BinaryOpc_match<LHS, RHS, true> m_SMin(const LHS &L, const RHS &R) {
790}
791
792template <typename LHS, typename RHS>
793inline auto m_SMinLike(const LHS &L, const RHS &R) {
795}
796
797template <typename LHS, typename RHS>
798inline BinaryOpc_match<LHS, RHS, true> m_SMax(const LHS &L, const RHS &R) {
800}
801
802template <typename LHS, typename RHS>
803inline auto m_SMaxLike(const LHS &L, const RHS &R) {
805}
806
807template <typename LHS, typename RHS>
808inline BinaryOpc_match<LHS, RHS, true> m_UMin(const LHS &L, const RHS &R) {
810}
811
812template <typename LHS, typename RHS>
813inline auto m_UMinLike(const LHS &L, const RHS &R) {
815}
816
817template <typename LHS, typename RHS>
818inline BinaryOpc_match<LHS, RHS, true> m_UMax(const LHS &L, const RHS &R) {
820}
821
822template <typename LHS, typename RHS>
823inline auto m_UMaxLike(const LHS &L, const RHS &R) {
825}
826
827template <typename LHS, typename RHS>
828inline BinaryOpc_match<LHS, RHS> m_UDiv(const LHS &L, const RHS &R) {
830}
831template <typename LHS, typename RHS>
832inline BinaryOpc_match<LHS, RHS> m_SDiv(const LHS &L, const RHS &R) {
834}
835
836template <typename LHS, typename RHS>
837inline BinaryOpc_match<LHS, RHS> m_URem(const LHS &L, const RHS &R) {
839}
840template <typename LHS, typename RHS>
841inline BinaryOpc_match<LHS, RHS> m_SRem(const LHS &L, const RHS &R) {
843}
844
845template <typename LHS, typename RHS>
846inline BinaryOpc_match<LHS, RHS> m_Shl(const LHS &L, const RHS &R) {
848}
849
850template <typename LHS, typename RHS>
851inline BinaryOpc_match<LHS, RHS> m_Sra(const LHS &L, const RHS &R) {
853}
854template <typename LHS, typename RHS>
855inline BinaryOpc_match<LHS, RHS> m_Srl(const LHS &L, const RHS &R) {
857}
858template <typename LHS, typename RHS>
863
864template <typename LHS, typename RHS>
865inline BinaryOpc_match<LHS, RHS> m_Rotl(const LHS &L, const RHS &R) {
867}
868
869template <typename LHS, typename RHS>
870inline BinaryOpc_match<LHS, RHS> m_Rotr(const LHS &L, const RHS &R) {
872}
873
874template <typename T0_P, typename T1_P, typename T2_P>
875inline TernaryOpc_match<T0_P, T1_P, T2_P>
876m_FShL(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
877 return m_TernaryOp(ISD::FSHL, Op0, Op1, Op2);
878}
879
880template <typename T0_P, typename T1_P, typename T2_P>
881inline TernaryOpc_match<T0_P, T1_P, T2_P>
882m_FShR(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
883 return m_TernaryOp(ISD::FSHR, Op0, Op1, Op2);
884}
885
886template <typename T0_P, typename T1_P, typename T2_P, bool Left>
888 T0_P Op0;
889 T1_P Op1;
890 T2_P Op2;
891
892 FunnelShiftLike_match(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2)
893 : Op0(Op0), Op1(Op1), Op2(Op2) {}
894
895 static bool hasComplementaryConstantShifts(const APInt &ShlV,
896 const APInt &SrlV,
897 unsigned BitWidth) {
898 unsigned SumWidth = std::max(ShlV.getBitWidth(), SrlV.getBitWidth()) + 1;
899 unsigned BitWidthBits = llvm::bit_width(BitWidth);
900 if (BitWidthBits > SumWidth)
901 return false;
902
903 return ShlV.zext(SumWidth) + SrlV.zext(SumWidth) ==
904 APInt(SumWidth, BitWidth);
905 }
906
908 return Op0.match(X) && Op1.match(Y) && Op2.match(Z);
909 }
910
911 bool matchShiftOr(SDValue N, unsigned BitWidth);
912
914 if (sd_match(N, Left ? m_FShL(Op0, Op1, Op2) : m_FShR(Op0, Op1, Op2)))
915 return true;
916
917 SDValue X, Z;
918 if (sd_match(N, Left ? m_Rotl(m_Value(X), m_Value(Z))
919 : m_Rotr(m_Value(X), m_Value(Z))))
920 return matchOperands(X, X, Z);
921
922 return matchShiftOr(N, N.getValueType().getScalarSizeInBits());
923 }
924};
925
926template <typename T0_P, typename T1_P, typename T2_P>
927inline FunnelShiftLike_match<T0_P, T1_P, T2_P, true>
928m_FShLLike(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
930}
931
932template <typename T0_P, typename T1_P, typename T2_P>
933inline FunnelShiftLike_match<T0_P, T1_P, T2_P, false>
934m_FShRLike(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
936}
937
938template <typename LHS, typename RHS>
942
943template <typename LHS, typename RHS>
944inline BinaryOpc_match<LHS, RHS, true> m_FAdd(const LHS &L, const RHS &R) {
946}
947
948template <typename LHS, typename RHS>
949inline BinaryOpc_match<LHS, RHS> m_FSub(const LHS &L, const RHS &R) {
951}
952
953template <typename LHS, typename RHS>
954inline BinaryOpc_match<LHS, RHS, true> m_FMul(const LHS &L, const RHS &R) {
956}
957
958template <typename LHS, typename RHS>
959inline BinaryOpc_match<LHS, RHS> m_FDiv(const LHS &L, const RHS &R) {
961}
962
963template <typename LHS, typename RHS>
964inline BinaryOpc_match<LHS, RHS> m_FRem(const LHS &L, const RHS &R) {
966}
967
968template <typename V1_t, typename V2_t>
969inline BinaryOpc_match<V1_t, V2_t> m_Shuffle(const V1_t &v1, const V2_t &v2) {
971}
972
973template <typename V1_t, typename V2_t, typename Mask_t>
974inline SDShuffle_match<V1_t, V2_t, Mask_t>
975m_Shuffle(const V1_t &v1, const V2_t &v2, const Mask_t &mask) {
977}
978
979template <typename LHS, typename RHS>
980inline BinaryOpc_match<LHS, RHS> m_ExtractElt(const LHS &Vec, const RHS &Idx) {
982}
983
984template <typename LHS, typename RHS>
986 const RHS &Idx) {
988}
989
990// === Unary operations ===
991template <typename Opnd_P, bool ExcludeChain = false> struct UnaryOpc_match {
992 unsigned Opcode;
993 Opnd_P Opnd;
995 UnaryOpc_match(unsigned Opc, const Opnd_P &Op,
996 SDNodeFlags Flgs = SDNodeFlags())
997 : Opcode(Opc), Opnd(Op), Flags(Flgs) {}
998
1000 if (sd_match(N, m_SpecificOpc(Opcode))) {
1002 assert(EO.Size == 1);
1003 if (!Opnd.match(N->getOperand(EO.FirstIndex)))
1004 return false;
1005
1006 return (Flags & N->getFlags()) == Flags;
1007 }
1008
1009 return false;
1010 }
1011};
1012
1013template <typename Opnd>
1014inline UnaryOpc_match<Opnd> m_UnaryOp(unsigned Opc, const Opnd &Op) {
1015 return UnaryOpc_match<Opnd>(Opc, Op);
1016}
1017template <typename Opnd>
1019 const Opnd &Op) {
1021}
1022
1023template <typename Opnd> inline UnaryOpc_match<Opnd> m_BitCast(const Opnd &Op) {
1025}
1026
1027template <typename Opnd>
1028inline UnaryOpc_match<Opnd> m_BSwap(const Opnd &Op) {
1030}
1031
1032template <typename Opnd>
1036
1037template <typename Opnd> inline UnaryOpc_match<Opnd> m_ZExt(const Opnd &Op) {
1039}
1040
1041template <typename Opnd>
1045
1046template <typename Opnd> inline auto m_SExt(const Opnd &Op) {
1048}
1049
1050template <typename Opnd> inline UnaryOpc_match<Opnd> m_AnyExt(const Opnd &Op) {
1052}
1053
1054template <typename Opnd> inline UnaryOpc_match<Opnd> m_Trunc(const Opnd &Op) {
1056}
1057
1058template <typename Opnd> inline auto m_Abs(const Opnd &Op) {
1061}
1062
1063template <typename Opnd> inline UnaryOpc_match<Opnd> m_FAbs(const Opnd &Op) {
1065}
1066
1067/// Match a zext or identity
1068/// Allows to peek through optional extensions
1069template <typename Opnd> inline auto m_ZExtOrSelf(const Opnd &Op) {
1070 return m_AnyOf(m_ZExt(Op), Op);
1071}
1072
1073/// Match a sext or identity
1074/// Allows to peek through optional extensions
1075template <typename Opnd> inline auto m_SExtOrSelf(const Opnd &Op) {
1076 return m_AnyOf(m_SExt(Op), Op);
1077}
1078
1079template <typename Opnd> inline auto m_SExtLike(const Opnd &Op) {
1080 return m_AnyOf(m_SExt(Op), m_NNegZExt(Op));
1081}
1082
1083/// Match a aext or identity
1084/// Allows to peek through optional extensions
1085template <typename Opnd>
1086inline Or<UnaryOpc_match<Opnd>, Opnd> m_AExtOrSelf(const Opnd &Op) {
1087 return Or<UnaryOpc_match<Opnd>, Opnd>(m_AnyExt(Op), Op);
1088}
1089
1090/// Match a trunc or identity
1091/// Allows to peek through optional truncations
1092template <typename Opnd>
1093inline Or<UnaryOpc_match<Opnd>, Opnd> m_TruncOrSelf(const Opnd &Op) {
1094 return Or<UnaryOpc_match<Opnd>, Opnd>(m_Trunc(Op), Op);
1095}
1096
1097template <typename Opnd> inline UnaryOpc_match<Opnd> m_VScale(const Opnd &Op) {
1099}
1100
1101template <typename Opnd> inline UnaryOpc_match<Opnd> m_FPToUI(const Opnd &Op) {
1103}
1104
1105template <typename Opnd> inline UnaryOpc_match<Opnd> m_FPToSI(const Opnd &Op) {
1107}
1108
1109template <typename Opnd> inline UnaryOpc_match<Opnd> m_Ctpop(const Opnd &Op) {
1111}
1112
1113template <typename Opnd> inline UnaryOpc_match<Opnd> m_Ctlz(const Opnd &Op) {
1115}
1116
1117template <typename Opnd> inline UnaryOpc_match<Opnd> m_Cttz(const Opnd &Op) {
1119}
1120
1121template <typename Opnd> inline UnaryOpc_match<Opnd> m_FNeg(const Opnd &Op) {
1123}
1124
1125template <typename Opnd>
1129
1130// === Constants ===
1133
1134 explicit ConstantInt_match(APInt *V) : BindVal(V) {}
1135
1137 // The logics here are similar to that in
1138 // SelectionDAG::isConstantIntBuildVectorOrConstantInt, but the latter also
1139 // treats GlobalAddressSDNode as a constant, which is difficult to turn into
1140 // APInt.
1141 if (auto *C = dyn_cast_or_null<ConstantSDNode>(N.getNode())) {
1142 if (BindVal)
1143 *BindVal = C->getAPIntValue();
1144 return true;
1145 }
1146
1147 APInt Discard;
1148 return ISD::isConstantSplatVector(N.getNode(),
1149 BindVal ? *BindVal : Discard);
1150 }
1151};
1152
1153template <typename T> struct Constant64_match {
1154 static_assert(sizeof(T) == 8, "T must be 64 bits wide");
1155
1157
1158 explicit Constant64_match(T &V) : BindVal(V) {}
1159
1161 APInt V;
1162 if (!ConstantInt_match(&V).match(N))
1163 return false;
1164
1165 if constexpr (std::is_signed_v<T>) {
1166 if (std::optional<int64_t> TrySExt = V.trySExtValue()) {
1167 BindVal = *TrySExt;
1168 return true;
1169 }
1170 }
1171
1172 if constexpr (std::is_unsigned_v<T>) {
1173 if (std::optional<uint64_t> TryZExt = V.tryZExtValue()) {
1174 BindVal = *TryZExt;
1175 return true;
1176 }
1177 }
1178
1179 return false;
1180 }
1181};
1182
1183/// Match any integer constants or splat of an integer constant.
1185/// Match any integer constants or splat of an integer constant; return the
1186/// specific constant or constant splat value.
1188/// Match any integer constants or splat of an integer constant that can fit in
1189/// 64 bits; return the specific constant or constant splat value, zero-extended
1190/// to 64 bits.
1194/// Match any integer constants or splat of an integer constant that can fit in
1195/// 64 bits; return the specific constant or constant splat value, sign-extended
1196/// to 64 bits.
1198 return Constant64_match<int64_t>(V);
1199}
1200
1201template <typename T0_P, typename T1_P, typename T2_P, bool Left>
1203 SDValue N, unsigned BitWidth) {
1204 SDValue X, Y, ShlAmt, SrlAmt;
1205 APInt ShlConst, SrlConst;
1206 if (!sd_match(
1207 N, m_Or(m_Shl(m_Value(X), m_Value(ShlAmt, m_ConstInt(ShlConst))),
1208 m_Srl(m_Value(Y), m_Value(SrlAmt, m_ConstInt(SrlConst))))) ||
1209 !hasComplementaryConstantShifts(ShlConst, SrlConst, BitWidth))
1210 return false;
1211
1212 return matchOperands(X, Y, Left ? ShlAmt : SrlAmt);
1213}
1214
1217
1218 explicit SpecificInt_match(APInt APV) : IntVal(std::move(APV)) {}
1219
1221 APInt ConstInt;
1222 if (sd_match(N, m_ConstInt(ConstInt)))
1223 return APInt::isSameValue(IntVal, ConstInt);
1224 return false;
1225 }
1226};
1227
1228/// Match a specific integer constant or constant splat value.
1230 return SpecificInt_match(std::move(V));
1231}
1233 return SpecificInt_match(APInt(64, V));
1234}
1235
1238
1239 explicit SpecificFP_match(APFloat V) : Val(V) {}
1240
1241 bool match(SDValue V) {
1242 if (const auto *CFP = dyn_cast<ConstantFPSDNode>(V.getNode()))
1243 return CFP->isExactlyValue(Val);
1244 if (ConstantFPSDNode *C = isConstOrConstSplatFP(V, /*AllowUndefs=*/true))
1245 return C->getValueAPF().compare(Val) == APFloat::cmpEqual;
1246 return false;
1247 }
1248};
1249
1250/// Match a specific float constant.
1252
1254 return SpecificFP_match(APFloat(V));
1255}
1256
1260 return C->isZero();
1261 return false;
1262 }
1263};
1264
1265/// Match a floating-point +0.0 or -0.0 constant or splat.
1267
1270
1272
1273 bool match(SDValue N) const { return isZeroOrZeroSplat(N, AllowUndefs); }
1274};
1275
1283
1291
1292inline Ones_match m_One(bool AllowUndefs = false) {
1293 return Ones_match(AllowUndefs);
1294}
1295inline Zero_match m_Zero(bool AllowUndefs = false) {
1296 return Zero_match(AllowUndefs);
1297}
1298inline AllOnes_match m_AllOnes(bool AllowUndefs = false) {
1299 return AllOnes_match(AllowUndefs);
1300}
1301
1302/// Match true boolean value based on the information provided by
1303/// TargetLowering.
1304inline auto m_True(const SelectionDAG &DAG) {
1305 return TLI_pred_match{
1306 [&DAG](SDValue N) {
1307 APInt ConstVal;
1308 if (sd_match(N, m_ConstInt(ConstVal)))
1310 N.getValueType())) {
1312 return ConstVal.isOne();
1314 return ConstVal.isAllOnes();
1316 return (ConstVal & 0x01) == 1;
1317 }
1318
1319 return false;
1320 },
1321 m_Value()};
1322}
1323/// Match false boolean value based on the information provided by
1324/// TargetLowering.
1325inline auto m_False(const SelectionDAG &DAG) {
1326 return TLI_pred_match{
1327 [&DAG](SDValue N) {
1328 APInt ConstVal;
1329 if (sd_match(N, m_ConstInt(ConstVal)))
1331 N.getValueType())) {
1334 return ConstVal.isZero();
1336 return (ConstVal & 0x01) == 0;
1337 }
1338
1339 return false;
1340 },
1341 m_Value()};
1342}
1343
1345 std::optional<ISD::CondCode> CCToMatch;
1347
1349
1350 explicit CondCode_match(ISD::CondCode *CC) : BindCC(CC) {}
1351
1353 if (auto *CC = dyn_cast<CondCodeSDNode>(N.getNode())) {
1354 if (CCToMatch && *CCToMatch != CC->get())
1355 return false;
1356
1357 if (BindCC)
1358 *BindCC = CC->get();
1359 return true;
1360 }
1361
1362 return false;
1363 }
1364};
1365
1366/// Match any conditional code SDNode.
1367inline CondCode_match m_CondCode() { return CondCode_match(nullptr); }
1368/// Match any conditional code SDNode and return its ISD::CondCode value.
1370 return CondCode_match(&CC);
1371}
1372/// Match a conditional code SDNode with a specific ISD::CondCode.
1376
1377/// Match a negate as a sub(0, v)
1378template <typename ValTy>
1380 return m_Sub(m_Zero(), V);
1381}
1382
1383/// Match a Not as a xor(v, -1) or xor(-1, v)
1384template <typename ValTy>
1386 return m_Xor(V, m_AllOnes());
1387}
1388
1389template <unsigned IntrinsicId, typename... OpndPreds>
1390inline auto m_IntrinsicWOChain(const OpndPreds &...Opnds) {
1391 return m_Node(ISD::INTRINSIC_WO_CHAIN, m_SpecificInt(IntrinsicId), Opnds...);
1392}
1393
1396
1398
1400 if (sd_match(N, m_Neg(m_Specific(V))))
1401 return true;
1402
1405 return LHS->getAPIntValue() == -RHS->getAPIntValue();
1406 });
1407 }
1408};
1409
1410/// Match a negation of a specific value V, either as sub(0, V) or as
1411/// constant(s) that are the negation of V's constant(s).
1415
1416template <typename... PatternTs> struct ReassociatableOpc_match {
1417 unsigned Opcode;
1418 std::tuple<PatternTs...> Patterns;
1419 constexpr static size_t NumPatterns =
1420 std::tuple_size_v<std::tuple<PatternTs...>>;
1421
1423
1424 ReassociatableOpc_match(unsigned Opcode, const PatternTs &...Patterns)
1425 : Opcode(Opcode), Patterns(Patterns...) {}
1426
1428 const PatternTs &...Patterns)
1430
1432 std::array<SDValue, NumPatterns> Leaves;
1433 size_t LeavesIdx = 0;
1434 if (!(collectLeaves(N, Leaves, LeavesIdx) && (LeavesIdx == NumPatterns)))
1435 return false;
1436
1438 return std::apply(
1439 [&](auto &...P) -> bool {
1440 return reassociatableMatchHelper(Leaves, Used, P...);
1441 },
1442 Patterns);
1443 }
1444
1445 bool collectLeaves(SDValue V, std::array<SDValue, NumPatterns> &Leaves,
1446 std::size_t &LeafIdx) {
1447 if (V->getOpcode() == Opcode && (Flags & V->getFlags()) == Flags) {
1448 for (size_t I = 0, N = V->getNumOperands(); I < N; I++)
1449 if ((LeafIdx == NumPatterns) ||
1450 !collectLeaves(V->getOperand(I), Leaves, LeafIdx))
1451 return false;
1452 } else {
1453 Leaves[LeafIdx] = V;
1454 LeafIdx++;
1455 }
1456 return true;
1457 }
1458
1459 // Searchs for a matching leaf for every sub-pattern.
1460 template <typename PatternHd, typename... PatternTl>
1461 [[nodiscard]] inline bool
1463 PatternHd &HeadPattern,
1464 PatternTl &...TailPatterns) {
1465 for (size_t Match = 0, N = Used.size(); Match < N; Match++) {
1466 if (Used[Match] || !(sd_match(Leaves[Match], HeadPattern)))
1467 continue;
1468 Used.set(Match);
1469 if (reassociatableMatchHelper(Leaves, Used, TailPatterns...))
1470 return true;
1471 Used.reset(Match);
1472 }
1473 return false;
1474 }
1475
1476 [[nodiscard]] inline bool
1478 Bitset<NumPatterns> &Used) {
1479 return true;
1480 }
1481};
1482
1483template <typename... PatternTs>
1484inline ReassociatableOpc_match<PatternTs...>
1485m_ReassociatableAdd(const PatternTs &...Patterns) {
1486 return ReassociatableOpc_match<PatternTs...>(ISD::ADD, Patterns...);
1487}
1488
1489template <typename... PatternTs>
1490inline ReassociatableOpc_match<PatternTs...>
1491m_ReassociatableOr(const PatternTs &...Patterns) {
1492 return ReassociatableOpc_match<PatternTs...>(ISD::OR, Patterns...);
1493}
1494
1495template <typename... PatternTs>
1496inline ReassociatableOpc_match<PatternTs...>
1497m_ReassociatableAnd(const PatternTs &...Patterns) {
1498 return ReassociatableOpc_match<PatternTs...>(ISD::AND, Patterns...);
1499}
1500
1501template <typename... PatternTs>
1502inline ReassociatableOpc_match<PatternTs...>
1503m_ReassociatableMul(const PatternTs &...Patterns) {
1504 return ReassociatableOpc_match<PatternTs...>(ISD::MUL, Patterns...);
1505}
1506
1507template <typename... PatternTs>
1508inline ReassociatableOpc_match<PatternTs...>
1509m_ReassociatableNSWAdd(const PatternTs &...Patterns) {
1510 return ReassociatableOpc_match<PatternTs...>(
1511 ISD::ADD, SDNodeFlags::NoSignedWrap, Patterns...);
1512}
1513
1514template <typename... PatternTs>
1515inline ReassociatableOpc_match<PatternTs...>
1516m_ReassociatableNUWAdd(const PatternTs &...Patterns) {
1517 return ReassociatableOpc_match<PatternTs...>(
1519}
1520
1521} // namespace SDPatternMatch
1522} // namespace llvm
1523#endif
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned uint64_t
This file implements a class to represent arbitrary precision integral constant values and operations...
#define X(NUM, ENUM, NAME)
Definition ELF.h:857
static constexpr unsigned long long mask(BlockVerifier::State S)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define T
#define T1
#define P(N)
const SmallVectorImpl< MachineOperand > & Cond
This file contains some templates that are useful if you are working with the STL at all.
This file implements the SmallBitVector class.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
This file describes how to lower LLVM code to machine code.
Value * RHS
Value * LHS
This file implements the C++20 <bit> header.
Class for arbitrary precision integers.
Definition APInt.h:78
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
Definition APInt.cpp:1057
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
Definition APInt.h:367
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
Definition APInt.h:376
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition APInt.h:1508
static bool isSameValue(const APInt &I1, const APInt &I2, bool SignedCompare=false)
Determine if two APInts have the same value, after zero-extending or sign-extending (if SignedCompare...
Definition APInt.h:550
bool isOne() const
Determine if this is a value of 1.
Definition APInt.h:385
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.
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...
const TargetLowering & getTargetLoweringInfo() const
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.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
Definition ISDOpcodes.h:835
@ POISON
POISON - A poison node.
Definition ISDOpcodes.h:236
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
Definition ISDOpcodes.h:603
@ BSWAP
Byte Swap and Counting operators.
Definition ISDOpcodes.h:795
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:264
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
Definition ISDOpcodes.h:869
@ FADD
Simple binary floating point operators.
Definition ISDOpcodes.h:418
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
Definition ISDOpcodes.h:755
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ CLMUL
Carry-less multiplication operations.
Definition ISDOpcodes.h:786
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:860
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
Definition ISDOpcodes.h:812
@ UNDEF
UNDEF - An undefined node.
Definition ISDOpcodes.h:233
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:777
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
Definition ISDOpcodes.h:657
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
Definition ISDOpcodes.h:617
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
Definition ISDOpcodes.h:579
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition ISDOpcodes.h:866
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
Definition ISDOpcodes.h:827
@ 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:735
@ VECTOR_REVERSE
VECTOR_REVERSE(VECTOR) - Returns a vector, of the same type as VECTOR, whose elements are shuffled us...
Definition ISDOpcodes.h:648
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
Definition ISDOpcodes.h:821
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition ISDOpcodes.h:942
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:747
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
Definition ISDOpcodes.h:205
@ VECTOR_SPLICE_RIGHT
VECTOR_SPLICE_RIGHT(VEC1, VEC2, OFFSET) - Shifts CONCAT_VECTORS(VEC1,VEC2) right by OFFSET elements a...
Definition ISDOpcodes.h:665
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
Definition ISDOpcodes.h:568
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition ISDOpcodes.h:872
@ ABS_MIN_POISON
ABS with a poison result for INT_MIN.
Definition ISDOpcodes.h:759
LLVM_ABI bool matchBinaryPredicate(SDValue LHS, SDValue RHS, const APInt &DemandedElts, 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...
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,...
AllOnesConstantMatch m_AllOnes()
cst_pred_ty< is_one > m_One()
Match an integer 1 or a vector with all elements equal to 1.
auto m_BinOp()
Match an arbitrary binary operation and ignore it.
auto m_VScale()
Matches a call to llvm.vscale().
is_zero m_Zero()
Match any null constant or a vector with all elements equal to 0.
BinaryOpc_match< Zero_match, ValTy, false > m_Neg(const ValTy &V)
Match a negate as a sub(0, v)
Result_match< 0, TernaryOpc_match< T0_P, T1_P, T2_P > > m_Load(const T0_P &Ch, const T1_P &Ptr, const T2_P &Offset)
ReassociatableOpc_match< PatternTs... > m_ReassociatableMul(const PatternTs &...Patterns)
auto m_SelectCCLike(const LTy &L, const RTy &R, const TTy &T, const FTy &F, const CCTy &CC)
auto m_ExactSr(const LHS &L, const RHS &R)
BinaryOpc_match< LHS, RHS > m_Srl(const LHS &L, const RHS &R)
auto m_SExtLike(const Opnd &Op)
auto m_SpecificVT(EVT RefVT, const Pattern &P)
Match a specific ValueType.
auto m_SelectCC(const LTy &L, const RTy &R, const TTy &T, const FTy &F, const CCTy &CC)
Opcode_match m_SpecificOpc(unsigned Opcode)
BinaryOpc_match< LHS, RHS > m_Sra(const LHS &L, const RHS &R)
BinaryOpc_match< LHS, RHS > m_FRem(const LHS &L, const RHS &R)
auto m_False(const SelectionDAG &DAG)
Match false boolean value based on the information provided by TargetLowering.
TLI_pred_match(const PredFuncT &Pred, const Pattern &P) -> TLI_pred_match< Pattern, PredFuncT >
auto m_Abs(const Opnd &Op)
Result_match< ResNo, Pattern > m_Result(const Pattern &P)
Match only if the SDValue is a certain result at ResNo.
auto m_MaxMinLike(const LHS &L, const RHS &R)
BinaryOpc_match< LHS, RHS, true > m_c_BinOp(unsigned Opc, const LHS &L, const RHS &R, SDNodeFlags Flgs=SDNodeFlags())
BinaryOpc_match< LHS, RHS, true > m_Mul(const LHS &L, const RHS &R)
BinaryOpc_match< LHS, RHS, true > m_Clmul(const LHS &L, const RHS &R)
auto m_UMinLike(const LHS &L, const RHS &R)
auto m_SelectLike(const T0_P &Cond, const T1_P &T, const T2_P &F)
TernaryOpc_match< LHS, RHS, IDX > m_InsertSubvector(const LHS &Base, const RHS &Sub, const IDX &Idx)
auto m_UMaxLike(const LHS &L, const RHS &R)
BinaryOpc_match< LHS, RHS, true > m_Or(const LHS &L, const RHS &R)
TernaryOpc_match< T0_P, T1_P, T2_P > m_TernaryOp(unsigned Opc, const T0_P &Op0, const T1_P &Op1, const T2_P &Op2)
TernaryOpc_match< T0_P, T1_P, T2_P > m_InsertElt(const T0_P &Vec, const T1_P &Val, const T2_P &Idx)
BinaryOpc_match< LHS, RHS, false, true > m_ChainedBinOp(unsigned Opc, const LHS &L, const RHS &R)
BinaryOpc_match< LHS, RHS, true > m_SMin(const LHS &L, const RHS &R)
auto m_IntrinsicWOChain(const OpndPreds &...Opnds)
UnaryOpc_match< Opnd > m_Trunc(const Opnd &Op)
BinaryOpc_match< LHS, RHS > m_FSub(const LHS &L, const RHS &R)
auto m_AddLike(const LHS &L, const RHS &R)
BinaryOpc_match< LHS, RHS > m_URem(const LHS &L, const RHS &R)
AnyZeroFP_match m_AnyZeroFP()
Match a floating-point +0.0 or -0.0 constant or splat.
UnaryOpc_match< Opnd > m_BSwap(const Opnd &Op)
Or< Preds... > m_AnyOf(const Preds &...preds)
BinaryOpc_match< LHS, RHS, true, true > m_c_ChainedBinOp(unsigned Opc, const LHS &L, const RHS &R)
Or< UnaryOpc_match< Opnd >, Opnd > m_TruncOrSelf(const Opnd &Op)
Match a trunc or identity Allows to peek through optional truncations.
UnaryOpc_match< Opnd > m_NNegZExt(const Opnd &Op)
TernaryOpc_match< T0_P, T1_P, T2_P > m_FShR(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2)
And< Preds... > m_AllOf(const Preds &...preds)
UnaryOpc_match< Opnd > m_VectorReverse(const Opnd &Op)
BinaryOpc_match< LHS, RHS > m_FDiv(const LHS &L, const RHS &R)
auto m_NSWAdd(const LHS &L, const RHS &R)
UnaryOpc_match< Opnd > m_BitCast(const Opnd &Op)
UnaryOpc_match< Opnd > m_FNeg(const Opnd &Op)
FunnelShiftLike_match< T0_P, T1_P, T2_P, false > m_FShRLike(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2)
Opcode_match m_Poison()
auto m_LegalType(const SelectionDAG &DAG, const Pattern &P)
Match legal ValueTypes based on the information provided by TargetLowering.
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.
auto m_True(const SelectionDAG &DAG)
Match true boolean value based on the information provided by TargetLowering.
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)
auto m_NUWAddLike(const LHS &L, const RHS &R)
SpecificFP_match m_SpecificFP(APFloat V)
Match a specific float constant.
Value_match m_Specific(SDValue N)
BinaryOpc_match< LHS, RHS > m_ExtractElt(const LHS &Vec, const RHS &Idx)
BinaryOpc_match< LHS, RHS > m_ExtractSubvector(const LHS &Vec, const RHS &Idx)
UnaryOpc_match< Opnd > m_BitReverse(const Opnd &Op)
BinaryOpc_match< LHS, RHS, true > m_And(const LHS &L, const RHS &R)
BinaryOpc_match< LHS, RHS > m_Sub(const LHS &L, const RHS &R)
TernaryOpc_match< T0_P, T1_P, T2_P, true > m_c_TernaryOp(unsigned Opc, const T0_P &Op0, const T1_P &Op1, const T2_P &Op2)
ReassociatableOpc_match< PatternTs... > m_ReassociatableNUWAdd(const PatternTs &...Patterns)
TernaryOpc_match< T0_P, T1_P, T2_P > m_SetCC(const T0_P &LHS, const T1_P &RHS, const T2_P &CC)
auto m_NSWAddLike(const LHS &L, const RHS &R)
auto m_VT(EVT &VT)
Retreive the ValueType of the current SDValue.
BinaryOpc_match< ValTy, AllOnes_match, true > m_Not(const ValTy &V)
Match a Not as a xor(v, -1) or xor(-1, v)
ReassociatableOpc_match< PatternTs... > m_ReassociatableOr(const PatternTs &...Patterns)
BinaryOpc_match< LHS, RHS > m_Rotr(const LHS &L, const RHS &R)
ReassociatableOpc_match< PatternTs... > m_ReassociatableAdd(const PatternTs &...Patterns)
UnaryOpc_match< Opnd > m_AnyExt(const Opnd &Op)
BinaryOpc_match< LHS, RHS > m_Rotl(const LHS &L, const RHS &R)
UnaryOpc_match< Opnd > m_Cttz(const Opnd &Op)
auto m_Node(unsigned Opcode, const OpndPreds &...preds)
BinaryOpc_match< LHS, RHS, true > m_DisjointOr(const LHS &L, const RHS &R)
auto m_SMaxLike(const LHS &L, const RHS &R)
TernaryOpc_match< T0_P, T1_P, T2_P > m_Select(const T0_P &Cond, const T1_P &T, const T2_P &F)
BinaryOpc_match< LHS, RHS > m_UDiv(const LHS &L, const RHS &R)
UnaryOpc_match< Opnd > m_Ctlz(const Opnd &Op)
SpecificNeg_match m_SpecificNeg(SDValue V)
Match a negation of a specific value V, either as sub(0, V) or as constant(s) that are the negation o...
BinaryOpc_match< LHS, RHS > m_SDiv(const LHS &L, const RHS &R)
BinaryOpc_match< LHS, RHS, true > m_FAdd(const LHS &L, const RHS &R)
Or< UnaryOpc_match< Opnd >, Opnd > m_AExtOrSelf(const Opnd &Op)
Match a aext or identity Allows to peek through optional extensions.
BinaryOpc_match< LHS, RHS, true > m_UMax(const LHS &L, const RHS &R)
TernaryOpc_match< T0_P, T1_P, T2_P > m_VSelect(const T0_P &Cond, const T1_P &T, const T2_P &F)
TernaryOpc_match< T0_P, T1_P, T2_P > m_FShL(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2)
UnaryOpc_match< Opnd > m_UnaryOp(unsigned Opc, const Opnd &Op)
auto m_SExt(const Opnd &Op)
bool sd_match(SDValue N, Pattern &&P)
ReassociatableOpc_match< PatternTs... > m_ReassociatableNSWAdd(const PatternTs &...Patterns)
BinaryOpc_match< LHS, RHS, true > m_Xor(const LHS &L, const RHS &R)
auto m_SMinLike(const LHS &L, const RHS &R)
BinaryOpc_match< LHS, RHS > m_SRem(const LHS &L, const RHS &R)
auto m_NoneOf(const Preds &...preds)
CondCode_match m_SpecificCondCode(ISD::CondCode CC)
Match a conditional code SDNode with a specific ISD::CondCode.
UnaryOpc_match< Opnd > m_ZExt(const Opnd &Op)
Value_match m_Value()
Match any valid SDValue.
BinaryOpc_match< LHS, RHS, true > m_Add(const LHS &L, const RHS &R)
auto m_SpecificVectorElementVT(EVT RefVT, const Pattern &P)
Match a vector ValueType.
BinaryOpc_match< LHS, RHS > m_Shl(const LHS &L, const RHS &R)
auto m_BitwiseLogic(const LHS &L, const RHS &R)
UnaryOpc_match< Opnd > m_Ctpop(const Opnd &Op)
auto m_LegalOp(const SelectionDAG &DAG, const Pattern &P)
Match legal SDNodes based on the information provided by TargetLowering.
ReassociatableOpc_match< PatternTs... > m_ReassociatableAnd(const PatternTs &...Patterns)
TernaryOpc_match< T0_P, T1_P, T2_P > m_SpliceRight(const T0_P &V1, const T1_P &V2, const T2_P &Offset)
UnaryOpc_match< Opnd > m_FPToSI(const Opnd &Op)
NUses_match< 1, Value_match > m_OneUse()
auto m_NUWAdd(const LHS &L, const RHS &R)
auto m_SExtOrSelf(const Opnd &Op)
Match a sext or identity Allows to peek through optional extensions.
CondCode_match m_CondCode()
Match any conditional code SDNode.
UnaryOpc_match< Opnd > m_FAbs(const Opnd &Op)
Not(const Pred &P) -> Not< Pred >
DeferredValue_match m_Deferred(SDValue &V)
Similar to m_Specific, but the specific value to match is determined by another sub-pattern in the sa...
TernaryOpc_match< T0_P, T1_P, T2_P, true, false > m_c_SetCC(const T0_P &LHS, const T1_P &RHS, const T2_P &CC)
BinaryOpc_match< LHS, RHS, true > m_FMul(const LHS &L, const RHS &R)
BinaryOpc_match< V1_t, V2_t > m_Shuffle(const V1_t &v1, const V2_t &v2)
ValueType_bind(const Pattern &P) -> ValueType_bind< Pattern >
ConstantInt_match m_ConstInt()
Match any integer constants or splat of an integer constant.
FunnelShiftLike_match< T0_P, T1_P, T2_P, true > m_FShLLike(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2)
auto m_ZExtOrSelf(const Opnd &Op)
Match a zext or identity Allows to peek through optional extensions.
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
LLVM_ABI bool isAllOnesOrAllOnesSplat(const MachineInstr &MI, const MachineRegisterInfo &MRI, bool AllowUndefs=false)
Return true if the value is a constant -1 integer or a splatted vector of a constant -1 integer (with...
Definition Utils.cpp:1557
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
Definition bit.h:325
LLVM_ABI ConstantFPSDNode * isConstOrConstSplatFP(SDValue N, bool AllowUndefs=false)
Returns the SDNode if it is a constant splat BuildVector or constant float.
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
@ Sub
Subtraction of integers.
DWARFExpression::Operation Op
constexpr unsigned BitWidth
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1933
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
LLVM_ABI bool isZeroOrZeroSplat(SDValue N, bool AllowUndefs=false)
Return true if the value is a constant 0 integer or a splatted vector of a constant 0 integer (with n...
LLVM_ABI bool isOnesOrOnesSplat(SDValue N, bool AllowUndefs=false)
Return true if the value is a constant 1 integer or a splatted vector of a constant 1 integer (with n...
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
#define N
Extended Value Type.
Definition ValueTypes.h:35
These are IR-level optimization flags that may be propagated to SDNodes.
And(const Pred &p, const Preds &...preds)
BinaryOpc_match(unsigned Opc, const LHS_P &L, const RHS_P &R, SDNodeFlags Flgs=SDNodeFlags())
std::optional< ISD::CondCode > CCToMatch
Provide number of operands that are not chain or glue, as well as the first index of such operand.
bool matchShiftOr(SDValue N, unsigned BitWidth)
bool matchOperands(SDValue X, SDValue Y, SDValue Z)
static bool hasComplementaryConstantShifts(const APInt &ShlV, const APInt &SrlV, unsigned BitWidth)
FunnelShiftLike_match(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2)
MaxMin_match(const LHS_P &L, const RHS_P &R)
Operands_match(const OpndPred &p, const OpndPreds &...preds)
Or(const Pred &p, const Preds &...preds)
bool reassociatableMatchHelper(ArrayRef< SDValue > Leaves, Bitset< NumPatterns > &Used)
bool reassociatableMatchHelper(ArrayRef< SDValue > Leaves, Bitset< NumPatterns > &Used, PatternHd &HeadPattern, PatternTl &...TailPatterns)
bool collectLeaves(SDValue V, std::array< SDValue, NumPatterns > &Leaves, std::size_t &LeafIdx)
ReassociatableOpc_match(unsigned Opcode, const PatternTs &...Patterns)
ReassociatableOpc_match(unsigned Opcode, SDNodeFlags Flags, const PatternTs &...Patterns)
Matching while capturing mask.
SDShuffle_match(const T0 &Op1, const T1 &Op2, const T2 &Mask)
TLI_pred_match(const PredFuncT &Pred, const Pattern &P)
TernaryOpc_match(unsigned Opc, const T0_P &Op0, const T1_P &Op1, const T2_P &Op2)
UnaryOpc_match(unsigned Opc, const Opnd_P &Op, SDNodeFlags Flgs=SDNodeFlags())
ValueType_bind(EVT &Bind, const Pattern &P)
ValueType_match(const PredFuncT &Pred, const Pattern &P)
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)