[llvm] f7976ed - [llvm-profgen] Add switch to allow use of first loadable segment for calculating offset

Wenlei He via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 15 19:02:37 PST 2021


Author: Wenlei He
Date: 2021-11-15T19:00:27-08:00
New Revision: f7976edc1ec48ae9f96bcc7524ae02373d126869

URL: https://github.com/llvm/llvm-project/commit/f7976edc1ec48ae9f96bcc7524ae02373d126869
DIFF: https://github.com/llvm/llvm-project/commit/f7976edc1ec48ae9f96bcc7524ae02373d126869.diff

LOG: [llvm-profgen] Add switch to allow use of first loadable segment for calculating offset

Adding `-use-loadable-segment-as-base` to allow use of first loadable segment for calculating offset. By default first executable segment is used for calculating offset. The switch helps compatibility with unsymbolized profile generated from older tools.

Differential Revision: https://reviews.llvm.org/D113727

Added: 
    

Modified: 
    llvm/test/tools/llvm-profgen/inline-cs-pseudoprobe.test
    llvm/tools/llvm-profgen/PerfReader.cpp
    llvm/tools/llvm-profgen/ProfiledBinary.cpp
    llvm/tools/llvm-profgen/ProfiledBinary.h

Removed: 
    


################################################################################
diff  --git a/llvm/test/tools/llvm-profgen/inline-cs-pseudoprobe.test b/llvm/test/tools/llvm-profgen/inline-cs-pseudoprobe.test
index f2c52e716db2f..648c06ebca3fb 100644
--- a/llvm/test/tools/llvm-profgen/inline-cs-pseudoprobe.test
+++ b/llvm/test/tools/llvm-profgen/inline-cs-pseudoprobe.test
@@ -1,5 +1,9 @@
 ; RUN: llvm-profgen --format=text --perfscript=%S/Inputs/inline-cs-pseudoprobe.perfscript --binary=%S/Inputs/inline-cs-pseudoprobe.perfbin --output=%t --skip-symbolization --profile-summary-cold-count=0 --use-offset=0
 ; RUN: FileCheck %s --input-file %t --check-prefix=CHECK-UNWINDER
+; RUN: llvm-profgen --format=text --perfscript=%S/Inputs/inline-cs-pseudoprobe.perfscript --binary=%S/Inputs/inline-cs-pseudoprobe.perfbin --output=%t --skip-symbolization --profile-summary-cold-count=0 --use-offset=1
+; RUN: FileCheck %s --input-file %t --check-prefix=CHECK-UNWINDER-OFFSET
+; RUN: llvm-profgen --format=text --perfscript=%S/Inputs/inline-cs-pseudoprobe.perfscript --binary=%S/Inputs/inline-cs-pseudoprobe.perfbin --output=%t --skip-symbolization --profile-summary-cold-count=0 --use-offset=1 --use-first-loadable-segment-as-base=1
+; RUN: FileCheck %s --input-file %t --check-prefix=CHECK-UNWINDER-OFFSET2
 ; RUN: llvm-profgen --format=text --perfscript=%S/Inputs/inline-cs-pseudoprobe.perfscript --binary=%S/Inputs/inline-cs-pseudoprobe.perfbin --output=%t --profile-summary-cold-count=0
 ; RUN: FileCheck %s --input-file %t
 
@@ -27,6 +31,23 @@
 ; CHECK-UNWINDER-NEXT: 20182b->201800:1
 ; CHECK-UNWINDER-NEXT: 201858->20180e:15
 
+
+; CHECK-UNWINDER-OFFSET:      3
+; CHECK-UNWINDER-OFFSET-NEXT: 800-858:1
+; CHECK-UNWINDER-OFFSET-NEXT: 80e-82b:1
+; CHECK-UNWINDER-OFFSET-NEXT: 80e-858:13
+; CHECK-UNWINDER-OFFSET-NEXT: 2
+; CHECK-UNWINDER-OFFSET-NEXT: 82b->800:1
+; CHECK-UNWINDER-OFFSET-NEXT: 858->80e:15
+
+; CHECK-UNWINDER-OFFSET2:      3
+; CHECK-UNWINDER-OFFSET2-NEXT: 1800-1858:1
+; CHECK-UNWINDER-OFFSET2-NEXT: 180e-182b:1
+; CHECK-UNWINDER-OFFSET2-NEXT: 180e-1858:13
+; CHECK-UNWINDER-OFFSET2-NEXT: 2
+; CHECK-UNWINDER-OFFSET2-NEXT: 182b->1800:1
+; CHECK-UNWINDER-OFFSET2-NEXT: 1858->180e:15
+
 ; clang -O3 -fexperimental-new-pass-manager -fuse-ld=lld -fpseudo-probe-for-profiling
 ; -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -Xclang -mdisable-tail-calls
 ; -g test.c  -o a.out

diff  --git a/llvm/tools/llvm-profgen/PerfReader.cpp b/llvm/tools/llvm-profgen/PerfReader.cpp
index deafa4dd48102..e39fb010083a9 100644
--- a/llvm/tools/llvm-profgen/PerfReader.cpp
+++ b/llvm/tools/llvm-profgen/PerfReader.cpp
@@ -27,6 +27,13 @@ static cl::opt<bool>
               cl::desc("Work with `--skip-symbolization` or "
                        "`--unsymbolized-profile` to write/read the "
                        "offset instead of virtual address."));
+
+static cl::opt<bool> UseLoadableSegmentAsBase(
+    "use-first-loadable-segment-as-base", cl::init(false), cl::ZeroOrMore,
+    cl::desc("Use first loadable segment address as base address "
+             "for offsets in unsymbolized profile. By default "
+             "first executable segment address is used"));
+
 static cl::opt<bool>
     IgnoreStackSamples("ignore-stack-samples", cl::init(false), cl::ZeroOrMore,
                        cl::desc("Ignore call stack samples for hybrid samples "
@@ -698,10 +705,19 @@ void PerfScriptReader::writeUnsymbolizedProfile(raw_fd_ostream &OS) {
     OS.indent(Indent);
     OS << Counter.size() << "\n";
     for (auto &I : Counter) {
-      uint64_t Start = UseOffset ? I.first.first
-                                 : Binary->offsetToVirtualAddr(I.first.first);
-      uint64_t End = UseOffset ? I.first.second
-                               : Binary->offsetToVirtualAddr(I.first.second);
+      uint64_t Start = I.first.first;
+      uint64_t End = I.first.second;
+
+      if (!UseOffset || (UseOffset && UseLoadableSegmentAsBase)) {
+        Start = Binary->offsetToVirtualAddr(Start);
+        End = Binary->offsetToVirtualAddr(End);
+      }
+
+      if (UseOffset && UseLoadableSegmentAsBase) {
+        Start -= Binary->getFirstLoadableAddress();
+        End -= Binary->getFirstLoadableAddress();
+      }
+
       OS.indent(Indent);
       OS << Twine::utohexstr(Start) << Separator << Twine::utohexstr(End) << ":"
          << I.second << "\n";
@@ -771,9 +787,13 @@ void UnsymbolizedProfileReader::readSampleCounters(TraceStream &TraceIt,
           Range.second.getAsInteger(16, Target))
         exitWithErrorForTraceLine(TraceIt);
 
-      if (!UseOffset) {
-        Source = Binary->virtualAddrToOffset(Source);
-        Target = Binary->virtualAddrToOffset(Target);
+      if (!UseOffset || (UseOffset && UseLoadableSegmentAsBase)) {
+        uint64_t BaseAddr = 0;
+        if (UseOffset && UseLoadableSegmentAsBase)
+          BaseAddr = Binary->getFirstLoadableAddress();
+
+        Source = Binary->virtualAddrToOffset(Source + BaseAddr);
+        Target = Binary->virtualAddrToOffset(Target + BaseAddr);
       }
 
       Counter[{Source, Target}] += Count;

diff  --git a/llvm/tools/llvm-profgen/ProfiledBinary.cpp b/llvm/tools/llvm-profgen/ProfiledBinary.cpp
index 1cf1d7b8b612c..e08a00d004b34 100644
--- a/llvm/tools/llvm-profgen/ProfiledBinary.cpp
+++ b/llvm/tools/llvm-profgen/ProfiledBinary.cpp
@@ -285,12 +285,16 @@ void ProfiledBinary::setPreferredTextSegmentAddresses(const ELFFile<ELFT> &Obj,
   // because we may build the tools on non-linux.
   uint32_t PageSize = 0x1000;
   for (const typename ELFT::Phdr &Phdr : PhdrRange) {
-    if ((Phdr.p_type == ELF::PT_LOAD) && (Phdr.p_flags & ELF::PF_X)) {
+    if (Phdr.p_type == ELF::PT_LOAD) {
+      if (!FirstLoadableAddress)
+        FirstLoadableAddress = Phdr.p_vaddr & ~(PageSize - 1U);
+      if (Phdr.p_flags & ELF::PF_X) {
         // Segments will always be loaded at a page boundary.
         PreferredTextSegmentAddresses.push_back(Phdr.p_vaddr &
                                                 ~(PageSize - 1U));
         TextSegmentOffsets.push_back(Phdr.p_offset & ~(PageSize - 1U));
       }
+    }
   }
 
   if (PreferredTextSegmentAddresses.empty())

diff  --git a/llvm/tools/llvm-profgen/ProfiledBinary.h b/llvm/tools/llvm-profgen/ProfiledBinary.h
index 3c4ed7b99747a..4249b78a91596 100644
--- a/llvm/tools/llvm-profgen/ProfiledBinary.h
+++ b/llvm/tools/llvm-profgen/ProfiledBinary.h
@@ -173,6 +173,8 @@ class ProfiledBinary {
   Triple TheTriple;
   // The runtime base address that the first executable segment is loaded at.
   uint64_t BaseAddress = 0;
+  // The runtime base address that the first loadabe segment is loaded at.
+  uint64_t FirstLoadableAddress = 0;
   // The preferred load address of each executable segment.
   std::vector<uint64_t> PreferredTextSegmentAddresses;
   // The file offset of each executable segment.
@@ -305,6 +307,8 @@ class ProfiledBinary {
 
   // Return the preferred load address for the first executable segment.
   uint64_t getPreferredBaseAddress() const { return PreferredTextSegmentAddresses[0]; }
+  // Return the preferred load address for the first loadable segment.
+  uint64_t getFirstLoadableAddress() const { return FirstLoadableAddress; }
   // Return the file offset for the first executable segment.
   uint64_t getTextSegmentOffset() const { return TextSegmentOffsets[0]; }
   const std::vector<uint64_t> &getPreferredTextSegmentAddresses() const {


        


More information about the llvm-commits mailing list