Path: blob/main/contrib/llvm-project/llvm/lib/CodeGenData/OutlinedHashTreeRecord.cpp
35232 views
//===-- OutlinedHashTreeRecord.cpp ----------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This defines the OutlinedHashTreeRecord class. This class holds the outlined9// hash tree for both serialization and deserialization processes. It utilizes10// two data formats for serialization: raw binary data and YAML.11// These two formats can be used interchangeably.12//13//===----------------------------------------------------------------------===//1415#include "llvm/CodeGenData/OutlinedHashTreeRecord.h"16#include "llvm/ObjectYAML/YAML.h"17#include "llvm/Support/Endian.h"18#include "llvm/Support/EndianStream.h"1920#define DEBUG_TYPE "outlined-hash-tree"2122using namespace llvm;23using namespace llvm::support;2425namespace llvm {26namespace yaml {2728template <> struct MappingTraits<HashNodeStable> {29static void mapping(IO &io, HashNodeStable &res) {30io.mapRequired("Hash", res.Hash);31io.mapRequired("Terminals", res.Terminals);32io.mapRequired("SuccessorIds", res.SuccessorIds);33}34};3536template <> struct CustomMappingTraits<IdHashNodeStableMapTy> {37static void inputOne(IO &io, StringRef Key, IdHashNodeStableMapTy &V) {38HashNodeStable NodeStable;39io.mapRequired(Key.str().c_str(), NodeStable);40unsigned Id;41if (Key.getAsInteger(0, Id)) {42io.setError("Id not an integer");43return;44}45V.insert({Id, NodeStable});46}4748static void output(IO &io, IdHashNodeStableMapTy &V) {49for (auto Iter = V.begin(); Iter != V.end(); ++Iter)50io.mapRequired(utostr(Iter->first).c_str(), Iter->second);51}52};5354} // namespace yaml55} // namespace llvm5657void OutlinedHashTreeRecord::serialize(raw_ostream &OS) const {58IdHashNodeStableMapTy IdNodeStableMap;59convertToStableData(IdNodeStableMap);60support::endian::Writer Writer(OS, endianness::little);61Writer.write<uint32_t>(IdNodeStableMap.size());6263for (const auto &[Id, NodeStable] : IdNodeStableMap) {64Writer.write<uint32_t>(Id);65Writer.write<uint64_t>(NodeStable.Hash);66Writer.write<uint32_t>(NodeStable.Terminals);67Writer.write<uint32_t>(NodeStable.SuccessorIds.size());68for (auto SuccessorId : NodeStable.SuccessorIds)69Writer.write<uint32_t>(SuccessorId);70}71}7273void OutlinedHashTreeRecord::deserialize(const unsigned char *&Ptr) {74IdHashNodeStableMapTy IdNodeStableMap;75auto NumIdNodeStableMap =76endian::readNext<uint32_t, endianness::little, unaligned>(Ptr);7778for (unsigned I = 0; I < NumIdNodeStableMap; ++I) {79auto Id = endian::readNext<uint32_t, endianness::little, unaligned>(Ptr);80HashNodeStable NodeStable;81NodeStable.Hash =82endian::readNext<uint64_t, endianness::little, unaligned>(Ptr);83NodeStable.Terminals =84endian::readNext<uint32_t, endianness::little, unaligned>(Ptr);85auto NumSuccessorIds =86endian::readNext<uint32_t, endianness::little, unaligned>(Ptr);87for (unsigned J = 0; J < NumSuccessorIds; ++J)88NodeStable.SuccessorIds.push_back(89endian::readNext<uint32_t, endianness::little, unaligned>(Ptr));9091IdNodeStableMap[Id] = std::move(NodeStable);92}9394convertFromStableData(IdNodeStableMap);95}9697void OutlinedHashTreeRecord::serializeYAML(yaml::Output &YOS) const {98IdHashNodeStableMapTy IdNodeStableMap;99convertToStableData(IdNodeStableMap);100101YOS << IdNodeStableMap;102}103104void OutlinedHashTreeRecord::deserializeYAML(yaml::Input &YIS) {105IdHashNodeStableMapTy IdNodeStableMap;106107YIS >> IdNodeStableMap;108YIS.nextDocument();109110convertFromStableData(IdNodeStableMap);111}112113void OutlinedHashTreeRecord::convertToStableData(114IdHashNodeStableMapTy &IdNodeStableMap) const {115// Build NodeIdMap116HashNodeIdMapTy NodeIdMap;117HashTree->walkGraph(118[&NodeIdMap](const HashNode *Current) {119size_t Index = NodeIdMap.size();120NodeIdMap[Current] = Index;121assert((Index + 1 == NodeIdMap.size()) &&122"Duplicate key in NodeIdMap: 'Current' should be unique.");123},124/*EdgeCallbackFn=*/nullptr, /*SortedWork=*/true);125126// Convert NodeIdMap to NodeStableMap127for (auto &P : NodeIdMap) {128auto *Node = P.first;129auto Id = P.second;130HashNodeStable NodeStable;131NodeStable.Hash = Node->Hash;132NodeStable.Terminals = Node->Terminals ? *Node->Terminals : 0;133for (auto &P : Node->Successors)134NodeStable.SuccessorIds.push_back(NodeIdMap[P.second.get()]);135IdNodeStableMap[Id] = NodeStable;136}137138// Sort the Successors so that they come out in the same order as in the map.139for (auto &P : IdNodeStableMap)140llvm::sort(P.second.SuccessorIds);141}142143void OutlinedHashTreeRecord::convertFromStableData(144const IdHashNodeStableMapTy &IdNodeStableMap) {145IdHashNodeMapTy IdNodeMap;146// Initialize the root node at 0.147IdNodeMap[0] = HashTree->getRoot();148assert(IdNodeMap[0]->Successors.empty());149150for (auto &P : IdNodeStableMap) {151auto Id = P.first;152const HashNodeStable &NodeStable = P.second;153assert(IdNodeMap.count(Id));154HashNode *Curr = IdNodeMap[Id];155Curr->Hash = NodeStable.Hash;156if (NodeStable.Terminals)157Curr->Terminals = NodeStable.Terminals;158auto &Successors = Curr->Successors;159assert(Successors.empty());160for (auto SuccessorId : NodeStable.SuccessorIds) {161auto Sucessor = std::make_unique<HashNode>();162IdNodeMap[SuccessorId] = Sucessor.get();163auto Hash = IdNodeStableMap.at(SuccessorId).Hash;164Successors[Hash] = std::move(Sucessor);165}166}167}168169170