brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.6 KiB · 426008f Raw
339 lines · cpp
1//===-------------- PGOCtxProfReadWriteTest.cpp ---------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/ADT/DenseSet.h"10#include "llvm/Bitcode/BitcodeAnalyzer.h"11#include "llvm/ProfileData/CtxInstrContextNode.h"12#include "llvm/ProfileData/PGOCtxProfReader.h"13#include "llvm/ProfileData/PGOCtxProfWriter.h"14#include "llvm/Support/Error.h"15#include "llvm/Support/MemoryBuffer.h"16#include "llvm/Support/raw_ostream.h"17#include "llvm/Testing/Support/SupportHelpers.h"18#include "gtest/gtest.h"19 20using namespace llvm;21using namespace llvm::ctx_profile;22 23class PGOCtxProfRWTest : public ::testing::Test {24  std::vector<std::unique_ptr<char[]>> Nodes;25  std::map<GUID, const ContextNode *> Roots;26 27public:28  ContextNode *createNode(GUID Guid, uint32_t NumCounters,29                          uint32_t NumCallsites, ContextNode *Next = nullptr) {30    auto AllocSize = ContextNode::getAllocSize(NumCounters, NumCallsites);31    auto *Mem = Nodes.emplace_back(std::make_unique<char[]>(AllocSize)).get();32    std::memset(Mem, 0, AllocSize);33    auto *Ret = new (Mem) ContextNode(Guid, NumCounters, NumCallsites, Next);34    // set the entrycount to something - unless we're creating an invalid root.35    if (Ret->counters_size() > 0)36      Ret->counters()[0] = 42;37    return Ret;38  }39 40  void SetUp() override {41    // Root (guid 1) has 2 callsites, one used for an indirect call to either42    // guid 2 or 4.43    // guid 2 calls guid 544    // guid 5 calls guid 245    // there's also a second root, guid3.46    auto *Root1 = createNode(1, 2, 2);47    Root1->counters()[0] = 10;48    Root1->counters()[1] = 11;49    Roots.insert({1, Root1});50    auto *L1 = createNode(2, 1, 1);51    L1->counters()[0] = 12;52    Root1->subContexts()[1] = createNode(4, 3, 1, L1);53    Root1->subContexts()[1]->counters()[0] = 13;54    Root1->subContexts()[1]->counters()[1] = 14;55    Root1->subContexts()[1]->counters()[2] = 15;56 57    auto *L3 = createNode(5, 6, 3);58    for (auto I = 0; I < 6; ++I)59      L3->counters()[I] = 16 + I;60    L1->subContexts()[0] = L3;61    L3->subContexts()[2] = createNode(2, 1, 1);62    L3->subContexts()[2]->counters()[0] = 30;63    auto *Root2 = createNode(3, 1, 0);64    Root2->counters()[0] = 40;65    Roots.insert({3, Root2});66  }67 68  const std::map<GUID, const ContextNode *> &roots() const { return Roots; }69};70 71void checkSame(const ContextNode &Raw, const PGOCtxProfContext &Profile) {72  EXPECT_EQ(Raw.guid(), Profile.guid());73  ASSERT_EQ(Raw.counters_size(), Profile.counters().size());74  for (auto I = 0U; I < Raw.counters_size(); ++I)75    EXPECT_EQ(Raw.counters()[I], Profile.counters()[I]);76 77  for (auto I = 0U; I < Raw.callsites_size(); ++I) {78    if (Raw.subContexts()[I] == nullptr)79      continue;80    EXPECT_TRUE(Profile.hasCallsite(I));81    const auto &ProfileTargets = Profile.callsite(I);82 83    std::map<GUID, const ContextNode *> Targets;84    for (const auto *N = Raw.subContexts()[I]; N; N = N->next())85      EXPECT_TRUE(Targets.insert({N->guid(), N}).second);86 87    EXPECT_EQ(Targets.size(), ProfileTargets.size());88    for (auto It : Targets) {89      auto PIt = ProfileTargets.find(It.second->guid());90      EXPECT_NE(PIt, ProfileTargets.end());91      checkSame(*It.second, PIt->second);92    }93  }94}95 96TEST_F(PGOCtxProfRWTest, RoundTrip) {97  llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true);98  {99    std::error_code EC;100    raw_fd_stream Out(ProfileFile.path(), EC);101    ASSERT_FALSE(EC);102    {103      PGOCtxProfileWriter Writer(Out);104      Writer.startContextSection();105      for (auto &[_, R] : roots())106        Writer.writeContextual(*R, nullptr, 1);107      Writer.endContextSection();108    }109  }110  {111    ErrorOr<std::unique_ptr<MemoryBuffer>> MB =112        MemoryBuffer::getFile(ProfileFile.path());113    ASSERT_TRUE(!!MB);114    ASSERT_NE(*MB, nullptr);115 116    // Check it's analyzable by the BCAnalyzer117    BitcodeAnalyzer BA((*MB)->getBuffer());118    std::string AnalyzerDump;119    raw_string_ostream OS(AnalyzerDump);120    BCDumpOptions Opts(OS);121 122    // As in, expect no error.123    EXPECT_FALSE(BA.analyze(Opts));124    EXPECT_TRUE(AnalyzerDump.find("<Metadata BlockID") != std::string::npos);125    EXPECT_TRUE(AnalyzerDump.find("<Context BlockID") != std::string::npos);126    EXPECT_TRUE(AnalyzerDump.find("<CalleeIndex codeid") != std::string::npos);127 128    PGOCtxProfileReader Reader((*MB)->getBuffer());129    auto Expected = Reader.loadProfiles();130    ASSERT_TRUE(!!Expected);131    auto &Ctxes = Expected->Contexts;132    EXPECT_EQ(Ctxes.size(), roots().size());133    EXPECT_EQ(Ctxes.size(), 2U);134    for (auto &[G, R] : roots())135      checkSame(*R, Ctxes.find(G)->second);136 137    DenseSet<GlobalValue::GUID> Guids;138    Ctxes.at(1U).getContainedGuids(Guids);139    EXPECT_THAT(Guids,140                testing::WhenSorted(testing::ElementsAre(1U, 2U, 4U, 5U)));141 142    Guids.clear();143    Ctxes.at(3U).getContainedGuids(Guids);144    EXPECT_THAT(Guids, testing::ElementsAre(3U));145  }146}147 148TEST_F(PGOCtxProfRWTest, InvalidCounters) {149  auto *R = createNode(1, 0, 1);150  llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true);151  {152    std::error_code EC;153    raw_fd_stream Out(ProfileFile.path(), EC);154    ASSERT_FALSE(EC);155    {156      PGOCtxProfileWriter Writer(Out);157      Writer.startContextSection();158      Writer.writeContextual(*R, nullptr, 2);159      Writer.endContextSection();160    }161  }162  {163    auto MB = MemoryBuffer::getFile(ProfileFile.path());164    ASSERT_TRUE(!!MB);165    ASSERT_NE(*MB, nullptr);166    PGOCtxProfileReader Reader((*MB)->getBuffer());167    auto Expected = Reader.loadProfiles();168    EXPECT_FALSE(Expected);169    consumeError(Expected.takeError());170  }171}172 173TEST_F(PGOCtxProfRWTest, CountersAllZero) {174  auto *R = createNode(1, 2, 1);175  R->counters()[0] = 0;176  llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true);177  {178    std::error_code EC;179    raw_fd_stream Out(ProfileFile.path(), EC);180    ASSERT_FALSE(EC);181    {182      PGOCtxProfileWriter Writer(Out);183      Writer.startContextSection();184      Writer.writeContextual(*R, nullptr, 42);185      Writer.endContextSection();186    }187  }188  {189    auto MB = MemoryBuffer::getFile(ProfileFile.path());190    ASSERT_TRUE(!!MB);191    ASSERT_NE(*MB, nullptr);192    PGOCtxProfileReader Reader((*MB)->getBuffer());193    auto Expected = Reader.loadProfiles();194    EXPECT_TRUE(!!Expected);195    EXPECT_TRUE(Expected->Contexts.empty());196  }197}198 199TEST_F(PGOCtxProfRWTest, CountersAllZeroWithOverride) {200  auto *R = createNode(42, 2, 1);201  R->counters()[0] = 0;202  llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true);203  {204    std::error_code EC;205    raw_fd_stream Out(ProfileFile.path(), EC);206    ASSERT_FALSE(EC);207    {208      PGOCtxProfileWriter Writer(Out, /*VersionOverride=*/std::nullopt,209                                 /*IncludeEmpty=*/true);210      Writer.startContextSection();211      Writer.writeContextual(*R, nullptr, 8);212      Writer.endContextSection();213    }214  }215  {216    auto MB = MemoryBuffer::getFile(ProfileFile.path());217    ASSERT_TRUE(!!MB);218    ASSERT_NE(*MB, nullptr);219    PGOCtxProfileReader Reader((*MB)->getBuffer());220    auto Expected = Reader.loadProfiles();221    EXPECT_TRUE(!!Expected);222    EXPECT_EQ(Expected->Contexts.size(), 1U);223    EXPECT_EQ(Expected->Contexts.begin()->second.guid(), 42U);224  }225}226 227TEST_F(PGOCtxProfRWTest, Empty) {228  PGOCtxProfileReader Reader("");229  auto Expected = Reader.loadProfiles();230  EXPECT_FALSE(Expected);231  consumeError(Expected.takeError());232}233 234TEST_F(PGOCtxProfRWTest, Invalid) {235  PGOCtxProfileReader Reader("Surely this is not valid");236  auto Expected = Reader.loadProfiles();237  EXPECT_FALSE(Expected);238  consumeError(Expected.takeError());239}240 241TEST_F(PGOCtxProfRWTest, ValidButEmpty) {242  llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true);243  {244    std::error_code EC;245    raw_fd_stream Out(ProfileFile.path(), EC);246    ASSERT_FALSE(EC);247    {248      PGOCtxProfileWriter Writer(Out);249      // don't write anything - this will just produce the metadata subblock.250    }251  }252  {253    auto MB = MemoryBuffer::getFile(ProfileFile.path());254    ASSERT_TRUE(!!MB);255    ASSERT_NE(*MB, nullptr);256 257    PGOCtxProfileReader Reader((*MB)->getBuffer());258    auto Expected = Reader.loadProfiles();259    EXPECT_TRUE(!!Expected);260    EXPECT_TRUE(Expected->Contexts.empty());261  }262}263 264TEST_F(PGOCtxProfRWTest, WrongVersion) {265  llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true);266  {267    std::error_code EC;268    raw_fd_stream Out(ProfileFile.path(), EC);269    ASSERT_FALSE(EC);270    {271      PGOCtxProfileWriter Writer(Out, PGOCtxProfileWriter::CurrentVersion + 1);272    }273  }274  {275    auto MB = MemoryBuffer::getFile(ProfileFile.path());276    ASSERT_TRUE(!!MB);277    ASSERT_NE(*MB, nullptr);278 279    PGOCtxProfileReader Reader((*MB)->getBuffer());280    auto Expected = Reader.loadProfiles();281    EXPECT_FALSE(Expected);282    consumeError(Expected.takeError());283  }284}285 286TEST_F(PGOCtxProfRWTest, DuplicateRoots) {287  llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true);288  {289    std::error_code EC;290    raw_fd_stream Out(ProfileFile.path(), EC);291    ASSERT_FALSE(EC);292    {293      PGOCtxProfileWriter Writer(Out, /*VersionOverride=*/std::nullopt,294                                 /*IncludeEmpty=*/true);295      Writer.startContextSection();296      Writer.writeContextual(*createNode(1, 1, 1), nullptr, 1);297      Writer.writeContextual(*createNode(1, 1, 1), nullptr, 1);298      Writer.endContextSection();299    }300  }301  {302    auto MB = MemoryBuffer::getFile(ProfileFile.path());303    ASSERT_TRUE(!!MB);304    ASSERT_NE(*MB, nullptr);305    PGOCtxProfileReader Reader((*MB)->getBuffer());306    auto Expected = Reader.loadProfiles();307    EXPECT_FALSE(Expected);308    consumeError(Expected.takeError());309  }310}311 312TEST_F(PGOCtxProfRWTest, DuplicateTargets) {313  llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true);314  {315    std::error_code EC;316    raw_fd_stream Out(ProfileFile.path(), EC);317    ASSERT_FALSE(EC);318    {319      auto *R = createNode(1, 1, 1);320      auto *L1 = createNode(2, 1, 0);321      auto *L2 = createNode(2, 1, 0, L1);322      R->subContexts()[0] = L2;323      PGOCtxProfileWriter Writer(Out);324      Writer.startContextSection();325      Writer.writeContextual(*R, nullptr, 1);326      Writer.endContextSection();327    }328  }329  {330    auto MB = MemoryBuffer::getFile(ProfileFile.path());331    ASSERT_TRUE(!!MB);332    ASSERT_NE(*MB, nullptr);333    PGOCtxProfileReader Reader((*MB)->getBuffer());334    auto Expected = Reader.loadProfiles();335    EXPECT_FALSE(Expected);336    consumeError(Expected.takeError());337  }338}339