llvm.org GIT mirror llvm / 5af7fe3
[PGO] Context sensitive PGO (part 2) Part 2 of CSPGO changes (mostly related to ProfileSummary). Note that I use a default parameter in setProfileSummary() and getSummary(). This is to break the dependency in clang. I will make the parameter explicit after changing clang in a separated patch. Differential Revision: https://reviews.llvm.org/D54175 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@355131 91177308-0d34-0410-b5e6-96231b3b80d8 Rong Xu 1 year, 8 months ago
17 changed file(s) with 185 addition(s) and 50 deletion(s). Raw diff Collapse all Expand all
225225 Only output names of functions whose max count value are below the cutoff
226226 value.
227227
228 .. option:: -showcs
229 Only show context sensitive profile counts. The default is to filter all
230 context sensitive profile counts.
231
228232 EXIT STATUS
229233 -----------
230234
7070 bool hasInstrumentationProfile() {
7171 return hasProfileSummary() &&
7272 Summary->getKind() == ProfileSummary::PSK_Instr;
73 }
74
75 /// Returns true if module \c M has context sensitive instrumentation profile.
76 bool hasCSInstrumentationProfile() {
77 return hasProfileSummary() &&
78 Summary->getKind() == ProfileSummary::PSK_CSInstr;
7379 }
7480
7581 /// Handle the invalidation of this information.
2727 #include "llvm/IR/GlobalIFunc.h"
2828 #include "llvm/IR/GlobalVariable.h"
2929 #include "llvm/IR/Metadata.h"
30 #include "llvm/IR/ProfileSummary.h"
3031 #include "llvm/IR/SymbolTableListTraits.h"
3132 #include "llvm/Support/CBindingWrapping.h"
3233 #include "llvm/Support/CodeGen.h"
867868 /// @{
868869
869870 /// Attach profile summary metadata to this module.
870 void setProfileSummary(Metadata *M);
871
872 /// Returns profile summary metadata
873 Metadata *getProfileSummary();
871 // TODO: Remove the default paramter.
872 void setProfileSummary(Metadata *M,
873 ProfileSummary::Kind Kind = ProfileSummary::PSK_Instr);
874
875 /// Returns profile summary metadata. When IsCS is true, use the context
876 /// sensitive profile summary.
877 Metadata *getProfileSummary(bool IsCS);
874878 /// @}
875879
876880 /// Returns true if PLT should be avoided for RTLib calls.
4141
4242 class ProfileSummary {
4343 public:
44 enum Kind { PSK_Instr, PSK_Sample };
44 enum Kind { PSK_Instr, PSK_CSInstr, PSK_Sample };
4545
4646 private:
4747 const Kind PSK;
48 static const char *KindStr[2];
4948 SummaryEntryVector DetailedSummary;
5049 uint64_t TotalCount, MaxCount, MaxInternalCount, MaxFunctionCount;
5150 uint32_t NumCounts, NumFunctions;
7676
7777 virtual bool isIRLevelProfile() const = 0;
7878
79 virtual bool hasCSIRLevelProfile() const = 0;
80
7981 /// Return the PGO symtab. There are three different readers:
8082 /// Raw, Text, and Indexed profile readers. The first two types
8183 /// of readers are used only by llvm-profdata tool, while the indexed
141143 /// Iterator over the profile data.
142144 line_iterator Line;
143145 bool IsIRLevelProfile = false;
146 bool HasCSIRLevelProfile = false;
144147
145148 Error readValueProfileData(InstrProfRecord &Record);
146149
154157 static bool hasFormat(const MemoryBuffer &Buffer);
155158
156159 bool isIRLevelProfile() const override { return IsIRLevelProfile; }
160
161 bool hasCSIRLevelProfile() const override { return HasCSIRLevelProfile; }
157162
158163 /// Read the header.
159164 Error readHeader() override;
211216 return (Version & VARIANT_MASK_IR_PROF) != 0;
212217 }
213218
219 bool hasCSIRLevelProfile() const override {
220 return (Version & VARIANT_MASK_CSIR_PROF) != 0;
221 }
222
214223 InstrProfSymtab &getSymtab() override {
215224 assert(Symtab.get());
216225 return *Symtab.get();
340349 virtual void setValueProfDataEndianness(support::endianness Endianness) = 0;
341350 virtual uint64_t getVersion() const = 0;
342351 virtual bool isIRLevelProfile() const = 0;
352 virtual bool hasCSIRLevelProfile() const = 0;
343353 virtual Error populateSymtab(InstrProfSymtab &) = 0;
344354 };
345355
382392
383393 bool isIRLevelProfile() const override {
384394 return (FormatVersion & VARIANT_MASK_IR_PROF) != 0;
395 }
396
397 bool hasCSIRLevelProfile() const override {
398 return (FormatVersion & VARIANT_MASK_CSIR_PROF) != 0;
385399 }
386400
387401 Error populateSymtab(InstrProfSymtab &Symtab) override {
411425 std::unique_ptr Remapper;
412426 /// Profile summary data.
413427 std::unique_ptr Summary;
428 /// Context sensitive profile summary data.
429 std::unique_ptr CS_Summary;
414430 // Index to the current record in the record array.
415431 unsigned RecordIndex;
416432
417433 // Read the profile summary. Return a pointer pointing to one byte past the
418434 // end of the summary data if it exists or the input \c Cur.
435 // \c UseCS indicates whether to use the context-sensitive profile summary.
419436 const unsigned char *readSummary(IndexedInstrProf::ProfVersion Version,
420 const unsigned char *Cur);
437 const unsigned char *Cur, bool UseCS);
421438
422439 public:
423440 IndexedInstrProfReader(
431448 /// Return the profile version.
432449 uint64_t getVersion() const { return Index->getVersion(); }
433450 bool isIRLevelProfile() const override { return Index->isIRLevelProfile(); }
451 bool hasCSIRLevelProfile() const override {
452 return Index->hasCSIRLevelProfile();
453 }
434454
435455 /// Return true if the given buffer is in an indexed instrprof format.
436456 static bool hasFormat(const MemoryBuffer &DataBuffer);
449469 std::vector &Counts);
450470
451471 /// Return the maximum of all known function counts.
452 uint64_t getMaximumFunctionCount() { return Summary->getMaxFunctionCount(); }
472 /// \c UseCS indicates whether to use the context-sensitive count.
473 uint64_t getMaximumFunctionCount(bool UseCS) {
474 if (UseCS) {
475 assert(CS_Summary && "No context sensitive profile summary");
476 return CS_Summary->getMaxFunctionCount();
477 } else {
478 assert(Summary && "No profile summary");
479 return Summary->getMaxFunctionCount();
480 }
481 }
453482
454483 /// Factory method to create an indexed reader.
455484 static Expected>
468497 // to be used by llvm-profdata (for dumping). Avoid using this when
469498 // the client is the compiler.
470499 InstrProfSymtab &getSymtab() override;
471 ProfileSummary &getSummary() { return *(Summary.get()); }
500
501 /// Return the profile summary.
502 /// \c UseCS indicates whether to use the context-sensitive summary.
503 // TODO: removed the defualt parameter.
504 ProfileSummary &getSummary(bool UseCS = false) {
505 if (UseCS) {
506 assert(CS_Summary && "No context sensitive summary");
507 return *(CS_Summary.get());
508 } else {
509 assert(Summary && "No profile summary");
510 return *(Summary.get());
511 }
512 }
472513 };
473514
474515 } // end namespace llvm
3232 class InstrProfWriter {
3333 public:
3434 using ProfilingData = SmallDenseMap;
35 enum ProfKind { PF_Unknown = 0, PF_FE, PF_IRLevel };
35 // PF_IRLevelWithCS is the profile from context sensitive IR instrumentation.
36 enum ProfKind { PF_Unknown = 0, PF_FE, PF_IRLevel, PF_IRLevelWithCS };
3637
3738 private:
3839 bool Sparse;
7374 std::unique_ptr writeBuffer();
7475
7576 /// Set the ProfileKind. Report error if mixing FE and IR level profiles.
76 Error setIsIRLevelProfile(bool IsIRLevel) {
77 /// \c WithCS indicates if this is for contenxt sensitive instrumentation.
78 Error setIsIRLevelProfile(bool IsIRLevel, bool WithCS) {
7779 if (ProfileKind == PF_Unknown) {
78 ProfileKind = IsIRLevel ? PF_IRLevel: PF_FE;
80 if (IsIRLevel)
81 ProfileKind = WithCS ? PF_IRLevelWithCS : PF_IRLevel;
82 else
83 ProfileKind = PF_FE;
7984 return Error::success();
8085 }
81 return (IsIRLevel == (ProfileKind == PF_IRLevel))
82 ? Error::success()
83 : make_error(
84 instrprof_error::unsupported_version);
86
87 if (((ProfileKind != PF_FE) && !IsIRLevel) ||
88 ((ProfileKind == PF_FE) && IsIRLevel))
89 return make_error(instrprof_error::unsupported_version);
90
91 // When merging a context-sensitive profile (WithCS == true) with an IRLevel
92 // profile, set the kind to PF_IRLevelWithCS.
93 if (ProfileKind == PF_IRLevel && WithCS)
94 ProfileKind = PF_IRLevelWithCS;
95
96 return Error::success();
8597 }
8698
8799 // Internal interface for testing purpose only.
7878 bool ProfileSummaryInfo::computeSummary() {
7979 if (Summary)
8080 return true;
81 auto *SummaryMD = M.getProfileSummary();
81 // First try to get context sensitive ProfileSummary.
82 auto *SummaryMD = M.getProfileSummary(/* IsCS */ true);
83 if (SummaryMD) {
84 Summary.reset(ProfileSummary::getFromMD(SummaryMD));
85 return true;
86 }
87 // This will actually return PSK_Instr or PSK_Sample summary.
88 SummaryMD = M.getProfileSummary(/* IsCS */ false);
8289 if (!SummaryMD)
8390 return false;
8491 Summary.reset(ProfileSummary::getFromMD(SummaryMD));
530530 addModuleFlag(ModFlagBehavior::Error, "Code Model", CL);
531531 }
532532
533 void Module::setProfileSummary(Metadata *M) {
534 addModuleFlag(ModFlagBehavior::Error, "ProfileSummary", M);
535 }
536
537 Metadata *Module::getProfileSummary() {
538 return getModuleFlag("ProfileSummary");
533 void Module::setProfileSummary(Metadata *M, ProfileSummary::Kind Kind) {
534 if (Kind == ProfileSummary::PSK_CSInstr)
535 addModuleFlag(ModFlagBehavior::Error, "CSProfileSummary", M);
536 else
537 addModuleFlag(ModFlagBehavior::Error, "ProfileSummary", M);
538 }
539
540 Metadata *Module::getProfileSummary(bool IsCS) {
541 return (IsCS ? getModuleFlag("CSProfileSummary")
542 : getModuleFlag("ProfileSummary"));
539543 }
540544
541545 void Module::setOwnedMemoryBuffer(std::unique_ptr MB) {
1919 #include "llvm/Support/Casting.h"
2020
2121 using namespace llvm;
22
23 const char *ProfileSummary::KindStr[2] = {"InstrProf", "SampleProfile"};
2422
2523 // Return an MDTuple with two elements. The first element is a string Key and
2624 // the second is a uint64_t Value.
6765 // "SampleProfile"). The rest of the elements of the outer MDTuple are specific
6866 // to the kind of profile summary as returned by getFormatSpecificMD.
6967 Metadata *ProfileSummary::getMD(LLVMContext &Context) {
68 const char *KindStr[3] = {"InstrProf", "CSInstrProf", "SampleProfile"};
7069 Metadata *Components[] = {
7170 getKeyValMD(Context, "ProfileFormat", KindStr[PSK]),
7271 getKeyValMD(Context, "TotalCount", getTotalCount()),
152151 else if (isKeyValuePair(dyn_cast_or_null(FormatMD), "ProfileFormat",
153152 "InstrProf"))
154153 SummaryKind = PSK_Instr;
154 else if (isKeyValuePair(dyn_cast_or_null(FormatMD), "ProfileFormat",
155 "CSInstrProf"))
156 SummaryKind = PSK_CSInstr;
155157 else
156158 return nullptr;
157159
161161 IsIRInstr = true;
162162 else if (Str.equals_lower("fe"))
163163 IsIRInstr = false;
164 else
164 else if (Str.equals_lower("csir")) {
165 IsIRInstr = true;
166 HasCSIRLevelProfile = true;
167 } else
165168 return error(instrprof_error::bad_header);
166169
167170 ++Line;
732735
733736 const unsigned char *
734737 IndexedInstrProfReader::readSummary(IndexedInstrProf::ProfVersion Version,
735 const unsigned char *Cur) {
738 const unsigned char *Cur, bool UseCS) {
736739 using namespace IndexedInstrProf;
737740 using namespace support;
738741
759762 DetailedSummary.emplace_back((uint32_t)Ent.Cutoff, Ent.MinBlockCount,
760763 Ent.NumBlocks);
761764 }
765 std::unique_ptr &Summary =
766 UseCS ? this->CS_Summary : this->Summary;
767
762768 // initialize InstrProfSummary using the SummaryData from disk.
763 this->Summary = llvm::make_unique(
764 ProfileSummary::PSK_Instr, DetailedSummary,
765 SummaryData->get(Summary::TotalBlockCount),
769 Summary = llvm::make_unique(
770 UseCS ? ProfileSummary::PSK_CSInstr : ProfileSummary::PSK_Instr,
771 DetailedSummary, SummaryData->get(Summary::TotalBlockCount),
766772 SummaryData->get(Summary::MaxBlockCount),
767773 SummaryData->get(Summary::MaxInternalBlockCount),
768774 SummaryData->get(Summary::MaxFunctionCount),
804810 IndexedInstrProf::ProfVersion::CurrentVersion)
805811 return error(instrprof_error::unsupported_version);
806812
807 Cur = readSummary((IndexedInstrProf::ProfVersion)FormatVersion, Cur);
813 Cur = readSummary((IndexedInstrProf::ProfVersion)FormatVersion, Cur,
814 /* UseCS */ false);
815 if (Header->Version & VARIANT_MASK_CSIR_PROF)
816 Cur = readSummary((IndexedInstrProf::ProfVersion)FormatVersion, Cur,
817 /* UseCS */ true);
808818
809819 // Read the hash type and start offset.
810820 IndexedInstrProf::HashT HashType = static_cast(
100100
101101 support::endianness ValueProfDataEndianness = support::little;
102102 InstrProfSummaryBuilder *SummaryBuilder;
103 InstrProfSummaryBuilder *CSSummaryBuilder;
103104
104105 InstrProfRecordWriterTrait() = default;
105106
141142 endian::Writer LE(Out, little);
142143 for (const auto &ProfileData : *V) {
143144 const InstrProfRecord &ProfRecord = ProfileData.second;
144 SummaryBuilder->addRecord(ProfRecord);
145 if (NamedInstrProfRecord::hasCSFlagInHash(ProfileData.first))
146 CSSummaryBuilder->addRecord(ProfRecord);
147 else
148 SummaryBuilder->addRecord(ProfRecord);
145149
146150 LE.write(ProfileData.first); // Function hash
147151 LE.write(ProfRecord.Counts.size());
252256
253257 InstrProfSummaryBuilder ISB(ProfileSummaryBuilder::DefaultCutoffs);
254258 InfoObj->SummaryBuilder = &ISB;
259 InstrProfSummaryBuilder CSISB(ProfileSummaryBuilder::DefaultCutoffs);
260 InfoObj->CSSummaryBuilder = &CSISB;
255261
256262 // Populate the hash table generator.
257263 for (const auto &I : FunctionData)
263269 Header.Version = IndexedInstrProf::ProfVersion::CurrentVersion;
264270 if (ProfileKind == PF_IRLevel)
265271 Header.Version |= VARIANT_MASK_IR_PROF;
272 if (ProfileKind == PF_IRLevelWithCS) {
273 Header.Version |= VARIANT_MASK_IR_PROF;
274 Header.Version |= VARIANT_MASK_CSIR_PROF;
275 }
266276 Header.Unused = 0;
267277 Header.HashType = static_cast(IndexedInstrProf::HashType);
268278 Header.HashOffset = 0;
286296 uint64_t SummaryOffset = OS.tell();
287297 for (unsigned I = 0; I < SummarySize / sizeof(uint64_t); I++)
288298 OS.write(0);
299 uint64_t CSSummaryOffset = 0;
300 uint64_t CSSummarySize = 0;
301 if (ProfileKind == PF_IRLevelWithCS) {
302 CSSummaryOffset = OS.tell();
303 CSSummarySize = SummarySize / sizeof(uint64_t);
304 for (unsigned I = 0; I < CSSummarySize; I++)
305 OS.write(0);
306 }
289307
290308 // Write the hash table.
291309 uint64_t HashTableStart = Generator.Emit(OS.OS, *InfoObj);
299317 setSummary(TheSummary.get(), *PS);
300318 InfoObj->SummaryBuilder = nullptr;
301319
320 // For Context Sensitive summary.
321 std::unique_ptr TheCSSummary = nullptr;
322 if (ProfileKind == PF_IRLevelWithCS) {
323 TheCSSummary = IndexedInstrProf::allocSummary(SummarySize);
324 std::unique_ptr CSPS = CSISB.getSummary();
325 setSummary(TheCSSummary.get(), *CSPS);
326 }
327 InfoObj->CSSummaryBuilder = nullptr;
328
302329 // Now do the final patch:
303330 PatchItem PatchItems[] = {
304331 // Patch the Header.HashOffset field.
305332 {HashTableStartFieldOffset, &HashTableStart, 1},
306333 // Patch the summary data.
307334 {SummaryOffset, reinterpret_cast(TheSummary.get()),
308 (int)(SummarySize / sizeof(uint64_t))}};
335 (int)(SummarySize / sizeof(uint64_t))},
336 {CSSummaryOffset, reinterpret_cast(TheCSSummary.get()),
337 (int)CSSummarySize}};
338
309339 OS.patch(PatchItems, sizeof(PatchItems) / sizeof(*PatchItems));
310340 }
311341
374404 Error InstrProfWriter::writeText(raw_fd_ostream &OS) {
375405 if (ProfileKind == PF_IRLevel)
376406 OS << "# IR level Instrumentation Flag\n:ir\n";
407 else if (ProfileKind == PF_IRLevelWithCS)
408 OS << "# CSIR level Instrumentation Flag\n:csir\n";
377409 InstrProfSymtab Symtab;
378410 for (const auto &I : FunctionData)
379411 if (shouldEncodeData(I.getValue()))
663663
664664 bool HotColdSplitting::run(Module &M) {
665665 bool Changed = false;
666 bool HasProfileSummary = M.getProfileSummary();
666 bool HasProfileSummary = (M.getProfileSummary(/* IsCS */ false) != nullptr);
667667 for (auto It = M.begin(), End = M.end(); It != End; ++It) {
668668 Function &F = *It;
669669
15941594 return false;
15951595
15961596 PSI = _PSI;
1597 if (M.getProfileSummary() == nullptr)
1598 M.setProfileSummary(Reader->getSummary().getMD(M.getContext()));
1597 if (M.getProfileSummary(/* IsCS */ false) == nullptr)
1598 M.setProfileSummary(Reader->getSummary().getMD(M.getContext()),
1599 ProfileSummary::PSK_Sample);
15991600
16001601 // Compute the total number of samples collected in this profile.
16011602 for (const auto &I : Reader->getProfiles())
11461146 getBBInfo(nullptr).UnknownCountInEdge = 2;
11471147
11481148 setInstrumentedCounts(CountFromProfile);
1149 ProgramMaxCount = PGOReader->getMaximumFunctionCount();
1149 ProgramMaxCount = PGOReader->getMaximumFunctionCount(IsCS);
11501150 return true;
11511151 }
11521152
15301530 StringRef("Cannot get PGOReader")));
15311531 return false;
15321532 }
1533 if (!PGOReader->hasCSIRLevelProfile() && IsCS)
1534 return false;
15331535
15341536 // TODO: might need to change the warning once the clang option is finalized.
15351537 if (!PGOReader->isIRLevelProfile()) {
15981600 }
15991601 }
16001602 }
1601 M.setProfileSummary(PGOReader->getSummary().getMD(M.getContext()));
1603 M.setProfileSummary(PGOReader->getSummary(IsCS).getMD(M.getContext()),
1604 IsCS ? ProfileSummary::PSK_CSInstr
1605 : ProfileSummary::PSK_Instr);
16021606
16031607 // Set function hotness attribute from the profile.
16041608 // We have to apply these attributes at the end because their presence
224224
225225 auto Reader = std::move(ReaderOrErr.get());
226226 bool IsIRProfile = Reader->isIRLevelProfile();
227 if (WC->Writer.setIsIRLevelProfile(IsIRProfile)) {
227 bool HasCSIRProfile = Reader->hasCSIRLevelProfile();
228 if (WC->Writer.setIsIRLevelProfile(IsIRProfile, HasCSIRProfile)) {
228229 WC->Err = make_error(
229230 "Merge IR generated profile with Clang generated profile.",
230231 std::error_code());
668669 uint32_t TopN, bool ShowIndirectCallTargets,
669670 bool ShowMemOPSizes, bool ShowDetailedSummary,
670671 std::vector DetailedSummaryCutoffs,
671 bool ShowAllFunctions, uint64_t ValueCutoff,
672 bool OnlyListBelow, const std::string &ShowFunction,
673 bool TextFormat, raw_fd_ostream &OS) {
672 bool ShowAllFunctions, bool ShowCS,
673 uint64_t ValueCutoff, bool OnlyListBelow,
674 const std::string &ShowFunction, bool TextFormat,
675 raw_fd_ostream &OS) {
674676 auto ReaderOrErr = InstrProfReader::create(Filename);
675677 std::vector Cutoffs = std::move(DetailedSummaryCutoffs);
676678 if (ShowDetailedSummary && Cutoffs.empty()) {
707709 OS << ":ir\n";
708710
709711 for (const auto &Func : *Reader) {
712 if (Reader->isIRLevelProfile()) {
713 bool FuncIsCS = NamedInstrProfRecord::hasCSFlagInHash(Func.Hash);
714 if (FuncIsCS != ShowCS)
715 continue;
716 }
710717 bool Show =
711718 ShowAllFunctions || (!ShowFunction.empty() &&
712719 Func.Name.find(ShowFunction) != Func.Name.npos);
898905 cl::value_desc("800000,901000,999999"));
899906 cl::opt ShowAllFunctions("all-functions", cl::init(false),
900907 cl::desc("Details for every function"));
908 cl::opt ShowCS("showcs", cl::init(false),
909 cl::desc("Show context sensitive counts"));
901910 cl::opt ShowFunction("function",
902911 cl::desc("Details for matching functions"));
903912
939948 return showInstrProfile(Filename, ShowCounts, TopNFunctions,
940949 ShowIndirectCallTargets, ShowMemOPSizes,
941950 ShowDetailedSummary, DetailedSummaryCutoffs,
942 ShowAllFunctions, ValueCutoff, OnlyListBelow,
943 ShowFunction, TextFormat, OS);
951 ShowAllFunctions, ShowCS, ValueCutoff,
952 OnlyListBelow, ShowFunction, TextFormat, OS);
944953 else
945954 return showSampleProfile(Filename, ShowCounts, ShowAllFunctions,
946955 ShowFunction, OS);
174174 ASSERT_EQ(288230376151711744U, NinetyFivePerc->MinCount);
175175 ASSERT_EQ(72057594037927936U, NinetyNinePerc->MinCount);
176176 };
177 ProfileSummary &PS = Reader->getSummary();
177 ProfileSummary &PS = Reader->getSummary(/* IsCS */ false);
178178 VerifySummary(PS);
179179
180180 // Test that conversion of summary to and from Metadata works.
188188
189189 // Test that summary can be attached to and read back from module.
190190 Module M("my_module", Context);
191 M.setProfileSummary(MD);
192 MD = M.getProfileSummary();
191 M.setProfileSummary(MD, ProfileSummary::PSK_Instr);
192 MD = M.getProfileSummary(/* IsCS */ false);
193193 ASSERT_TRUE(MD);
194194 PSFromMD = ProfileSummary::getFromMD(MD);
195195 ASSERT_TRUE(PSFromMD);
800800 auto Profile = Writer.writeBuffer();
801801 readProfile(std::move(Profile));
802802
803 ASSERT_EQ(1ULL << 63, Reader->getMaximumFunctionCount());
803 ASSERT_EQ(1ULL << 63, Reader->getMaximumFunctionCount(/* IsCS */ false));
804804 }
805805
806806 TEST_P(MaybeSparseInstrProfTest, get_weighted_function_counts) {
190190 delete PS;
191191
192192 // Test that summary can be attached to and read back from module.
193 M.setProfileSummary(MD);
194 MD = M.getProfileSummary();
193 M.setProfileSummary(MD, ProfileSummary::PSK_Sample);
194 MD = M.getProfileSummary(/* IsCS */ false);
195195 ASSERT_TRUE(MD);
196196 PS = ProfileSummary::getFromMD(MD);
197197 ASSERT_TRUE(PS);