xref: /freebsd/contrib/llvm-project/llvm/lib/Bitcode/Writer/ValueEnumerator.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- Bitcode/Writer/ValueEnumerator.h - Number values ---------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This class gives values and types Unique ID's.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #ifndef LLVM_LIB_BITCODE_WRITER_VALUEENUMERATOR_H
140b57cec5SDimitry Andric #define LLVM_LIB_BITCODE_WRITER_VALUEENUMERATOR_H
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
170b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
180b57cec5SDimitry Andric #include "llvm/ADT/UniqueVector.h"
190b57cec5SDimitry Andric #include "llvm/IR/Attributes.h"
200b57cec5SDimitry Andric #include "llvm/IR/UseListOrder.h"
210b57cec5SDimitry Andric #include <cassert>
220b57cec5SDimitry Andric #include <cstdint>
230b57cec5SDimitry Andric #include <utility>
240b57cec5SDimitry Andric #include <vector>
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric namespace llvm {
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric class BasicBlock;
290b57cec5SDimitry Andric class Comdat;
30fe6060f1SDimitry Andric class DIArgList;
310b57cec5SDimitry Andric class Function;
320b57cec5SDimitry Andric class Instruction;
330b57cec5SDimitry Andric class LocalAsMetadata;
340b57cec5SDimitry Andric class MDNode;
350b57cec5SDimitry Andric class Metadata;
360b57cec5SDimitry Andric class Module;
370b57cec5SDimitry Andric class NamedMDNode;
380b57cec5SDimitry Andric class raw_ostream;
390b57cec5SDimitry Andric class Type;
400b57cec5SDimitry Andric class Value;
410b57cec5SDimitry Andric class ValueSymbolTable;
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric class ValueEnumerator {
440b57cec5SDimitry Andric public:
450b57cec5SDimitry Andric   using TypeList = std::vector<Type *>;
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric   // For each value, we remember its Value* and occurrence frequency.
480b57cec5SDimitry Andric   using ValueList = std::vector<std::pair<const Value *, unsigned>>;
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric   /// Attribute groups as encoded in bitcode are almost AttributeSets, but they
510b57cec5SDimitry Andric   /// include the AttributeList index, so we have to track that in our map.
520b57cec5SDimitry Andric   using IndexAndAttrSet = std::pair<unsigned, AttributeSet>;
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric   UseListOrderStack UseListOrders;
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric private:
570b57cec5SDimitry Andric   using TypeMapType = DenseMap<Type *, unsigned>;
580b57cec5SDimitry Andric   TypeMapType TypeMap;
590b57cec5SDimitry Andric   TypeList Types;
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric   using ValueMapType = DenseMap<const Value *, unsigned>;
620b57cec5SDimitry Andric   ValueMapType ValueMap;
630b57cec5SDimitry Andric   ValueList Values;
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric   using ComdatSetType = UniqueVector<const Comdat *>;
660b57cec5SDimitry Andric   ComdatSetType Comdats;
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric   std::vector<const Metadata *> MDs;
690b57cec5SDimitry Andric   std::vector<const Metadata *> FunctionMDs;
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric   /// Index of information about a piece of metadata.
720b57cec5SDimitry Andric   struct MDIndex {
730b57cec5SDimitry Andric     unsigned F = 0;  ///< The ID of the function for this metadata, if any.
740b57cec5SDimitry Andric     unsigned ID = 0; ///< The implicit ID of this metadata in bitcode.
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric     MDIndex() = default;
MDIndexMDIndex770b57cec5SDimitry Andric     explicit MDIndex(unsigned F) : F(F) {}
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric     /// Check if this has a function tag, and it's different from NewF.
hasDifferentFunctionMDIndex800b57cec5SDimitry Andric     bool hasDifferentFunction(unsigned NewF) const { return F && F != NewF; }
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric     /// Fetch the MD this references out of the given metadata array.
getMDIndex830b57cec5SDimitry Andric     const Metadata *get(ArrayRef<const Metadata *> MDs) const {
840b57cec5SDimitry Andric       assert(ID && "Expected non-zero ID");
850b57cec5SDimitry Andric       assert(ID <= MDs.size() && "Expected valid ID");
860b57cec5SDimitry Andric       return MDs[ID - 1];
870b57cec5SDimitry Andric     }
880b57cec5SDimitry Andric   };
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric   using MetadataMapType = DenseMap<const Metadata *, MDIndex>;
910b57cec5SDimitry Andric   MetadataMapType MetadataMap;
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric   /// Range of metadata IDs, as a half-open range.
940b57cec5SDimitry Andric   struct MDRange {
950b57cec5SDimitry Andric     unsigned First = 0;
960b57cec5SDimitry Andric     unsigned Last = 0;
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric     /// Number of strings in the prefix of the metadata range.
990b57cec5SDimitry Andric     unsigned NumStrings = 0;
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric     MDRange() = default;
MDRangeMDRange1020b57cec5SDimitry Andric     explicit MDRange(unsigned First) : First(First) {}
1030b57cec5SDimitry Andric   };
1040b57cec5SDimitry Andric   SmallDenseMap<unsigned, MDRange, 1> FunctionMDInfo;
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric   bool ShouldPreserveUseListOrder;
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric   using AttributeGroupMapType = DenseMap<IndexAndAttrSet, unsigned>;
1090b57cec5SDimitry Andric   AttributeGroupMapType AttributeGroupMap;
1100b57cec5SDimitry Andric   std::vector<IndexAndAttrSet> AttributeGroups;
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric   using AttributeListMapType = DenseMap<AttributeList, unsigned>;
1130b57cec5SDimitry Andric   AttributeListMapType AttributeListMap;
1140b57cec5SDimitry Andric   std::vector<AttributeList> AttributeLists;
1150b57cec5SDimitry Andric 
1160b57cec5SDimitry Andric   /// GlobalBasicBlockIDs - This map memoizes the basic block ID's referenced by
1170b57cec5SDimitry Andric   /// the "getGlobalBasicBlockID" method.
1180b57cec5SDimitry Andric   mutable DenseMap<const BasicBlock*, unsigned> GlobalBasicBlockIDs;
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric   using InstructionMapType = DenseMap<const Instruction *, unsigned>;
1210b57cec5SDimitry Andric   InstructionMapType InstructionMap;
1220b57cec5SDimitry Andric   unsigned InstructionCount;
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric   /// BasicBlocks - This contains all the basic blocks for the currently
1250b57cec5SDimitry Andric   /// incorporated function.  Their reverse mapping is stored in ValueMap.
1260b57cec5SDimitry Andric   std::vector<const BasicBlock*> BasicBlocks;
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric   /// When a function is incorporated, this is the size of the Values list
1290b57cec5SDimitry Andric   /// before incorporation.
1300b57cec5SDimitry Andric   unsigned NumModuleValues;
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric   /// When a function is incorporated, this is the size of the Metadatas list
1330b57cec5SDimitry Andric   /// before incorporation.
1340b57cec5SDimitry Andric   unsigned NumModuleMDs = 0;
1350b57cec5SDimitry Andric   unsigned NumMDStrings = 0;
1360b57cec5SDimitry Andric 
1370b57cec5SDimitry Andric   unsigned FirstFuncConstantID;
1380b57cec5SDimitry Andric   unsigned FirstInstID;
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric public:
1410b57cec5SDimitry Andric   ValueEnumerator(const Module &M, bool ShouldPreserveUseListOrder);
1420b57cec5SDimitry Andric   ValueEnumerator(const ValueEnumerator &) = delete;
1430b57cec5SDimitry Andric   ValueEnumerator &operator=(const ValueEnumerator &) = delete;
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric   void dump() const;
1460b57cec5SDimitry Andric   void print(raw_ostream &OS, const ValueMapType &Map, const char *Name) const;
1470b57cec5SDimitry Andric   void print(raw_ostream &OS, const MetadataMapType &Map,
1480b57cec5SDimitry Andric              const char *Name) const;
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric   unsigned getValueID(const Value *V) const;
1510b57cec5SDimitry Andric 
getMetadataID(const Metadata * MD)1520b57cec5SDimitry Andric   unsigned getMetadataID(const Metadata *MD) const {
1530b57cec5SDimitry Andric     auto ID = getMetadataOrNullID(MD);
1540b57cec5SDimitry Andric     assert(ID != 0 && "Metadata not in slotcalculator!");
1550b57cec5SDimitry Andric     return ID - 1;
1560b57cec5SDimitry Andric   }
1570b57cec5SDimitry Andric 
getMetadataOrNullID(const Metadata * MD)1580b57cec5SDimitry Andric   unsigned getMetadataOrNullID(const Metadata *MD) const {
1590b57cec5SDimitry Andric     return MetadataMap.lookup(MD).ID;
1600b57cec5SDimitry Andric   }
1610b57cec5SDimitry Andric 
numMDs()1620b57cec5SDimitry Andric   unsigned numMDs() const { return MDs.size(); }
1630b57cec5SDimitry Andric 
shouldPreserveUseListOrder()1640b57cec5SDimitry Andric   bool shouldPreserveUseListOrder() const { return ShouldPreserveUseListOrder; }
1650b57cec5SDimitry Andric 
getTypeID(Type * T)1660b57cec5SDimitry Andric   unsigned getTypeID(Type *T) const {
1670b57cec5SDimitry Andric     TypeMapType::const_iterator I = TypeMap.find(T);
1680b57cec5SDimitry Andric     assert(I != TypeMap.end() && "Type not in ValueEnumerator!");
1690b57cec5SDimitry Andric     return I->second-1;
1700b57cec5SDimitry Andric   }
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric   unsigned getInstructionID(const Instruction *I) const;
1730b57cec5SDimitry Andric   void setInstructionID(const Instruction *I);
1740b57cec5SDimitry Andric 
getAttributeListID(AttributeList PAL)1750b57cec5SDimitry Andric   unsigned getAttributeListID(AttributeList PAL) const {
1760b57cec5SDimitry Andric     if (PAL.isEmpty()) return 0;  // Null maps to zero.
1770b57cec5SDimitry Andric     AttributeListMapType::const_iterator I = AttributeListMap.find(PAL);
1780b57cec5SDimitry Andric     assert(I != AttributeListMap.end() && "Attribute not in ValueEnumerator!");
1790b57cec5SDimitry Andric     return I->second;
1800b57cec5SDimitry Andric   }
1810b57cec5SDimitry Andric 
getAttributeGroupID(IndexAndAttrSet Group)1820b57cec5SDimitry Andric   unsigned getAttributeGroupID(IndexAndAttrSet Group) const {
1830b57cec5SDimitry Andric     if (!Group.second.hasAttributes())
1840b57cec5SDimitry Andric       return 0; // Null maps to zero.
1850b57cec5SDimitry Andric     AttributeGroupMapType::const_iterator I = AttributeGroupMap.find(Group);
1860b57cec5SDimitry Andric     assert(I != AttributeGroupMap.end() && "Attribute not in ValueEnumerator!");
1870b57cec5SDimitry Andric     return I->second;
1880b57cec5SDimitry Andric   }
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric   /// getFunctionConstantRange - Return the range of values that corresponds to
1910b57cec5SDimitry Andric   /// function-local constants.
getFunctionConstantRange(unsigned & Start,unsigned & End)1920b57cec5SDimitry Andric   void getFunctionConstantRange(unsigned &Start, unsigned &End) const {
1930b57cec5SDimitry Andric     Start = FirstFuncConstantID;
1940b57cec5SDimitry Andric     End = FirstInstID;
1950b57cec5SDimitry Andric   }
1960b57cec5SDimitry Andric 
getValues()1970b57cec5SDimitry Andric   const ValueList &getValues() const { return Values; }
1980b57cec5SDimitry Andric 
1990b57cec5SDimitry Andric   /// Check whether the current block has any metadata to emit.
hasMDs()2000b57cec5SDimitry Andric   bool hasMDs() const { return NumModuleMDs < MDs.size(); }
2010b57cec5SDimitry Andric 
2020b57cec5SDimitry Andric   /// Get the MDString metadata for this block.
getMDStrings()2030b57cec5SDimitry Andric   ArrayRef<const Metadata *> getMDStrings() const {
204bdd1243dSDimitry Andric     return ArrayRef(MDs).slice(NumModuleMDs, NumMDStrings);
2050b57cec5SDimitry Andric   }
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric   /// Get the non-MDString metadata for this block.
getNonMDStrings()2080b57cec5SDimitry Andric   ArrayRef<const Metadata *> getNonMDStrings() const {
209bdd1243dSDimitry Andric     return ArrayRef(MDs).slice(NumModuleMDs).slice(NumMDStrings);
2100b57cec5SDimitry Andric   }
2110b57cec5SDimitry Andric 
getTypes()2120b57cec5SDimitry Andric   const TypeList &getTypes() const { return Types; }
2130b57cec5SDimitry Andric 
getBasicBlocks()2140b57cec5SDimitry Andric   const std::vector<const BasicBlock*> &getBasicBlocks() const {
2150b57cec5SDimitry Andric     return BasicBlocks;
2160b57cec5SDimitry Andric   }
2170b57cec5SDimitry Andric 
getAttributeLists()2180b57cec5SDimitry Andric   const std::vector<AttributeList> &getAttributeLists() const { return AttributeLists; }
2190b57cec5SDimitry Andric 
getAttributeGroups()2200b57cec5SDimitry Andric   const std::vector<IndexAndAttrSet> &getAttributeGroups() const {
2210b57cec5SDimitry Andric     return AttributeGroups;
2220b57cec5SDimitry Andric   }
2230b57cec5SDimitry Andric 
getComdats()2240b57cec5SDimitry Andric   const ComdatSetType &getComdats() const { return Comdats; }
2250b57cec5SDimitry Andric   unsigned getComdatID(const Comdat *C) const;
2260b57cec5SDimitry Andric 
2270b57cec5SDimitry Andric   /// getGlobalBasicBlockID - This returns the function-specific ID for the
2280b57cec5SDimitry Andric   /// specified basic block.  This is relatively expensive information, so it
2290b57cec5SDimitry Andric   /// should only be used by rare constructs such as address-of-label.
2300b57cec5SDimitry Andric   unsigned getGlobalBasicBlockID(const BasicBlock *BB) const;
2310b57cec5SDimitry Andric 
2320b57cec5SDimitry Andric   /// incorporateFunction/purgeFunction - If you'd like to deal with a function,
2330b57cec5SDimitry Andric   /// use these two methods to get its data into the ValueEnumerator!
2340b57cec5SDimitry Andric   void incorporateFunction(const Function &F);
2350b57cec5SDimitry Andric 
2360b57cec5SDimitry Andric   void purgeFunction();
237*0fca6ea1SDimitry Andric   uint64_t computeBitsRequiredForTypeIndices() const;
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric private:
2400b57cec5SDimitry Andric   void OptimizeConstants(unsigned CstStart, unsigned CstEnd);
2410b57cec5SDimitry Andric 
2420b57cec5SDimitry Andric   /// Reorder the reachable metadata.
2430b57cec5SDimitry Andric   ///
2440b57cec5SDimitry Andric   /// This is not just an optimization, but is mandatory for emitting MDString
2450b57cec5SDimitry Andric   /// correctly.
2460b57cec5SDimitry Andric   void organizeMetadata();
2470b57cec5SDimitry Andric 
2480b57cec5SDimitry Andric   /// Drop the function tag from the transitive operands of the given node.
2490b57cec5SDimitry Andric   void dropFunctionFromMetadata(MetadataMapType::value_type &FirstMD);
2500b57cec5SDimitry Andric 
2510b57cec5SDimitry Andric   /// Incorporate the function metadata.
2520b57cec5SDimitry Andric   ///
2530b57cec5SDimitry Andric   /// This should be called before enumerating LocalAsMetadata for the
2540b57cec5SDimitry Andric   /// function.
2550b57cec5SDimitry Andric   void incorporateFunctionMetadata(const Function &F);
2560b57cec5SDimitry Andric 
2570b57cec5SDimitry Andric   /// Enumerate a single instance of metadata with the given function tag.
2580b57cec5SDimitry Andric   ///
2590b57cec5SDimitry Andric   /// If \c MD has already been enumerated, check that \c F matches its
2600b57cec5SDimitry Andric   /// function tag.  If not, call \a dropFunctionFromMetadata().
2610b57cec5SDimitry Andric   ///
2620b57cec5SDimitry Andric   /// Otherwise, mark \c MD as visited.  Assign it an ID, or just return it if
2630b57cec5SDimitry Andric   /// it's an \a MDNode.
2640b57cec5SDimitry Andric   const MDNode *enumerateMetadataImpl(unsigned F, const Metadata *MD);
2650b57cec5SDimitry Andric 
2660b57cec5SDimitry Andric   unsigned getMetadataFunctionID(const Function *F) const;
2670b57cec5SDimitry Andric 
2680b57cec5SDimitry Andric   /// Enumerate reachable metadata in (almost) post-order.
2690b57cec5SDimitry Andric   ///
2700b57cec5SDimitry Andric   /// Enumerate all the metadata reachable from MD.  We want to minimize the
2710b57cec5SDimitry Andric   /// cost of reading bitcode records, and so the primary consideration is that
2720b57cec5SDimitry Andric   /// operands of uniqued nodes are resolved before the nodes are read.  This
2730b57cec5SDimitry Andric   /// avoids re-uniquing them on the context and factors away RAUW support.
2740b57cec5SDimitry Andric   ///
2750b57cec5SDimitry Andric   /// This algorithm guarantees that subgraphs of uniqued nodes are in
2760b57cec5SDimitry Andric   /// post-order.  Distinct subgraphs reachable only from a single uniqued node
2770b57cec5SDimitry Andric   /// will be in post-order.
2780b57cec5SDimitry Andric   ///
2790b57cec5SDimitry Andric   /// \note The relative order of a distinct and uniqued node is irrelevant.
2800b57cec5SDimitry Andric   /// \a organizeMetadata() will later partition distinct nodes ahead of
2810b57cec5SDimitry Andric   /// uniqued ones.
2820b57cec5SDimitry Andric   ///{
2830b57cec5SDimitry Andric   void EnumerateMetadata(const Function *F, const Metadata *MD);
2840b57cec5SDimitry Andric   void EnumerateMetadata(unsigned F, const Metadata *MD);
2850b57cec5SDimitry Andric   ///}
2860b57cec5SDimitry Andric 
2870b57cec5SDimitry Andric   void EnumerateFunctionLocalMetadata(const Function &F,
2880b57cec5SDimitry Andric                                       const LocalAsMetadata *Local);
2890b57cec5SDimitry Andric   void EnumerateFunctionLocalMetadata(unsigned F, const LocalAsMetadata *Local);
290fe6060f1SDimitry Andric   void EnumerateFunctionLocalListMetadata(const Function &F,
291fe6060f1SDimitry Andric                                           const DIArgList *ArgList);
292fe6060f1SDimitry Andric   void EnumerateFunctionLocalListMetadata(unsigned F, const DIArgList *Arglist);
2930b57cec5SDimitry Andric   void EnumerateNamedMDNode(const NamedMDNode *NMD);
2940b57cec5SDimitry Andric   void EnumerateValue(const Value *V);
2950b57cec5SDimitry Andric   void EnumerateType(Type *T);
2960b57cec5SDimitry Andric   void EnumerateOperandType(const Value *V);
2970b57cec5SDimitry Andric   void EnumerateAttributes(AttributeList PAL);
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric   void EnumerateValueSymbolTable(const ValueSymbolTable &ST);
3000b57cec5SDimitry Andric   void EnumerateNamedMetadata(const Module &M);
3010b57cec5SDimitry Andric };
3020b57cec5SDimitry Andric 
3030b57cec5SDimitry Andric } // end namespace llvm
3040b57cec5SDimitry Andric 
3050b57cec5SDimitry Andric #endif // LLVM_LIB_BITCODE_WRITER_VALUEENUMERATOR_H
306