LLVM 19.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(Pred &&p, Preds &&...preds)
334 : And<Preds...>(std::forward<Preds>(preds)...), P(std::forward<Pred>(p)) {
335 }
336
337 template <typename MatchContext>
338 bool match(const MatchContext &Ctx, SDValue N) {
339 return P.match(Ctx, N) && And<Preds...>::match(Ctx, N);
340 }
341};
342
343template <typename... Preds> struct Or {
344 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
345 return false;
346 }
347};
348
349template <typename Pred, typename... Preds>
350struct Or<Pred, Preds...> : Or<Preds...> {
351 Pred P;
352 Or(Pred &&p, Preds &&...preds)
353 : Or<Preds...>(std::forward<Preds>(preds)...), P(std::forward<Pred>(p)) {}
354
355 template <typename MatchContext>
356 bool match(const MatchContext &Ctx, SDValue N) {
357 return P.match(Ctx, N) || Or<Preds...>::match(Ctx, N);
358 }
359};
360
361template <typename... Preds> And<Preds...> m_AllOf(Preds &&...preds) {
362 return And<Preds...>(std::forward<Preds>(preds)...);
363}
364
365template <typename... Preds> Or<Preds...> m_AnyOf(Preds &&...preds) {
366 return Or<Preds...>(std::forward<Preds>(preds)...);
367}
368
369// === Generic node matching ===
370template <unsigned OpIdx, typename... OpndPreds> struct Operands_match {
371 template <typename MatchContext>
372 bool match(const MatchContext &Ctx, SDValue N) {
373 // Returns false if there are more operands than predicates;
374 return N->getNumOperands() == OpIdx;
375 }
376};
377
378template <unsigned OpIdx, typename OpndPred, typename... OpndPreds>
379struct Operands_match<OpIdx, OpndPred, OpndPreds...>
380 : Operands_match<OpIdx + 1, OpndPreds...> {
381 OpndPred P;
382
383 Operands_match(OpndPred &&p, OpndPreds &&...preds)
384 : Operands_match<OpIdx + 1, OpndPreds...>(
385 std::forward<OpndPreds>(preds)...),
386 P(std::forward<OpndPred>(p)) {}
387
388 template <typename MatchContext>
389 bool match(const MatchContext &Ctx, SDValue N) {
390 if (OpIdx < N->getNumOperands())
391 return P.match(Ctx, N->getOperand(OpIdx)) &&
393
394 // This is the case where there are more predicates than operands.
395 return false;
396 }
397};
398
399template <typename... OpndPreds>
400auto m_Node(unsigned Opcode, OpndPreds &&...preds) {
402 std::forward<OpndPreds>(preds)...));
403}
404
405/// Provide number of operands that are not chain or glue, as well as the first
406/// index of such operand.
407template <bool ExcludeChain> struct EffectiveOperands {
408 unsigned Size = 0;
409 unsigned FirstIndex = 0;
410
412 const unsigned TotalNumOps = N->getNumOperands();
413 FirstIndex = TotalNumOps;
414 for (unsigned I = 0; I < TotalNumOps; ++I) {
415 // Count the number of non-chain and non-glue nodes (we ignore chain
416 // and glue by default) and retreive the operand index offset.
417 EVT VT = N->getOperand(I).getValueType();
418 if (VT != MVT::Glue && VT != MVT::Other) {
419 ++Size;
420 if (FirstIndex == TotalNumOps)
421 FirstIndex = I;
422 }
423 }
424 }
425};
426
427template <> struct EffectiveOperands<false> {
428 unsigned Size = 0;
429 unsigned FirstIndex = 0;
430
431 explicit EffectiveOperands(SDValue N) : Size(N->getNumOperands()) {}
432};
433
434// === Binary operations ===
435template <typename LHS_P, typename RHS_P, bool Commutable = false,
436 bool ExcludeChain = false>
438 unsigned Opcode;
439 LHS_P LHS;
440 RHS_P RHS;
441
442 BinaryOpc_match(unsigned Opc, const LHS_P &L, const RHS_P &R)
443 : Opcode(Opc), LHS(L), RHS(R) {}
444
445 template <typename MatchContext>
446 bool match(const MatchContext &Ctx, SDValue N) {
447 if (sd_context_match(N, Ctx, m_Opc(Opcode))) {
449 assert(EO.Size == 2);
450 return (LHS.match(Ctx, N->getOperand(EO.FirstIndex)) &&
451 RHS.match(Ctx, N->getOperand(EO.FirstIndex + 1))) ||
452 (Commutable && LHS.match(Ctx, N->getOperand(EO.FirstIndex + 1)) &&
453 RHS.match(Ctx, N->getOperand(EO.FirstIndex)));
454 }
455
456 return false;
457 }
458};
459
460template <typename LHS, typename RHS>
461inline BinaryOpc_match<LHS, RHS, false> m_BinOp(unsigned Opc, const LHS &L,
462 const RHS &R) {
463 return BinaryOpc_match<LHS, RHS, false>(Opc, L, R);
464}
465template <typename LHS, typename RHS>
466inline BinaryOpc_match<LHS, RHS, true> m_c_BinOp(unsigned Opc, const LHS &L,
467 const RHS &R) {
468 return BinaryOpc_match<LHS, RHS, true>(Opc, L, R);
469}
470
471template <typename LHS, typename RHS>
472inline BinaryOpc_match<LHS, RHS, false, true>
473m_ChainedBinOp(unsigned Opc, const LHS &L, const RHS &R) {
475}
476template <typename LHS, typename RHS>
477inline BinaryOpc_match<LHS, RHS, true, true>
478m_c_ChainedBinOp(unsigned Opc, const LHS &L, const RHS &R) {
480}
481
482// Common binary operations
483template <typename LHS, typename RHS>
484inline BinaryOpc_match<LHS, RHS, true> m_Add(const LHS &L, const RHS &R) {
486}
487
488template <typename LHS, typename RHS>
489inline BinaryOpc_match<LHS, RHS, false> m_Sub(const LHS &L, const RHS &R) {
491}
492
493template <typename LHS, typename RHS>
494inline BinaryOpc_match<LHS, RHS, true> m_Mul(const LHS &L, const RHS &R) {
496}
497
498template <typename LHS, typename RHS>
499inline BinaryOpc_match<LHS, RHS, true> m_And(const LHS &L, const RHS &R) {
501}
502
503template <typename LHS, typename RHS>
504inline BinaryOpc_match<LHS, RHS, true> m_Or(const LHS &L, const RHS &R) {
506}
507
508template <typename LHS, typename RHS>
509inline BinaryOpc_match<LHS, RHS, true> m_Xor(const LHS &L, const RHS &R) {
511}
512
513template <typename LHS, typename RHS>
514inline BinaryOpc_match<LHS, RHS, true> m_SMin(const LHS &L, const RHS &R) {
516}
517
518template <typename LHS, typename RHS>
519inline BinaryOpc_match<LHS, RHS, true> m_SMax(const LHS &L, const RHS &R) {
521}
522
523template <typename LHS, typename RHS>
524inline BinaryOpc_match<LHS, RHS, true> m_UMin(const LHS &L, const RHS &R) {
526}
527
528template <typename LHS, typename RHS>
529inline BinaryOpc_match<LHS, RHS, true> m_UMax(const LHS &L, const RHS &R) {
531}
532
533template <typename LHS, typename RHS>
534inline BinaryOpc_match<LHS, RHS, false> m_UDiv(const LHS &L, const RHS &R) {
536}
537template <typename LHS, typename RHS>
538inline BinaryOpc_match<LHS, RHS, false> m_SDiv(const LHS &L, const RHS &R) {
540}
541
542template <typename LHS, typename RHS>
543inline BinaryOpc_match<LHS, RHS, false> m_URem(const LHS &L, const RHS &R) {
545}
546template <typename LHS, typename RHS>
547inline BinaryOpc_match<LHS, RHS, false> m_SRem(const LHS &L, const RHS &R) {
549}
550
551template <typename LHS, typename RHS>
552inline BinaryOpc_match<LHS, RHS, false> m_Shl(const LHS &L, const RHS &R) {
554}
555
556template <typename LHS, typename RHS>
557inline BinaryOpc_match<LHS, RHS, false> m_Sra(const LHS &L, const RHS &R) {
559}
560template <typename LHS, typename RHS>
561inline BinaryOpc_match<LHS, RHS, false> m_Srl(const LHS &L, const RHS &R) {
563}
564
565template <typename LHS, typename RHS>
566inline BinaryOpc_match<LHS, RHS, true> m_FAdd(const LHS &L, const RHS &R) {
568}
569
570template <typename LHS, typename RHS>
571inline BinaryOpc_match<LHS, RHS, false> m_FSub(const LHS &L, const RHS &R) {
573}
574
575template <typename LHS, typename RHS>
576inline BinaryOpc_match<LHS, RHS, true> m_FMul(const LHS &L, const RHS &R) {
578}
579
580template <typename LHS, typename RHS>
581inline BinaryOpc_match<LHS, RHS, false> m_FDiv(const LHS &L, const RHS &R) {
583}
584
585template <typename LHS, typename RHS>
586inline BinaryOpc_match<LHS, RHS, false> m_FRem(const LHS &L, const RHS &R) {
588}
589
590// === Unary operations ===
591template <typename Opnd_P, bool ExcludeChain = false> struct UnaryOpc_match {
592 unsigned Opcode;
593 Opnd_P Opnd;
594
595 UnaryOpc_match(unsigned Opc, const Opnd_P &Op) : Opcode(Opc), Opnd(Op) {}
596
597 template <typename MatchContext>
598 bool match(const MatchContext &Ctx, SDValue N) {
599 if (sd_context_match(N, Ctx, m_Opc(Opcode))) {
601 assert(EO.Size == 1);
602 return Opnd.match(Ctx, N->getOperand(EO.FirstIndex));
603 }
604
605 return false;
606 }
607};
608
609template <typename Opnd>
610inline UnaryOpc_match<Opnd> m_UnaryOp(unsigned Opc, const Opnd &Op) {
611 return UnaryOpc_match<Opnd>(Opc, Op);
612}
613template <typename Opnd>
615 const Opnd &Op) {
616 return UnaryOpc_match<Opnd, true>(Opc, Op);
617}
618
619template <typename Opnd> inline UnaryOpc_match<Opnd> m_ZExt(const Opnd &Op) {
621}
622
623template <typename Opnd> inline UnaryOpc_match<Opnd> m_SExt(const Opnd &Op) {
625}
626
627template <typename Opnd> inline UnaryOpc_match<Opnd> m_AnyExt(const Opnd &Op) {
629}
630
631template <typename Opnd> inline UnaryOpc_match<Opnd> m_Trunc(const Opnd &Op) {
633}
634
635/// Match a zext or identity
636/// Allows to peek through optional extensions
637template <typename Opnd>
639 return Or<UnaryOpc_match<Opnd>, Opnd>(m_ZExt(std::forward<Opnd>(Op)),
640 std::forward<Opnd>(Op));
641}
642
643/// Match a sext or identity
644/// Allows to peek through optional extensions
645template <typename Opnd>
647 return Or<UnaryOpc_match<Opnd>, Opnd>(m_SExt(std::forward<Opnd>(Op)),
648 std::forward<Opnd>(Op));
649}
650
651/// Match a aext or identity
652/// Allows to peek through optional extensions
653template <typename Opnd>
655 return Or<UnaryOpc_match<Opnd>, Opnd>(m_AnyExt(std::forward<Opnd>(Op)),
656 std::forward<Opnd>(Op));
657}
658
659/// Match a trunc or identity
660/// Allows to peek through optional truncations
661template <typename Opnd>
663 return Or<UnaryOpc_match<Opnd>, Opnd>(m_Trunc(std::forward<Opnd>(Op)),
664 std::forward<Opnd>(Op));
665}
666
667// === Constants ===
670
671 explicit ConstantInt_match(APInt *V) : BindVal(V) {}
672
673 template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
674 // The logics here are similar to that in
675 // SelectionDAG::isConstantIntBuildVectorOrConstantInt, but the latter also
676 // treats GlobalAddressSDNode as a constant, which is difficult to turn into
677 // APInt.
678 if (auto *C = dyn_cast_or_null<ConstantSDNode>(N.getNode())) {
679 if (BindVal)
680 *BindVal = C->getAPIntValue();
681 return true;
682 }
683
684 APInt Discard;
685 return ISD::isConstantSplatVector(N.getNode(),
686 BindVal ? *BindVal : Discard);
687 }
688};
689/// Match any interger constants or splat of an integer constant.
690inline ConstantInt_match m_ConstInt() { return ConstantInt_match(nullptr); }
691/// Match any interger constants or splat of an integer constant; return the
692/// specific constant or constant splat value.
694
697
698 explicit SpecificInt_match(APInt APV) : IntVal(std::move(APV)) {}
699
700 template <typename MatchContext>
701 bool match(const MatchContext &Ctx, SDValue N) {
702 APInt ConstInt;
703 if (sd_context_match(N, Ctx, m_ConstInt(ConstInt)))
704 return APInt::isSameValue(IntVal, ConstInt);
705 return false;
706 }
707};
708
709/// Match a specific integer constant or constant splat value.
711 return SpecificInt_match(std::move(V));
712}
714 return SpecificInt_match(APInt(64, V));
715}
716
717inline SpecificInt_match m_Zero() { return m_SpecificInt(0U); }
718inline SpecificInt_match m_One() { return m_SpecificInt(1U); }
720
721/// Match true boolean value based on the information provided by
722/// TargetLowering.
723inline auto m_True() {
724 return TLI_pred_match{
725 [](const TargetLowering &TLI, SDValue N) {
726 APInt ConstVal;
727 if (sd_match(N, m_ConstInt(ConstVal)))
728 switch (TLI.getBooleanContents(N.getValueType())) {
730 return ConstVal.isOne();
732 return ConstVal.isAllOnes();
734 return (ConstVal & 0x01) == 1;
735 }
736
737 return false;
738 },
739 m_Value()};
740}
741/// Match false boolean value based on the information provided by
742/// TargetLowering.
743inline auto m_False() {
744 return TLI_pred_match{
745 [](const TargetLowering &TLI, SDValue N) {
746 APInt ConstVal;
747 if (sd_match(N, m_ConstInt(ConstVal)))
748 switch (TLI.getBooleanContents(N.getValueType())) {
751 return ConstVal.isZero();
753 return (ConstVal & 0x01) == 0;
754 }
755
756 return false;
757 },
758 m_Value()};
759}
760
761/// Match a negate as a sub(0, v)
762template <typename ValTy>
764 return m_Sub(m_Zero(), V);
765}
766
767/// Match a Not as a xor(v, -1) or xor(-1, v)
768template <typename ValTy>
770 return m_Xor(V, m_AllOnes());
771}
772
773} // namespace SDPatternMatch
774} // namespace llvm
775#endif
This file implements a class to represent arbitrary precision integral constant values and operations...
#define I(x, y, z)
Definition: MD5.cpp:58
#define P(N)
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:76
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
Definition: APInt.h:349
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
Definition: APInt.h:358
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:531
bool isOne() const
Determine if this is a value of 1.
Definition: APInt.h:367
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:225
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
@ ADD
Simple integer binary arithmetic operators.
Definition: ISDOpcodes.h:239
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
Definition: ISDOpcodes.h:783
@ FADD
Simple binary floating point operators.
Definition: ISDOpcodes.h:390
@ SIGN_EXTEND
Conversion operators.
Definition: ISDOpcodes.h:774
@ SHL
Shift and rotation operations.
Definition: ISDOpcodes.h:705
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition: ISDOpcodes.h:780
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
Definition: ISDOpcodes.h:674
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition: ISDOpcodes.h:680
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition: ISDOpcodes.h:786
bool isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
class_match< BinaryOperator > m_BinOp()
Match an arbitrary binary operation and ignore it.
Definition: PatternMatch.h:100
Opcode_match m_Opc(unsigned Opcode)
BinaryOpc_match< LHS, RHS, false > m_FDiv(const LHS &L, const RHS &R)
auto m_SpecificVT(EVT RefVT, const Pattern &P)
Match a specific ValueType.
BinaryOpc_match< LHS, RHS, true > m_Mul(const LHS &L, const RHS &R)
BinaryOpc_match< LHS, RHS, false > m_SRem(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)
UnaryOpc_match< Opnd > m_SExt(const Opnd &Op)
BinaryOpc_match< LHS, RHS, true > m_SMin(const LHS &L, const RHS &R)
BinaryOpc_match< LHS, RHS, false > m_Sub(const LHS &L, const RHS &R)
BinaryOpc_match< ValTy, SpecificInt_match, true > m_Not(const ValTy &V)
Match a Not as a xor(v, -1) or xor(-1, v)
UnaryOpc_match< Opnd > m_Trunc(const Opnd &Op)
BinaryOpc_match< LHS, RHS, false > m_Sra(const LHS &L, const RHS &R)
Or< UnaryOpc_match< Opnd >, Opnd > m_ZExtOrSelf(Opnd &&Op)
Match a zext or identity Allows to peek through optional extensions.
BinaryOpc_match< LHS, RHS, true, true > m_c_ChainedBinOp(unsigned Opc, const LHS &L, const RHS &R)
auto m_LegalType(const Pattern &P)
Match legal ValueTypes based on the information provided by TargetLowering.
SpecificInt_match m_AllOnes()
BinaryOpc_match< LHS, RHS, true > m_UMin(const LHS &L, const RHS &R)
BinaryOpc_match< LHS, RHS, true > m_SMax(const LHS &L, const RHS &R)
BinaryOpc_match< LHS, RHS, false > m_Srl(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)
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.
SpecificInt_match m_One()
BinaryOpc_match< LHS, RHS, false > m_SDiv(const LHS &L, const RHS &R)
And< Preds... > m_AllOf(Preds &&...preds)
SpecificInt_match m_Zero()
UnaryOpc_match< Opnd > m_AnyExt(const Opnd &Op)
BinaryOpc_match< LHS, RHS, false > m_FRem(const LHS &L, const RHS &R)
BinaryOpc_match< LHS, RHS, false > m_Shl(const LHS &L, const RHS &R)
Or< UnaryOpc_match< Opnd >, Opnd > m_TruncOrSelf(Opnd &&Op)
Match a trunc or identity Allows to peek through optional truncations.
BinaryOpc_match< LHS, RHS, false > 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)
SwitchContext< MatchContext, Pattern > m_Context(const MatchContext &Ctx, Pattern &&P)
BinaryOpc_match< LHS, RHS, true > m_FAdd(const LHS &L, const RHS &R)
Or< Preds... > m_AnyOf(Preds &&...preds)
BinaryOpc_match< LHS, RHS, true > m_UMax(const LHS &L, const RHS &R)
bool sd_match(SDNode *N, const SelectionDAG *DAG, Pattern &&P)
UnaryOpc_match< Opnd > m_UnaryOp(unsigned Opc, const Opnd &Op)
BinaryOpc_match< LHS, RHS, true > m_Xor(const LHS &L, const RHS &R)
BinaryOpc_match< LHS, RHS, false > m_FSub(const LHS &L, const RHS &R)
auto m_Node(unsigned Opcode, OpndPreds &&...preds)
UnaryOpc_match< Opnd > m_ZExt(const Opnd &Op)
Value_match m_Value()
Match any valid SDValue.
BinaryOpc_match< LHS, RHS, false > m_URem(const LHS &L, const RHS &R)
BinaryOpc_match< LHS, RHS, true > m_Add(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.
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...
Or< UnaryOpc_match< Opnd >, Opnd > m_AExtOrSelf(Opnd &&Op)
Match a aext or identity Allows to peek through optional extensions.
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.
Or< UnaryOpc_match< Opnd >, Opnd > m_SExtOrSelf(Opnd &&Op)
Match a sext or identity Allows to peek through optional extensions.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
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 &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)
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)
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)
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)