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