1975293f0SEugene Zelenko //===- Bitcode/Writer/ValueEnumerator.h - Number values ---------*- C++ -*-===//
2c1d10d67SChris Lattner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6c1d10d67SChris Lattner //
7c1d10d67SChris Lattner //===----------------------------------------------------------------------===//
8c1d10d67SChris Lattner //
9c1d10d67SChris Lattner // This class gives values and types Unique ID's.
10c1d10d67SChris Lattner //
11c1d10d67SChris Lattner //===----------------------------------------------------------------------===//
12c1d10d67SChris Lattner 
13a7c40ef0SBenjamin Kramer #ifndef LLVM_LIB_BITCODE_WRITER_VALUEENUMERATOR_H
14a7c40ef0SBenjamin Kramer #define LLVM_LIB_BITCODE_WRITER_VALUEENUMERATOR_H
15c1d10d67SChris Lattner 
16975293f0SEugene Zelenko #include "llvm/ADT/ArrayRef.h"
17c1d10d67SChris Lattner #include "llvm/ADT/DenseMap.h"
18dad0a645SDavid Majnemer #include "llvm/ADT/UniqueVector.h"
199fb823bbSChandler Carruth #include "llvm/IR/Attributes.h"
201f66c856SDuncan P. N. Exon Smith #include "llvm/IR/UseListOrder.h"
21975293f0SEugene Zelenko #include <cassert>
22975293f0SEugene Zelenko #include <cstdint>
23975293f0SEugene Zelenko #include <utility>
24c1d10d67SChris Lattner #include <vector>
25c1d10d67SChris Lattner 
26c1d10d67SChris Lattner namespace llvm {
27c1d10d67SChris Lattner 
287c37b019SChris Lattner class BasicBlock;
29dad0a645SDavid Majnemer class Comdat;
30*e5d844b5SStephen Tozer class DIArgList;
31c1d10d67SChris Lattner class Function;
32975293f0SEugene Zelenko class Instruction;
335bf8fef5SDuncan P. N. Exon Smith class LocalAsMetadata;
34df84e8baSDevang Patel class MDNode;
35975293f0SEugene Zelenko class Metadata;
36975293f0SEugene Zelenko class Module;
3799ff5a86SDevang Patel class NamedMDNode;
3878037a90SChad Rosier class raw_ostream;
39975293f0SEugene Zelenko class Type;
40975293f0SEugene Zelenko class Value;
41975293f0SEugene Zelenko class ValueSymbolTable;
42c1d10d67SChris Lattner 
43079b96e6SBenjamin Kramer class ValueEnumerator {
44c1d10d67SChris Lattner public:
45975293f0SEugene Zelenko   using TypeList = std::vector<Type *>;
46c1d10d67SChris Lattner 
47c1d10d67SChris Lattner   // For each value, we remember its Value* and occurrence frequency.
48975293f0SEugene Zelenko   using ValueList = std::vector<std::pair<const Value *, unsigned>>;
491f66c856SDuncan P. N. Exon Smith 
50b4a2d187SReid Kleckner   /// Attribute groups as encoded in bitcode are almost AttributeSets, but they
51b4a2d187SReid Kleckner   /// include the AttributeList index, so we have to track that in our map.
52975293f0SEugene Zelenko   using IndexAndAttrSet = std::pair<unsigned, AttributeSet>;
53b4a2d187SReid Kleckner 
541f66c856SDuncan P. N. Exon Smith   UseListOrderStack UseListOrders;
551f66c856SDuncan P. N. Exon Smith 
56c1d10d67SChris Lattner private:
57975293f0SEugene Zelenko   using TypeMapType = DenseMap<Type *, unsigned>;
58c1d10d67SChris Lattner   TypeMapType TypeMap;
5952523561SChris Lattner   TypeList Types;
60c1d10d67SChris Lattner 
61975293f0SEugene Zelenko   using ValueMapType = DenseMap<const Value *, unsigned>;
62c1d10d67SChris Lattner   ValueMapType ValueMap;
6352523561SChris Lattner   ValueList Values;
64dad0a645SDavid Majnemer 
65975293f0SEugene Zelenko   using ComdatSetType = UniqueVector<const Comdat *>;
66dad0a645SDavid Majnemer   ComdatSetType Comdats;
67dad0a645SDavid Majnemer 
685bf8fef5SDuncan P. N. Exon Smith   std::vector<const Metadata *> MDs;
69520f8542SDuncan P. N. Exon Smith   std::vector<const Metadata *> FunctionMDs;
70520f8542SDuncan P. N. Exon Smith 
71520f8542SDuncan P. N. Exon Smith   /// Index of information about a piece of metadata.
72520f8542SDuncan P. N. Exon Smith   struct MDIndex {
73520f8542SDuncan P. N. Exon Smith     unsigned F = 0;  ///< The ID of the function for this metadata, if any.
74520f8542SDuncan P. N. Exon Smith     unsigned ID = 0; ///< The implicit ID of this metadata in bitcode.
75520f8542SDuncan P. N. Exon Smith 
76520f8542SDuncan P. N. Exon Smith     MDIndex() = default;
MDIndexMDIndex77520f8542SDuncan P. N. Exon Smith     explicit MDIndex(unsigned F) : F(F) {}
78520f8542SDuncan P. N. Exon Smith 
79520f8542SDuncan P. N. Exon Smith     /// Check if this has a function tag, and it's different from NewF.
hasDifferentFunctionMDIndex80520f8542SDuncan P. N. Exon Smith     bool hasDifferentFunction(unsigned NewF) const { return F && F != NewF; }
81520f8542SDuncan P. N. Exon Smith 
82520f8542SDuncan P. N. Exon Smith     /// Fetch the MD this references out of the given metadata array.
getMDIndex83520f8542SDuncan P. N. Exon Smith     const Metadata *get(ArrayRef<const Metadata *> MDs) const {
84520f8542SDuncan P. N. Exon Smith       assert(ID && "Expected non-zero ID");
85520f8542SDuncan P. N. Exon Smith       assert(ID <= MDs.size() && "Expected valid ID");
86520f8542SDuncan P. N. Exon Smith       return MDs[ID - 1];
87520f8542SDuncan P. N. Exon Smith     }
88520f8542SDuncan P. N. Exon Smith   };
899695eb32SDuncan P. N. Exon Smith 
90975293f0SEugene Zelenko   using MetadataMapType = DenseMap<const Metadata *, MDIndex>;
9161b406ecSTeresa Johnson   MetadataMapType MetadataMap;
92520f8542SDuncan P. N. Exon Smith 
93520f8542SDuncan P. N. Exon Smith   /// Range of metadata IDs, as a half-open range.
94520f8542SDuncan P. N. Exon Smith   struct MDRange {
95520f8542SDuncan P. N. Exon Smith     unsigned First = 0;
96520f8542SDuncan P. N. Exon Smith     unsigned Last = 0;
97520f8542SDuncan P. N. Exon Smith 
98520f8542SDuncan P. N. Exon Smith     /// Number of strings in the prefix of the metadata range.
99520f8542SDuncan P. N. Exon Smith     unsigned NumStrings = 0;
100520f8542SDuncan P. N. Exon Smith 
101975293f0SEugene Zelenko     MDRange() = default;
MDRangeMDRange102520f8542SDuncan P. N. Exon Smith     explicit MDRange(unsigned First) : First(First) {}
103520f8542SDuncan P. N. Exon Smith   };
104520f8542SDuncan P. N. Exon Smith   SmallDenseMap<unsigned, MDRange, 1> FunctionMDInfo;
105520f8542SDuncan P. N. Exon Smith 
106458593a4SDuncan P. N. Exon Smith   bool ShouldPreserveUseListOrder;
107c1d10d67SChris Lattner 
108975293f0SEugene Zelenko   using AttributeGroupMapType = DenseMap<IndexAndAttrSet, unsigned>;
10992ed7006SBill Wendling   AttributeGroupMapType AttributeGroupMap;
110b4a2d187SReid Kleckner   std::vector<IndexAndAttrSet> AttributeGroups;
11151f612ebSBill Wendling 
112975293f0SEugene Zelenko   using AttributeListMapType = DenseMap<AttributeList, unsigned>;
113b4a2d187SReid Kleckner   AttributeListMapType AttributeListMap;
114b4a2d187SReid Kleckner   std::vector<AttributeList> AttributeLists;
115e4bbad63SChris Lattner 
116f540d74bSChris Lattner   /// GlobalBasicBlockIDs - This map memoizes the basic block ID's referenced by
117f540d74bSChris Lattner   /// the "getGlobalBasicBlockID" method.
118f540d74bSChris Lattner   mutable DenseMap<const BasicBlock*, unsigned> GlobalBasicBlockIDs;
119f540d74bSChris Lattner 
120975293f0SEugene Zelenko   using InstructionMapType = DenseMap<const Instruction *, unsigned>;
121af206b8cSDevang Patel   InstructionMapType InstructionMap;
122af206b8cSDevang Patel   unsigned InstructionCount;
123af206b8cSDevang Patel 
1247c37b019SChris Lattner   /// BasicBlocks - This contains all the basic blocks for the currently
1257c37b019SChris Lattner   /// incorporated function.  Their reverse mapping is stored in ValueMap.
1267c37b019SChris Lattner   std::vector<const BasicBlock*> BasicBlocks;
1277c37b019SChris Lattner 
1285f640b9cSChris Lattner   /// When a function is incorporated, this is the size of the Values list
1295f640b9cSChris Lattner   /// before incorporation.
130e6e364c1SChris Lattner   unsigned NumModuleValues;
131c828c546SDan Gohman 
13261b406ecSTeresa Johnson   /// When a function is incorporated, this is the size of the Metadatas list
133c828c546SDan Gohman   /// before incorporation.
1349342911fSDuncan P. N. Exon Smith   unsigned NumModuleMDs = 0;
1359342911fSDuncan P. N. Exon Smith   unsigned NumMDStrings = 0;
136c828c546SDan Gohman 
137e6e364c1SChris Lattner   unsigned FirstFuncConstantID;
138e6e364c1SChris Lattner   unsigned FirstInstID;
139c1d10d67SChris Lattner 
140c1d10d67SChris Lattner public:
141458593a4SDuncan P. N. Exon Smith   ValueEnumerator(const Module &M, bool ShouldPreserveUseListOrder);
142975293f0SEugene Zelenko   ValueEnumerator(const ValueEnumerator &) = delete;
143975293f0SEugene Zelenko   ValueEnumerator &operator=(const ValueEnumerator &) = delete;
144c1d10d67SChris Lattner 
14578037a90SChad Rosier   void dump() const;
14678037a90SChad Rosier   void print(raw_ostream &OS, const ValueMapType &Map, const char *Name) const;
1475bf8fef5SDuncan P. N. Exon Smith   void print(raw_ostream &OS, const MetadataMapType &Map,
1485bf8fef5SDuncan P. N. Exon Smith              const char *Name) const;
14978037a90SChad Rosier 
15005eb617dSDevang Patel   unsigned getValueID(const Value *V) const;
151975293f0SEugene Zelenko 
getMetadataID(const Metadata * MD)1529a6f64e7SDuncan P. N. Exon Smith   unsigned getMetadataID(const Metadata *MD) const {
1539a6f64e7SDuncan P. N. Exon Smith     auto ID = getMetadataOrNullID(MD);
1549a6f64e7SDuncan P. N. Exon Smith     assert(ID != 0 && "Metadata not in slotcalculator!");
1559a6f64e7SDuncan P. N. Exon Smith     return ID - 1;
1569a6f64e7SDuncan P. N. Exon Smith   }
157975293f0SEugene Zelenko 
getMetadataOrNullID(const Metadata * MD)1589a6f64e7SDuncan P. N. Exon Smith   unsigned getMetadataOrNullID(const Metadata *MD) const {
159520f8542SDuncan P. N. Exon Smith     return MetadataMap.lookup(MD).ID;
1609a6f64e7SDuncan P. N. Exon Smith   }
161975293f0SEugene Zelenko 
numMDs()162d4d3dfd8STeresa Johnson   unsigned numMDs() const { return MDs.size(); }
163c1d10d67SChris Lattner 
shouldPreserveUseListOrder()164458593a4SDuncan P. N. Exon Smith   bool shouldPreserveUseListOrder() const { return ShouldPreserveUseListOrder; }
165458593a4SDuncan P. N. Exon Smith 
getTypeID(Type * T)166229907cdSChris Lattner   unsigned getTypeID(Type *T) const {
167c1d10d67SChris Lattner     TypeMapType::const_iterator I = TypeMap.find(T);
168c1d10d67SChris Lattner     assert(I != TypeMap.end() && "Type not in ValueEnumerator!");
169c1d10d67SChris Lattner     return I->second-1;
170c1d10d67SChris Lattner   }
171c1d10d67SChris Lattner 
172af206b8cSDevang Patel   unsigned getInstructionID(const Instruction *I) const;
173af206b8cSDevang Patel   void setInstructionID(const Instruction *I);
174af206b8cSDevang Patel 
getAttributeListID(AttributeList PAL)175b4a2d187SReid Kleckner   unsigned getAttributeListID(AttributeList PAL) const {
1768a923e7cSChris Lattner     if (PAL.isEmpty()) return 0;  // Null maps to zero.
177b4a2d187SReid Kleckner     AttributeListMapType::const_iterator I = AttributeListMap.find(PAL);
178b4a2d187SReid Kleckner     assert(I != AttributeListMap.end() && "Attribute not in ValueEnumerator!");
179e4bbad63SChris Lattner     return I->second;
180e4bbad63SChris Lattner   }
181e4bbad63SChris Lattner 
getAttributeGroupID(IndexAndAttrSet Group)182b4a2d187SReid Kleckner   unsigned getAttributeGroupID(IndexAndAttrSet Group) const {
183b4a2d187SReid Kleckner     if (!Group.second.hasAttributes())
184b4a2d187SReid Kleckner       return 0; // Null maps to zero.
185b4a2d187SReid Kleckner     AttributeGroupMapType::const_iterator I = AttributeGroupMap.find(Group);
18692ed7006SBill Wendling     assert(I != AttributeGroupMap.end() && "Attribute not in ValueEnumerator!");
18751f612ebSBill Wendling     return I->second;
18851f612ebSBill Wendling   }
18951f612ebSBill Wendling 
190e6e364c1SChris Lattner   /// getFunctionConstantRange - Return the range of values that corresponds to
191e6e364c1SChris Lattner   /// function-local constants.
getFunctionConstantRange(unsigned & Start,unsigned & End)192e6e364c1SChris Lattner   void getFunctionConstantRange(unsigned &Start, unsigned &End) const {
193e6e364c1SChris Lattner     Start = FirstFuncConstantID;
194e6e364c1SChris Lattner     End = FirstInstID;
195e6e364c1SChris Lattner   }
196e6e364c1SChris Lattner 
getValues()19752523561SChris Lattner   const ValueList &getValues() const { return Values; }
1989342911fSDuncan P. N. Exon Smith 
1999342911fSDuncan P. N. Exon Smith   /// Check whether the current block has any metadata to emit.
hasMDs()2009342911fSDuncan P. N. Exon Smith   bool hasMDs() const { return NumModuleMDs < MDs.size(); }
2019342911fSDuncan P. N. Exon Smith 
2020b76b723SDuncan P. N. Exon Smith   /// Get the MDString metadata for this block.
getMDStrings()2036565a0d4SDuncan P. N. Exon Smith   ArrayRef<const Metadata *> getMDStrings() const {
2049342911fSDuncan P. N. Exon Smith     return makeArrayRef(MDs).slice(NumModuleMDs, NumMDStrings);
2056565a0d4SDuncan P. N. Exon Smith   }
2069342911fSDuncan P. N. Exon Smith 
2070b76b723SDuncan P. N. Exon Smith   /// Get the non-MDString metadata for this block.
getNonMDStrings()2086565a0d4SDuncan P. N. Exon Smith   ArrayRef<const Metadata *> getNonMDStrings() const {
2099342911fSDuncan P. N. Exon Smith     return makeArrayRef(MDs).slice(NumModuleMDs).slice(NumMDStrings);
210df84e8baSDevang Patel   }
2116565a0d4SDuncan P. N. Exon Smith 
getTypes()212c1d10d67SChris Lattner   const TypeList &getTypes() const { return Types; }
213975293f0SEugene Zelenko 
getBasicBlocks()2147c37b019SChris Lattner   const std::vector<const BasicBlock*> &getBasicBlocks() const {
2157c37b019SChris Lattner     return BasicBlocks;
2167c37b019SChris Lattner   }
217975293f0SEugene Zelenko 
getAttributeLists()218b4a2d187SReid Kleckner   const std::vector<AttributeList> &getAttributeLists() const { return AttributeLists; }
219975293f0SEugene Zelenko 
getAttributeGroups()220b4a2d187SReid Kleckner   const std::vector<IndexAndAttrSet> &getAttributeGroups() const {
22192ed7006SBill Wendling     return AttributeGroups;
22251f612ebSBill Wendling   }
223c1d10d67SChris Lattner 
getComdats()224dad0a645SDavid Majnemer   const ComdatSetType &getComdats() const { return Comdats; }
225dad0a645SDavid Majnemer   unsigned getComdatID(const Comdat *C) const;
226dad0a645SDavid Majnemer 
227f540d74bSChris Lattner   /// getGlobalBasicBlockID - This returns the function-specific ID for the
228f540d74bSChris Lattner   /// specified basic block.  This is relatively expensive information, so it
229f540d74bSChris Lattner   /// should only be used by rare constructs such as address-of-label.
230f540d74bSChris Lattner   unsigned getGlobalBasicBlockID(const BasicBlock *BB) const;
231f540d74bSChris Lattner 
2326a11b64cSChad Rosier   /// incorporateFunction/purgeFunction - If you'd like to deal with a function,
233c1d10d67SChris Lattner   /// use these two methods to get its data into the ValueEnumerator!
2346a11b64cSChad Rosier   void incorporateFunction(const Function &F);
235975293f0SEugene Zelenko 
2366a11b64cSChad Rosier   void purgeFunction();
2377b028108SDavid Blaikie   uint64_t computeBitsRequiredForTypeIndicies() const;
238c1d10d67SChris Lattner 
239c1d10d67SChris Lattner private:
240430e80d6SChris Lattner   void OptimizeConstants(unsigned CstStart, unsigned CstEnd);
241430e80d6SChris Lattner 
242520f8542SDuncan P. N. Exon Smith   /// Reorder the reachable metadata.
243520f8542SDuncan P. N. Exon Smith   ///
244520f8542SDuncan P. N. Exon Smith   /// This is not just an optimization, but is mandatory for emitting MDString
245520f8542SDuncan P. N. Exon Smith   /// correctly.
2466565a0d4SDuncan P. N. Exon Smith   void organizeMetadata();
2476565a0d4SDuncan P. N. Exon Smith 
248520f8542SDuncan P. N. Exon Smith   /// Drop the function tag from the transitive operands of the given node.
2499695eb32SDuncan P. N. Exon Smith   void dropFunctionFromMetadata(MetadataMapType::value_type &FirstMD);
250520f8542SDuncan P. N. Exon Smith 
251520f8542SDuncan P. N. Exon Smith   /// Incorporate the function metadata.
252520f8542SDuncan P. N. Exon Smith   ///
253520f8542SDuncan P. N. Exon Smith   /// This should be called before enumerating LocalAsMetadata for the
254520f8542SDuncan P. N. Exon Smith   /// function.
255520f8542SDuncan P. N. Exon Smith   void incorporateFunctionMetadata(const Function &F);
256520f8542SDuncan P. N. Exon Smith 
25771480bd0SDuncan P. N. Exon Smith   /// Enumerate a single instance of metadata with the given function tag.
25871480bd0SDuncan P. N. Exon Smith   ///
25971480bd0SDuncan P. N. Exon Smith   /// If \c MD has already been enumerated, check that \c F matches its
26071480bd0SDuncan P. N. Exon Smith   /// function tag.  If not, call \a dropFunctionFromMetadata().
26171480bd0SDuncan P. N. Exon Smith   ///
26271480bd0SDuncan P. N. Exon Smith   /// Otherwise, mark \c MD as visited.  Assign it an ID, or just return it if
26371480bd0SDuncan P. N. Exon Smith   /// it's an \a MDNode.
26471480bd0SDuncan P. N. Exon Smith   const MDNode *enumerateMetadataImpl(unsigned F, const Metadata *MD);
265520f8542SDuncan P. N. Exon Smith 
26621521891SPeter Collingbourne   unsigned getMetadataFunctionID(const Function *F) const;
26730805b24SDuncan P. N. Exon Smith 
26830805b24SDuncan P. N. Exon Smith   /// Enumerate reachable metadata in (almost) post-order.
26930805b24SDuncan P. N. Exon Smith   ///
27030805b24SDuncan P. N. Exon Smith   /// Enumerate all the metadata reachable from MD.  We want to minimize the
27130805b24SDuncan P. N. Exon Smith   /// cost of reading bitcode records, and so the primary consideration is that
27230805b24SDuncan P. N. Exon Smith   /// operands of uniqued nodes are resolved before the nodes are read.  This
27330805b24SDuncan P. N. Exon Smith   /// avoids re-uniquing them on the context and factors away RAUW support.
27430805b24SDuncan P. N. Exon Smith   ///
27530805b24SDuncan P. N. Exon Smith   /// This algorithm guarantees that subgraphs of uniqued nodes are in
27630805b24SDuncan P. N. Exon Smith   /// post-order.  Distinct subgraphs reachable only from a single uniqued node
27730805b24SDuncan P. N. Exon Smith   /// will be in post-order.
27830805b24SDuncan P. N. Exon Smith   ///
27930805b24SDuncan P. N. Exon Smith   /// \note The relative order of a distinct and uniqued node is irrelevant.
28030805b24SDuncan P. N. Exon Smith   /// \a organizeMetadata() will later partition distinct nodes ahead of
28130805b24SDuncan P. N. Exon Smith   /// uniqued ones.
28230805b24SDuncan P. N. Exon Smith   ///{
28321521891SPeter Collingbourne   void EnumerateMetadata(const Function *F, const Metadata *MD);
284520f8542SDuncan P. N. Exon Smith   void EnumerateMetadata(unsigned F, const Metadata *MD);
28530805b24SDuncan P. N. Exon Smith   ///}
28630805b24SDuncan P. N. Exon Smith 
287520f8542SDuncan P. N. Exon Smith   void EnumerateFunctionLocalMetadata(const Function &F,
288520f8542SDuncan P. N. Exon Smith                                       const LocalAsMetadata *Local);
289520f8542SDuncan P. N. Exon Smith   void EnumerateFunctionLocalMetadata(unsigned F, const LocalAsMetadata *Local);
290*e5d844b5SStephen Tozer   void EnumerateFunctionLocalListMetadata(const Function &F,
291*e5d844b5SStephen Tozer                                           const DIArgList *ArgList);
292*e5d844b5SStephen Tozer   void EnumerateFunctionLocalListMetadata(unsigned F, const DIArgList *Arglist);
29399ff5a86SDevang Patel   void EnumerateNamedMDNode(const NamedMDNode *NMD);
294572218b5SVictor Hernandez   void EnumerateValue(const Value *V);
295229907cdSChris Lattner   void EnumerateType(Type *T);
296572218b5SVictor Hernandez   void EnumerateOperandType(const Value *V);
297b518054bSReid Kleckner   void EnumerateAttributes(AttributeList PAL);
298c1d10d67SChris Lattner 
299c1d10d67SChris Lattner   void EnumerateValueSymbolTable(const ValueSymbolTable &ST);
30049e9bf8cSRafael Espindola   void EnumerateNamedMetadata(const Module &M);
301c1d10d67SChris Lattner };
302c1d10d67SChris Lattner 
303975293f0SEugene Zelenko } // end namespace llvm
304c1d10d67SChris Lattner 
305975293f0SEugene Zelenko #endif // LLVM_LIB_BITCODE_WRITER_VALUEENUMERATOR_H
306