1 //===- unittest/ProfileData/SampleProfTest.cpp -------------------*- C++ 2 //-*-===// 3 // 4 // The LLVM Compiler Infrastructure 5 // 6 // This file is distributed under the University of Illinois Open Source 7 // License. See LICENSE.TXT for details. 8 // 9 //===----------------------------------------------------------------------===// 10 11 #include "llvm/IR/Metadata.h" 12 #include "llvm/ProfileData/SampleProfReader.h" 13 #include "llvm/ProfileData/SampleProfWriter.h" 14 #include "gtest/gtest.h" 15 16 #include <cstdarg> 17 18 using namespace llvm; 19 using namespace sampleprof; 20 21 static ::testing::AssertionResult NoError(std::error_code EC) { 22 if (!EC) 23 return ::testing::AssertionSuccess(); 24 return ::testing::AssertionFailure() << "error " << EC.value() << ": " 25 << EC.message(); 26 } 27 28 namespace { 29 30 struct SampleProfTest : ::testing::Test { 31 std::string Data; 32 std::unique_ptr<raw_ostream> OS; 33 std::unique_ptr<SampleProfileWriter> Writer; 34 std::unique_ptr<SampleProfileReader> Reader; 35 36 SampleProfTest() 37 : Data(), OS(new raw_string_ostream(Data)), Writer(), Reader() {} 38 39 void createWriter(SampleProfileFormat Format) { 40 auto WriterOrErr = SampleProfileWriter::create(OS, Format); 41 ASSERT_TRUE(NoError(WriterOrErr.getError())); 42 Writer = std::move(WriterOrErr.get()); 43 } 44 45 void readProfile(std::unique_ptr<MemoryBuffer> &Profile) { 46 auto ReaderOrErr = SampleProfileReader::create(Profile, getGlobalContext()); 47 ASSERT_TRUE(NoError(ReaderOrErr.getError())); 48 Reader = std::move(ReaderOrErr.get()); 49 } 50 51 void testRoundTrip(SampleProfileFormat Format) { 52 createWriter(Format); 53 54 StringRef FooName("_Z3fooi"); 55 FunctionSamples FooSamples; 56 FooSamples.setName(FooName); 57 FooSamples.addTotalSamples(7711); 58 FooSamples.addHeadSamples(610); 59 FooSamples.addBodySamples(1, 0, 610); 60 FooSamples.addBodySamples(2, 0, 600); 61 FooSamples.addBodySamples(4, 0, 60000); 62 FooSamples.addBodySamples(8, 0, 60351); 63 FooSamples.addBodySamples(10, 0, 605); 64 65 StringRef BarName("_Z3bari"); 66 FunctionSamples BarSamples; 67 BarSamples.setName(BarName); 68 BarSamples.addTotalSamples(20301); 69 BarSamples.addHeadSamples(1437); 70 BarSamples.addBodySamples(1, 0, 1437); 71 72 StringMap<FunctionSamples> Profiles; 73 Profiles[FooName] = std::move(FooSamples); 74 Profiles[BarName] = std::move(BarSamples); 75 76 std::error_code EC; 77 EC = Writer->write(Profiles); 78 ASSERT_TRUE(NoError(EC)); 79 80 Writer->getOutputStream().flush(); 81 82 auto Profile = MemoryBuffer::getMemBufferCopy(Data); 83 readProfile(Profile); 84 85 EC = Reader->read(); 86 ASSERT_TRUE(NoError(EC)); 87 88 StringMap<FunctionSamples> &ReadProfiles = Reader->getProfiles(); 89 ASSERT_EQ(2u, ReadProfiles.size()); 90 91 FunctionSamples &ReadFooSamples = ReadProfiles[FooName]; 92 ASSERT_EQ(7711u, ReadFooSamples.getTotalSamples()); 93 ASSERT_EQ(610u, ReadFooSamples.getHeadSamples()); 94 95 FunctionSamples &ReadBarSamples = ReadProfiles[BarName]; 96 ASSERT_EQ(20301u, ReadBarSamples.getTotalSamples()); 97 ASSERT_EQ(1437u, ReadBarSamples.getHeadSamples()); 98 99 auto VerifySummary = [](SampleProfileSummary &Summary) mutable { 100 ASSERT_EQ(123603u, Summary.getTotalSamples()); 101 ASSERT_EQ(6u, Summary.getNumLinesWithSamples()); 102 ASSERT_EQ(2u, Summary.getNumFunctions()); 103 ASSERT_EQ(1437u, Summary.getMaxFunctionCount()); 104 ASSERT_EQ(60351u, Summary.getMaxSamplesPerLine()); 105 106 uint32_t Cutoff = 800000; 107 auto Predicate = [&Cutoff](const ProfileSummaryEntry &PE) { 108 return PE.Cutoff == Cutoff; 109 }; 110 std::vector<ProfileSummaryEntry> &Details = Summary.getDetailedSummary(); 111 auto EightyPerc = std::find_if(Details.begin(), Details.end(), Predicate); 112 Cutoff = 900000; 113 auto NinetyPerc = std::find_if(Details.begin(), Details.end(), Predicate); 114 Cutoff = 950000; 115 auto NinetyFivePerc = 116 std::find_if(Details.begin(), Details.end(), Predicate); 117 Cutoff = 990000; 118 auto NinetyNinePerc = 119 std::find_if(Details.begin(), Details.end(), Predicate); 120 ASSERT_EQ(60000u, EightyPerc->MinCount); 121 ASSERT_EQ(60000u, NinetyPerc->MinCount); 122 ASSERT_EQ(60000u, NinetyFivePerc->MinCount); 123 ASSERT_EQ(610u, NinetyNinePerc->MinCount); 124 }; 125 126 SampleProfileSummary &Summary = Reader->getSummary(); 127 VerifySummary(Summary); 128 129 // Test that conversion of summary to and from Metadata works. 130 Metadata *MD = Summary.getMD(getGlobalContext()); 131 ASSERT_TRUE(MD); 132 ProfileSummary *PS = ProfileSummary::getFromMD(MD); 133 ASSERT_TRUE(PS); 134 ASSERT_TRUE(isa<SampleProfileSummary>(PS)); 135 SampleProfileSummary *SPS = cast<SampleProfileSummary>(PS); 136 VerifySummary(*SPS); 137 delete SPS; 138 139 // Test that summary can be attached to and read back from module. 140 Module M("my_module", getGlobalContext()); 141 M.setProfileSummary(MD); 142 MD = M.getProfileSummary(); 143 ASSERT_TRUE(MD); 144 PS = ProfileSummary::getFromMD(MD); 145 ASSERT_TRUE(PS); 146 ASSERT_TRUE(isa<SampleProfileSummary>(PS)); 147 SPS = cast<SampleProfileSummary>(PS); 148 VerifySummary(*SPS); 149 delete SPS; 150 } 151 }; 152 153 TEST_F(SampleProfTest, roundtrip_text_profile) { 154 testRoundTrip(SampleProfileFormat::SPF_Text); 155 } 156 157 TEST_F(SampleProfTest, roundtrip_binary_profile) { 158 testRoundTrip(SampleProfileFormat::SPF_Binary); 159 } 160 161 TEST_F(SampleProfTest, sample_overflow_saturation) { 162 const uint64_t Max = std::numeric_limits<uint64_t>::max(); 163 sampleprof_error Result; 164 165 StringRef FooName("_Z3fooi"); 166 FunctionSamples FooSamples; 167 Result = FooSamples.addTotalSamples(1); 168 ASSERT_EQ(Result, sampleprof_error::success); 169 170 Result = FooSamples.addHeadSamples(1); 171 ASSERT_EQ(Result, sampleprof_error::success); 172 173 Result = FooSamples.addBodySamples(10, 0, 1); 174 ASSERT_EQ(Result, sampleprof_error::success); 175 176 Result = FooSamples.addTotalSamples(Max); 177 ASSERT_EQ(Result, sampleprof_error::counter_overflow); 178 ASSERT_EQ(FooSamples.getTotalSamples(), Max); 179 180 Result = FooSamples.addHeadSamples(Max); 181 ASSERT_EQ(Result, sampleprof_error::counter_overflow); 182 ASSERT_EQ(FooSamples.getHeadSamples(), Max); 183 184 Result = FooSamples.addBodySamples(10, 0, Max); 185 ASSERT_EQ(Result, sampleprof_error::counter_overflow); 186 ErrorOr<uint64_t> BodySamples = FooSamples.findSamplesAt(10, 0); 187 ASSERT_FALSE(BodySamples.getError()); 188 ASSERT_EQ(BodySamples.get(), Max); 189 } 190 191 } // end anonymous namespace 192