diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2021-07-29 20:15:26 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2021-07-29 20:15:26 +0000 |
| commit | 344a3780b2e33f6ca763666c380202b18aab72a3 (patch) | |
| tree | f0b203ee6eb71d7fdd792373e3c81eb18d6934dd /llvm/tools/llvm-profdata/llvm-profdata.cpp | |
| parent | b60736ec1405bb0a8dd40989f67ef4c93da068ab (diff) | |
vendor/llvm-project/llvmorg-13-init-16847-g88e66fa60ae5vendor/llvm-project/llvmorg-12.0.1-rc2-0-ge7dac564cd0evendor/llvm-project/llvmorg-12.0.1-0-gfed41342a82f
Diffstat (limited to 'llvm/tools/llvm-profdata/llvm-profdata.cpp')
| -rw-r--r-- | llvm/tools/llvm-profdata/llvm-profdata.cpp | 212 |
1 files changed, 147 insertions, 65 deletions
diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp index 8dc43924c067..66d70120ac9b 100644 --- a/llvm/tools/llvm-profdata/llvm-profdata.cpp +++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp @@ -20,6 +20,7 @@ #include "llvm/ProfileData/SampleProfReader.h" #include "llvm/ProfileData/SampleProfWriter.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/Discriminator.h" #include "llvm/Support/Errc.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Format.h" @@ -54,6 +55,14 @@ static void warn(Twine Message, std::string Whence = "", WithColor::note() << Hint << "\n"; } +static void warn(Error E, StringRef Whence = "") { + if (E.isA<InstrProfError>()) { + handleAllErrors(std::move(E), [&](const InstrProfError &IPE) { + warn(IPE.message(), std::string(Whence), std::string("")); + }); + } +} + static void exitWithError(Twine Message, std::string Whence = "", std::string Hint = "") { WithColor::error(); @@ -243,7 +252,8 @@ static void loadInput(const WeightedFile &Input, SymbolRemapper *Remapper, auto Reader = std::move(ReaderOrErr.get()); bool IsIRProfile = Reader->isIRLevelProfile(); bool HasCSIRProfile = Reader->hasCSIRLevelProfile(); - if (WC->Writer.setIsIRLevelProfile(IsIRProfile, HasCSIRProfile)) { + if (Error E = WC->Writer.setIsIRLevelProfile(IsIRProfile, HasCSIRProfile)) { + consumeError(std::move(E)); WC->Errors.emplace_back( make_error<StringError>( "Merge IR generated profile with Clang generated profile.", @@ -297,16 +307,19 @@ static void writeInstrProfile(StringRef OutputFilename, InstrProfWriter &Writer) { std::error_code EC; raw_fd_ostream Output(OutputFilename.data(), EC, - OutputFormat == PF_Text ? sys::fs::OF_Text + OutputFormat == PF_Text ? sys::fs::OF_TextWithCRLF : sys::fs::OF_None); if (EC) exitWithErrorCode(EC, OutputFilename); if (OutputFormat == PF_Text) { if (Error E = Writer.writeText(Output)) - exitWithError(std::move(E)); + warn(std::move(E)); } else { - Writer.write(Output); + if (Output.is_displayed()) + exitWithError("cannot write a non-text format profile to the terminal"); + if (Error E = Writer.write(Output)) + warn(std::move(E)); } } @@ -315,12 +328,9 @@ static void mergeInstrProfile(const WeightedFileVector &Inputs, StringRef OutputFilename, ProfileFormat OutputFormat, bool OutputSparse, unsigned NumThreads, FailureMode FailMode) { - if (OutputFilename.compare("-") == 0) - exitWithError("Cannot write indexed profdata format to stdout."); - if (OutputFormat != PF_Binary && OutputFormat != PF_Compact_Binary && OutputFormat != PF_Ext_Binary && OutputFormat != PF_Text) - exitWithError("Unknown format is specified."); + exitWithError("unknown format is specified"); std::mutex ErrorLock; SmallSet<instrprof_error, 4> WriterErrorCodes; @@ -383,7 +393,7 @@ static void mergeInstrProfile(const WeightedFileVector &Inputs, } if (NumErrors == Inputs.size() || (NumErrors > 0 && FailMode == failIfAnyAreInvalid)) - exitWithError("No profiles could be merged."); + exitWithError("no profile can be merged"); writeInstrProfile(OutputFilename, OutputFormat, Contexts[0]->Writer); } @@ -441,6 +451,25 @@ static void updateInstrProfileEntry(InstrProfileEntry &IFE, const uint64_t ColdPercentileIdx = 15; const uint64_t HotPercentileIdx = 11; +using sampleprof::FSDiscriminatorPass; + +// Internal options to set FSDiscriminatorPass. Used in merge and show +// commands. +static cl::opt<FSDiscriminatorPass> FSDiscriminatorPassOption( + "fs-discriminator-pass", cl::init(PassLast), cl::Hidden, + cl::desc("Zero out the discriminator bits for the FS discrimiantor " + "pass beyond this value. The enum values are defined in " + "Support/Discriminator.h"), + cl::values(clEnumVal(Base, "Use base discriminators only"), + clEnumVal(Pass1, "Use base and pass 1 discriminators"), + clEnumVal(Pass2, "Use base and pass 1-2 discriminators"), + clEnumVal(Pass3, "Use base and pass 1-3 discriminators"), + clEnumVal(PassLast, "Use all discriminator bits (default)"))); + +static unsigned getDiscriminatorMask() { + return getN1Bits(getFSPassBitEnd(FSDiscriminatorPassOption.getValue())); +} + /// Adjust the instr profile in \p WC based on the sample profile in /// \p Reader. static void @@ -522,18 +551,18 @@ static void supplementInstrProfile( unsigned SupplMinSizeThreshold, float ZeroCounterThreshold, unsigned InstrProfColdThreshold) { if (OutputFilename.compare("-") == 0) - exitWithError("Cannot write indexed profdata format to stdout."); + exitWithError("cannot write indexed profdata format to stdout"); if (Inputs.size() != 1) - exitWithError("Expect one input to be an instr profile."); + exitWithError("expect one input to be an instr profile"); if (Inputs[0].Weight != 1) - exitWithError("Expect instr profile doesn't have weight."); + exitWithError("expect instr profile doesn't have weight"); StringRef InstrFilename = Inputs[0].Filename; // Read sample profile. LLVMContext Context; - auto ReaderOrErr = - sampleprof::SampleProfileReader::create(SampleFilename.str(), Context); + auto ReaderOrErr = sampleprof::SampleProfileReader::create( + SampleFilename.str(), Context, FSDiscriminatorPassOption); if (std::error_code EC = ReaderOrErr.getError()) exitWithErrorCode(EC, SampleFilename); auto Reader = std::move(ReaderOrErr.get()); @@ -564,12 +593,13 @@ remapSamples(const sampleprof::FunctionSamples &Samples, Result.addTotalSamples(Samples.getTotalSamples()); Result.addHeadSamples(Samples.getHeadSamples()); for (const auto &BodySample : Samples.getBodySamples()) { - Result.addBodySamples(BodySample.first.LineOffset, - BodySample.first.Discriminator, + uint32_t MaskedDiscriminator = + BodySample.first.Discriminator & getDiscriminatorMask(); + Result.addBodySamples(BodySample.first.LineOffset, MaskedDiscriminator, BodySample.second.getSamples()); for (const auto &Target : BodySample.second.getCallTargets()) { Result.addCalledTargetSamples(BodySample.first.LineOffset, - BodySample.first.Discriminator, + MaskedDiscriminator, Remapper(Target.first()), Target.second); } } @@ -656,15 +686,19 @@ static void mergeSampleProfile(const WeightedFileVector &Inputs, SymbolRemapper *Remapper, StringRef OutputFilename, ProfileFormat OutputFormat, StringRef ProfileSymbolListFile, bool CompressAllSections, - bool UseMD5, bool GenPartialProfile, FailureMode FailMode) { + bool UseMD5, bool GenPartialProfile, + bool SampleMergeColdContext, bool SampleTrimColdContext, + bool SampleColdContextFrameDepth, FailureMode FailMode) { using namespace sampleprof; StringMap<FunctionSamples> ProfileMap; SmallVector<std::unique_ptr<sampleprof::SampleProfileReader>, 5> Readers; LLVMContext Context; sampleprof::ProfileSymbolList WriterList; Optional<bool> ProfileIsProbeBased; + Optional<bool> ProfileIsCS; for (const auto &Input : Inputs) { - auto ReaderOrErr = SampleProfileReader::create(Input.Filename, Context); + auto ReaderOrErr = SampleProfileReader::create(Input.Filename, Context, + FSDiscriminatorPassOption); if (std::error_code EC = ReaderOrErr.getError()) { warnOrExitGivenError(FailMode, EC, Input.Filename); continue; @@ -683,11 +717,14 @@ mergeSampleProfile(const WeightedFileVector &Inputs, SymbolRemapper *Remapper, } StringMap<FunctionSamples> &Profiles = Reader->getProfiles(); - if (ProfileIsProbeBased && + if (ProfileIsProbeBased.hasValue() && ProfileIsProbeBased != FunctionSamples::ProfileIsProbeBased) exitWithError( "cannot merge probe-based profile with non-probe-based profile"); ProfileIsProbeBased = FunctionSamples::ProfileIsProbeBased; + if (ProfileIsCS.hasValue() && ProfileIsCS != FunctionSamples::ProfileIsCS) + exitWithError("cannot merge CS profile with non-CS profile"); + ProfileIsCS = FunctionSamples::ProfileIsCS; for (StringMap<FunctionSamples>::iterator I = Profiles.begin(), E = Profiles.end(); I != E; ++I) { @@ -696,7 +733,7 @@ mergeSampleProfile(const WeightedFileVector &Inputs, SymbolRemapper *Remapper, Remapper ? remapSamples(I->second, *Remapper, Result) : FunctionSamples(); FunctionSamples &Samples = Remapper ? Remapped : I->second; - StringRef FName = Samples.getName(); + StringRef FName = Samples.getNameWithContext(); MergeResult(Result, ProfileMap[FName].merge(Samples, Input.Weight)); if (Result != sampleprof_error::success) { std::error_code EC = make_error_code(Result); @@ -709,6 +746,22 @@ mergeSampleProfile(const WeightedFileVector &Inputs, SymbolRemapper *Remapper, if (ReaderList) WriterList.merge(*ReaderList); } + + if (ProfileIsCS && (SampleMergeColdContext || SampleTrimColdContext)) { + // Use threshold calculated from profile summary unless specified. + SampleProfileSummaryBuilder Builder(ProfileSummaryBuilder::DefaultCutoffs); + auto Summary = Builder.computeSummaryForProfiles(ProfileMap); + uint64_t SampleProfColdThreshold = + ProfileSummaryBuilder::getColdCountThreshold( + (Summary->getDetailedSummary())); + + // Trim and merge cold context profile using cold threshold above; + SampleContextTrimmer(ProfileMap) + .trimAndMergeColdContextProfiles( + SampleProfColdThreshold, SampleTrimColdContext, + SampleMergeColdContext, SampleColdContextFrameDepth); + } + auto WriterOrErr = SampleProfileWriter::create(OutputFilename, FormatMap[OutputFormat]); if (std::error_code EC = WriterOrErr.getError()) @@ -720,7 +773,8 @@ mergeSampleProfile(const WeightedFileVector &Inputs, SymbolRemapper *Remapper, auto Buffer = getInputFileBuf(ProfileSymbolListFile); handleExtBinaryWriter(*Writer, OutputFormat, Buffer.get(), WriterList, CompressAllSections, UseMD5, GenPartialProfile); - Writer->write(ProfileMap); + if (std::error_code EC = Writer->write(ProfileMap)) + exitWithErrorCode(std::move(EC)); } static WeightedFile parseWeightedFile(const StringRef &WeightedFilename) { @@ -729,7 +783,7 @@ static WeightedFile parseWeightedFile(const StringRef &WeightedFilename) { uint64_t Weight; if (WeightStr.getAsInteger(10, Weight) || Weight < 1) - exitWithError("Input weight must be a positive integer."); + exitWithError("input weight must be a positive integer"); return {std::string(FileName), Weight}; } @@ -808,8 +862,7 @@ static int merge_main(int argc, const char *argv[]) { cl::alias RemappingFileA("r", cl::desc("Alias for --remapping-file"), cl::aliasopt(RemappingFile)); cl::opt<std::string> OutputFilename("output", cl::value_desc("output"), - cl::init("-"), cl::Required, - cl::desc("Output file")); + cl::init("-"), cl::desc("Output file")); cl::alias OutputFilenameA("o", cl::desc("Alias for --output"), cl::aliasopt(OutputFilename)); cl::opt<ProfileKinds> ProfileKind( @@ -851,6 +904,18 @@ static int merge_main(int argc, const char *argv[]) { "use-md5", cl::init(false), cl::Hidden, cl::desc("Choose to use MD5 to represent string in name table (only " "meaningful for -extbinary)")); + cl::opt<bool> SampleMergeColdContext( + "sample-merge-cold-context", cl::init(false), cl::Hidden, + cl::desc( + "Merge context sample profiles whose count is below cold threshold")); + cl::opt<bool> SampleTrimColdContext( + "sample-trim-cold-context", cl::init(false), cl::Hidden, + cl::desc( + "Trim context sample profiles whose count is below cold threshold")); + cl::opt<uint32_t> SampleColdContextFrameDepth( + "sample-frame-depth-for-cold-context", cl::init(1), cl::ZeroOrMore, + cl::desc("Keep the last K frames while merging cold profile. 1 means the " + "context-less base profile")); cl::opt<bool> GenPartialProfile( "gen-partial-profile", cl::init(false), cl::Hidden, cl::desc("Generate a partial profile (only meaningful for -extbinary)")); @@ -866,16 +931,16 @@ static int merge_main(int argc, const char *argv[]) { "sample profile, if the ratio of the number of zero counters " "divided by the the total number of counters is above the " "threshold, the profile of the function will be regarded as " - "being harmful for performance and will be dropped. ")); + "being harmful for performance and will be dropped.")); cl::opt<unsigned> SupplMinSizeThreshold( "suppl-min-size-threshold", cl::init(10), cl::Hidden, cl::desc("If the size of a function is smaller than the threshold, " "assume it can be inlined by PGO early inliner and it won't " - "be adjusted based on sample profile. ")); + "be adjusted based on sample profile.")); cl::opt<unsigned> InstrProfColdThreshold( "instr-prof-cold-threshold", cl::init(0), cl::Hidden, cl::desc("User specified cold threshold for instr profile which will " - "override the cold threshold got from profile summary. ")); + "override the cold threshold got from profile summary.")); cl::ParseCommandLineOptions(argc, argv, "LLVM profile data merger\n"); @@ -891,7 +956,7 @@ static int merge_main(int argc, const char *argv[]) { parseInputFilenamesFile(Buffer.get(), WeightedInputs); if (WeightedInputs.empty()) - exitWithError("No input files specified. See " + + exitWithError("no input files specified. See " + sys::path::filename(argv[0]) + " -help"); if (DumpInputFileList) { @@ -921,7 +986,9 @@ static int merge_main(int argc, const char *argv[]) { else mergeSampleProfile(WeightedInputs, Remapper.get(), OutputFilename, OutputFormat, ProfileSymbolListFile, CompressAllSections, - UseMD5, GenPartialProfile, FailureMode); + UseMD5, GenPartialProfile, SampleMergeColdContext, + SampleTrimColdContext, SampleColdContextFrameDepth, + FailureMode); return 0; } @@ -938,7 +1005,7 @@ static void overlapInstrProfile(const std::string &BaseFilename, OverlapStats Overlap; Error E = Overlap.accumulateCounts(BaseFilename, TestFilename, IsCS); if (E) - exitWithError(std::move(E), "Error in getting profile count sums"); + exitWithError(std::move(E), "error in getting profile count sums"); if (Overlap.Base.CountSum < 1.0f) { OS << "Sum of edge counts for profile " << BaseFilename << " is 0.\n"; exit(0); @@ -1548,14 +1615,15 @@ void SampleOverlapAggregator::computeSampleProfileOverlap(raw_fd_ostream &OS) { StringMap<const FunctionSamples *> BaseFuncProf; const auto &BaseProfiles = BaseReader->getProfiles(); for (const auto &BaseFunc : BaseProfiles) { - BaseFuncProf.try_emplace(BaseFunc.second.getName(), &(BaseFunc.second)); + BaseFuncProf.try_emplace(BaseFunc.second.getNameWithContext(), + &(BaseFunc.second)); } ProfOverlap.UnionCount = BaseFuncProf.size(); const auto &TestProfiles = TestReader->getProfiles(); for (const auto &TestFunc : TestProfiles) { SampleOverlapStats FuncOverlap; - FuncOverlap.TestName = TestFunc.second.getName(); + FuncOverlap.TestName = TestFunc.second.getNameWithContext(); assert(TestStats.count(FuncOverlap.TestName) && "TestStats should have records for all functions in test profile " "except inlinees"); @@ -1582,7 +1650,7 @@ void SampleOverlapAggregator::computeSampleProfileOverlap(raw_fd_ostream &OS) { // Two functions match with each other. Compute function-level overlap and // aggregate them into profile-level overlap. - FuncOverlap.BaseName = Match->second->getName(); + FuncOverlap.BaseName = Match->second->getNameWithContext(); assert(BaseStats.count(FuncOverlap.BaseName) && "BaseStats should have records for all functions in base profile " "except inlinees"); @@ -1631,10 +1699,11 @@ void SampleOverlapAggregator::computeSampleProfileOverlap(raw_fd_ostream &OS) { // Traverse through functions in base profile but not in test profile. for (const auto &F : BaseFuncProf) { - assert(BaseStats.count(F.second->getName()) && + assert(BaseStats.count(F.second->getNameWithContext()) && "BaseStats should have records for all functions in base profile " "except inlinees"); - const FuncSampleStats &FuncStats = BaseStats[F.second->getName()]; + const FuncSampleStats &FuncStats = + BaseStats[F.second->getNameWithContext()]; ++ProfOverlap.BaseUniqueCount; ProfOverlap.BaseUniqueSample += FuncStats.SampleSum; @@ -1665,7 +1734,7 @@ void SampleOverlapAggregator::initializeSampleProfileOverlap() { FuncSampleStats FuncStats; getFuncSampleStats(I.second, FuncStats, BaseHotThreshold); ProfOverlap.BaseSample += FuncStats.SampleSum; - BaseStats.try_emplace(I.second.getName(), FuncStats); + BaseStats.try_emplace(I.second.getNameWithContext(), FuncStats); } const auto &TestProf = TestReader->getProfiles(); @@ -1674,7 +1743,7 @@ void SampleOverlapAggregator::initializeSampleProfileOverlap() { FuncSampleStats FuncStats; getFuncSampleStats(I.second, FuncStats, TestHotThreshold); ProfOverlap.TestSample += FuncStats.SampleSum; - TestStats.try_emplace(I.second.getName(), FuncStats); + TestStats.try_emplace(I.second.getNameWithContext(), FuncStats); } ProfOverlap.BaseName = StringRef(BaseFilename); @@ -1815,11 +1884,13 @@ std::error_code SampleOverlapAggregator::loadProfiles() { using namespace sampleprof; LLVMContext Context; - auto BaseReaderOrErr = SampleProfileReader::create(BaseFilename, Context); + auto BaseReaderOrErr = SampleProfileReader::create(BaseFilename, Context, + FSDiscriminatorPassOption); if (std::error_code EC = BaseReaderOrErr.getError()) exitWithErrorCode(EC, BaseFilename); - auto TestReaderOrErr = SampleProfileReader::create(TestFilename, Context); + auto TestReaderOrErr = SampleProfileReader::create(TestFilename, Context, + FSDiscriminatorPassOption); if (std::error_code EC = TestReaderOrErr.getError()) exitWithErrorCode(EC, TestFilename); @@ -1833,6 +1904,8 @@ std::error_code SampleOverlapAggregator::loadProfiles() { if (BaseReader->profileIsProbeBased() != TestReader->profileIsProbeBased()) exitWithError( "cannot compare probe-based profile with non-probe-based profile"); + if (BaseReader->profileIsCS() != TestReader->profileIsCS()) + exitWithError("cannot compare CS profile with non-CS profile"); // Load BaseHotThreshold and TestHotThreshold as 99-percentile threshold in // profile summary. @@ -1888,21 +1961,24 @@ static int overlap_main(int argc, const char *argv[]) { cl::opt<std::string> Output("output", cl::value_desc("output"), cl::init("-"), cl::desc("Output file")); cl::alias OutputA("o", cl::desc("Alias for --output"), cl::aliasopt(Output)); - cl::opt<bool> IsCS("cs", cl::init(false), - cl::desc("For context sensitive counts")); + cl::opt<bool> IsCS( + "cs", cl::init(false), + cl::desc("For context sensitive PGO counts. Does not work with CSSPGO.")); cl::opt<unsigned long long> ValueCutoff( "value-cutoff", cl::init(-1), cl::desc( - "Function level overlap information for every function in test " + "Function level overlap information for every function (with calling " + "context for csspgo) in test " "profile with max count value greater then the parameter value")); cl::opt<std::string> FuncNameFilter( "function", - cl::desc("Function level overlap information for matching functions")); + cl::desc("Function level overlap information for matching functions. For " + "CSSPGO this takes a a function name with calling context")); cl::opt<unsigned long long> SimilarityCutoff( "similarity-cutoff", cl::init(0), - cl::desc( - "For sample profiles, list function names for overlapped functions " - "with similarities below the cutoff (percentage times 10000).")); + cl::desc("For sample profiles, list function names (with calling context " + "for csspgo) for overlapped functions " + "with similarities below the cutoff (percentage times 10000).")); cl::opt<ProfileKinds> ProfileKind( cl::desc("Profile kind:"), cl::init(instr), cl::values(clEnumVal(instr, "Instrumentation profile (default)"), @@ -1910,7 +1986,7 @@ static int overlap_main(int argc, const char *argv[]) { cl::ParseCommandLineOptions(argc, argv, "LLVM profile data overlap tool\n"); std::error_code EC; - raw_fd_ostream OS(Output.data(), EC, sys::fs::OF_Text); + raw_fd_ostream OS(Output.data(), EC, sys::fs::OF_TextWithCRLF); if (EC) exitWithErrorCode(EC, Output); @@ -1926,7 +2002,8 @@ static int overlap_main(int argc, const char *argv[]) { return 0; } -typedef struct ValueSitesStats { +namespace { +struct ValueSitesStats { ValueSitesStats() : TotalNumValueSites(0), TotalNumValueSitesWithValueProfile(0), TotalNumValues(0) {} @@ -1934,7 +2011,8 @@ typedef struct ValueSitesStats { uint64_t TotalNumValueSitesWithValueProfile; uint64_t TotalNumValues; std::vector<unsigned> ValueSitesHistogram; -} ValueSitesStats; +}; +} // namespace static void traverseAllValueSites(const InstrProfRecord &Func, uint32_t VK, ValueSitesStats &Stats, raw_fd_ostream &OS, @@ -1991,7 +2069,7 @@ static int showInstrProfile(const std::string &Filename, bool ShowCounts, bool ShowAllFunctions, bool ShowCS, uint64_t ValueCutoff, bool OnlyListBelow, const std::string &ShowFunction, bool TextFormat, - raw_fd_ostream &OS) { + bool ShowBinaryIds, raw_fd_ostream &OS) { auto ReaderOrErr = InstrProfReader::create(Filename); std::vector<uint32_t> Cutoffs = std::move(DetailedSummaryCutoffs); if (ShowDetailedSummary && Cutoffs.empty()) { @@ -2173,6 +2251,11 @@ static int showInstrProfile(const std::string &Filename, bool ShowCounts, OS << "Total count: " << PS->getTotalCount() << "\n"; PS->printDetailedSummary(OS); } + + if (ShowBinaryIds) + if (Error E = Reader->printBinaryIds(OS)) + exitWithError(std::move(E), Filename); + return 0; } @@ -2307,9 +2390,9 @@ showHotFunctionList(const StringMap<sampleprof::FunctionSamples> &Profiles, (ProfileTotalSample > 0) ? (Func.getTotalSamples() * 100.0) / ProfileTotalSample : 0; - PrintValues.emplace_back( - HotFuncInfo(Func.getName(), Func.getTotalSamples(), TotalSamplePercent, - FuncPair.second.second, Func.getEntrySamples())); + PrintValues.emplace_back(HotFuncInfo( + Func.getNameWithContext(), Func.getTotalSamples(), TotalSamplePercent, + FuncPair.second.second, Func.getEntrySamples())); } dumpHotFunctionList(ColumnTitle, ColumnOffset, PrintValues, HotFuncCount, Profiles.size(), HotFuncSample, ProfileTotalSample, @@ -2326,12 +2409,12 @@ static int showSampleProfile(const std::string &Filename, bool ShowCounts, raw_fd_ostream &OS) { using namespace sampleprof; LLVMContext Context; - auto ReaderOrErr = SampleProfileReader::create(Filename, Context); + auto ReaderOrErr = + SampleProfileReader::create(Filename, Context, FSDiscriminatorPassOption); if (std::error_code EC = ReaderOrErr.getError()) exitWithErrorCode(EC, Filename); auto Reader = std::move(ReaderOrErr.get()); - if (ShowSectionInfoOnly) { showSectionInfo(Reader.get(), OS); return 0; @@ -2423,12 +2506,11 @@ static int show_main(int argc, const char *argv[]) { cl::desc("Show the information of each section in the sample profile. " "The flag is only usable when the sample profile is in " "extbinary format")); + cl::opt<bool> ShowBinaryIds("binary-ids", cl::init(false), + cl::desc("Show binary ids in the profile. ")); cl::ParseCommandLineOptions(argc, argv, "LLVM profile data summary\n"); - if (OutputFilename.empty()) - OutputFilename = "-"; - if (Filename == OutputFilename) { errs() << sys::path::filename(argv[0]) << ": Input file name cannot be the same as the output file name!\n"; @@ -2436,7 +2518,7 @@ static int show_main(int argc, const char *argv[]) { } std::error_code EC; - raw_fd_ostream OS(OutputFilename.data(), EC, sys::fs::OF_Text); + raw_fd_ostream OS(OutputFilename.data(), EC, sys::fs::OF_TextWithCRLF); if (EC) exitWithErrorCode(EC, OutputFilename); @@ -2444,11 +2526,11 @@ static int show_main(int argc, const char *argv[]) { WithColor::warning() << "-function argument ignored: showing all functions\n"; if (ProfileKind == instr) - return showInstrProfile(Filename, ShowCounts, TopNFunctions, - ShowIndirectCallTargets, ShowMemOPSizes, - ShowDetailedSummary, DetailedSummaryCutoffs, - ShowAllFunctions, ShowCS, ValueCutoff, - OnlyListBelow, ShowFunction, TextFormat, OS); + return showInstrProfile( + Filename, ShowCounts, TopNFunctions, ShowIndirectCallTargets, + ShowMemOPSizes, ShowDetailedSummary, DetailedSummaryCutoffs, + ShowAllFunctions, ShowCS, ValueCutoff, OnlyListBelow, ShowFunction, + TextFormat, ShowBinaryIds, OS); else return showSampleProfile(Filename, ShowCounts, ShowAllFunctions, ShowDetailedSummary, ShowFunction, |
