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