[llvm] [InstrProf] Disambiguate zero bitmaps in text profiles (PR #213906)

via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 4 23:48:52 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-pgo

Author: Karim Alweheshy (karim-alweheshy)

<details>
<summary>Changes</summary>

## Summary

- Always emit the bitmap-byte count in instrumentation text profiles, including an explicit `$0` for records without bitmap data.
- Treat only numeric-looking `$...` lines as bitmap counts so a following Swift `$s...` function name is not consumed as malformed bitmap metadata.
- Add a reduced legacy-input regression and update the affected text-output expectation.

## Motivation

`InstrProfWriter` currently omits the bitmap field when it is empty, while `TextInstrProfReader` treats any following line beginning with `$` as the bitmap-byte count. If the next function is a Swift mangled name such as `$s4main3fooyyF`, a valid writer-produced text profile cannot be read back and `llvm-profdata merge` reports `number of bitmap bytes is not a valid integer`.

Writing `$0` makes new text profiles unambiguous. Narrowing the legacy reader check allows existing profiles with the omitted field to recover Swift names. Names beginning with `$` followed by a digit remain inherently ambiguous in legacy text, but writer-produced profiles no longer rely on that boundary.

## Testing

- Reproduced the original failure with Apple LLVM 21 as a negative control.
- Verified the split-file fixture and FileCheck assertions against the expected canonical output.
- Verified changed C++ lines with `clang-format --dry-run --Werror`.
- Verified `git diff --check`.
- LLVM premerge passes on Linux, Linux AArch64, Windows, and macOS arm64; formatter, ABI-annotation, project-computation, and libc++ checks also pass.
- This sparse checkout intentionally has no local full LLVM build.


---
Full diff: https://github.com/llvm/llvm-project/pull/213906.diff


8 Files Affected:

- (modified) llvm/lib/ProfileData/InstrProfReader.cpp (+6-2) 
- (modified) llvm/lib/ProfileData/InstrProfWriter.cpp (+2-2) 
- (modified) llvm/test/tools/llvm-profdata/Inputs/CSIR_profile.proftext (+2) 
- (modified) llvm/test/tools/llvm-profdata/Inputs/IR_profile.proftext (+2) 
- (modified) llvm/test/tools/llvm-profdata/Inputs/cs.proftext (+2) 
- (modified) llvm/test/tools/llvm-profdata/Inputs/instr-remap.expected (+6) 
- (modified) llvm/test/tools/llvm-profdata/merge-filter.test (+6-1) 
- (added) llvm/test/tools/llvm-profdata/text-zero-bitmap.test (+25) 


``````````diff
diff --git a/llvm/lib/ProfileData/InstrProfReader.cpp b/llvm/lib/ProfileData/InstrProfReader.cpp
index 05770f83ed160..44f938ae90553 100644
--- a/llvm/lib/ProfileData/InstrProfReader.cpp
+++ b/llvm/lib/ProfileData/InstrProfReader.cpp
@@ -444,8 +444,12 @@ Error TextInstrProfReader::readNextRecord(NamedInstrProfRecord &Record) {
     Record.Counts.push_back(Count);
   }
 
-  // Bitmap byte information is indicated with special character.
-  if (Line->starts_with("$")) {
+  // Bitmap byte information is indicated by '$' followed by an integer. Only
+  // treat numeric-looking lines as bitmap records so function names such as
+  // Swift manglings beginning with "$s" remain unambiguous.
+  StringRef BitmapSize =
+      Line->starts_with("$") ? Line->drop_front(1).trim() : StringRef();
+  if (!BitmapSize.empty() && isDigit(BitmapSize.front())) {
     Record.BitmapBytes.clear();
     // Read the number of bitmap bytes.
     uint64_t NumBitmapBytes;
diff --git a/llvm/lib/ProfileData/InstrProfWriter.cpp b/llvm/lib/ProfileData/InstrProfWriter.cpp
index 3dbbcc69ba9e2..1dbace34692e2 100644
--- a/llvm/lib/ProfileData/InstrProfWriter.cpp
+++ b/llvm/lib/ProfileData/InstrProfWriter.cpp
@@ -749,8 +749,8 @@ void InstrProfWriter::writeRecordInText(StringRef Name, uint64_t Hash,
   for (uint64_t Count : Func.Counts)
     OS << Count << "\n";
 
-  if (Func.BitmapBytes.size() > 0) {
-    OS << "# Num Bitmap Bytes:\n$" << Func.BitmapBytes.size() << "\n";
+  OS << "# Num Bitmap Bytes:\n$" << Func.BitmapBytes.size() << "\n";
+  if (!Func.BitmapBytes.empty()) {
     OS << "# Bitmap Byte Values:\n";
     for (uint8_t Byte : Func.BitmapBytes) {
       OS << "0x";
diff --git a/llvm/test/tools/llvm-profdata/Inputs/CSIR_profile.proftext b/llvm/test/tools/llvm-profdata/Inputs/CSIR_profile.proftext
index 0881a532a22e9..ea0645c4f53d3 100644
--- a/llvm/test/tools/llvm-profdata/Inputs/CSIR_profile.proftext
+++ b/llvm/test/tools/llvm-profdata/Inputs/CSIR_profile.proftext
@@ -8,4 +8,6 @@ bar
 # Counter Values:
 99938
 62
+# Num Bitmap Bytes:
+$0
 
diff --git a/llvm/test/tools/llvm-profdata/Inputs/IR_profile.proftext b/llvm/test/tools/llvm-profdata/Inputs/IR_profile.proftext
index 7b7340ec2956a..88321a2ec448e 100644
--- a/llvm/test/tools/llvm-profdata/Inputs/IR_profile.proftext
+++ b/llvm/test/tools/llvm-profdata/Inputs/IR_profile.proftext
@@ -6,4 +6,6 @@ main
 1
 # Counter Values:
 1
+# Num Bitmap Bytes:
+$0
 
diff --git a/llvm/test/tools/llvm-profdata/Inputs/cs.proftext b/llvm/test/tools/llvm-profdata/Inputs/cs.proftext
index 99e1825b03602..44bf125c0a89b 100644
--- a/llvm/test/tools/llvm-profdata/Inputs/cs.proftext
+++ b/llvm/test/tools/llvm-profdata/Inputs/cs.proftext
@@ -8,3 +8,5 @@ bar
 # Counter Values:
 99938
 62
+# Num Bitmap Bytes:
+$0
diff --git a/llvm/test/tools/llvm-profdata/Inputs/instr-remap.expected b/llvm/test/tools/llvm-profdata/Inputs/instr-remap.expected
index f5ff527301155..373967ef1976c 100644
--- a/llvm/test/tools/llvm-profdata/Inputs/instr-remap.expected
+++ b/llvm/test/tools/llvm-profdata/Inputs/instr-remap.expected
@@ -8,6 +8,8 @@ bar
 # Counter Values:
 31
 42
+# Num Bitmap Bytes:
+$0
 
 bar
 # Func Hash:
@@ -17,6 +19,8 @@ bar
 # Counter Values:
 500
 600
+# Num Bitmap Bytes:
+$0
 
 baz
 # Func Hash:
@@ -26,4 +30,6 @@ baz
 # Counter Values:
 7
 8
+# Num Bitmap Bytes:
+$0
 
diff --git a/llvm/test/tools/llvm-profdata/merge-filter.test b/llvm/test/tools/llvm-profdata/merge-filter.test
index 5c47c6a75a7c4..97432c9f01290 100644
--- a/llvm/test/tools/llvm-profdata/merge-filter.test
+++ b/llvm/test/tools/llvm-profdata/merge-filter.test
@@ -31,6 +31,8 @@ CHECK-NEXT: 2
 CHECK-NEXT: # Counter Values:
 CHECK-NEXT: 499500
 CHECK-NEXT: 179900
+CHECK-NEXT: # Num Bitmap Bytes:
+CHECK-NEXT: $0
 CHECK-NEXT: 
 CHECK-NEXT: foo2
 CHECK-NEXT: # Func Hash:
@@ -40,6 +42,8 @@ CHECK-NEXT: 2
 CHECK-NEXT: # Counter Values:
 CHECK-NEXT: 500500
 CHECK-NEXT: 180100
+CHECK-NEXT: # Num Bitmap Bytes:
+CHECK-NEXT: $0
 
 RUN: llvm-profdata merge --instr %p/Inputs/basic.proftext --text --function="foo" --no-function="^foo$" | FileCheck %s --check-prefix=CHECK-FILTER4
 CHECK-FILTER4: foo2
@@ -50,6 +54,8 @@ CHECK-NEXT: 2
 CHECK-NEXT: # Counter Values:
 CHECK-NEXT: 500500
 CHECK-NEXT: 180100
+CHECK-NEXT: # Num Bitmap Bytes:
+CHECK-NEXT: $0
 
 RUN: llvm-profdata merge --sample %p/Inputs/cs-sample.proftext --text --function="main.*@.*_Z5funcBi" | FileCheck %s --check-prefix=CHECK-FILTER5
 CHECK-FILTER5: [main:3.1 @ _Z5funcBi:1 @ _Z8funcLeafi]:500853:20
@@ -66,4 +72,3 @@ CHECK-NEXT:  0: 19
 CHECK-NEXT:  1: 19 _Z8funcLeafi:20
 CHECK-NEXT:  3: 12
 CHECK-NEXT:  !Attributes: 1
-
diff --git a/llvm/test/tools/llvm-profdata/text-zero-bitmap.test b/llvm/test/tools/llvm-profdata/text-zero-bitmap.test
new file mode 100644
index 0000000000000..445b076a5e847
--- /dev/null
+++ b/llvm/test/tools/llvm-profdata/text-zero-bitmap.test
@@ -0,0 +1,25 @@
+# A missing zero-bitmap record must not make a following Swift function name
+# look like a bitmap count. The text writer makes the record explicit so its
+# output can be read back without ambiguity.
+RUN: split-file %s %t
+RUN: llvm-profdata merge --instr --text %t/legacy.proftext -o %t/a
+RUN: FileCheck %s --input-file=%t/a --check-prefix=GENERATED
+RUN: llvm-profdata merge --instr --text %t/a -o %t/b
+RUN: diff %t/a %t/b
+
+GENERATED-LABEL: !zero_bitmap
+GENERATED: # Num Bitmap Bytes:
+GENERATED-NEXT: $0
+GENERATED: $s4main3fooyyF
+GENERATED: # Num Bitmap Bytes:
+GENERATED-NEXT: $0
+
+;--- legacy.proftext
+!zero_bitmap
+1
+1
+7
+$s4main3fooyyF
+2
+1
+9

``````````

</details>


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


More information about the llvm-commits mailing list