1356843Sdim//===- GIMatchDagOperands.h - Represent a shared operand list for nodes ---===//
2356843Sdim//
3356843Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4356843Sdim// See https://llvm.org/LICENSE.txt for license information.
5356843Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6356843Sdim//
7356843Sdim//===----------------------------------------------------------------------===//
8356843Sdim//
9356843Sdim//
10356843Sdim//===----------------------------------------------------------------------===//
11356843Sdim
12356843Sdim#ifndef LLVM_UTILS_TABLEGEN_GIMATCHDAGOPERANDS_H
13356843Sdim#define LLVM_UTILS_TABLEGEN_GIMATCHDAGOPERANDS_H
14356843Sdim
15356843Sdim#include "llvm/ADT/FoldingSet.h"
16356843Sdim#include "llvm/ADT/StringMap.h"
17356843Sdim#include "llvm/ADT/StringRef.h"
18356843Sdim#include "llvm/Support/raw_ostream.h"
19356843Sdim
20356843Sdim#include <vector>
21356843Sdim
22356843Sdimnamespace llvm {
23356843Sdimclass CodeGenInstruction;
24356843Sdim/// Describes an operand of a MachineInstr w.r.t the DAG Matching. This
25356843Sdim/// information is derived from CodeGenInstruction::Operands but is more
26356843Sdim/// readily available for context-less access as we don't need to know which
27356843Sdim/// instruction it's used with or know how many defs that instruction had.
28356843Sdim///
29356843Sdim/// There may be multiple GIMatchDagOperand's with the same contents. However,
30356843Sdim/// they are uniqued within the set of instructions that have the same overall
31356843Sdim/// operand list. For example, given:
32356843Sdim///     Inst1 operands ($dst:<def>, $src1, $src2)
33356843Sdim///     Inst2 operands ($dst:<def>, $src1, $src2)
34356843Sdim///     Inst3 operands ($dst:<def>, $src)
35356843Sdim/// $src1 will have a single instance of GIMatchDagOperand shared by Inst1 and
36356843Sdim/// Inst2, as will $src2. $dst however, will have two instances one shared
37356843Sdim/// between Inst1 and Inst2 and one unique to Inst3. We could potentially
38356843Sdim/// fully de-dupe the GIMatchDagOperand instances but the saving is not expected
39356843Sdim/// to be worth the overhead.
40356843Sdim///
41356843Sdim/// The result of this is that the address of the object can be relied upon to
42356843Sdim/// trivially identify commonality between two instructions which will be useful
43356843Sdim/// when generating the matcher. When the pointers differ, the contents can be
44356843Sdim/// inspected instead.
45356843Sdimclass GIMatchDagOperand {
46356843Sdim  unsigned Idx;
47356843Sdim  StringRef Name;
48356843Sdim  bool IsDef;
49356843Sdim
50356843Sdimpublic:
51356843Sdim  GIMatchDagOperand(unsigned Idx, StringRef Name, bool IsDef)
52356843Sdim      : Idx(Idx), Name(Name), IsDef(IsDef) {}
53356843Sdim
54356843Sdim  unsigned getIdx() const { return Idx; }
55356843Sdim  StringRef getName() const { return Name; }
56356843Sdim  bool isDef() const { return IsDef; }
57356843Sdim
58356843Sdim  /// This object isn't a FoldingSetNode but it's part of one. See FoldingSet
59356843Sdim  /// for details on the Profile function.
60356843Sdim  void Profile(FoldingSetNodeID &ID) const;
61356843Sdim
62356843Sdim  /// A helper that behaves like Profile() but is also usable without the object.
63356843Sdim  /// We use size_t here to match enumerate<...>::index(). If we don't match
64356843Sdim  /// that the hashes won't be equal.
65356843Sdim  static void Profile(FoldingSetNodeID &ID, size_t Idx, StringRef Name,
66356843Sdim                      bool IsDef);
67356843Sdim};
68356843Sdim
69356843Sdim/// A list of GIMatchDagOperands for an instruction without any association with
70356843Sdim/// a particular instruction.
71356843Sdim///
72356843Sdim/// An important detail to be aware of with this class is that they are shared
73356843Sdim/// with other instructions of a similar 'shape'. For example, all the binary
74356843Sdim/// instructions are likely to share a single GIMatchDagOperandList. This is
75356843Sdim/// primarily a memory optimization as it's fairly common to have a large number
76356843Sdim/// of instructions but only a few 'shapes'.
77356843Sdim///
78356843Sdim/// See GIMatchDagOperandList::Profile() for the details on how they are folded.
79356843Sdimclass GIMatchDagOperandList : public FoldingSetNode {
80356843Sdimpublic:
81356843Sdim  using value_type = GIMatchDagOperand;
82356843Sdim
83356843Sdimprotected:
84356843Sdim  using vector_type = SmallVector<GIMatchDagOperand, 3>;
85356843Sdim
86356843Sdimpublic:
87356843Sdim  using iterator = vector_type::iterator;
88356843Sdim  using const_iterator = vector_type::const_iterator;
89356843Sdim
90356843Sdimprotected:
91356843Sdim  vector_type Operands;
92356843Sdim  StringMap<unsigned> OperandsByName;
93356843Sdim
94356843Sdimpublic:
95356843Sdim  void add(StringRef Name, unsigned Idx, bool IsDef);
96356843Sdim
97356843Sdim  /// See FoldingSet for details.
98356843Sdim  void Profile(FoldingSetNodeID &ID) const;
99356843Sdim
100356843Sdim  iterator begin() { return Operands.begin(); }
101356843Sdim  const_iterator begin() const { return Operands.begin(); }
102356843Sdim  iterator end() { return Operands.end(); }
103356843Sdim  const_iterator end() const { return Operands.end(); }
104356843Sdim
105356843Sdim  const value_type &operator[](unsigned I) const { return Operands[I]; }
106356843Sdim  const value_type &operator[](StringRef K) const;
107356843Sdim
108356843Sdim  void print(raw_ostream &OS) const;
109356843Sdim#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
110356843Sdim  LLVM_DUMP_METHOD void dump() const { print(errs()); }
111356843Sdim#endif // if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
112356843Sdim};
113356843Sdim
114356843Sdim/// This is the portion of GIMatchDagContext that directly relates to
115356843Sdim/// GIMatchDagOperandList and GIMatchDagOperandList.
116356843Sdimclass GIMatchDagOperandListContext {
117356843Sdim  FoldingSet<GIMatchDagOperandList> OperandLists;
118356843Sdim  std::vector<std::unique_ptr<GIMatchDagOperandList>> OperandListsOwner;
119356843Sdim
120356843Sdimpublic:
121356843Sdim  const GIMatchDagOperandList &makeEmptyOperandList();
122356843Sdim  const GIMatchDagOperandList &makeOperandList(const CodeGenInstruction &I);
123356843Sdim  const GIMatchDagOperandList &makeMIPredicateOperandList();
124356843Sdim  const GIMatchDagOperandList &makeTwoMOPredicateOperandList();
125356843Sdim
126356843Sdim  void print(raw_ostream &OS) const;
127356843Sdim#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
128356843Sdim  LLVM_DUMP_METHOD void dump() const { print(errs()); }
129356843Sdim#endif // if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
130356843Sdim};
131356843Sdim
132356843Sdim} // end namespace llvm
133356843Sdim#endif // ifndef LLVM_UTILS_TABLEGEN_GIMATCHDAGOPERANDS_H
134