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