llvm.org GIT mirror llvm / 6667715
[InstrProf] Support for external functions in text format. Summary: External functions appearing as indirect call targets could not be found in the SymTab, and the value:counter record was represented, in the text format, using an empty string for the name. This would then cause a silent parsing error when reading. This CL: - adds explicit support for such functions - fixes the places where we would not propagate errors when reading - addresses a performance issue due to eager resorting of the SymTab. Reviewers: xur, eraman, davidxl Reviewed By: davidxl Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D44717 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@328132 91177308-0d34-0410-b5e6-96231b3b80d8 Mircea Trofin 1 year, 6 months ago
7 changed file(s) with 106 addition(s) and 32 deletion(s). Raw diff Collapse all Expand all
424424 // A map from function runtime address to function name MD5 hash.
425425 // This map is only populated and used by raw instr profile reader.
426426 AddrHashMap AddrToMD5Map;
427 bool Sorted = false;
428
429 static StringRef getExternalSymbol() {
430 return "** External Symbol **";
431 }
432
433 // If the symtab is created by a series of calls to \c addFuncName, \c
434 // finalizeSymtab needs to be called before looking up function names.
435 // This is required because the underlying map is a vector (for space
436 // efficiency) which needs to be sorted.
437 inline void finalizeSymtab();
427438
428439 public:
429 InstrProfSymtab() = default;
440 InstrProfSymtab() = default;
430441
431442 /// Create InstrProfSymtab from an object file section which
432443 /// contains function PGO names. When section may contain raw
455466 /// \p IterRange. This interface is used by IndexedProfReader.
456467 template Error create(const NameIterRange &IterRange);
457468
458 // If the symtab is created by a series of calls to \c addFuncName, \c
459 // finalizeSymtab needs to be called before looking up function names.
460 // This is required because the underlying map is a vector (for space
461 // efficiency) which needs to be sorted.
462 inline void finalizeSymtab();
463
464469 /// Update the symtab by adding \p FuncName to the table. This interface
465470 /// is used by the raw and text profile readers.
466471 Error addFuncName(StringRef FuncName) {
467472 if (FuncName.empty())
468473 return make_error(instrprof_error::malformed);
469474 auto Ins = NameTab.insert(FuncName);
470 if (Ins.second)
475 if (Ins.second) {
471476 MD5NameMap.push_back(std::make_pair(
472477 IndexedInstrProf::ComputeHash(FuncName), Ins.first->getKey()));
478 Sorted = false;
479 }
473480 return Error::success();
474481 }
475482
489496 /// Return function's PGO name from the name's md5 hash value.
490497 /// If not found, return an empty string.
491498 inline StringRef getFuncName(uint64_t FuncMD5Hash);
499
500 /// Just like getFuncName, except that it will return a non-empty StringRef
501 /// if the function is external to this symbol table. All such cases
502 /// will be represented using the same StringRef value.
503 inline StringRef getFuncNameOrExternalSymbol(uint64_t FuncMD5Hash);
504
505 /// True if Symbol is the value used to represent external symbols.
506 static bool isExternalSymbol(const StringRef &Symbol) {
507 return Symbol == InstrProfSymtab::getExternalSymbol();
508 }
492509
493510 /// Return function from the name's md5 hash. Return nullptr if not found.
494511 inline Function *getFunction(uint64_t FuncMD5Hash);
523540 }
524541
525542 void InstrProfSymtab::finalizeSymtab() {
543 if (Sorted)
544 return;
526545 std::sort(MD5NameMap.begin(), MD5NameMap.end(), less_first());
527546 std::sort(MD5FuncMap.begin(), MD5FuncMap.end(), less_first());
528547 std::sort(AddrToMD5Map.begin(), AddrToMD5Map.end(), less_first());
529548 AddrToMD5Map.erase(std::unique(AddrToMD5Map.begin(), AddrToMD5Map.end()),
530549 AddrToMD5Map.end());
550 Sorted = true;
551 }
552
553 StringRef InstrProfSymtab::getFuncNameOrExternalSymbol(uint64_t FuncMD5Hash) {
554 StringRef ret = getFuncName(FuncMD5Hash);
555 if (ret.empty())
556 return InstrProfSymtab::getExternalSymbol();
557 return ret;
531558 }
532559
533560 StringRef InstrProfSymtab::getFuncName(uint64_t FuncMD5Hash) {
561 finalizeSymtab();
534562 auto Result =
535563 std::lower_bound(MD5NameMap.begin(), MD5NameMap.end(), FuncMD5Hash,
536564 [](const std::pair &LHS,
541569 }
542570
543571 Function* InstrProfSymtab::getFunction(uint64_t FuncMD5Hash) {
572 finalizeSymtab();
544573 auto Result =
545574 std::lower_bound(MD5FuncMap.begin(), MD5FuncMap.end(), FuncMD5Hash,
546575 [](const std::pair &LHS,
100100 return make_error(Err);
101101 }
102102
103 Error error(Error E) { return error(InstrProfError::take(std::move(E))); }
103 Error error(Error &&E) { return error(InstrProfError::take(std::move(E))); }
104104
105105 /// Clear the current error and return a successful one.
106106 Error success() { return error(instrprof_error::success); }
354354 }
355355 }
356356 }
357
357 Sorted = false;
358358 finalizeSymtab();
359359 return Error::success();
360360 }
460460 while (P < EndP && *P == 0)
461461 P++;
462462 }
463 Symtab.finalizeSymtab();
464463 return Error::success();
465464 }
466465
199199 std::pair VD = Line->rsplit(':');
200200 uint64_t TakenCount, Value;
201201 if (ValueKind == IPVK_IndirectCallTarget) {
202 if (Error E = Symtab->addFuncName(VD.first))
203 return E;
204 Value = IndexedInstrProf::ComputeHash(VD.first);
202 if (InstrProfSymtab::isExternalSymbol(VD.first)) {
203 Value = 0;
204 } else {
205 if (Error E = Symtab->addFuncName(VD.first))
206 return E;
207 Value = IndexedInstrProf::ComputeHash(VD.first);
208 }
205209 } else {
206210 READ_NUM(VD.first, Value);
207211 }
226230 ++Line;
227231 // If we hit EOF while looking for a name, we're done.
228232 if (Line.is_at_end()) {
229 Symtab->finalizeSymtab();
230233 return error(instrprof_error::eof);
231234 }
232235
233236 // Read the function name.
234237 Record.Name = *Line++;
235238 if (Error E = Symtab->addFuncName(Record.Name))
236 return E;
239 return error(std::move(E));
237240
238241 // Read the function hash.
239242 if (Line.is_at_end())
264267
265268 // Check if value profile data exists and read it if so.
266269 if (Error E = readValueProfileData(Record))
267 return E;
268
269 // This is needed to avoid two pass parsing because llvm-profdata
270 // does dumping while reading.
271 Symtab->finalizeSymtab();
270 return error(std::move(E));
271
272272 return success();
273273 }
274274
330330 continue;
331331 Symtab.mapAddress(FPtr, I->NameRef);
332332 }
333 Symtab.finalizeSymtab();
334333 return success();
335334 }
336335
448447 if (atEnd())
449448 // At this point, ValueDataStart field points to the next header.
450449 if (Error E = readNextHeader(getNextHeaderPos()))
451 return E;
450 return error(std::move(E));
452451
453452 // Read name ad set it in Record.
454453 if (Error E = readName(Record))
455 return E;
454 return error(std::move(E));
456455
457456 // Read FuncHash and set it in Record.
458457 if (Error E = readFuncHash(Record))
459 return E;
458 return error(std::move(E));
460459
461460 // Read raw counts and set Record.
462461 if (Error E = readRawCounts(Record))
463 return E;
462 return error(std::move(E));
464463
465464 // Read value data and set Record.
466465 if (Error E = readValueProfilingData(Record))
467 return E;
466 return error(std::move(E));
468467
469468 // Iterate.
470469 advanceData();
360360 std::unique_ptr VD = Func.getValueForSite(VK, S);
361361 for (uint32_t I = 0; I < ND; I++) {
362362 if (VK == IPVK_IndirectCallTarget)
363 OS << Symtab.getFuncName(VD[I].Value) << ":" << VD[I].Count << "\n";
363 OS << Symtab.getFuncNameOrExternalSymbol(VD[I].Value) << ":"
364 << VD[I].Count << "\n";
364365 else
365366 OS << VD[I].Value << ":" << VD[I].Count << "\n";
366367 }
378379 if (shouldEncodeData(I.getValue()))
379380 if (Error E = Symtab.addFuncName(I.getKey()))
380381 return E;
381 Symtab.finalizeSymtab();
382382
383383 for (const auto &I : FunctionData)
384384 if (shouldEncodeData(I.getValue()))
0 RUN: echo ":ir" > %t.input
1 RUN: echo "_ZN6Thread5StartEv" >> %t.input
2 RUN: echo "# Func Hash:" >> %t.input
3 RUN: echo "288793635542036872" >> %t.input
4 RUN: echo "# Num Counters:" >> %t.input
5 RUN: echo "3" >> %t.input
6 RUN: echo "# Counter Values:" >> %t.input
7 RUN: echo "0" >> %t.input
8 RUN: echo "12" >> %t.input
9 RUN: echo "12" >> %t.input
10 RUN: echo "# Num Value Kinds:" >> %t.input
11 RUN: echo "1" >> %t.input
12 RUN: echo "# ValueKind = IPVK_IndirectCallTarget:" >> %t.input
13 RUN: echo "0" >> %t.input
14 RUN: echo "# NumValueSites:" >> %t.input
15 RUN: echo "2" >> %t.input
16 RUN: echo "2" >> %t.input
17 RUN: echo "f1:10" >> %t.input
18 RUN: echo "f2:0" >> %t.input
19 RUN: echo "1" >> %t.input
20 RUN: echo ":10" >> %t.input
21
22 RUN: not llvm-profdata merge %t.input -text -output=/dev/null 2>&1 | FileCheck %s --check-prefix=BROKEN
23 BROKEN: Malformed instrumentation profile data
24
25 RUN: echo ":ir" > %t.input
26 RUN: echo "_ZN6Thread5StartEv" >> %t.input
27 RUN: echo "# Func Hash:" >> %t.input
28 RUN: echo "288793635542036872" >> %t.input
29 RUN: echo "# Num Counters:" >> %t.input
30 RUN: echo "3" >> %t.input
31 RUN: echo "# Counter Values:" >> %t.input
32 RUN: echo "0" >> %t.input
33 RUN: echo "12" >> %t.input
34 RUN: echo "12" >> %t.input
35 RUN: echo "# Num Value Kinds:" >> %t.input
36 RUN: echo "1" >> %t.input
37 RUN: echo "# ValueKind = IPVK_IndirectCallTarget:" >> %t.input
38 RUN: echo "0" >> %t.input
39 RUN: echo "# NumValueSites:" >> %t.input
40 RUN: echo "2" >> %t.input
41 RUN: echo "2" >> %t.input
42 RUN: echo "f1:10" >> %t.input
43 RUN: echo "f2:0" >> %t.input
44 RUN: echo "1" >> %t.input
45 RUN: echo "** External Symbol **:10" >> %t.input
46
47 # RUN: llvm-profdata merge %t.input -text -output=%t.out && cat %t.out | FileCheck %s
48
49 CHECK: ** External Symbol **:10
768768 Symtab.mapAddress(uint64_t(callee3), 0x3000ULL);
769769 Symtab.mapAddress(uint64_t(callee4), 0x4000ULL);
770770 // Missing mapping for callee5
771 Symtab.finalizeSymtab();
772771
773772 VPData->deserializeTo(Record, &Symtab.getAddrHashMap());
774773
857856 EXPECT_THAT_ERROR(Symtab.addFuncName("blah_1"), Succeeded());
858857 EXPECT_THAT_ERROR(Symtab.addFuncName("blah_2"), Succeeded());
859858 EXPECT_THAT_ERROR(Symtab.addFuncName("blah_3"), Succeeded());
860 // Finalize it
861 Symtab.finalizeSymtab();
862859
863860 // Check again
864861 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("blah_1"));