[llvm] [llvm-profgen] Support Arm SPE and BRBE branch profiles (PR #209769)

via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 15 07:35:17 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-binary-utilities

Author: Sergey Shcherbinin (SergeyShch01)

<details>
<summary>Changes</summary>

Profile support:
- Read Arm SPE branch samples by reusing the LBR machinery and modeling each sample as a single-entry LBR stack.
- Process AArch64 BRBE branch stacks through the existing LBR path.
- Add AArch64 tests for SPE and BRBE profiles.

New options:
- --spe-br-prof selects Arm SPE input.
- --perf-binary selects the perf executable.
- --page-size and --use-system-page-size control profiling page size.
- --warn-not-symbolized reports symbolization failures only for addresses covered by recorded MMAP ranges.

Bug fixes:
- Preserve a zero-valued first PT_LOAD address.
- Report perf invocation failures and prevent stale redirected output.

These changes are part of the work to introduce the universal profile-guided loop data prefetcher described in:
https://discourse.llvm.org/t/rfc-universal-profile-guided-automatic-software-loop-data-prefetcher-for-llvm/90916

Assisted by GPT-5

---

Patch is 47.71 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/209769.diff


15 Files Affected:

- (modified) llvm/docs/CommandGuide/llvm-profgen.rst (+32-5) 
- (added) llvm/test/tools/llvm-profgen/AArch64/brbe-branch-profile.test (+57) 
- (added) llvm/test/tools/llvm-profgen/AArch64/brbe-perfdata.test (+127) 
- (added) llvm/test/tools/llvm-profgen/AArch64/first-loadable-address.test (+58) 
- (added) llvm/test/tools/llvm-profgen/AArch64/page-size.test (+67) 
- (added) llvm/test/tools/llvm-profgen/AArch64/perf-binary-error.test (+46) 
- (added) llvm/test/tools/llvm-profgen/AArch64/spe-branch-profile.test (+74) 
- (added) llvm/test/tools/llvm-profgen/AArch64/spe-perfdata.test (+84) 
- (added) llvm/test/tools/llvm-profgen/AArch64/spe-range-gap.test (+66) 
- (added) llvm/test/tools/llvm-profgen/AArch64/warn-not-symbolized-mmap.test (+118) 
- (modified) llvm/tools/llvm-profgen/PerfReader.cpp (+141-18) 
- (modified) llvm/tools/llvm-profgen/PerfReader.h (+19-3) 
- (modified) llvm/tools/llvm-profgen/ProfiledBinary.cpp (+40-6) 
- (modified) llvm/tools/llvm-profgen/ProfiledBinary.h (+49-1) 
- (modified) llvm/tools/llvm-profgen/llvm-profgen.cpp (+8-4) 


``````````diff
diff --git a/llvm/docs/CommandGuide/llvm-profgen.rst b/llvm/docs/CommandGuide/llvm-profgen.rst
index 006cdfecf4f88..978aa3446ba44 100644
--- a/llvm/docs/CommandGuide/llvm-profgen.rst
+++ b/llvm/docs/CommandGuide/llvm-profgen.rst
@@ -21,8 +21,10 @@ At least one of the following commands are required:
 
 .. option:: --perfscript=<string[,string,...]>
 
-  Path of perf-script trace created by Linux perf tool with `script`
-  command(the raw perf.data should be profiled with -b).
+  Path of a trace created by the Linux ``perf script`` command. For LBR or BRBE
+  input, the raw perf data must contain branch stacks, for example from
+  recording with ``-b``. With ``--spe-br-prof``, the trace must contain Arm SPE
+  branch samples.
 
 .. option:: --etm=<string>
 
@@ -31,8 +33,9 @@ At least one of the following commands are required:
 
 .. option:: --perfdata=<perfdata>, --pd
 
-   Path of raw perf data created by Linux perf tool (it should be profiled
-   with -b).
+   Path of raw perf data created by the Linux perf tool. For LBR or BRBE input,
+   it must contain branch stacks, for example from recording with ``-b``. With
+   ``--spe-br-prof``, it must contain Arm SPE branch samples.
 
 .. option:: --unsymbolized-profile=<unsymbolized profile>, --up
 
@@ -71,6 +74,31 @@ OPTIONS
 
   Print mmap events.
 
+.. option:: --spe-br-prof
+
+  Read the input as an Arm SPE branch profile. Requires perf 6.13 or later to
+  process all branch samples; older versions provide only mispredicted
+  branches.
+
+.. option:: --perf-binary=<filename>
+
+  Path to the ``perf`` executable used to convert ``--perfdata`` input. If this
+  option is omitted, ``llvm-profgen`` searches for ``perf`` in ``PATH``.
+
+.. option:: --page-size=<bytes>
+
+  Page size of the system on which the profile was recorded. The value must be
+  a power of two. The default is 4096 bytes.
+
+.. option:: --use-system-page-size
+
+  Use the page size of the system running ``llvm-profgen``. This option cannot
+  be used together with ``--page-size``.
+
+.. option:: --warn-not-symbolized
+
+  Warn when an address covered by a recorded mmap range cannot be symbolized.
+
 .. option:: --show-disassembly
 
   Print disassembled code.
@@ -102,4 +130,3 @@ OPTIONS
 
    File path of a Linux perf raw trace (generated by ``perf report -D``) 
    consisting of memory access events.
-
diff --git a/llvm/test/tools/llvm-profgen/AArch64/brbe-branch-profile.test b/llvm/test/tools/llvm-profgen/AArch64/brbe-branch-profile.test
new file mode 100644
index 0000000000000..918e34f316efd
--- /dev/null
+++ b/llvm/test/tools/llvm-profgen/AArch64/brbe-branch-profile.test
@@ -0,0 +1,57 @@
+# RUN: split-file %s %t
+# RUN: yaml2obj %t/binary.yaml -o %t/brbe-branch-profile.exe
+# RUN: llvm-profgen --binary=%t/brbe-branch-profile.exe \
+# RUN:   --perfscript=%t/perfscript --skip-symbolization --use-offset=0 \
+# RUN:   --format=text --output=%t/profile
+# RUN: FileCheck %s --input-file=%t/profile
+
+## perf script represents Arm BRBE records using the same branch-stack format
+## as X86 LBR records. Verify that the generic LBR path handles an AArch64
+## binary, canonicalizes runtime addresses, and reconstructs the execution
+## range between consecutive branch records.
+# CHECK:      1
+# CHECK-NEXT: 1008-100c:1
+# CHECK-NEXT: 2
+# CHECK-NEXT: 1000->1008:1
+# CHECK-NEXT: 100c->1000:1
+
+#--- binary.yaml
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_DYN
+  Machine: EM_AARCH64
+  Entry:   0x1000
+Sections:
+  - Name:         .text
+    Type:         SHT_PROGBITS
+    Flags:        [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address:      0x1000
+    Offset:       0x1000
+    AddressAlign: 0x4
+    ## b 0x1008
+    ## nop
+    ## nop
+    ## b 0x1000
+    ## ret
+    Content:      020000141F2003D51F2003D5FDFFFF17C0035FD6
+ProgramHeaders:
+  - Type:     PT_LOAD
+    Flags:    [ PF_X, PF_R ]
+    Offset:   0
+    VAddr:    0
+    FileSize: 0x1014
+    MemSize:  0x1014
+    Align:    0x10000
+Symbols:
+  - Name:    foo
+    Type:    STT_FUNC
+    Section: .text
+    Binding: STB_GLOBAL
+    Value:   0x1000
+    Size:    0x14
+
+#--- perfscript
+PERF_RECORD_MMAP2 1/1: [0x700000000000(0x2000) @ 0 00:00 0 0]: r-xp /tmp/brbe-branch-profile.exe
+70000000100c 0x70000000100c/0x700000001000/P/-/-/0 0x700000001000/0x700000001008/P/-/-/0
diff --git a/llvm/test/tools/llvm-profgen/AArch64/brbe-perfdata.test b/llvm/test/tools/llvm-profgen/AArch64/brbe-perfdata.test
new file mode 100644
index 0000000000000..d510f73be058f
--- /dev/null
+++ b/llvm/test/tools/llvm-profgen/AArch64/brbe-perfdata.test
@@ -0,0 +1,127 @@
+# REQUIRES: system-linux
+
+# RUN: split-file %s %t
+# RUN: yaml2obj %t/binary.yaml -o %t/brbe-perfdata.exe
+# RUN: touch %t/perf.data
+# RUN: chmod +x %t/mock-perf %t/mock-perf-fail
+# RUN: llvm-profgen --binary=%t/brbe-perfdata.exe \
+# RUN:   --perfdata=%t/perf.data --perf-binary=%t/mock-perf \
+# RUN:   --skip-symbolization --use-offset=0 --format=text --output=%t/profile
+# RUN: FileCheck %s --check-prefix=PROFILE --input-file=%t/profile
+# RUN: not llvm-profgen --binary=%t/brbe-perfdata.exe \
+# RUN:   --perfdata=%t/perf.data --perf-binary=%t/mock-perf-fail \
+# RUN:   --output=/dev/null 2>&1 \
+# RUN:   | FileCheck %s --check-prefix=SECOND-ERROR
+
+## Verify that the non-SPE perfdata path requests ip,brstack. The first mock
+## invocation deliberately writes the complete second output plus a duplicate
+## sample. Without truncating the shared redirect file, that stale sample
+## survives the second invocation and doubles every profile count.
+# PROFILE:      1
+# PROFILE-NEXT: 1008-100c:1
+# PROFILE-NEXT: 2
+# PROFILE-NEXT: 1000->1008:1
+# PROFILE-NEXT: 100c->1000:1
+
+## The first invocation also leaves a longer stderr message. Verify that an
+## error from the second invocation contains only its own stderr.
+# SECOND-ERROR: error: Perf script failed with exit code 7
+# SECOND-ERROR-NEXT: second invocation failed
+# SECOND-ERROR-NOT: STALE-FIRST-STDERR
+
+#--- mock-perf
+#!/bin/sh
+
+if [ "$1" != "script" ] || [ "$2" != "--show-mmap-events" ] || \
+   [ "$3" != "-F" ] || [ "$5" != "-i" ] || [ ! -f "$6" ]; then
+  echo "unexpected perf arguments: $*" >&2
+  exit 2
+fi
+
+emit_sample() {
+  printf '%s\n' 'PERF_RECORD_MMAP2 1/1: [0x700000000000(0x2000) @ 0 00:00 0 0]: r-xp /tmp/brbe-perfdata.exe'
+  printf '%s\n' '70000000100c 0x70000000100c/0x700000001000/P/-/-/0 0x700000001000/0x700000001008/P/-/-/0'
+}
+
+case "$4" in
+  comm,pid)
+    if [ "$#" -ne 6 ]; then
+      echo "unexpected mmap arguments: $*" >&2
+      exit 2
+    fi
+    emit_sample
+    printf '%s\n' '70000000100c 0x70000000100c/0x700000001000/P/-/-/0 0x700000001000/0x700000001008/P/-/-/0'
+    ;;
+  ip,brstack)
+    if [ "$#" -ne 8 ] || [ "$7" != "--pid" ] || [ "$8" != "1" ]; then
+      echo "unexpected sample arguments: $*" >&2
+      exit 2
+    fi
+    emit_sample
+    ;;
+  *)
+    echo "unexpected perf fields: $4" >&2
+    exit 2
+    ;;
+esac
+
+#--- mock-perf-fail
+#!/bin/sh
+
+if [ "$1" != "script" ] || [ "$2" != "--show-mmap-events" ] || \
+   [ "$3" != "-F" ] || [ "$5" != "-i" ] || [ ! -f "$6" ]; then
+  echo "unexpected perf arguments: $*" >&2
+  exit 2
+fi
+
+case "$4" in
+  comm,pid)
+    printf '%s\n' 'PERF_RECORD_MMAP2 1/1: [0x700000000000(0x2000) @ 0 00:00 0 0]: r-xp /tmp/brbe-perfdata.exe'
+    printf '%s\n' 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx STALE-FIRST-STDERR' >&2
+    ;;
+  ip,brstack)
+    printf '%s\n' 'second invocation failed' >&2
+    exit 7
+    ;;
+  *)
+    echo "unexpected perf fields: $4" >&2
+    exit 2
+    ;;
+esac
+
+#--- binary.yaml
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_DYN
+  Machine: EM_AARCH64
+  Entry:   0x1000
+Sections:
+  - Name:         .text
+    Type:         SHT_PROGBITS
+    Flags:        [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address:      0x1000
+    Offset:       0x1000
+    AddressAlign: 0x4
+    ## b 0x1008
+    ## nop
+    ## nop
+    ## b 0x1000
+    ## ret
+    Content:      020000141F2003D51F2003D5FDFFFF17C0035FD6
+ProgramHeaders:
+  - Type:     PT_LOAD
+    Flags:    [ PF_X, PF_R ]
+    Offset:   0
+    VAddr:    0
+    FileSize: 0x1014
+    MemSize:  0x1014
+    Align:    0x10000
+Symbols:
+  - Name:    foo
+    Type:    STT_FUNC
+    Section: .text
+    Binding: STB_GLOBAL
+    Value:   0x1000
+    Size:    0x14
diff --git a/llvm/test/tools/llvm-profgen/AArch64/first-loadable-address.test b/llvm/test/tools/llvm-profgen/AArch64/first-loadable-address.test
new file mode 100644
index 0000000000000..3264d81866b8b
--- /dev/null
+++ b/llvm/test/tools/llvm-profgen/AArch64/first-loadable-address.test
@@ -0,0 +1,58 @@
+# RUN: split-file %s %t
+# RUN: yaml2obj %t/binary.yaml -o %t/first-loadable-address.exe
+# RUN: llvm-profgen --binary=%t/first-loadable-address.exe \
+# RUN:   --perfscript=%t/perfscript --skip-symbolization --format=text \
+# RUN:   --page-size=65536 --use-offset=1 \
+# RUN:   --use-first-loadable-segment-as-base=1 --output=%t/profile
+# RUN: FileCheck %s --input-file=%t/profile
+
+## The first PT_LOAD has a valid zero virtual address. Ensure it is not treated
+## as an unset value and overwritten by the following executable PT_LOAD.
+# CHECK:      0
+# CHECK-NEXT: 1
+# CHECK-NEXT: 11008->11000:1
+
+#--- binary.yaml
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_DYN
+  Machine: EM_AARCH64
+  Entry:   0x0000000000011000
+Sections:
+  - Name:         .text
+    Type:         SHT_PROGBITS
+    Flags:        [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address:      0x0000000000011000
+    Offset:       0x0000000000001000
+    AddressAlign: 0x4
+    ## nop
+    ## nop
+    ## ret
+    Content:      1F2003D51F2003D5C0035FD6
+ProgramHeaders:
+  - Type:     PT_LOAD
+    Flags:    [ PF_R ]
+    Offset:   0x0
+    VAddr:    0x0
+    FileSize: 0x1000
+    MemSize:  0x1000
+    Align:    0x10000
+  - Type:     PT_LOAD
+    Flags:    [ PF_X, PF_R ]
+    VAddr:    0x0000000000011000
+    Align:    0x10000
+    FirstSec: .text
+    LastSec:  .text
+Symbols:
+  - Name:    foo
+    Type:    STT_FUNC
+    Section: .text
+    Binding: STB_GLOBAL
+    Value:   0x0000000000011000
+    Size:    0xC
+
+#--- perfscript
+PERF_RECORD_MMAP2 1/1: [0x700000000000(0x10000) @ 0 00:00 0 0]: r-xp /tmp/first-loadable-address.exe
+700000001000 0x700000001008/0x700000001000/P/-/-/0
diff --git a/llvm/test/tools/llvm-profgen/AArch64/page-size.test b/llvm/test/tools/llvm-profgen/AArch64/page-size.test
new file mode 100644
index 0000000000000..dba631c6ce5d4
--- /dev/null
+++ b/llvm/test/tools/llvm-profgen/AArch64/page-size.test
@@ -0,0 +1,67 @@
+# RUN: split-file %s %t
+# RUN: yaml2obj %t/binary.yaml -o %t/page-size.exe
+
+## A 64 KiB profiling system maps the executable segment from file offset zero.
+# RUN: llvm-profgen --binary=%t/page-size.exe --perfscript=%t/64k.perfscript \
+# RUN:   --skip-symbolization --use-offset=0 --format=text --page-size=65536 \
+# RUN:   --output=%t/explicit-64k.prof
+# RUN: FileCheck %s --check-prefix=PROFILE --input-file=%t/explicit-64k.prof
+
+# RUN: not llvm-profgen --binary=%t/page-size.exe --show-disassembly-only \
+# RUN:   --page-size=3 --output=/dev/null 2>&1 \
+# RUN:   | FileCheck %s --check-prefix=INVALID
+# RUN: not llvm-profgen --binary=%t/page-size.exe --show-disassembly-only \
+# RUN:   --page-size=4096 --use-system-page-size --output=/dev/null 2>&1 \
+# RUN:   | FileCheck %s --check-prefix=CONFLICT
+
+# PROFILE:      0
+# PROFILE-NEXT: 1
+# PROFILE-NEXT: 11008->11000:1
+
+# INVALID: error: --page-size must be a power of two
+# CONFLICT: error: --page-size and --use-system-page-size cannot be used together
+
+#--- binary.yaml
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_DYN
+  Machine: EM_AARCH64
+  Entry:   0x0000000000011000
+Sections:
+  - Name:         .text
+    Type:         SHT_PROGBITS
+    Flags:        [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address:      0x0000000000011000
+    Offset:       0x0000000000001000
+    AddressAlign: 0x4
+    ## nop
+    ## nop
+    ## ret
+    Content:      1F2003D51F2003D5C0035FD6
+ProgramHeaders:
+  - Type:     PT_LOAD
+    Flags:    [ PF_R ]
+    Offset:   0x0
+    VAddr:    0x0000000000010000
+    FileSize: 0x1000
+    MemSize:  0x1000
+    Align:    0x10000
+  - Type:     PT_LOAD
+    Flags:    [ PF_X, PF_R ]
+    VAddr:    0x0000000000011000
+    Align:    0x10000
+    FirstSec: .text
+    LastSec:  .text
+Symbols:
+  - Name:    foo
+    Type:    STT_FUNC
+    Section: .text
+    Binding: STB_GLOBAL
+    Value:   0x0000000000011000
+    Size:    0xC
+
+#--- 64k.perfscript
+PERF_RECORD_MMAP2 1/1: [0x700000000000(0x10000) @ 0 00:00 0 0]: r-xp /tmp/page-size.exe
+700000001000 0x700000001008/0x700000001000/P/-/-/0
diff --git a/llvm/test/tools/llvm-profgen/AArch64/perf-binary-error.test b/llvm/test/tools/llvm-profgen/AArch64/perf-binary-error.test
new file mode 100644
index 0000000000000..5458f205a7bad
--- /dev/null
+++ b/llvm/test/tools/llvm-profgen/AArch64/perf-binary-error.test
@@ -0,0 +1,46 @@
+# RUN: split-file %s %t
+# RUN: yaml2obj %t/binary.yaml -o %t/perf-binary-error.exe
+# RUN: touch %t/perf.data
+
+# RUN: not llvm-profgen --binary=%t/perf-binary-error.exe \
+# RUN:   --perfdata=%t/perf.data --perf-binary yaml2obj --output=/dev/null \
+# RUN:   2>&1 | FileCheck %s --check-prefix=EXIT
+# RUN: not llvm-profgen --binary=%t/perf-binary-error.exe \
+# RUN:   --perfdata=%t/perf.data --perf-binary=%t/missing-perf \
+# RUN:   --output=/dev/null 2>&1 | FileCheck %s --check-prefix=EXEC
+
+# EXIT: error: Perf script failed with exit code 1
+# EXIT: yaml2obj
+# EXEC: error: Failed to execute perf script
+
+#--- binary.yaml
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_DYN
+  Machine: EM_AARCH64
+Sections:
+  - Name:         .text
+    Type:         SHT_PROGBITS
+    Flags:        [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address:      0x1000
+    Offset:       0x1000
+    AddressAlign: 0x4
+    ## ret
+    Content:      C0035FD6
+ProgramHeaders:
+  - Type:     PT_LOAD
+    Flags:    [ PF_X, PF_R ]
+    Offset:   0
+    VAddr:    0
+    Align:    0x1000
+    FirstSec: .text
+    LastSec:  .text
+Symbols:
+  - Name:    foo
+    Type:    STT_FUNC
+    Section: .text
+    Binding: STB_GLOBAL
+    Value:   0x1000
+    Size:    0x4
diff --git a/llvm/test/tools/llvm-profgen/AArch64/spe-branch-profile.test b/llvm/test/tools/llvm-profgen/AArch64/spe-branch-profile.test
new file mode 100644
index 0000000000000..2c2477dcf41ca
--- /dev/null
+++ b/llvm/test/tools/llvm-profgen/AArch64/spe-branch-profile.test
@@ -0,0 +1,74 @@
+# RUN: split-file %s %t
+# RUN: yaml2obj %t/binary.yaml -o %t/spe-branch-profile.exe
+# RUN: llvm-profgen --binary=%t/spe-branch-profile.exe \
+# RUN:   --perfscript=%t/perfscript --spe-br-prof --skip-symbolization \
+# RUN:   --use-offset=0 --format=text --output=%t/profile 2>&1 \
+# RUN:   | FileCheck --allow-empty %s --check-prefix=NO-WARN
+# RUN: FileCheck %s --input-file=%t/profile
+# RUN: llvm-profgen --binary=%t/spe-branch-profile.exe \
+# RUN:   --perfscript=%t/malformed.perfscript --spe-br-prof \
+# RUN:   --skip-symbolization --output=/dev/null 2>&1 \
+# RUN:   | FileCheck %s --check-prefix=INVALID
+
+## Arm SPE prints each branch as <Dst> <Src>. Use different source and
+## destination addresses to verify their order, canonicalize them through the
+## runtime MMAP, and infer the executed range up to the nearest transfer. The
+## second record is a not-taken conditional branch whose destination is the
+## fall-through instruction rather than the statically encoded branch target.
+# NO-WARN-NOT: warning: {{.*}}branch targets do not match the binary
+
+# CHECK:      2
+# CHECK-NEXT: 1000-1008:1
+# CHECK-NEXT: 100c-100c:1
+# CHECK-NEXT: 2
+# CHECK-NEXT: 1008->1000:1
+# CHECK-NEXT: 1008->100c:1
+
+# INVALID: warning: Invalid Arm SPE branch record at line 2: 70000000100a
+# INVALID-NOT: warning: Invalid Arm SPE branch record
+
+#--- binary.yaml
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_DYN
+  Machine: EM_AARCH64
+  Entry:   0x1000
+Sections:
+  - Name:         .text
+    Type:         SHT_PROGBITS
+    Flags:        [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address:      0x1000
+    Offset:       0x1000
+    AddressAlign: 0x4
+    ## nop
+    ## nop
+    ## b.eq 0x1000
+    ## ret
+    Content:      1F2003D51F2003D5C0FFFF54C0035FD6
+ProgramHeaders:
+  - Type:     PT_LOAD
+    Flags:    [ PF_X, PF_R ]
+    Offset:   0
+    VAddr:    0
+    FileSize: 0x1010
+    MemSize:  0x1010
+    Align:    0x10000
+Symbols:
+  - Name:    foo
+    Type:    STT_FUNC
+    Section: .text
+    Binding: STB_GLOBAL
+    Value:   0x1000
+    Size:    0x10
+
+#--- perfscript
+PERF_RECORD_MMAP2 1/1: [0x700000000000(0x2000) @ 0 00:00 0 0]: r-xp /tmp/spe-branch-profile.exe
+700000001000 700000001008
+70000000100c 700000001008
+
+#--- malformed.perfscript
+PERF_RECORD_MMAP2 1/1: [0x700000000000(0x2000) @ 0 00:00 0 0]: r-xp /tmp/spe-branch-profile.exe
+70000000100a
+700000003000 700000003004
diff --git a/llvm/test/tools/llvm-profgen/AArch64/spe-perfdata.test b/llvm/test/tools/llvm-profgen/AArch64/spe-perfdata.test
new file mode 100644
index 0000000000000..32188d9f0afb5
--- /dev/null
+++ b/llvm/test/tools/llvm-profgen/AArch64/spe-perfdata.test
@@ -0,0 +1,84 @@
+# REQUIRES: system-linux
+
+# RUN: split-file %s %t
+# RUN: yaml2obj %t/binary.yaml -o %t/spe-perfdata.exe
+# RUN: touch %t/perf.data
+# RUN: chmod +x %t/mock-perf
+# RUN: llvm-profgen --binary=%t/spe-perfdata.exe \
+# RUN:   --perfdata=%t/perf.data --perf-binary=%t/mock-perf --spe-br-prof \
+# RUN:   --skip-symbolization --use-offset=0 --format=text --output=%t/profile
+# RUN: FileCheck %s --input-file=%t/profile
+
+## The mock validates both perf invocations, including the addr field required
+## for Arm SPE, while the profile checks that the second invocation's output
+## is consumed.
+# CHECK:      1
+# CHECK-NEXT: 1000-1008:1
+# CHECK-NEXT: 1
+# CHECK-NEXT: 1008->1000:1
+
+#--- mock-perf
+#!/bin/sh
+
+if [ "$1" != "script" ] || [ "$2" != "--show-mmap-events" ] || \
+   [ "$3" != "-F" ] || [ "$5" != "-i" ] || [ ! -f "$6" ]; then
+  echo "unexpected perf arguments: $*" >&2
+  exit 2
+fi
+
+case "$4" in
+  comm,pid)
+    if [ "$#" -ne 6 ]; then
+      echo "unexpected mmap arguments: $*" >&2
+      exit 2
+    fi
+    printf '%s\n' 'PERF_RECORD_MMAP2 1/1: [0x700000000000(0x2000) @ 0 00:00 0 0]: r-xp /tmp/spe-perfdata.exe'
+    ;;
+  ip,addr)
+    if [ "$#" -ne 8 ] || [ "$7" != "--pid" ] || [ "$8" != "1" ]; then
+      echo "unexpected sample arguments: $*" >&2
+      exit 2
+    fi
+    printf '%s\n' 'PERF_RECORD_MMAP2 1/1: [0x700000000000(0x2000) @ 0 00:00 0 0]: r-xp /tmp/spe-perfdata.exe'
+    printf '%s\n' '700000001000 700000001008'
+    ;;
+  *)
+    echo "unexpected perf fields: $4" >&2
+    exit 2
+    ;;
+esac
+
+#--- binary.yaml
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_DYN
+  Machine: EM_AARCH64
+  Entry:   0x1000
+Sections:
+  - Name:         .text
+    Type:         SHT_PROGBITS
+    Flags:        [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address:      0x1000
+    Offset:       0x1000
+    AddressAlign: 0x4
+    ## nop
+    ## nop
+    ## b 0x1000
+    Content:      1F2003D51F2003D5FEFFFF17
+ProgramHeaders:
+  - Type:     PT_LOAD
+    Flags:    [ PF_X, PF_R ]
+    Offset:   0
+    VAddr:    0
+    FileSize: 0x100C
+    MemSize:  0x100C
+    Align:    0x10000
+Symbols:
+  - Name:    foo
+    Type:    STT_FUNC
+    Section: .text
+    Binding: STB_GLOBAL
+    Value:   0x1000
+    Size:    0xC
diff --git a/llvm/test/tools/llvm-profgen/AArch64/spe-range-gap.test b/llvm/test/tools/llvm-profgen/AArch64/spe-range-gap.test
new file mode 100644
index 0000000000000..534e65c27c4e9
--- /dev/null
+++ b/llvm/test/tools/llvm-profgen/AArch64/spe-range-gap.test
@@ -0,0 +1,66 @@
+# RUN: split-file %s %t
+# RUN: yaml2obj %t/binary.yaml -o %t/spe-range-gap.exe
+# RUN: llvm-profgen --binary=%t/spe-range-gap.exe \
+# RUN:   --perfscript=%t/perfscript --spe-br-prof --skip-symbolization \
+# RUN:   --use-offset=0 --format=text --output=%t/profile
+# RUN: FileCheck %s --input-file=%t/profile
+
+## The decoded instruction addresses are 0x1000, 0x1004, and 0x2000. Do not
+## extend the inferred range across the address gap to the transfer at 0x2000.
+## The independently recorded branch count must remain unchanged.
+# CHECK:  ...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/209769


More information about the llvm-commits mailing list