diff --git a/llvm/tools/llvm-profgen/ProfileGenerator.h b/llvm/tools/llvm-profgen/ProfileGenerator.h --- a/llvm/tools/llvm-profgen/ProfileGenerator.h +++ b/llvm/tools/llvm-profgen/ProfileGenerator.h @@ -228,6 +228,7 @@ FunctionSamples & getFunctionProfileForContext(const SampleContextFrameVector &Context, bool WasLeafInlined = false); + void computeFuncSizeForSampleHitFunction(); // Post processing for profiles before writing out, such as mermining // and trimming cold profiles, running preinliner on profiles. void postProcessProfiles(); diff --git a/llvm/tools/llvm-profgen/ProfileGenerator.cpp b/llvm/tools/llvm-profgen/ProfileGenerator.cpp --- a/llvm/tools/llvm-profgen/ProfileGenerator.cpp +++ b/llvm/tools/llvm-profgen/ProfileGenerator.cpp @@ -425,6 +425,10 @@ void CSProfileGenerator::generateProfile() { FunctionSamples::ProfileIsCS = true; + + if (Binary->getTrackFuncContextSize()) + computeFuncSizeForSampleHitFunction(); + if (Binary->usePseudoProbes()) { // Enable pseudo probe functionalities in SampleProf FunctionSamples::ProfileIsProbeBased = true; @@ -435,6 +439,22 @@ postProcessProfiles(); } +void CSProfileGenerator::computeFuncSizeForSampleHitFunction() { + std::unordered_map FuncRanges; + for (const auto &CI : SampleCounters) { + for (auto Item : CI.second.RangeCounter) { + uint64_t RangeStartOffset = Item.first.first; + auto FuncRange = Binary->findFuncOffsetRange(RangeStartOffset); + if (FuncRange.second != 0) + FuncRanges[FuncRange.first] = FuncRange.second; + } + } + + for (auto I : FuncRanges) { + Binary->computeFuncSizeForRange(I.first, I.second); + } +} + void CSProfileGenerator::generateLineNumBasedProfile() { for (const auto &CI : SampleCounters) { const StringBasedCtxKey *CtxKey = diff --git a/llvm/tools/llvm-profgen/ProfiledBinary.h b/llvm/tools/llvm-profgen/ProfiledBinary.h --- a/llvm/tools/llvm-profgen/ProfiledBinary.h +++ b/llvm/tools/llvm-profgen/ProfiledBinary.h @@ -231,7 +231,6 @@ SampleContextFrameVector symbolize(const InstructionPointer &IP, bool UseCanonicalFnName = false, bool UseProbeDiscriminator = false); - /// Decode the interesting parts of the binary and build internal data /// structures. On high level, the parts of interest are: /// 1. Text sections, including the main code section and the PLT @@ -357,6 +356,8 @@ getExpandedContext(const SmallVectorImpl &Stack, bool &WasLeafInlined); + void computeFuncSizeForRange(uint64_t StartOffset, uint64_t EndOffset); + const MCDecodedPseudoProbe *getCallProbeForAddr(uint64_t Address) const { return ProbeDecoder.getCallProbeForAddr(Address); } @@ -384,6 +385,8 @@ return ProbeDecoder.getInlinerDescForProbe(Probe); } + bool getTrackFuncContextSize() { return TrackFuncContextSize; } + bool getIsLoadedByMMap() { return IsLoadedByMMap; } void setIsLoadedByMMap(bool Value) { IsLoadedByMMap = Value; } diff --git a/llvm/tools/llvm-profgen/ProfiledBinary.cpp b/llvm/tools/llvm-profgen/ProfiledBinary.cpp --- a/llvm/tools/llvm-profgen/ProfiledBinary.cpp +++ b/llvm/tools/llvm-profgen/ProfiledBinary.cpp @@ -353,22 +353,7 @@ if (Disassembled) { const MCInstrDesc &MCDesc = MII->get(Inst.getOpcode()); - // Populate a vector of the symbolized callsite at this location - // We don't need symbolized info for probe-based profile, just use an - // empty stack as an entry to indicate a valid binary offset - SampleContextFrameVector SymbolizedCallStack; - if (TrackFuncContextSize) { - InstructionPointer IP(this, Offset); - // TODO: reallocation of Offset2LocStackMap will lead to dangling - // strings We need ProfiledBinary to owned these string. - Offset2LocStackMap[Offset] = symbolize(IP, true, UsePseudoProbes); - SampleContextFrameVector &SymbolizedCallStack = - Offset2LocStackMap[Offset]; - // Record instruction size for the corresponding context - if (TrackFuncContextSize && !SymbolizedCallStack.empty()) - FuncSizeTracker.addInstructionForContext(Offset2LocStackMap[Offset], - Size); - } + // Record instruction size. Offset2InstSizeMap[Offset] = Size; @@ -560,6 +545,26 @@ return CallStack; } +void ProfiledBinary::computeFuncSizeForRange(uint64_t StartOffset, + uint64_t EndOffset) { + uint64_t StartAddr = offsetToVirtualAddr(StartOffset); + uint64_t EndAddr = offsetToVirtualAddr(EndOffset); + + InstructionPointer IP(this, StartAddr, true); + while (IP.Address < EndAddr) { + uint64_t Offset = virtualAddrToOffset(IP.Address); + + const SampleContextFrameVector &SymbolizedCallStack = + getFrameLocationStack(Offset, UsePseudoProbes); + uint64_t Size = Offset2InstSizeMap[Offset]; + + // Record instruction size for the corresponding context + FuncSizeTracker.addInstructionForContext(SymbolizedCallStack, Size); + + IP.advance(); + } +} + InstructionPointer::InstructionPointer(const ProfiledBinary *Binary, uint64_t Address, bool RoundToNext) : Binary(Binary), Address(Address) {