1 //===- unittest/ProfileData/InstrProfTest.cpp -------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "llvm/ProfileData/InstrProfReader.h" 11 #include "llvm/ProfileData/InstrProfWriter.h" 12 #include "llvm/Support/Compression.h" 13 #include "gtest/gtest.h" 14 15 #include <cstdarg> 16 17 using namespace llvm; 18 19 static ::testing::AssertionResult NoError(std::error_code EC) { 20 if (!EC) 21 return ::testing::AssertionSuccess(); 22 return ::testing::AssertionFailure() << "error " << EC.value() 23 << ": " << EC.message(); 24 } 25 26 static ::testing::AssertionResult ErrorEquals(std::error_code Expected, 27 std::error_code Found) { 28 if (Expected == Found) 29 return ::testing::AssertionSuccess(); 30 return ::testing::AssertionFailure() << "error " << Found.value() 31 << ": " << Found.message(); 32 } 33 34 namespace { 35 36 struct InstrProfTest : ::testing::Test { 37 InstrProfWriter Writer; 38 std::unique_ptr<IndexedInstrProfReader> Reader; 39 40 void readProfile(std::unique_ptr<MemoryBuffer> Profile) { 41 auto ReaderOrErr = IndexedInstrProfReader::create(std::move(Profile)); 42 ASSERT_TRUE(NoError(ReaderOrErr.getError())); 43 Reader = std::move(ReaderOrErr.get()); 44 } 45 }; 46 47 TEST_F(InstrProfTest, write_and_read_empty_profile) { 48 auto Profile = Writer.writeBuffer(); 49 readProfile(std::move(Profile)); 50 ASSERT_TRUE(Reader->begin() == Reader->end()); 51 } 52 53 TEST_F(InstrProfTest, write_and_read_one_function) { 54 InstrProfRecord Record("foo", 0x1234, {1, 2, 3, 4}); 55 Writer.addRecord(std::move(Record)); 56 auto Profile = Writer.writeBuffer(); 57 readProfile(std::move(Profile)); 58 59 auto I = Reader->begin(), E = Reader->end(); 60 ASSERT_TRUE(I != E); 61 ASSERT_EQ(StringRef("foo"), I->Name); 62 ASSERT_EQ(0x1234U, I->Hash); 63 ASSERT_EQ(4U, I->Counts.size()); 64 ASSERT_EQ(1U, I->Counts[0]); 65 ASSERT_EQ(2U, I->Counts[1]); 66 ASSERT_EQ(3U, I->Counts[2]); 67 ASSERT_EQ(4U, I->Counts[3]); 68 ASSERT_TRUE(++I == E); 69 } 70 71 TEST_F(InstrProfTest, get_instr_prof_record) { 72 InstrProfRecord Record1("foo", 0x1234, {1, 2}); 73 InstrProfRecord Record2("foo", 0x1235, {3, 4}); 74 Writer.addRecord(std::move(Record1)); 75 Writer.addRecord(std::move(Record2)); 76 auto Profile = Writer.writeBuffer(); 77 readProfile(std::move(Profile)); 78 79 ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("foo", 0x1234); 80 ASSERT_TRUE(NoError(R.getError())); 81 ASSERT_EQ(2U, R.get().Counts.size()); 82 ASSERT_EQ(1U, R.get().Counts[0]); 83 ASSERT_EQ(2U, R.get().Counts[1]); 84 85 R = Reader->getInstrProfRecord("foo", 0x1235); 86 ASSERT_TRUE(NoError(R.getError())); 87 ASSERT_EQ(2U, R.get().Counts.size()); 88 ASSERT_EQ(3U, R.get().Counts[0]); 89 ASSERT_EQ(4U, R.get().Counts[1]); 90 91 R = Reader->getInstrProfRecord("foo", 0x5678); 92 ASSERT_TRUE(ErrorEquals(instrprof_error::hash_mismatch, R.getError())); 93 94 R = Reader->getInstrProfRecord("bar", 0x1234); 95 ASSERT_TRUE(ErrorEquals(instrprof_error::unknown_function, R.getError())); 96 } 97 98 TEST_F(InstrProfTest, get_function_counts) { 99 InstrProfRecord Record1("foo", 0x1234, {1, 2}); 100 InstrProfRecord Record2("foo", 0x1235, {3, 4}); 101 Writer.addRecord(std::move(Record1)); 102 Writer.addRecord(std::move(Record2)); 103 auto Profile = Writer.writeBuffer(); 104 readProfile(std::move(Profile)); 105 106 std::vector<uint64_t> Counts; 107 ASSERT_TRUE(NoError(Reader->getFunctionCounts("foo", 0x1234, Counts))); 108 ASSERT_EQ(2U, Counts.size()); 109 ASSERT_EQ(1U, Counts[0]); 110 ASSERT_EQ(2U, Counts[1]); 111 112 ASSERT_TRUE(NoError(Reader->getFunctionCounts("foo", 0x1235, Counts))); 113 ASSERT_EQ(2U, Counts.size()); 114 ASSERT_EQ(3U, Counts[0]); 115 ASSERT_EQ(4U, Counts[1]); 116 117 std::error_code EC; 118 EC = Reader->getFunctionCounts("foo", 0x5678, Counts); 119 ASSERT_TRUE(ErrorEquals(instrprof_error::hash_mismatch, EC)); 120 121 EC = Reader->getFunctionCounts("bar", 0x1234, Counts); 122 ASSERT_TRUE(ErrorEquals(instrprof_error::unknown_function, EC)); 123 } 124 125 TEST_F(InstrProfTest, get_icall_data_read_write) { 126 InstrProfRecord Record1("caller", 0x1234, {1, 2}); 127 InstrProfRecord Record2("callee1", 0x1235, {3, 4}); 128 InstrProfRecord Record3("callee2", 0x1235, {3, 4}); 129 InstrProfRecord Record4("callee3", 0x1235, {3, 4}); 130 131 // 4 value sites. 132 Record1.reserveSites(IPVK_IndirectCallTarget, 4); 133 InstrProfValueData VD0[] = {{(uint64_t) "callee1", 1}, 134 {(uint64_t) "callee2", 2}, 135 {(uint64_t) "callee3", 3}}; 136 Record1.addValueData(IPVK_IndirectCallTarget, 0, VD0, 3, nullptr); 137 // No value profile data at the second site. 138 Record1.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr); 139 InstrProfValueData VD2[] = {{(uint64_t) "callee1", 1}, 140 {(uint64_t) "callee2", 2}}; 141 Record1.addValueData(IPVK_IndirectCallTarget, 2, VD2, 2, nullptr); 142 InstrProfValueData VD3[] = {{(uint64_t) "callee1", 1}}; 143 Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr); 144 145 Writer.addRecord(std::move(Record1)); 146 Writer.addRecord(std::move(Record2)); 147 Writer.addRecord(std::move(Record3)); 148 Writer.addRecord(std::move(Record4)); 149 auto Profile = Writer.writeBuffer(); 150 readProfile(std::move(Profile)); 151 152 ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234); 153 ASSERT_TRUE(NoError(R.getError())); 154 ASSERT_EQ(4U, R.get().getNumValueSites(IPVK_IndirectCallTarget)); 155 ASSERT_EQ(3U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 0)); 156 ASSERT_EQ(0U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 1)); 157 ASSERT_EQ(2U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 2)); 158 ASSERT_EQ(1U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 3)); 159 160 std::unique_ptr<InstrProfValueData[]> VD = 161 R.get().getValueForSite(IPVK_IndirectCallTarget, 0); 162 163 ASSERT_EQ(3U, VD[0].Count); 164 ASSERT_EQ(2U, VD[1].Count); 165 ASSERT_EQ(1U, VD[2].Count); 166 167 ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee3")); 168 ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee2")); 169 ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee1")); 170 } 171 172 TEST_F(InstrProfTest, get_icall_data_read_write_with_weight) { 173 InstrProfRecord Record1("caller", 0x1234, {1, 2}); 174 InstrProfRecord Record2("callee1", 0x1235, {3, 4}); 175 InstrProfRecord Record3("callee2", 0x1235, {3, 4}); 176 InstrProfRecord Record4("callee3", 0x1235, {3, 4}); 177 178 // 4 value sites. 179 Record1.reserveSites(IPVK_IndirectCallTarget, 4); 180 InstrProfValueData VD0[] = {{(uint64_t) "callee1", 1}, 181 {(uint64_t) "callee2", 2}, 182 {(uint64_t) "callee3", 3}}; 183 Record1.addValueData(IPVK_IndirectCallTarget, 0, VD0, 3, nullptr); 184 // No value profile data at the second site. 185 Record1.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr); 186 InstrProfValueData VD2[] = {{(uint64_t) "callee1", 1}, 187 {(uint64_t) "callee2", 2}}; 188 Record1.addValueData(IPVK_IndirectCallTarget, 2, VD2, 2, nullptr); 189 InstrProfValueData VD3[] = {{(uint64_t) "callee1", 1}}; 190 Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr); 191 192 Writer.addRecord(std::move(Record1), 10); 193 Writer.addRecord(std::move(Record2)); 194 Writer.addRecord(std::move(Record3)); 195 Writer.addRecord(std::move(Record4)); 196 auto Profile = Writer.writeBuffer(); 197 readProfile(std::move(Profile)); 198 199 ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234); 200 ASSERT_TRUE(NoError(R.getError())); 201 ASSERT_EQ(4U, R.get().getNumValueSites(IPVK_IndirectCallTarget)); 202 ASSERT_EQ(3U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 0)); 203 ASSERT_EQ(0U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 1)); 204 ASSERT_EQ(2U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 2)); 205 ASSERT_EQ(1U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 3)); 206 207 std::unique_ptr<InstrProfValueData[]> VD = 208 R.get().getValueForSite(IPVK_IndirectCallTarget, 0); 209 ASSERT_EQ(30U, VD[0].Count); 210 ASSERT_EQ(20U, VD[1].Count); 211 ASSERT_EQ(10U, VD[2].Count); 212 213 ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee3")); 214 ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee2")); 215 ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee1")); 216 } 217 218 TEST_F(InstrProfTest, get_icall_data_read_write_big_endian) { 219 InstrProfRecord Record1("caller", 0x1234, {1, 2}); 220 InstrProfRecord Record2("callee1", 0x1235, {3, 4}); 221 InstrProfRecord Record3("callee2", 0x1235, {3, 4}); 222 InstrProfRecord Record4("callee3", 0x1235, {3, 4}); 223 224 // 4 value sites. 225 Record1.reserveSites(IPVK_IndirectCallTarget, 4); 226 InstrProfValueData VD0[] = {{(uint64_t) "callee1", 1}, 227 {(uint64_t) "callee2", 2}, 228 {(uint64_t) "callee3", 3}}; 229 Record1.addValueData(IPVK_IndirectCallTarget, 0, VD0, 3, nullptr); 230 // No value profile data at the second site. 231 Record1.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr); 232 InstrProfValueData VD2[] = {{(uint64_t) "callee1", 1}, 233 {(uint64_t) "callee2", 2}}; 234 Record1.addValueData(IPVK_IndirectCallTarget, 2, VD2, 2, nullptr); 235 InstrProfValueData VD3[] = {{(uint64_t) "callee1", 1}}; 236 Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr); 237 238 Writer.addRecord(std::move(Record1)); 239 Writer.addRecord(std::move(Record2)); 240 Writer.addRecord(std::move(Record3)); 241 Writer.addRecord(std::move(Record4)); 242 243 // Set big endian output. 244 Writer.setValueProfDataEndianness(support::big); 245 246 auto Profile = Writer.writeBuffer(); 247 readProfile(std::move(Profile)); 248 249 // Set big endian input. 250 Reader->setValueProfDataEndianness(support::big); 251 252 ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234); 253 ASSERT_TRUE(NoError(R.getError())); 254 ASSERT_EQ(4U, R.get().getNumValueSites(IPVK_IndirectCallTarget)); 255 ASSERT_EQ(3U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 0)); 256 ASSERT_EQ(0U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 1)); 257 ASSERT_EQ(2U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 2)); 258 ASSERT_EQ(1U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 3)); 259 260 std::unique_ptr<InstrProfValueData[]> VD = 261 R.get().getValueForSite(IPVK_IndirectCallTarget, 0); 262 ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee3")); 263 ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee2")); 264 ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee1")); 265 266 // Restore little endian default: 267 Writer.setValueProfDataEndianness(support::little); 268 } 269 270 TEST_F(InstrProfTest, get_icall_data_merge1) { 271 static const char caller[] = "caller"; 272 static const char callee1[] = "callee1"; 273 static const char callee2[] = "callee2"; 274 static const char callee3[] = "callee3"; 275 static const char callee4[] = "callee4"; 276 277 InstrProfRecord Record11(caller, 0x1234, {1, 2}); 278 InstrProfRecord Record12(caller, 0x1234, {1, 2}); 279 InstrProfRecord Record2(callee1, 0x1235, {3, 4}); 280 InstrProfRecord Record3(callee2, 0x1235, {3, 4}); 281 InstrProfRecord Record4(callee3, 0x1235, {3, 4}); 282 InstrProfRecord Record5(callee3, 0x1235, {3, 4}); 283 InstrProfRecord Record6(callee4, 0x1235, {3, 5}); 284 285 // 5 value sites. 286 Record11.reserveSites(IPVK_IndirectCallTarget, 5); 287 InstrProfValueData VD0[] = {{uint64_t(callee1), 1}, 288 {uint64_t(callee2), 2}, 289 {uint64_t(callee3), 3}, 290 {uint64_t(callee4), 4}}; 291 Record11.addValueData(IPVK_IndirectCallTarget, 0, VD0, 4, nullptr); 292 293 // No value profile data at the second site. 294 Record11.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr); 295 296 InstrProfValueData VD2[] = { 297 {uint64_t(callee1), 1}, {uint64_t(callee2), 2}, {uint64_t(callee3), 3}}; 298 Record11.addValueData(IPVK_IndirectCallTarget, 2, VD2, 3, nullptr); 299 300 InstrProfValueData VD3[] = {{uint64_t(callee1), 1}}; 301 Record11.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr); 302 303 InstrProfValueData VD4[] = {{uint64_t(callee1), 1}, 304 {uint64_t(callee2), 2}, 305 {uint64_t(callee3), 3}}; 306 Record11.addValueData(IPVK_IndirectCallTarget, 4, VD4, 3, nullptr); 307 308 // A differnt record for the same caller. 309 Record12.reserveSites(IPVK_IndirectCallTarget, 5); 310 InstrProfValueData VD02[] = {{uint64_t(callee2), 5}, {uint64_t(callee3), 3}}; 311 Record12.addValueData(IPVK_IndirectCallTarget, 0, VD02, 2, nullptr); 312 313 // No value profile data at the second site. 314 Record12.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr); 315 316 InstrProfValueData VD22[] = { 317 {uint64_t(callee2), 1}, {uint64_t(callee3), 3}, {uint64_t(callee4), 4}}; 318 Record12.addValueData(IPVK_IndirectCallTarget, 2, VD22, 3, nullptr); 319 320 Record12.addValueData(IPVK_IndirectCallTarget, 3, nullptr, 0, nullptr); 321 322 InstrProfValueData VD42[] = {{uint64_t(callee1), 1}, 323 {uint64_t(callee2), 2}, 324 {uint64_t(callee3), 3}}; 325 Record12.addValueData(IPVK_IndirectCallTarget, 4, VD42, 3, nullptr); 326 327 Writer.addRecord(std::move(Record11)); 328 // Merge profile data. 329 Writer.addRecord(std::move(Record12)); 330 331 Writer.addRecord(std::move(Record2)); 332 Writer.addRecord(std::move(Record3)); 333 Writer.addRecord(std::move(Record4)); 334 Writer.addRecord(std::move(Record5)); 335 Writer.addRecord(std::move(Record6)); 336 auto Profile = Writer.writeBuffer(); 337 readProfile(std::move(Profile)); 338 339 ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234); 340 ASSERT_TRUE(NoError(R.getError())); 341 ASSERT_EQ(5U, R.get().getNumValueSites(IPVK_IndirectCallTarget)); 342 ASSERT_EQ(4U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 0)); 343 ASSERT_EQ(0U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 1)); 344 ASSERT_EQ(4U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 2)); 345 ASSERT_EQ(1U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 3)); 346 ASSERT_EQ(3U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 4)); 347 348 std::unique_ptr<InstrProfValueData[]> VD = 349 R.get().getValueForSite(IPVK_IndirectCallTarget, 0); 350 ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee2")); 351 ASSERT_EQ(7U, VD[0].Count); 352 ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee3")); 353 ASSERT_EQ(6U, VD[1].Count); 354 ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee4")); 355 ASSERT_EQ(4U, VD[2].Count); 356 ASSERT_EQ(StringRef((const char *)VD[3].Value, 7), StringRef("callee1")); 357 ASSERT_EQ(1U, VD[3].Count); 358 359 std::unique_ptr<InstrProfValueData[]> VD_2( 360 R.get().getValueForSite(IPVK_IndirectCallTarget, 2)); 361 ASSERT_EQ(StringRef((const char *)VD_2[0].Value, 7), StringRef("callee3")); 362 ASSERT_EQ(6U, VD_2[0].Count); 363 ASSERT_EQ(StringRef((const char *)VD_2[1].Value, 7), StringRef("callee4")); 364 ASSERT_EQ(4U, VD_2[1].Count); 365 ASSERT_EQ(StringRef((const char *)VD_2[2].Value, 7), StringRef("callee2")); 366 ASSERT_EQ(3U, VD_2[2].Count); 367 ASSERT_EQ(StringRef((const char *)VD_2[3].Value, 7), StringRef("callee1")); 368 ASSERT_EQ(1U, VD_2[3].Count); 369 370 std::unique_ptr<InstrProfValueData[]> VD_3( 371 R.get().getValueForSite(IPVK_IndirectCallTarget, 3)); 372 ASSERT_EQ(StringRef((const char *)VD_3[0].Value, 7), StringRef("callee1")); 373 ASSERT_EQ(1U, VD_3[0].Count); 374 375 std::unique_ptr<InstrProfValueData[]> VD_4( 376 R.get().getValueForSite(IPVK_IndirectCallTarget, 4)); 377 ASSERT_EQ(StringRef((const char *)VD_4[0].Value, 7), StringRef("callee3")); 378 ASSERT_EQ(6U, VD_4[0].Count); 379 ASSERT_EQ(StringRef((const char *)VD_4[1].Value, 7), StringRef("callee2")); 380 ASSERT_EQ(4U, VD_4[1].Count); 381 ASSERT_EQ(StringRef((const char *)VD_4[2].Value, 7), StringRef("callee1")); 382 ASSERT_EQ(2U, VD_4[2].Count); 383 } 384 385 TEST_F(InstrProfTest, get_icall_data_merge1_saturation) { 386 static const char bar[] = "bar"; 387 388 const uint64_t Max = std::numeric_limits<uint64_t>::max(); 389 390 InstrProfRecord Record1("foo", 0x1234, {1}); 391 auto Result1 = Writer.addRecord(std::move(Record1)); 392 ASSERT_EQ(Result1, instrprof_error::success); 393 394 // Verify counter overflow. 395 InstrProfRecord Record2("foo", 0x1234, {Max}); 396 auto Result2 = Writer.addRecord(std::move(Record2)); 397 ASSERT_EQ(Result2, instrprof_error::counter_overflow); 398 399 InstrProfRecord Record3(bar, 0x9012, {8}); 400 auto Result3 = Writer.addRecord(std::move(Record3)); 401 ASSERT_EQ(Result3, instrprof_error::success); 402 403 InstrProfRecord Record4("baz", 0x5678, {3, 4}); 404 Record4.reserveSites(IPVK_IndirectCallTarget, 1); 405 InstrProfValueData VD4[] = {{uint64_t(bar), 1}}; 406 Record4.addValueData(IPVK_IndirectCallTarget, 0, VD4, 1, nullptr); 407 auto Result4 = Writer.addRecord(std::move(Record4)); 408 ASSERT_EQ(Result4, instrprof_error::success); 409 410 // Verify value data counter overflow. 411 InstrProfRecord Record5("baz", 0x5678, {5, 6}); 412 Record5.reserveSites(IPVK_IndirectCallTarget, 1); 413 InstrProfValueData VD5[] = {{uint64_t(bar), Max}}; 414 Record5.addValueData(IPVK_IndirectCallTarget, 0, VD5, 1, nullptr); 415 auto Result5 = Writer.addRecord(std::move(Record5)); 416 ASSERT_EQ(Result5, instrprof_error::counter_overflow); 417 418 auto Profile = Writer.writeBuffer(); 419 readProfile(std::move(Profile)); 420 421 // Verify saturation of counts. 422 ErrorOr<InstrProfRecord> ReadRecord1 = 423 Reader->getInstrProfRecord("foo", 0x1234); 424 ASSERT_TRUE(NoError(ReadRecord1.getError())); 425 ASSERT_EQ(Max, ReadRecord1.get().Counts[0]); 426 427 ErrorOr<InstrProfRecord> ReadRecord2 = 428 Reader->getInstrProfRecord("baz", 0x5678); 429 ASSERT_EQ(1U, ReadRecord2.get().getNumValueSites(IPVK_IndirectCallTarget)); 430 std::unique_ptr<InstrProfValueData[]> VD = 431 ReadRecord2.get().getValueForSite(IPVK_IndirectCallTarget, 0); 432 ASSERT_EQ(StringRef("bar"), StringRef((const char *)VD[0].Value, 3)); 433 ASSERT_EQ(Max, VD[0].Count); 434 } 435 436 // This test tests that when there are too many values 437 // for a given site, the merged results are properly 438 // truncated. 439 TEST_F(InstrProfTest, get_icall_data_merge_site_trunc) { 440 static const char caller[] = "caller"; 441 442 InstrProfRecord Record11(caller, 0x1234, {1, 2}); 443 InstrProfRecord Record12(caller, 0x1234, {1, 2}); 444 445 // 2 value sites. 446 Record11.reserveSites(IPVK_IndirectCallTarget, 2); 447 InstrProfValueData VD0[255]; 448 for (int I = 0; I < 255; I++) { 449 VD0[I].Value = 2 * I; 450 VD0[I].Count = 2 * I + 1000; 451 } 452 453 Record11.addValueData(IPVK_IndirectCallTarget, 0, VD0, 255, nullptr); 454 Record11.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr); 455 456 Record12.reserveSites(IPVK_IndirectCallTarget, 2); 457 InstrProfValueData VD1[255]; 458 for (int I = 0; I < 255; I++) { 459 VD1[I].Value = 2 * I + 1; 460 VD1[I].Count = 2 * I + 1001; 461 } 462 463 Record12.addValueData(IPVK_IndirectCallTarget, 0, VD1, 255, nullptr); 464 Record12.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr); 465 466 Writer.addRecord(std::move(Record11)); 467 // Merge profile data. 468 Writer.addRecord(std::move(Record12)); 469 470 auto Profile = Writer.writeBuffer(); 471 readProfile(std::move(Profile)); 472 473 ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234); 474 ASSERT_TRUE(NoError(R.getError())); 475 std::unique_ptr<InstrProfValueData[]> VD( 476 R.get().getValueForSite(IPVK_IndirectCallTarget, 0)); 477 ASSERT_EQ(2U, R.get().getNumValueSites(IPVK_IndirectCallTarget)); 478 ASSERT_EQ(255U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 0)); 479 for (unsigned I = 0; I < 255; I++) { 480 ASSERT_EQ(VD[I].Value, 509 - I); 481 ASSERT_EQ(VD[I].Count, 1509 - I); 482 } 483 } 484 485 // Synthesize runtime value profile data. 486 ValueProfNode Site1Values[5] = {{{uint64_t("callee1"), 400}, &Site1Values[1]}, 487 {{uint64_t("callee2"), 1000}, &Site1Values[2]}, 488 {{uint64_t("callee3"), 500}, &Site1Values[3]}, 489 {{uint64_t("callee4"), 300}, &Site1Values[4]}, 490 {{uint64_t("callee5"), 100}, 0}}; 491 492 ValueProfNode Site2Values[4] = {{{uint64_t("callee5"), 800}, &Site2Values[1]}, 493 {{uint64_t("callee3"), 1000}, &Site2Values[2]}, 494 {{uint64_t("callee2"), 2500}, &Site2Values[3]}, 495 {{uint64_t("callee1"), 1300}, 0}}; 496 497 ValueProfNode Site3Values[3] = {{{uint64_t("callee6"), 800}, &Site3Values[1]}, 498 {{uint64_t("callee3"), 1000}, &Site3Values[2]}, 499 {{uint64_t("callee4"), 5500}, 0}}; 500 501 ValueProfNode Site4Values[2] = {{{uint64_t("callee2"), 1800}, &Site4Values[1]}, 502 {{uint64_t("callee3"), 2000}, 0}}; 503 504 static ValueProfNode *ValueProfNodes[5] = {&Site1Values[0], &Site2Values[0], 505 &Site3Values[0], &Site4Values[0], 0}; 506 static uint16_t NumValueSites[IPVK_Last + 1] = {5}; 507 TEST_F(InstrProfTest, runtime_value_prof_data_read_write) { 508 ValueProfRuntimeRecord RTRecord; 509 initializeValueProfRuntimeRecord(&RTRecord, &NumValueSites[0], 510 &ValueProfNodes[0]); 511 512 ValueProfData *VPData = serializeValueProfDataFromRT(&RTRecord, nullptr); 513 514 InstrProfRecord Record("caller", 0x1234, {1ULL << 31, 2}); 515 516 VPData->deserializeTo(Record, 0); 517 518 // Now read data from Record and sanity check the data 519 ASSERT_EQ(5U, Record.getNumValueSites(IPVK_IndirectCallTarget)); 520 ASSERT_EQ(5U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 0)); 521 ASSERT_EQ(4U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 1)); 522 ASSERT_EQ(3U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 2)); 523 ASSERT_EQ(2U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 3)); 524 ASSERT_EQ(0U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 4)); 525 526 auto Cmp = [](const InstrProfValueData &VD1, const InstrProfValueData &VD2) { 527 return VD1.Count > VD2.Count; 528 }; 529 std::unique_ptr<InstrProfValueData[]> VD_0( 530 Record.getValueForSite(IPVK_IndirectCallTarget, 0)); 531 std::sort(&VD_0[0], &VD_0[5], Cmp); 532 ASSERT_EQ(StringRef((const char *)VD_0[0].Value, 7), StringRef("callee2")); 533 ASSERT_EQ(1000U, VD_0[0].Count); 534 ASSERT_EQ(StringRef((const char *)VD_0[1].Value, 7), StringRef("callee3")); 535 ASSERT_EQ(500U, VD_0[1].Count); 536 ASSERT_EQ(StringRef((const char *)VD_0[2].Value, 7), StringRef("callee1")); 537 ASSERT_EQ(400U, VD_0[2].Count); 538 ASSERT_EQ(StringRef((const char *)VD_0[3].Value, 7), StringRef("callee4")); 539 ASSERT_EQ(300U, VD_0[3].Count); 540 ASSERT_EQ(StringRef((const char *)VD_0[4].Value, 7), StringRef("callee5")); 541 ASSERT_EQ(100U, VD_0[4].Count); 542 543 std::unique_ptr<InstrProfValueData[]> VD_1( 544 Record.getValueForSite(IPVK_IndirectCallTarget, 1)); 545 std::sort(&VD_1[0], &VD_1[4], Cmp); 546 ASSERT_EQ(StringRef((const char *)VD_1[0].Value, 7), StringRef("callee2")); 547 ASSERT_EQ(2500U, VD_1[0].Count); 548 ASSERT_EQ(StringRef((const char *)VD_1[1].Value, 7), StringRef("callee1")); 549 ASSERT_EQ(1300U, VD_1[1].Count); 550 ASSERT_EQ(StringRef((const char *)VD_1[2].Value, 7), StringRef("callee3")); 551 ASSERT_EQ(1000U, VD_1[2].Count); 552 ASSERT_EQ(StringRef((const char *)VD_1[3].Value, 7), StringRef("callee5")); 553 ASSERT_EQ(800U, VD_1[3].Count); 554 555 std::unique_ptr<InstrProfValueData[]> VD_2( 556 Record.getValueForSite(IPVK_IndirectCallTarget, 2)); 557 std::sort(&VD_2[0], &VD_2[3], Cmp); 558 ASSERT_EQ(StringRef((const char *)VD_2[0].Value, 7), StringRef("callee4")); 559 ASSERT_EQ(5500U, VD_2[0].Count); 560 ASSERT_EQ(StringRef((const char *)VD_2[1].Value, 7), StringRef("callee3")); 561 ASSERT_EQ(1000U, VD_2[1].Count); 562 ASSERT_EQ(StringRef((const char *)VD_2[2].Value, 7), StringRef("callee6")); 563 ASSERT_EQ(800U, VD_2[2].Count); 564 565 std::unique_ptr<InstrProfValueData[]> VD_3( 566 Record.getValueForSite(IPVK_IndirectCallTarget, 3)); 567 std::sort(&VD_3[0], &VD_3[2], Cmp); 568 ASSERT_EQ(StringRef((const char *)VD_3[0].Value, 7), StringRef("callee3")); 569 ASSERT_EQ(2000U, VD_3[0].Count); 570 ASSERT_EQ(StringRef((const char *)VD_3[1].Value, 7), StringRef("callee2")); 571 ASSERT_EQ(1800U, VD_3[1].Count); 572 573 finalizeValueProfRuntimeRecord(&RTRecord); 574 free(VPData); 575 } 576 577 TEST_F(InstrProfTest, get_max_function_count) { 578 InstrProfRecord Record1("foo", 0x1234, {1ULL << 31, 2}); 579 InstrProfRecord Record2("bar", 0, {1ULL << 63}); 580 InstrProfRecord Record3("baz", 0x5678, {0, 0, 0, 0}); 581 Writer.addRecord(std::move(Record1)); 582 Writer.addRecord(std::move(Record2)); 583 Writer.addRecord(std::move(Record3)); 584 auto Profile = Writer.writeBuffer(); 585 readProfile(std::move(Profile)); 586 587 ASSERT_EQ(1ULL << 63, Reader->getMaximumFunctionCount()); 588 } 589 590 TEST_F(InstrProfTest, get_weighted_function_counts) { 591 InstrProfRecord Record1("foo", 0x1234, {1, 2}); 592 InstrProfRecord Record2("foo", 0x1235, {3, 4}); 593 Writer.addRecord(std::move(Record1), 3); 594 Writer.addRecord(std::move(Record2), 5); 595 auto Profile = Writer.writeBuffer(); 596 readProfile(std::move(Profile)); 597 598 std::vector<uint64_t> Counts; 599 ASSERT_TRUE(NoError(Reader->getFunctionCounts("foo", 0x1234, Counts))); 600 ASSERT_EQ(2U, Counts.size()); 601 ASSERT_EQ(3U, Counts[0]); 602 ASSERT_EQ(6U, Counts[1]); 603 604 ASSERT_TRUE(NoError(Reader->getFunctionCounts("foo", 0x1235, Counts))); 605 ASSERT_EQ(2U, Counts.size()); 606 ASSERT_EQ(15U, Counts[0]); 607 ASSERT_EQ(20U, Counts[1]); 608 } 609 610 TEST_F(InstrProfTest, instr_prof_symtab_test) { 611 std::vector<StringRef> FuncNames; 612 FuncNames.push_back("func1"); 613 FuncNames.push_back("func2"); 614 FuncNames.push_back("func3"); 615 FuncNames.push_back("bar1"); 616 FuncNames.push_back("bar2"); 617 FuncNames.push_back("bar3"); 618 InstrProfSymtab Symtab; 619 Symtab.create(FuncNames); 620 StringRef R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func1")); 621 ASSERT_EQ(StringRef("func1"), R); 622 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func2")); 623 ASSERT_EQ(StringRef("func2"), R); 624 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func3")); 625 ASSERT_EQ(StringRef("func3"), R); 626 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar1")); 627 ASSERT_EQ(StringRef("bar1"), R); 628 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar2")); 629 ASSERT_EQ(StringRef("bar2"), R); 630 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar3")); 631 ASSERT_EQ(StringRef("bar3"), R); 632 633 // Now incrementally update the symtab 634 Symtab.addFuncName("blah_1"); 635 Symtab.addFuncName("blah_2"); 636 Symtab.addFuncName("blah_3"); 637 // Finalize it 638 Symtab.finalizeSymtab(); 639 640 // Check again 641 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("blah_1")); 642 ASSERT_EQ(StringRef("blah_1"), R); 643 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("blah_2")); 644 ASSERT_EQ(StringRef("blah_2"), R); 645 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("blah_3")); 646 ASSERT_EQ(StringRef("blah_3"), R); 647 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func1")); 648 ASSERT_EQ(StringRef("func1"), R); 649 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func2")); 650 ASSERT_EQ(StringRef("func2"), R); 651 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func3")); 652 ASSERT_EQ(StringRef("func3"), R); 653 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar1")); 654 ASSERT_EQ(StringRef("bar1"), R); 655 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar2")); 656 ASSERT_EQ(StringRef("bar2"), R); 657 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar3")); 658 ASSERT_EQ(StringRef("bar3"), R); 659 } 660 661 TEST_F(InstrProfTest, instr_prof_symtab_compression_test) { 662 std::vector<std::string> FuncNames1; 663 std::vector<std::string> FuncNames2; 664 for (int I = 0; I < 10 * 1024; I++) { 665 std::string str; 666 raw_string_ostream OS(str); 667 OS << "func_" << I; 668 FuncNames1.push_back(OS.str()); 669 str.clear(); 670 OS << "fooooooooooooooo_" << I; 671 FuncNames1.push_back(OS.str()); 672 str.clear(); 673 OS << "BAR_" << I; 674 FuncNames2.push_back(OS.str()); 675 str.clear(); 676 OS << "BlahblahBlahblahBar_" << I; 677 FuncNames2.push_back(OS.str()); 678 } 679 680 for (int Padding = 0; Padding < 10; Padding++) { 681 for (int DoCompression = 0; DoCompression < 2; DoCompression++) { 682 // Compressing: 683 std::string FuncNameStrings1; 684 collectPGOFuncNameStrings(FuncNames1, 685 (DoCompression != 0 && zlib::isAvailable()), 686 FuncNameStrings1); 687 688 // Compressing: 689 std::string FuncNameStrings2; 690 collectPGOFuncNameStrings(FuncNames2, 691 (DoCompression != 0 && zlib::isAvailable()), 692 FuncNameStrings2); 693 694 // Join with paddings: 695 std::string FuncNameStrings = FuncNameStrings1; 696 for (int P = 0; P < Padding; P++) { 697 FuncNameStrings.push_back('\0'); 698 } 699 FuncNameStrings += FuncNameStrings2; 700 701 // Now decompress: 702 InstrProfSymtab Symtab; 703 Symtab.create(StringRef(FuncNameStrings)); 704 705 // Now do the checks: 706 // First sampling some data points: 707 StringRef R = Symtab.getFuncName(IndexedInstrProf::ComputeHash(FuncNames1[0])); 708 ASSERT_EQ(StringRef("func_0"), R); 709 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash(FuncNames1[1])); 710 ASSERT_EQ(StringRef("fooooooooooooooo_0"), R); 711 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash(FuncNames1[998])); 712 ASSERT_EQ(StringRef("func_499"), R); 713 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash(FuncNames1[999])); 714 ASSERT_EQ(StringRef("fooooooooooooooo_499"), R); 715 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash(FuncNames2[100])); 716 ASSERT_EQ(StringRef("BAR_50"), R); 717 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash(FuncNames2[101])); 718 ASSERT_EQ(StringRef("BlahblahBlahblahBar_50"), R); 719 for (int I = 0; I < 10 * 1024; I++) { 720 std::string N[4]; 721 N[0] = FuncNames1[2 * I]; 722 N[1] = FuncNames1[2 * I + 1]; 723 N[2] = FuncNames2[2 * I]; 724 N[3] = FuncNames2[2 * I + 1]; 725 for (int J = 0; J < 4; J++) { 726 StringRef R = Symtab.getFuncName(IndexedInstrProf::ComputeHash(N[J])); 727 ASSERT_EQ(StringRef(N[J]), R); 728 } 729 } 730 } 731 } 732 } 733 734 } // end anonymous namespace 735