1 //===- GIMatchDagOperands.h - Represent a shared operand list for nodes ---===//
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 //
9 //
10 //===----------------------------------------------------------------------===//
11 
12 #ifndef LLVM_UTILS_TABLEGEN_GIMATCHDAGOPERANDS_H
13 #define LLVM_UTILS_TABLEGEN_GIMATCHDAGOPERANDS_H
14 
15 #include "llvm/ADT/FoldingSet.h"
16 #include "llvm/ADT/StringMap.h"
17 #include "llvm/ADT/StringRef.h"
18 #include "llvm/Support/raw_ostream.h"
19 
20 #include <vector>
21 
22 namespace llvm {
23 class CodeGenInstruction;
24 /// Describes an operand of a MachineInstr w.r.t the DAG Matching. This
25 /// information is derived from CodeGenInstruction::Operands but is more
26 /// readily available for context-less access as we don't need to know which
27 /// instruction it's used with or know how many defs that instruction had.
28 ///
29 /// There may be multiple GIMatchDagOperand's with the same contents. However,
30 /// they are uniqued within the set of instructions that have the same overall
31 /// operand list. For example, given:
32 ///     Inst1 operands ($dst:<def>, $src1, $src2)
33 ///     Inst2 operands ($dst:<def>, $src1, $src2)
34 ///     Inst3 operands ($dst:<def>, $src)
35 /// $src1 will have a single instance of GIMatchDagOperand shared by Inst1 and
36 /// Inst2, as will $src2. $dst however, will have two instances one shared
37 /// between Inst1 and Inst2 and one unique to Inst3. We could potentially
38 /// fully de-dupe the GIMatchDagOperand instances but the saving is not expected
39 /// to be worth the overhead.
40 ///
41 /// The result of this is that the address of the object can be relied upon to
42 /// trivially identify commonality between two instructions which will be useful
43 /// when generating the matcher. When the pointers differ, the contents can be
44 /// inspected instead.
45 class GIMatchDagOperand {
46   unsigned Idx;
47   StringRef Name;
48   bool IsDef;
49 
50 public:
GIMatchDagOperand(unsigned Idx,StringRef Name,bool IsDef)51   GIMatchDagOperand(unsigned Idx, StringRef Name, bool IsDef)
52       : Idx(Idx), Name(Name), IsDef(IsDef) {}
53 
getIdx()54   unsigned getIdx() const { return Idx; }
getName()55   StringRef getName() const { return Name; }
isDef()56   bool isDef() const { return IsDef; }
57 
58   /// This object isn't a FoldingSetNode but it's part of one. See FoldingSet
59   /// for details on the Profile function.
60   void Profile(FoldingSetNodeID &ID) const;
61 
62   /// A helper that behaves like Profile() but is also usable without the object.
63   /// We use size_t here to match enumerate<...>::index(). If we don't match
64   /// that the hashes won't be equal.
65   static void Profile(FoldingSetNodeID &ID, size_t Idx, StringRef Name,
66                       bool IsDef);
67 };
68 
69 /// A list of GIMatchDagOperands for an instruction without any association with
70 /// a particular instruction.
71 ///
72 /// An important detail to be aware of with this class is that they are shared
73 /// with other instructions of a similar 'shape'. For example, all the binary
74 /// instructions are likely to share a single GIMatchDagOperandList. This is
75 /// primarily a memory optimization as it's fairly common to have a large number
76 /// of instructions but only a few 'shapes'.
77 ///
78 /// See GIMatchDagOperandList::Profile() for the details on how they are folded.
79 class GIMatchDagOperandList : public FoldingSetNode {
80 public:
81   using value_type = GIMatchDagOperand;
82 
83 protected:
84   using vector_type = SmallVector<GIMatchDagOperand, 3>;
85 
86 public:
87   using iterator = vector_type::iterator;
88   using const_iterator = vector_type::const_iterator;
89 
90 protected:
91   vector_type Operands;
92   StringMap<unsigned> OperandsByName;
93 
94 public:
95   void add(StringRef Name, unsigned Idx, bool IsDef);
96 
97   /// See FoldingSet for details.
98   void Profile(FoldingSetNodeID &ID) const;
99 
begin()100   iterator begin() { return Operands.begin(); }
begin()101   const_iterator begin() const { return Operands.begin(); }
end()102   iterator end() { return Operands.end(); }
end()103   const_iterator end() const { return Operands.end(); }
104 
105   const value_type &operator[](unsigned I) const { return Operands[I]; }
106   const value_type &operator[](StringRef K) const;
107 
108   void print(raw_ostream &OS) const;
109 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump()110   LLVM_DUMP_METHOD void dump() const { print(errs()); }
111 #endif // if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
112 };
113 
114 /// This is the portion of GIMatchDagContext that directly relates to
115 /// GIMatchDagOperandList and GIMatchDagOperandList.
116 class GIMatchDagOperandListContext {
117   FoldingSet<GIMatchDagOperandList> OperandLists;
118   std::vector<std::unique_ptr<GIMatchDagOperandList>> OperandListsOwner;
119 
120 public:
121   const GIMatchDagOperandList &makeEmptyOperandList();
122   const GIMatchDagOperandList &makeOperandList(const CodeGenInstruction &I);
123   const GIMatchDagOperandList &makeMIPredicateOperandList();
124   const GIMatchDagOperandList &makeTwoMOPredicateOperandList();
125 
126   void print(raw_ostream &OS) const;
127 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump()128   LLVM_DUMP_METHOD void dump() const { print(errs()); }
129 #endif // if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
130 };
131 
132 } // end namespace llvm
133 #endif // ifndef LLVM_UTILS_TABLEGEN_GIMATCHDAGOPERANDS_H
134