LLVM 20.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/STLExtras.h"
21
22namespace llvm {
23namespace SDPatternMatch {
24
25/// MatchContext can repurpose existing patterns to behave differently under
26/// a certain context. For instance, `m_Opc(ISD::ADD)` matches plain ADD nodes
27/// in normal circumstances, but matches VP_ADD nodes under a custom
28/// VPMatchContext. This design is meant to facilitate code / pattern reusing.
30 const SelectionDAG *DAG;
31 const TargetLowering *TLI;
32
33public:
34 explicit BasicMatchContext(const SelectionDAG *DAG)
35 : DAG(DAG), TLI(DAG ? &DAG->getTargetLoweringInfo() : nullptr) {}
36
37 explicit BasicMatchContext(const TargetLowering *TLI)
38 : DAG(nullptr), TLI(TLI) {}
39
40 // A valid MatchContext has to implement the following functions.
41
42 const SelectionDAG *getDAG() const { return DAG; }
43
44 const TargetLowering *getTLI() const { return TLI; }
45
46 /// Return true if N effectively has opcode Opcode.
47 bool match(SDValue N, unsigned Opcode) const {
48 return N->getOpcode() == Opcode;
49 }
50};
51
52template <typename Pattern, typename MatchContext>
53[[nodiscard]] bool sd_context_match(SDValue N, const MatchContext &Ctx,
54 Pattern &&P) {
55 return P.match(Ctx, N);
56}
57
58template <typename Pattern, typename MatchContext>
59[[nodiscard]] bool sd_context_match(SDNode *N, const MatchContext &Ctx,
60 Pattern &&P) {
61 return sd_context_match(SDValue(N, 0), Ctx, P);
62}
63
64template <typename Pattern>
65[[nodiscard]] bool sd_match(SDNode *N, const SelectionDAG *DAG, Pattern &&P) {
67}
68
69template <typename Pattern>
70[[nodiscard]] bool sd_match(SDValue N, const SelectionDAG *DAG, Pattern &&P) {
72}
73
74template <typename Pattern>
75[[nodiscard]] bool sd_match(SDNode *N, Pattern &&P) {
76 return sd_match(N, nullptr, P);
77}
78
79template <typename Pattern>
80[[nodiscard]] bool sd_match(SDValue N, Pattern &&P) {
81 return sd_match(N, nullptr, P);
82}
83
84// === Utilities ===
87
88 Value_match() = default;
89
91
92 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
93 if (MatchVal)
94 return MatchVal == N;
95 return N.getNode();
96 }
97};
98
99/// Match any valid SDValue.
100inline Value_match m_Value() { return Value_match(); }
101
103 assert(N);
104 return Value_match(N);
105}
106
109
111
112 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
113 return N == MatchVal;
114 }
115};
116
117/// Similar to m_Specific, but the specific value to match is determined by
118/// another sub-pattern in the same sd_match() expression. For instance,
119/// We cannot match `(add V, V)` with `m_Add(m_Value(X), m_Specific(X))` since
120/// `X` is not initialized at the time it got copied into `m_Specific`. Instead,
121/// we should use `m_Add(m_Value(X), m_Deferred(X))`.
123 return DeferredValue_match(V);
124}
125
127 unsigned Opcode;
128
129 explicit Opcode_match(unsigned Opc) : Opcode(Opc) {}
130
131 template <typename MatchContext>
132 bool match(const MatchContext &Ctx, SDValue N) {
133 return Ctx.match(N, Opcode);
134 }
135};
136
137inline Opcode_match m_Opc(unsigned Opcode) { return Opcode_match(Opcode); }
138
139template <unsigned NumUses, typename Pattern> struct NUses_match {
141
142 explicit NUses_match(const Pattern &P) : P(P) {}
143
144 template <typename MatchContext>
145 bool match(const MatchContext &Ctx, SDValue N) {
146 // SDNode::hasNUsesOfValue is pretty expensive when the SDNode produces
147 // multiple results, hence we check the subsequent pattern here before
148 // checking the number of value users.
149 return P.match(Ctx, N) && N->hasNUsesOfValue(NumUses, N.getResNo());
150 }
151};
152
153template <typename Pattern>
156}
157template <unsigned N, typename Pattern>
160}
161
164}
165template <unsigned N> inline NUses_match<N, Value_match> m_NUses() {
167}
168
171
172 explicit Value_bind(SDValue &N) : BindVal(N) {}
173
174 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
175 BindVal = N;
176 return true;
177 }
178};
179
180inline Value_bind m_Value(SDValue &N) { return Value_bind(N); }
181
182template <typename Pattern, typename PredFuncT> struct TLI_pred_match {
184 PredFuncT PredFunc;
185
186 TLI_pred_match(const PredFuncT &Pred, const Pattern &P)
187 : P(P), PredFunc(Pred) {}
188
189 template <typename MatchContext>
190 bool match(const MatchContext &Ctx, SDValue N) {
191 assert(Ctx.getTLI() && "TargetLowering is required for this pattern.");
192 return PredFunc(*Ctx.getTLI(), N) && P.match(Ctx, N);
193 }
194};
195
196// Explicit deduction guide.
197template <typename PredFuncT, typename Pattern>
198TLI_pred_match(const PredFuncT &Pred, const Pattern &P)
200
201/// Match legal SDNodes based on the information provided by TargetLowering.
202template <typename Pattern> inline auto m_LegalOp(const Pattern &P) {
203 return TLI_pred_match{[](const TargetLowering &TLI, SDValue N) {
204 return TLI.isOperationLegal(N->getOpcode(),
205 N.getValueType());
206 },
207 P};
208}
209
210/// Switch to a different MatchContext for subsequent patterns.
211template <typename NewMatchContext, typename Pattern> struct SwitchContext {
212 const NewMatchContext &Ctx;
214
215 template <typename OrigMatchContext>
216 bool match(const OrigMatchContext &, SDValue N) {
217 return P.match(Ctx, N);
218 }
219};
220
221template <typename MatchContext, typename Pattern>
222inline SwitchContext<MatchContext, Pattern> m_Context(const MatchContext &Ctx,
223 Pattern &&P) {
224 return SwitchContext<MatchContext, Pattern>{Ctx, std::move(P)};
225}
226
227// === Value type ===
230
231 explicit ValueType_bind(EVT &Bind) : BindVT(Bind) {}
232
233 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
234 BindVT = N.getValueType();
235 return true;
236 }
237};
238
239/// Retreive the ValueType of the current SDValue.
240inline ValueType_bind m_VT(EVT &VT) { return ValueType_bind(VT); }
241
242template <typename Pattern, typename PredFuncT> struct ValueType_match {
243 PredFuncT PredFunc;
245
246 ValueType_match(const PredFuncT &Pred, const Pattern &P)
247 : PredFunc(Pred), P(P) {}
248
249 template <typename MatchContext>
250 bool match(const MatchContext &Ctx, SDValue N) {
251 return PredFunc(N.getValueType()) && P.match(Ctx, N);
252 }
253};
254
255// Explicit deduction guide.
256template <typename PredFuncT, typename Pattern>
257ValueType_match(const PredFuncT &Pred, const Pattern &P)
259
260/// Match a specific ValueType.
261template <typename Pattern>
262inline auto m_SpecificVT(EVT RefVT, const Pattern &P) {
263 return ValueType_match{[=](EVT VT) { return VT == RefVT; }, P};
264}
265inline auto m_SpecificVT(EVT RefVT) {
266 return ValueType_match{[=](EVT VT) { return VT == RefVT; }, m_Value()};
267}
268
269inline auto m_Glue() { return m_SpecificVT(MVT::Glue); }
270inline auto m_OtherVT() { return m_SpecificVT(MVT::Other); }
271
272/// Match any integer ValueTypes.
273template <typename Pattern> inline auto m_IntegerVT(const Pattern &P) {
274 return ValueType_match{[](EVT VT) { return VT.isInteger(); }, P};
275}
276inline auto m_IntegerVT() {
277 return ValueType_match{[](EVT VT) { return VT.isInteger(); }, m_Value()};
278}
279
280/// Match any floating point ValueTypes.
281template <typename Pattern> inline auto m_FloatingPointVT(const Pattern &P) {
282 return ValueType_match{[](EVT VT) { return VT.isFloatingPoint(); }, P};
283}
284inline auto m_FloatingPointVT() {
285 return ValueType_match{[](EVT VT) { return VT.isFloatingPoint(); },
286 m_Value()};
287}
288
289/// Match any vector ValueTypes.
290template <typename Pattern> inline auto m_VectorVT(const Pattern &P) {
291 return ValueType_match{[](EVT VT) { return VT.isVector(); }, P};
292}
293inline auto m_VectorVT() {
294 return ValueType_match{[](EVT VT) { return VT.isVector(); }, m_Value()};
295}
296
297/// Match fixed-length vector ValueTypes.
298template <typename Pattern> inline auto m_FixedVectorVT(const Pattern &P) {
299 return ValueType_match{[](EVT VT) { return VT.isFixedLengthVector(); }, P};
300}
301inline auto m_FixedVectorVT() {
302 return ValueType_match{[](EVT VT) { return VT.isFixedLengthVector(); },
303 m_Value()};
304}
305
306/// Match scalable vector ValueTypes.
307template <typename Pattern> inline auto m_ScalableVectorVT(const Pattern &P) {
308 return ValueType_match{[](EVT VT) { return VT.isScalableVector(); }, P};
309}
310inline auto m_ScalableVectorVT() {
311 return ValueType_match{[](EVT VT) { return VT.isScalableVector(); },
312 m_Value()};
313}
314
315/// Match legal ValueTypes based on the information provided by TargetLowering.
316template <typename Pattern> inline auto m_LegalType(const Pattern &P) {
317 return TLI_pred_match{[](const TargetLowering &TLI, SDValue N) {
318 return TLI.isTypeLegal(N.getValueType());
319 },
320 P};
321}
322
323// === Patterns combinators ===
324template <typename... Preds> struct And {
325 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
326 return true;
327 }
328};
329
330template <typename Pred, typename... Preds>
331struct And<Pred, Preds...> : And<Preds...> {
332 Pred P;
333 And(const Pred &p, const Preds &...preds) : And<Preds...>(preds...), P(p) {}
334
335 template <typename MatchContext>
336 bool match(const MatchContext &Ctx, SDValue N) {
337 return P.match(Ctx, N) && And<Preds...>::match(Ctx, N);
338 }
339};
340
341template <typename... Preds> struct Or {
342 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
343 return false;
344 }
345};
346
347template <typename Pred, typename... Preds>
348struct Or<Pred, Preds...> : Or<Preds...> {
349 Pred P;
350 Or(const Pred &p, const Preds &...preds) : Or<Preds...>(preds...), P(p) {}
351
352 template <typename MatchContext>
353 bool match(const MatchContext &Ctx, SDValue N) {
354 return P.match(Ctx, N) || Or<Preds...>::match(Ctx, N);
355 }
356};
357
358template <typename Pred> struct Not {
359 Pred P;
360
361 explicit Not(const Pred &P) : P(P) {}
362
363 template <typename MatchContext>
364 bool match(const MatchContext &Ctx, SDValue N) {
365 return !P.match(Ctx, N);
366 }
367};
368// Explicit deduction guide.
369template <typename Pred> Not(const Pred &P) -> Not<Pred>;
370
371/// Match if the inner pattern does NOT match.
372template <typename Pred> inline Not<Pred> m_Unless(const Pred &P) {
373 return Not{P};
374}
375
376template <typename... Preds> And<Preds...> m_AllOf(const Preds &...preds) {
377 return And<Preds...>(preds...);
378}
379
380template <typename... Preds> Or<Preds...> m_AnyOf(const Preds &...preds) {
381 return Or<Preds...>(preds...);
382}
383
384template <typename... Preds> auto m_NoneOf(const Preds &...preds) {
385 return m_Unless(m_AnyOf(preds...));
386}
387
388// === Generic node matching ===
389template <unsigned OpIdx, typename... OpndPreds> struct Operands_match {
390 template <typename MatchContext>
391 bool match(const MatchContext &Ctx, SDValue N) {
392 // Returns false if there are more operands than predicates;
393 return N->getNumOperands() == OpIdx;
394 }
395};
396
397template <unsigned OpIdx, typename OpndPred, typename... OpndPreds>
398struct Operands_match<OpIdx, OpndPred, OpndPreds...>
399 : Operands_match<OpIdx + 1, OpndPreds...> {
400 OpndPred P;
401
402 Operands_match(const OpndPred &p, const OpndPreds &...preds)
403 : Operands_match<OpIdx + 1, OpndPreds...>(preds...), P(p) {}
404
405 template <typename MatchContext>
406 bool match(const MatchContext &Ctx, SDValue N) {
407 if (OpIdx < N->getNumOperands())
408 return P.match(Ctx, N->getOperand(OpIdx)) &&
410
411 // This is the case where there are more predicates than operands.
412 return false;
413 }
414};
415
416template <typename... OpndPreds>
417auto m_Node(unsigned Opcode, const OpndPreds &...preds) {
418 return m_AllOf(m_Opc(Opcode), Operands_match<0, OpndPreds...>(preds...));
419}
420
421/// Provide number of operands that are not chain or glue, as well as the first
422/// index of such operand.
423template <bool ExcludeChain> struct EffectiveOperands {
424 unsigned Size = 0;
425 unsigned FirstIndex = 0;
426
428 const unsigned TotalNumOps = N->getNumOperands();
429 FirstIndex = TotalNumOps;
430 for (unsigned I = 0; I < TotalNumOps; ++I) {
431 // Count the number of non-chain and non-glue nodes (we ignore chain
432 // and glue by default) and retreive the operand index offset.
433 EVT VT = N->getOperand(I).getValueType();
434 if (VT != MVT::Glue && VT != MVT::Other) {
435 ++Size;
436 if (FirstIndex == TotalNumOps)
437 FirstIndex = I;
438 }
439 }
440 }
441};
442
443template <> struct EffectiveOperands<false> {
444 unsigned Size = 0;
445 unsigned FirstIndex = 0;
446
447 explicit EffectiveOperands(SDValue N) : Size(N->getNumOperands()) {}
448};
449
450// === Ternary operations ===
451template <typename T0_P, typename T1_P, typename T2_P, bool Commutable = false,
452 bool ExcludeChain = false>
454 unsigned Opcode;
455 T0_P Op0;
456 T1_P Op1;
457 T2_P Op2;
458
459 TernaryOpc_match(unsigned Opc, const T0_P &Op0, const T1_P &Op1,
460 const T2_P &Op2)
461 : Opcode(Opc), Op0(Op0), Op1(Op1), Op2(Op2) {}
462
463 template <typename MatchContext>
464 bool match(const MatchContext &Ctx, SDValue N) {
465 if (sd_context_match(N, Ctx, m_Opc(Opcode))) {
467 assert(EO.Size == 3);
468 return ((Op0.match(Ctx, N->getOperand(EO.FirstIndex)) &&
469 Op1.match(Ctx, N->getOperand(EO.FirstIndex + 1))) ||
470 (Commutable && Op0.match(Ctx, N->getOperand(EO.FirstIndex + 1)) &&
471 Op1.match(Ctx, N->getOperand(EO.FirstIndex)))) &&
472 Op2.match(Ctx, N->getOperand(EO.FirstIndex + 2));
473 }
474
475 return false;
476 }
477};
478
479template <typename T0_P, typename T1_P, typename T2_P>
480inline TernaryOpc_match<T0_P, T1_P, T2_P>
481m_SetCC(const T0_P &LHS, const T1_P &RHS, const T2_P &CC) {
483}
484
485template <typename T0_P, typename T1_P, typename T2_P>
486inline TernaryOpc_match<T0_P, T1_P, T2_P, true, false>
487m_c_SetCC(const T0_P &LHS, const T1_P &RHS, const T2_P &CC) {
489 CC);
490}
491
492template <typename T0_P, typename T1_P, typename T2_P>
493inline TernaryOpc_match<T0_P, T1_P, T2_P>
494m_Select(const T0_P &Cond, const T1_P &T, const T2_P &F) {
496}
497
498template <typename T0_P, typename T1_P, typename T2_P>
499inline TernaryOpc_match<T0_P, T1_P, T2_P>
500m_VSelect(const T0_P &Cond, const T1_P &T, const T2_P &F) {
502}
503
504// === Binary operations ===
505template <typename LHS_P, typename RHS_P, bool Commutable = false,
506 bool ExcludeChain = false>
508 unsigned Opcode;
509 LHS_P LHS;
510 RHS_P RHS;
511
512 BinaryOpc_match(unsigned Opc, const LHS_P &L, const RHS_P &R)
513 : Opcode(Opc), LHS(L), RHS(R) {}
514
515 template <typename MatchContext>
516 bool match(const MatchContext &Ctx, SDValue N) {
517 if (sd_context_match(N, Ctx, m_Opc(Opcode))) {
519 assert(EO.Size == 2);
520 return (LHS.match(Ctx, N->getOperand(EO.FirstIndex)) &&
521 RHS.match(Ctx, N->getOperand(EO.FirstIndex + 1))) ||
522 (Commutable && LHS.match(Ctx, N->getOperand(EO.FirstIndex + 1)) &&
523 RHS.match(Ctx, N->getOperand(EO.FirstIndex)));
524 }
525
526 return false;
527 }
528};
529
530template <typename LHS, typename RHS>
531inline BinaryOpc_match<LHS, RHS> m_BinOp(unsigned Opc, const LHS &L,
532 const RHS &R) {
533 return BinaryOpc_match<LHS, RHS>(Opc, L, R);
534}
535template <typename LHS, typename RHS>
536inline BinaryOpc_match<LHS, RHS, true> m_c_BinOp(unsigned Opc, const LHS &L,
537 const RHS &R) {
538 return BinaryOpc_match<LHS, RHS, true>(Opc, L, R);
539}
540
541template <typename LHS, typename RHS>
542inline BinaryOpc_match<LHS, RHS, false, true>
543m_ChainedBinOp(unsigned Opc, const LHS &L, const RHS &R) {
545}
546template <typename LHS, typename RHS>
547inline BinaryOpc_match<LHS, RHS, true, true>
548m_c_ChainedBinOp(unsigned Opc, const LHS &L, const RHS &R) {
550}
551
552// Common binary operations
553template <typename LHS, typename RHS>
554inline BinaryOpc_match<LHS, RHS, true> m_Add(const LHS &L, const RHS &R) {
556}
557
558template <typename LHS, typename RHS>
559inline BinaryOpc_match<LHS, RHS> m_Sub(const LHS &L, const RHS &R) {
561}
562
563template <typename LHS, typename RHS>
564inline BinaryOpc_match<LHS, RHS, true> m_Mul(const LHS &L, const RHS &R) {
566}
567
568template <typename LHS, typename RHS>
569inline BinaryOpc_match<LHS, RHS, true> m_And(const LHS &L, const RHS &R) {
571}
572
573template <typename LHS, typename RHS>
574inline BinaryOpc_match<LHS, RHS, true> m_Or(const LHS &L, const RHS &R) {
576}
577
578template <typename LHS, typename RHS>
579inline BinaryOpc_match<LHS, RHS, true> m_Xor(const LHS &L, const RHS &R) {
581}
582
583template <typename LHS, typename RHS>
584inline BinaryOpc_match<LHS, RHS, true> m_SMin(const LHS &L, const RHS &R) {
586}
587
588template <typename LHS, typename RHS>
589inline BinaryOpc_match<LHS, RHS, true> m_SMax(const LHS &L, const RHS &R) {
591}
592
593template <typename LHS, typename RHS>
594inline BinaryOpc_match<LHS, RHS, true> m_UMin(const LHS &L, const RHS &R) {
596}
597
598template <typename LHS, typename RHS>
599inline BinaryOpc_match<LHS, RHS, true> m_UMax(const LHS &L, const RHS &R) {
601}
602
603template <typename LHS, typename RHS>
604inline BinaryOpc_match<LHS, RHS> m_UDiv(const LHS &L, const RHS &R) {
606}
607template <typename LHS, typename RHS>
608inline BinaryOpc_match<LHS, RHS> m_SDiv(const LHS &L, const RHS &R) {
610}
611
612template <typename LHS, typename RHS>
613inline BinaryOpc_match<LHS, RHS> m_URem(const LHS &L, const RHS &R) {
615}
616template <typename LHS, typename RHS>
617inline BinaryOpc_match<LHS, RHS> m_SRem(const LHS &L, const RHS &R) {
619}
620
621template <typename LHS, typename RHS>
622inline BinaryOpc_match<LHS, RHS> m_Shl(const LHS &L, const RHS &R) {
624}
625
626template <typename LHS, typename RHS>
627inline BinaryOpc_match<LHS, RHS> m_Sra(const LHS &L, const RHS &R) {
629}
630template <typename LHS, typename RHS>
631inline BinaryOpc_match<LHS, RHS> m_Srl(const LHS &L, const RHS &R) {
633}
634
635template <typename LHS, typename RHS>
636inline BinaryOpc_match<LHS, RHS, true> m_FAdd(const LHS &L, const RHS &R) {
638}
639
640template <typename LHS, typename RHS>
641inline BinaryOpc_match<LHS, RHS> m_FSub(const LHS &L, const RHS &R) {
643}
644
645template <typename LHS, typename RHS>
646inline BinaryOpc_match<LHS, RHS, true> m_FMul(const LHS &L, const RHS &R) {
648}
649
650template <typename LHS, typename RHS>
651inline BinaryOpc_match<LHS, RHS> m_FDiv(const LHS &L, const RHS &R) {
653}
654
655template <typename LHS, typename RHS>
656inline BinaryOpc_match<LHS, RHS> m_FRem(const LHS &L, const RHS &R) {
658}
659
660// === Unary operations ===
661template <typename Opnd_P, bool ExcludeChain = false> struct UnaryOpc_match {
662 unsigned Opcode;
663 Opnd_P Opnd;
664
665 UnaryOpc_match(unsigned Opc, const Opnd_P &Op) : Opcode(Opc), Opnd(Op) {}
666
667 template <typename MatchContext>
668 bool match(const MatchContext &Ctx, SDValue N) {
669 if (sd_context_match(N, Ctx, m_Opc(Opcode))) {
671 assert(EO.Size == 1);
672 return Opnd.match(Ctx, N->getOperand(EO.FirstIndex));
673 }
674
675 return false;
676 }
677};
678
679template <typename Opnd>
680inline UnaryOpc_match<Opnd> m_UnaryOp(unsigned Opc, const Opnd &Op) {
681 return UnaryOpc_match<Opnd>(Opc, Op);
682}
683template <typename Opnd>
685 const Opnd &Op) {
686 return UnaryOpc_match<Opnd, true>(Opc, Op);
687}
688
689template <typename Opnd>
692}
693
694template <typename Opnd> inline UnaryOpc_match<Opnd> m_ZExt(const Opnd &Op) {
696}
697
698template <typename Opnd> inline auto m_SExt(const Opnd &Op) {
700}
701
702template <typename Opnd> inline UnaryOpc_match<Opnd> m_AnyExt(const Opnd &Op) {
704}
705
706template <typename Opnd> inline UnaryOpc_match<Opnd> m_Trunc(const Opnd &Op) {
708}
709
710/// Match a zext or identity
711/// Allows to peek through optional extensions
712template <typename Opnd> inline auto m_ZExtOrSelf(const Opnd &Op) {
713 return m_AnyOf(m_ZExt(Op), Op);
714}
715
716/// Match a sext or identity
717/// Allows to peek through optional extensions
718template <typename Opnd> inline auto m_SExtOrSelf(const Opnd &Op) {
719 return m_AnyOf(m_SExt(Op), Op);
720}
721
722/// Match a aext or identity
723/// Allows to peek through optional extensions
724template <typename Opnd>
725inline Or<UnaryOpc_match<Opnd>, Opnd> m_AExtOrSelf(const Opnd &Op) {
726 return Or<UnaryOpc_match<Opnd>, Opnd>(m_AnyExt(Op), Op);
727}
728
729/// Match a trunc or identity
730/// Allows to peek through optional truncations
731template <typename Opnd>
732inline Or<UnaryOpc_match<Opnd>, Opnd> m_TruncOrSelf(const Opnd &Op) {
733 return Or<UnaryOpc_match<Opnd>, Opnd>(m_Trunc(Op), Op);
734}
735
736template <typename Opnd> inline UnaryOpc_match<Opnd> m_VScale(const Opnd &Op) {
738}
739
740// === Constants ===
743
744 explicit ConstantInt_match(APInt *V) : BindVal(V) {}
745
746 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
747 // The logics here are similar to that in
748 // SelectionDAG::isConstantIntBuildVectorOrConstantInt, but the latter also
749 // treats GlobalAddressSDNode as a constant, which is difficult to turn into
750 // APInt.
751 if (auto *C = dyn_cast_or_null<ConstantSDNode>(N.getNode())) {
752 if (BindVal)
753 *BindVal = C->getAPIntValue();
754 return true;
755 }
756
757 APInt Discard;
758 return ISD::isConstantSplatVector(N.getNode(),
759 BindVal ? *BindVal : Discard);
760 }
761};
762/// Match any interger constants or splat of an integer constant.
763inline ConstantInt_match m_ConstInt() { return ConstantInt_match(nullptr); }
764/// Match any interger constants or splat of an integer constant; return the
765/// specific constant or constant splat value.
767
770
771 explicit SpecificInt_match(APInt APV) : IntVal(std::move(APV)) {}
772
773 template <typename MatchContext>
774 bool match(const MatchContext &Ctx, SDValue N) {
775 APInt ConstInt;
776 if (sd_context_match(N, Ctx, m_ConstInt(ConstInt)))
777 return APInt::isSameValue(IntVal, ConstInt);
778 return false;
779 }
780};
781
782/// Match a specific integer constant or constant splat value.
784 return SpecificInt_match(std::move(V));
785}
787 return SpecificInt_match(APInt(64, V));
788}
789
790inline SpecificInt_match m_Zero() { return m_SpecificInt(0U); }
791inline SpecificInt_match m_One() { return m_SpecificInt(1U); }
792
794
795 AllOnes_match() = default;
796
797 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
799 }
800};
801
803
804/// Match true boolean value based on the information provided by
805/// TargetLowering.
806inline auto m_True() {
807 return TLI_pred_match{
808 [](const TargetLowering &TLI, SDValue N) {
809 APInt ConstVal;
810 if (sd_match(N, m_ConstInt(ConstVal)))
811 switch (TLI.getBooleanContents(N.getValueType())) {
813 return ConstVal.isOne();
815 return ConstVal.isAllOnes();
817 return (ConstVal & 0x01) == 1;
818 }
819
820 return false;
821 },
822 m_Value()};
823}
824/// Match false boolean value based on the information provided by
825/// TargetLowering.
826inline auto m_False() {
827 return TLI_pred_match{
828 [](const TargetLowering &TLI, SDValue N) {
829 APInt ConstVal;
830 if (sd_match(N, m_ConstInt(ConstVal)))
831 switch (TLI.getBooleanContents(N.getValueType())) {
834 return ConstVal.isZero();
836 return (ConstVal & 0x01) == 0;
837 }
838
839 return false;
840 },
841 m_Value()};
842}
843
845 std::optional<ISD::CondCode> CCToMatch;
847
849
851
852 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
853 if (auto *CC = dyn_cast<CondCodeSDNode>(N.getNode())) {
854 if (CCToMatch && *CCToMatch != CC->get())
855 return false;
856
857 if (BindCC)
858 *BindCC = CC->get();
859 return true;
860 }
861
862 return false;
863 }
864};
865
866/// Match any conditional code SDNode.
867inline CondCode_match m_CondCode() { return CondCode_match(nullptr); }
868/// Match any conditional code SDNode and return its ISD::CondCode value.
870 return CondCode_match(&CC);
871}
872/// Match a conditional code SDNode with a specific ISD::CondCode.
874 return CondCode_match(CC);
875}
876
877/// Match a negate as a sub(0, v)
878template <typename ValTy>
880 return m_Sub(m_Zero(), V);
881}
882
883/// Match a Not as a xor(v, -1) or xor(-1, v)
884template <typename ValTy>
886 return m_Xor(V, m_AllOnes());
887}
888
889} // namespace SDPatternMatch
890} // namespace llvm
891#endif
This file implements a class to represent arbitrary precision integral constant values and operations...
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
#define P(N)
const SmallVectorImpl< MachineOperand > & Cond
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file contains some templates that are useful if you are working with the STL at all.
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:351
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
Definition: APInt.h:360
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:533
bool isOne() const
Determine if this is a value of 1.
Definition: APInt.h:369
This class represents an Operation in the Expression.
MatchResult match(StringRef Buffer, const SourceMgr &SM) const
Matches the pattern string against the input buffer Buffer.
Definition: FileCheck.cpp:1077
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.
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:228
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:779
@ ADD
Simple integer binary arithmetic operators.
Definition: ISDOpcodes.h:246
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
Definition: ISDOpcodes.h:813
@ FADD
Simple binary floating point operators.
Definition: ISDOpcodes.h:397
@ SIGN_EXTEND
Conversion operators.
Definition: ISDOpcodes.h:804
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
Definition: ISDOpcodes.h:756
@ SHL
Shift and rotation operations.
Definition: ISDOpcodes.h:734
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition: ISDOpcodes.h:810
@ VSCALE
VSCALE(IMM) - Returns the runtime scaling factor used to calculate the number of elements within a sc...
Definition: ISDOpcodes.h:1372
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
Definition: ISDOpcodes.h:696
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
Definition: ISDOpcodes.h:765
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition: ISDOpcodes.h:708
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition: ISDOpcodes.h:816
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:1578
class_match< BinaryOperator > m_BinOp()
Match an arbitrary binary operation and ignore it.
Definition: PatternMatch.h:100
VScaleVal_match m_VScale()
Opcode_match m_Opc(unsigned Opcode)
BinaryOpc_match< LHS, RHS > m_Srl(const LHS &L, const RHS &R)
auto m_SpecificVT(EVT RefVT, const Pattern &P)
Match a specific ValueType.
BinaryOpc_match< LHS, RHS > m_Sra(const LHS &L, const RHS &R)
BinaryOpc_match< LHS, RHS > m_FRem(const LHS &L, const RHS &R)
BinaryOpc_match< LHS, RHS, true > m_Mul(const LHS &L, const RHS &R)
BinaryOpc_match< LHS, RHS, true > m_Or(const LHS &L, const RHS &R)
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)
BinaryOpc_match< LHS, RHS > m_URem(const LHS &L, const RHS &R)
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.
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.
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)
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.
Value_match m_Specific(SDValue N)
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)
SpecificInt_match m_One()
SpecificInt_match m_Zero()
UnaryOpc_match< Opnd > m_AnyExt(const Opnd &Op)
auto m_Node(unsigned Opcode, const OpndPreds &...preds)
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)
BinaryOpc_match< SpecificInt_match, ValTy > m_Neg(const ValTy &V)
Match a negate as a sub(0, v)
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)
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)
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_True()
Match true boolean value based on the information provided by TargetLowering.
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)
AllOnes_match m_AllOnes()
bool sd_context_match(SDValue N, const MatchContext &Ctx, Pattern &&P)
BinaryOpc_match< LHS, RHS, true > m_FMul(const LHS &L, const RHS &R)
ConstantInt_match m_ConstInt()
Match any interger 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
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:1546
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:1849
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858
#define N
Extended Value Type.
Definition: ValueTypes.h:34
bool match(const MatchContext &, SDValue N)
And(const Pred &p, const Preds &...preds)
bool match(const MatchContext &Ctx, SDValue N)
bool match(const MatchContext &, SDValue N)
bool match(const MatchContext &Ctx, SDValue N)
BinaryOpc_match(unsigned Opc, const LHS_P &L, const RHS_P &R)
bool match(const MatchContext &, SDValue N)
std::optional< ISD::CondCode > CCToMatch
bool match(const MatchContext &, SDValue N)
bool match(const MatchContext &, SDValue N)
Provide number of operands that are not chain or glue, as well as the first index of such operand.
bool match(const MatchContext &Ctx, SDValue N)
bool match(const MatchContext &Ctx, 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)
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)
bool match(const MatchContext &Ctx, SDValue N)
UnaryOpc_match(unsigned Opc, const Opnd_P &Op)
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)