[llvm] [Sample Profile] make page size configurable for ProfiledBinary (PR #206867)

via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 30 18:51:58 PDT 2026


https://github.com/wjx951753 updated https://github.com/llvm/llvm-project/pull/206867

>From 25be8c56f6e01bfa61abf9c5896f596c375ddc08 Mon Sep 17 00:00:00 2001
From: wangjx6 <wangjiaxin35 at huawei.com>
Date: Wed, 1 Jul 2026 09:41:00 +0800
Subject: [PATCH] [Sample Profile] make page size configurable for
 ProfiledBinary

---
 .../Inputs/multi-load-segs-64k.perfscript     | 11 +++++++
 llvm/test/tools/llvm-profgen/page-size.test   | 33 +++++++++++++++++++
 llvm/tools/llvm-profgen/ProfiledBinary.cpp    | 21 +++++++-----
 3 files changed, 57 insertions(+), 8 deletions(-)
 create mode 100644 llvm/test/tools/llvm-profgen/Inputs/multi-load-segs-64k.perfscript
 create mode 100644 llvm/test/tools/llvm-profgen/page-size.test

diff --git a/llvm/test/tools/llvm-profgen/Inputs/multi-load-segs-64k.perfscript b/llvm/test/tools/llvm-profgen/Inputs/multi-load-segs-64k.perfscript
new file mode 100644
index 0000000000000..8db032298220e
--- /dev/null
+++ b/llvm/test/tools/llvm-profgen/Inputs/multi-load-segs-64k.perfscript
@@ -0,0 +1,11 @@
+PERF_RECORD_MMAP2 3476378/3476378: [0x200000(0x10000) @ 0 00:23 51215901 72455]: r-xp multi-load-segs.perfbin
+PERF_RECORD_MMAP2 3476378/3476378: [0x201000(0x1000) @ 0x1000 00:23 51215901 72455]: r-xp multi-load-segs.perfbin
+PERF_RECORD_MMAP2 3476378/3476378: [0x400000(0x1000) @ 0x200000 00:23 51215901 72455]: r-xp multi-load-segs.perfbin
+
+	          201a1e
+	    7f9f03a46d95
+	          20178a
+ 0x201a56/0x201a10/P/-/-/4  0x201a56/0x201a10/P/-/-/4  0x201a56/0x201a10/P/-/-/4  0x201a56/0x201a10/P/-/-/5  0x201a56/0x201a10/P/-/-/4  0x201a56/0x201a10/P/-/-/5  0x201a56/0x201a10/P/-/-/5  0x201a56/0x201a10/P/-/-/5  0x201a56/0x201a10/P/-/-/4  0x201a56/0x201a10/P/-/-/3  0x201a56/0x201a10/P/-/-/7  0x201a56/0x201a10/P/-/-/4  0x201a56/0x201a10/P/-/-/4  0x201a56/0x201a10/P/-/-/4  0x201a56/0x201a10/P/-/-/3  0x201a56/0x201a10/P/-/-/6  0x201a56/0x201a10/P/-/-/4  0x201a56/0x201a10/P/-/-/4  0x201a56/0x201a10/P/-/-/4  0x201a56/0x201a10/P/-/-/4  0x201a56/0x201a10/P/-/-/4  0x201a56/0x201a10/P/-/-/4  0x201a56/0x201a10/P/-/-/3  0x201a56/0x201a10/P/-/-/6  0x201a56/0x201a10/P/-/-/4  0x201a56/0x201a10/P/-/-/4  0x201a56/0x201a10/P/-/-/4  0x201a56/0x201a10/P/-/-/4  0x201a56/0x201a10/P/-/-/4  0x201a56/0x201a10/P/-/-/4  0x201a56/0x201a10/P/-/-/3  0x201a56/0x201a10/P/-/-/6 
+
+	       
+
diff --git a/llvm/test/tools/llvm-profgen/page-size.test b/llvm/test/tools/llvm-profgen/page-size.test
new file mode 100644
index 0000000000000..65ef70c6d5e06
--- /dev/null
+++ b/llvm/test/tools/llvm-profgen/page-size.test
@@ -0,0 +1,33 @@
+; RUN: not llvm-profgen --perfscript=%S/Inputs/multi-load-segs.perfscript --binary=%S/Inputs/multi-load-segs.perfbin --output=%t --format=text --csspgo-preinliner=0 --gen-cs-nested-profile=0 --page-size=0 2>&1 | FileCheck %s --check-prefix=INVALID
+; RUN: not llvm-profgen --perfscript=%S/Inputs/multi-load-segs.perfscript --binary=%S/Inputs/multi-load-segs.perfbin --output=%t --format=text --csspgo-preinliner=0 --gen-cs-nested-profile=0 --page-size=3 2>&1 | FileCheck %s --check-prefix=INVALID
+; RUN: llvm-profgen --perfscript=%S/Inputs/multi-load-segs.perfscript --binary=%S/Inputs/multi-load-segs.perfbin --output=%t --format=text --csspgo-preinliner=0 --gen-cs-nested-profile=0 --page-size=4096
+; RUN: FileCheck %s --input-file %t
+; RUN: llvm-profgen --perfscript=%S/Inputs/multi-load-segs-64k.perfscript --binary=%S/Inputs/multi-load-segs.perfbin --output=%t --format=text --csspgo-preinliner=0 --gen-cs-nested-profile=0 --page-size=65536
+; RUN: FileCheck %s --input-file %t --check-prefix=CHECK-64K
+
+;;  %S/Inputs/multi-load-segs.perfbin is an ELF image with two executable load segments.
+; running llvm-readelf -l %S/Inputs/multi-load-segs.perfbin gives:
+;;  LOAD           0x000000 0x0000000000200000 0x0000000000200000 0x00075c 0x00075c R   0x1000
+;;  LOAD           0x000760 0x0000000000201760 0x0000000000201760 0x0004c0 0x0004c0 R E 0x1000
+;;  LOAD           0x000c20 0x0000000000202c20 0x0000000000202c20 0x0001f0 0x0001f0 RW  0x1000
+;;  LOAD           0x000e10 0x0000000000203e10 0x0000000000203e10 0x000040 0x000058 RW  0x1000
+;;  LOAD           0x200000 0x0000000000400000 0x0000000000400000 0x0005e8 0x0005e8 R E 0x200000
+
+; INVALID: Number in -page-size=<num> must be positive power of two
+
+; CHECK:      [main:2 @ _Z10sort_arrayv:6 @ _Z11bubble_sortPii]:465:0
+; CHECK-NEXT:  4: 31
+; CHECK-NEXT:  5: 31
+; CHECK-NEXT:  7: 31
+; CHECK-NEXT:  8: 31
+; CHECK-NEXT:  65516: 31
+; CHECK-NEXT:    !Attributes: 1
+
+; CHECK-64K:      [main:2 @ _Z10sort_arrayv:6 @ _Z11bubble_sortPii]:465:0
+; CHECK-64K-NEXT:  4: 31
+; CHECK-64K-NEXT:  5: 31
+; CHECK-64K-NEXT:  7: 31
+; CHECK-64K-NEXT:  8: 31
+; CHECK-64K-NEXT:  65516: 31
+; CHECK-64K-NEXT:    !Attributes: 1
+
diff --git a/llvm/tools/llvm-profgen/ProfiledBinary.cpp b/llvm/tools/llvm-profgen/ProfiledBinary.cpp
index 08fd6917c9f3a..13c92933fab30 100644
--- a/llvm/tools/llvm-profgen/ProfiledBinary.cpp
+++ b/llvm/tools/llvm-profgen/ProfiledBinary.cpp
@@ -81,6 +81,12 @@ static cl::opt<bool>
                  cl::desc("Generate the profile for Linux kernel binary."),
                  cl::cat(ProfGenCategory));
 
+static cl::opt<unsigned> PageSize(
+    "page-size", cl::init(0x1000),
+    cl::desc("Page size for aligning segment addresses. Use 4096 for 4KB "
+             "pages (default) or 65536 for 64KB pages (e.g. AArch64)."),
+    cl::cat(ProfGenCategory));
+
 namespace sampleprof {
 
 static const Target *getTarget(const ObjectFile *Obj) {
@@ -362,22 +368,21 @@ template <class ELFT>
 void ProfiledBinary::setPreferredTextSegmentAddresses(const ELFFile<ELFT> &Obj,
                                                       StringRef FileName) {
   const auto &PhdrRange = unwrapOrError(Obj.program_headers(), FileName);
-  // FIXME: This should be the page size of the system running profiling.
-  // However such info isn't available at post-processing time, assuming
-  // 4K page now. Note that we don't use EXEC_PAGESIZE from <linux/param.h>
-  // because we may build the tools on non-linux.
-  uint64_t PageSize = 0x1000;
+  uint64_t LocalPageSize = PageSize;
+  if (!LocalPageSize || (LocalPageSize & (LocalPageSize - 1)))
+    exitWithError("Number in -page-size=<num> must be positive power of two", FileName);
+
   for (const typename ELFT::Phdr &Phdr : PhdrRange) {
     if (Phdr.p_type == ELF::PT_INTERP)
       HasInterp = true;
     if (Phdr.p_type == ELF::PT_LOAD) {
       if (!FirstLoadableAddress)
-        FirstLoadableAddress = Phdr.p_vaddr & ~(PageSize - 1U);
+        FirstLoadableAddress = Phdr.p_vaddr & ~(LocalPageSize - 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));
+                                                ~(LocalPageSize - 1U));
+        TextSegmentOffsets.push_back(Phdr.p_offset & ~(LocalPageSize - 1U));
       } else {
         PhdrInfo Info;
         Info.FileOffset = Phdr.p_offset;



More information about the llvm-commits mailing list