aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/llvm14/utils/TableGen/GlobalISel/GIMatchDagOperands.h
blob: c2d30574231d489d1cd7d602b4ddae58effefb2e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
//===- GIMatchDagOperands.h - Represent a shared operand list for nodes ---===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_UTILS_TABLEGEN_GIMATCHDAGOPERANDS_H
#define LLVM_UTILS_TABLEGEN_GIMATCHDAGOPERANDS_H

#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"

#include <vector>

namespace llvm {
class CodeGenInstruction;
/// Describes an operand of a MachineInstr w.r.t the DAG Matching. This
/// information is derived from CodeGenInstruction::Operands but is more
/// readily available for context-less access as we don't need to know which
/// instruction it's used with or know how many defs that instruction had.
///
/// There may be multiple GIMatchDagOperand's with the same contents. However,
/// they are uniqued within the set of instructions that have the same overall
/// operand list. For example, given:
///     Inst1 operands ($dst:<def>, $src1, $src2)
///     Inst2 operands ($dst:<def>, $src1, $src2)
///     Inst3 operands ($dst:<def>, $src)
/// $src1 will have a single instance of GIMatchDagOperand shared by Inst1 and
/// Inst2, as will $src2. $dst however, will have two instances one shared
/// between Inst1 and Inst2 and one unique to Inst3. We could potentially
/// fully de-dupe the GIMatchDagOperand instances but the saving is not expected
/// to be worth the overhead.
///
/// The result of this is that the address of the object can be relied upon to
/// trivially identify commonality between two instructions which will be useful
/// when generating the matcher. When the pointers differ, the contents can be
/// inspected instead.
class GIMatchDagOperand {
  unsigned Idx;
  StringRef Name;
  bool IsDef;

public:
  GIMatchDagOperand(unsigned Idx, StringRef Name, bool IsDef)
      : Idx(Idx), Name(Name), IsDef(IsDef) {}

  unsigned getIdx() const { return Idx; }
  StringRef getName() const { return Name; }
  bool isDef() const { return IsDef; }

  /// This object isn't a FoldingSetNode but it's part of one. See FoldingSet
  /// for details on the Profile function.
  void Profile(FoldingSetNodeID &ID) const;

  /// A helper that behaves like Profile() but is also usable without the object.
  /// We use size_t here to match enumerate<...>::index(). If we don't match
  /// that the hashes won't be equal.
  static void Profile(FoldingSetNodeID &ID, size_t Idx, StringRef Name,
                      bool IsDef);
};

/// A list of GIMatchDagOperands for an instruction without any association with
/// a particular instruction.
///
/// An important detail to be aware of with this class is that they are shared
/// with other instructions of a similar 'shape'. For example, all the binary
/// instructions are likely to share a single GIMatchDagOperandList. This is
/// primarily a memory optimization as it's fairly common to have a large number
/// of instructions but only a few 'shapes'.
///
/// See GIMatchDagOperandList::Profile() for the details on how they are folded.
class GIMatchDagOperandList : public FoldingSetNode {
public:
  using value_type = GIMatchDagOperand;

protected:
  using vector_type = SmallVector<GIMatchDagOperand, 3>;

public:
  using iterator = vector_type::iterator;
  using const_iterator = vector_type::const_iterator;

protected:
  vector_type Operands;
  StringMap<unsigned> OperandsByName;

public:
  void add(StringRef Name, unsigned Idx, bool IsDef);

  /// See FoldingSet for details.
  void Profile(FoldingSetNodeID &ID) const;

  iterator begin() { return Operands.begin(); }
  const_iterator begin() const { return Operands.begin(); }
  iterator end() { return Operands.end(); }
  const_iterator end() const { return Operands.end(); }

  const value_type &operator[](unsigned I) const { return Operands[I]; }
  const value_type &operator[](StringRef K) const;

  void print(raw_ostream &OS) const;
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
  LLVM_DUMP_METHOD void dump() const { print(errs()); }
#endif // if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
};

/// This is the portion of GIMatchDagContext that directly relates to
/// GIMatchDagOperandList and GIMatchDagOperandList.
class GIMatchDagOperandListContext {
  FoldingSet<GIMatchDagOperandList> OperandLists;
  std::vector<std::unique_ptr<GIMatchDagOperandList>> OperandListsOwner;

public:
  const GIMatchDagOperandList &makeEmptyOperandList();
  const GIMatchDagOperandList &makeOperandList(const CodeGenInstruction &I);
  const GIMatchDagOperandList &makeMIPredicateOperandList();
  const GIMatchDagOperandList &makeTwoMOPredicateOperandList();

  void print(raw_ostream &OS) const;
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
  LLVM_DUMP_METHOD void dump() const { print(errs()); }
#endif // if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
};

} // end namespace llvm
#endif // ifndef LLVM_UTILS_TABLEGEN_GIMATCHDAGOPERANDS_H