[llvm] [SHT_LLVM_BB_ADDR_MAP][obj2yaml] Implements PGOAnalysisMap for elf2yaml and tests. (PR #80924)

Micah Weston via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 12 12:13:13 PST 2024


https://github.com/red1bluelost updated https://github.com/llvm/llvm-project/pull/80924

>From bc438a6044382edfc23f9c3dad1a983ffdff7467 Mon Sep 17 00:00:00 2001
From: Micah Weston <micahsweston at gmail.com>
Date: Wed, 1 Nov 2023 13:24:00 -0400
Subject: [PATCH 1/2] [SHT_LLVM_BB_ADDR_MAP][obj2yaml] Implements
 PGOAnalysisMap for elf2yaml and tests.

---
 .../ELF/bb-addr-map-pgo-analysis-map.yaml     | 232 ++++++++++++++++++
 .../ELF/bb-addr-map-pgo-analysis-map.yaml     |  83 +++++++
 llvm/tools/obj2yaml/elf2yaml.cpp              |  34 +++
 3 files changed, 349 insertions(+)
 create mode 100644 llvm/test/tools/obj2yaml/ELF/bb-addr-map-pgo-analysis-map.yaml
 create mode 100644 llvm/test/tools/yaml2obj/ELF/bb-addr-map-pgo-analysis-map.yaml

diff --git a/llvm/test/tools/obj2yaml/ELF/bb-addr-map-pgo-analysis-map.yaml b/llvm/test/tools/obj2yaml/ELF/bb-addr-map-pgo-analysis-map.yaml
new file mode 100644
index 00000000000000..3bb03e6efb8ec1
--- /dev/null
+++ b/llvm/test/tools/obj2yaml/ELF/bb-addr-map-pgo-analysis-map.yaml
@@ -0,0 +1,232 @@
+## Check how obj2yaml produces YAML PGO Analysis Map in .llvm_bb_addr_map.
+
+## Check that obj2yaml uses the "Entries" tag to describe an .llvm_bb_addr_map section.
+
+# RUN: yaml2obj --docnum=1 %s -o %t1
+# RUN: obj2yaml %t1 | FileCheck %s --check-prefix=VALID
+
+# VALID:      --- !ELF
+# VALID-NEXT: FileHeader:
+# VALID-NEXT:   Class: ELFCLASS64
+# VALID-NEXT:   Data:  ELFDATA2LSB
+# VALID-NEXT:   Type:  ET_EXEC
+# VALID-NEXT: Sections:
+# VALID-NEXT:   - Name: .llvm_bb_addr_map
+# VALID-NEXT:     Type: SHT_LLVM_BB_ADDR_MAP
+# VALID-NEXT:     Entries:
+# VALID-NEXT:       - Version: 2
+# VALID-NEXT:         Feature: 0x7
+## The 'BaseAddress' field is omitted when it's zero.
+# VALID-NEXT:         BBRanges:
+# VALID-NEXT:           - BBEntries:
+# VALID-NEXT:             - ID:            0
+# VALID-NEXT:               AddressOffset: 0x1
+# VALID-NEXT:               Size:          0x2
+# VALID-NEXT:               Metadata:      0x3
+# VALID-NEXT:             - ID:            2
+# VALID-NEXT:               AddressOffset: 0x4
+# VALID-NEXT:               Size:          0x5
+# VALID-NEXT:               Metadata:      0x6
+# VALID-NEXT:             - ID:            4
+# VALID-NEXT:               AddressOffset: 0xFFFFFFFFFFFFFFF7
+# VALID-NEXT:               Size:          0xFFFFFFFFFFFFFFF8
+# VALID-NEXT:               Metadata:      0xFFFFFFFFFFFFFFF9
+# VALID-NEXT:       - Version: 2
+# VALID-NEXT:         Feature: 0xA
+# VALID-NEXT:         BBRanges:
+# VALID-NEXT:           - BaseAddress: 0xFFFFFFFFFFFFFF20
+# VALID-NEXT:             BBEntries:
+# VALID-NEXT:               - ID:            6
+# VALID-NEXT:                 AddressOffset: 0xA
+# VALID-NEXT:                 Size:          0xB
+# VALID-NEXT:                 Metadata:      0xC
+# VALID-NEXT:     PGOAnalyses:
+# VALID-NEXT:       - FuncEntryCount: 100
+# VALID-NEXT:         PGOBBEntries:
+# VALID-NEXT:           - BBFreq:        100
+# VALID-NEXT:             Successors:
+# VALID-NEXT:               - ID:        2
+# VALID-NEXT:                 BrProb:    0x80000000
+# VALID-NEXT:               - ID:        4
+# VALID-NEXT:                 BrProb:    0x80000000
+# VALID-NEXT:           - BBFreq:        50
+# VALID-NEXT:             Successors:
+# VALID-NEXT:               - ID:        4
+# VALID-NEXT:                 BrProb:    0xFFFFFFFF
+# VALID-NEXT:           - BBFreq:        100
+# VALID-NEXT:             Successors:    []
+# VALID-NEXT:         PGOBBEntries:
+# VALID-NEXT:           - BBFreq:        20
+
+--- !ELF
+FileHeader:
+  Class: ELFCLASS64
+  Data:  ELFDATA2LSB
+  Type:  ET_EXEC
+Sections:
+  - Name:   .llvm_bb_addr_map
+    Type:   SHT_LLVM_BB_ADDR_MAP
+    ShSize: [[SIZE=<none>]]
+    Entries:
+      - Version: 2
+        Feature: 0x7
+        BBRanges:
+          - BaseAddress: 0x0
+            BBEntries:
+              - ID:            0
+                AddressOffset: 0x1
+                Size:          0x2
+                Metadata:      0x3
+              - ID:            2
+                AddressOffset: 0x4
+                Size:          0x5
+                Metadata:      0x6
+              - ID:            4
+                AddressOffset: 0xFFFFFFFFFFFFFFF7
+                Size:          0xFFFFFFFFFFFFFFF8
+                Metadata:      0xFFFFFFFFFFFFFFF9
+      - Version:   2
+        Feature:   0xA
+        BBRanges:
+          - BaseAddress:   0xFFFFFFFFFFFFFF20
+            BBEntries:
+             - ID:            6
+               AddressOffset: 0xA
+               Size:          0xB
+               Metadata:      0xC
+    PGOAnalyses:
+      - FuncEntryCount: 100
+        PGOBBEntries:
+          - BBFreq:        100
+            Successors:
+              - ID:        2
+                BrProb:    0x80000000
+              - ID:        4
+                BrProb:    0x80000000
+          - BBFreq:        50
+            Successors:
+              - ID:        4
+                BrProb:    0xFFFFFFFF
+          - BBFreq:        100
+            Successors: []
+      - PGOBBEntries:
+          - BBFreq:        20
+
+## Check obj2yaml can dump multiple .llvm_bb_addr_map sections.
+
+# RUN: yaml2obj --docnum=2 %s -o %t2
+# RUN: obj2yaml %t2 | FileCheck %s --check-prefix=MULTI
+
+# MULTI:      --- !ELF
+# MULTI-NEXT: FileHeader:
+# MULTI-NEXT:   Class: ELFCLASS64
+# MULTI-NEXT:   Data:  ELFDATA2LSB
+# MULTI-NEXT:   Type:  ET_EXEC
+# MULTI-NEXT: Sections:
+# MULTI-NEXT:   - Name: .llvm_bb_addr_map
+# MULTI-NEXT:     Type: SHT_LLVM_BB_ADDR_MAP
+# MULTI-NEXT:     Entries:
+## Fieldx 'BaseAddress' is omitted when it is zero.
+# MULTI-NEXT:       - Version: 0
+# MULTI-NEXT:         Feature: 0x3
+# MULTI-NEXT:         BBRanges:
+# MULTI-NEXT:           - BBEntries:
+# MULTI-NEXT:              - ID:            0
+# MULTI-NEXT:                AddressOffset: 0x1
+# MULTI-NEXT:                Size:          0x2
+# MULTI-NEXT:                Metadata:      0x3
+# MULTI-NEXT:     PGOAnalyses:
+# MULTI-NEXT:       - FuncEntryCount: 0
+# MULTI-NEXT:         PGOBBEntries:
+# MULTI-NEXT:           - BBFreq: 0
+# MULTI-NEXT:   - Name: '.llvm_bb_addr_map (1)'
+# MULTI-NEXT:     Type: SHT_LLVM_BB_ADDR_MAP
+# MULTI-NEXT:     Entries:
+# MULTI-NEXT:       - Version:   0
+# MULTI-NEXT:         Feature:   0x1
+# MULTI-NEXT:         BBRanges:
+# MULTI-NEXT:           - BaseAddress:   0x20
+# MULTI-NEXT:             BBEntries: []
+# MULTI-NEXT:     PGOAnalyses:
+# MULTI-NEXT:       - FuncEntryCount: 0
+
+--- !ELF
+FileHeader:
+  Class: ELFCLASS64
+  Data:  ELFDATA2LSB
+  Type:  ET_EXEC
+Sections:
+  - Name: .llvm_bb_addr_map
+    Type: SHT_LLVM_BB_ADDR_MAP
+    Entries:
+## Check that obj2yaml does not emit the 'BaseAddress' and 'Feature' fields when
+## they are zero.
+      - Version: 0
+        Feature: 0x3
+        BBRanges:
+          - BaseAddress: 0x0
+            BBEntries:
+              - AddressOffset: 0x1
+                Size:          0x2
+                Metadata:      0x3
+    PGOAnalyses:
+      - FuncEntryCount: 0
+        PGOBBEntries:
+          - BBFreq:        0
+  - Name: '.llvm_bb_addr_map (1)'
+    Type:  SHT_LLVM_BB_ADDR_MAP
+    Entries:
+      - Version: 0
+        Feature: 0x1
+        BBRanges:
+          - BaseAddress: 0x20
+    PGOAnalyses:
+      - FuncEntryCount: 0
+
+## Check that obj2yaml uses the "Content" tag to describe an .llvm_bb_addr_map section
+## when it can't extract the entries, for example, when the section is truncated.
+
+# RUN: yaml2obj --docnum=1 -DSIZE=0x1D %s -o %t3
+# RUN: obj2yaml %t3 | FileCheck %s --check-prefixes=TRUNCATED,INVALID
+
+# INVALID:           --- !ELF
+# INVALID-NEXT:      FileHeader:
+# INVALID-NEXT:        Class: ELFCLASS64
+# INVALID-NEXT:        Data:  ELFDATA2LSB
+# INVALID-NEXT:        Type:  ET_EXEC
+# INVALID-NEXT:      Sections:
+# INVALID-NEXT:        - Name:    .llvm_bb_addr_map
+# INVALID-NEXT:          Type:    SHT_LLVM_BB_ADDR_MAP
+# TRUNCATED-NEXT:        Content: {{([[:xdigit:]]{58})}}{{$}}
+# TRUNCATED-NEXT:        Content: {{([[:xdigit:]]{58})}}{{$}}
+
+## Check that obj2yaml will fail when original YAML does not provide a PGO
+## field that was enabled in the feature byte
+
+# RUN: yaml2obj --docnum=3 %s -o %t4
+# RUN: obj2yaml %t4 | FileCheck %s --check-prefix=MISSING-FEC
+
+--- !ELF
+FileHeader:
+  Class: ELFCLASS64
+  Data:  ELFDATA2LSB
+  Type:  ET_EXEC
+Sections:
+  - Name: '.llvm_bb_addr_map'
+    Type:  SHT_LLVM_BB_ADDR_MAP
+    Entries:
+      - Version: 0
+        Feature: 0x1
+        BBRanges:
+          - BaseAddress: 0x20
+
+# MISSING-FEC:           --- !ELF
+# MISSING-FEC-NEXT:      FileHeader:
+# MISSING-FEC-NEXT:        Class: ELFCLASS64
+# MISSING-FEC-NEXT:        Data:  ELFDATA2LSB
+# MISSING-FEC-NEXT:        Type:  ET_EXEC
+# MISSING-FEC-NEXT:      Sections:
+# MISSING-FEC-NEXT:        - Name:    .llvm_bb_addr_map
+# MISSING-FEC-NEXT:          Type:    SHT_LLVM_BB_ADDR_MAP
+# MISSING-FEC-NEXT:          Content: '{{([[:xdigit:]]+)}}'{{$}}
+
diff --git a/llvm/test/tools/yaml2obj/ELF/bb-addr-map-pgo-analysis-map.yaml b/llvm/test/tools/yaml2obj/ELF/bb-addr-map-pgo-analysis-map.yaml
new file mode 100644
index 00000000000000..4dfaf60be3c0ed
--- /dev/null
+++ b/llvm/test/tools/yaml2obj/ELF/bb-addr-map-pgo-analysis-map.yaml
@@ -0,0 +1,83 @@
+## Check how yaml2obj produces PGO Analysis Map in .llvm_bb_addr_map section.
+
+# RUN: yaml2obj --docnum=1 %s -o %t1
+# RUN: llvm-readobj --sections --section-data %t1 | FileCheck %s
+
+# Case 4: Specify Entries.
+# CHECK:        Name: .llvm_bb_addr_map (1)
+# CHECK:        SectionData (
+# CHECK-NEXT:     0000: 02072000 00000000 0000010B 010203E8
+# CHECK-NEXT:     0010: 07E80702 0CEEDDBB F70E0D91 A2C48801
+# CHECK-NEXT:   )
+
+# Case 7: Not including a field which is enabled in feature doesn't emit value
+# CHECK:        Name: .llvm_bb_addr_map (1)
+# CHECK:        SectionData (
+# CHECK-NEXT:     0000: 02012000 00000000 0000020D 010203 |
+# CHECK-NEXT:   )
+
+--- !ELF
+FileHeader:
+  Class: ELFCLASS64
+  Data:  ELFDATA2LSB
+  Type:  ET_EXEC
+Sections:
+
+## Test the following cases:
+
+## 1) We can produce an .llvm_bb_addr_map section from a description with
+##    Entries and PGO Analysis data.
+  - Name: '.llvm_bb_addr_map (1)'
+    Type: SHT_LLVM_BB_ADDR_MAP
+    Entries:
+      - Version: 2
+        Feature: 0x7
+        BBRanges:
+          - BaseAddress: 0x0000000000000020
+            BBEntries:
+              - ID:            11
+                AddressOffset: 0x00000001
+                Size:          0x00000002
+                Metadata:      0x00000003
+    PGOAnalyses:
+      - FuncEntryCount: 1000
+        PGOBBEntries:
+          - BBFreq:        1000
+            Successors:
+              - ID:        12
+                BrProb:    0xeeeeeeee
+              - ID:        13
+                BrProb:    0x11111111
+
+## 2) According to feature we have FuncEntryCount but none is provided in yaml
+  - Name: '.llvm_bb_addr_map (2)'
+    Type: SHT_LLVM_BB_ADDR_MAP
+    Entries:
+      - Version: 2
+        Feature: 0x1
+        BBRanges:
+          - BaseAddress:   0x0000000000000020
+            NumBlocks: 2
+            BBEntries:
+             - ID:            13
+               AddressOffset: 0x00000001
+               Size:          0x00000002
+               Metadata:      0x00000003
+
+## Check that yaml2obj generates a warning when we use unsupported feature.
+# RUN: yaml2obj --docnum=2  %s 2>&1 | FileCheck %s --check-prefix=INVALID-FEATURE
+# INVALID-FEATURE: warning: invalid encoding for BBAddrMap::Features: 0xff
+
+--- !ELF
+FileHeader:
+  Class: ELFCLASS64
+  Data:  ELFDATA2LSB
+  Type:  ET_EXEC
+Sections:
+  - Name: '.llvm_bb_addr_map'
+    Type: SHT_LLVM_BB_ADDR_MAP
+    Entries:
+      - Version: 2
+##  Specify unsupported feature
+        Feature: 0xFF
+
diff --git a/llvm/tools/obj2yaml/elf2yaml.cpp b/llvm/tools/obj2yaml/elf2yaml.cpp
index 38a69f77ff8362..e1fe004abecf51 100644
--- a/llvm/tools/obj2yaml/elf2yaml.cpp
+++ b/llvm/tools/obj2yaml/elf2yaml.cpp
@@ -889,6 +889,8 @@ ELFDumper<ELFT>::dumpBBAddrMapSection(const Elf_Shdr *Shdr) {
   DataExtractor Data(Content, Obj.isLE(), ELFT::Is64Bits ? 8 : 4);
 
   std::vector<ELFYAML::BBAddrMapEntry> Entries;
+  bool FoundPGOAnalysis = false;
+  std::vector<ELFYAML::PGOAnalysisMapEntry> PGOAnalyses;
   DataExtractor::Cursor Cur(0);
   uint8_t Version = 0;
   uint8_t Feature = 0;
@@ -905,6 +907,7 @@ ELFDumper<ELFT>::dumpBBAddrMapSection(const Elf_Shdr *Shdr) {
     }
     uint64_t NumBBRanges = 1;
     uint64_t NumBlocks = 0;
+    uint32_t TotalNumBlocks = 0;
     auto FeatureOrErr = llvm::object::BBAddrMap::Features::decode(Feature);
     if (!FeatureOrErr)
       return FeatureOrErr.takeError();
@@ -934,10 +937,39 @@ ELFDumper<ELFT>::dumpBBAddrMapSection(const Elf_Shdr *Shdr) {
         uint64_t Metadata = Data.getULEB128(Cur);
         BBEntries.push_back({ID, Offset, Size, Metadata});
       }
+      TotalNumBlocks += BBEntries.size();
       BBRanges.push_back({BaseAddress, /*NumBlocks=*/{}, BBEntries});
     }
     Entries.push_back(
         {Version, Feature, /*NumBBRanges=*/{}, std::move(BBRanges)});
+
+    ELFYAML::PGOAnalysisMapEntry &PGOAnalysis = PGOAnalyses.emplace_back();
+    if (FeatureOrErr->hasPGOAnalysis()) {
+      FoundPGOAnalysis = true;
+
+      if (FeatureOrErr->FuncEntryCount)
+        PGOAnalysis.FuncEntryCount = Data.getULEB128(Cur);
+
+      if (FeatureOrErr->hasPGOAnalysisBBData()) {
+        auto &PGOBBEntries = PGOAnalysis.PGOBBEntries.emplace();
+        for (uint64_t BlockIndex = 0; Cur && BlockIndex < TotalNumBlocks;
+             ++BlockIndex) {
+          auto &PGOBBEntry = PGOBBEntries.emplace_back();
+          if (FeatureOrErr->BBFreq)
+            PGOBBEntry.BBFreq = Data.getULEB128(Cur);
+
+          if (FeatureOrErr->BrProb) {
+            auto &SuccEntries = PGOBBEntry.Successors.emplace();
+            uint64_t SuccCount = Data.getULEB128(Cur);
+            for (uint64_t SuccIdx = 0; SuccIdx < SuccCount; ++SuccIdx) {
+              uint32_t ID = Data.getULEB128(Cur);
+              uint32_t BrProb = Data.getULEB128(Cur);
+              SuccEntries.push_back({ID, BrProb});
+            }
+          }
+        }
+      }
+    }
   }
 
   if (!Cur) {
@@ -946,6 +978,8 @@ ELFDumper<ELFT>::dumpBBAddrMapSection(const Elf_Shdr *Shdr) {
     S->Content = yaml::BinaryRef(Content);
   } else {
     S->Entries = std::move(Entries);
+    if (FoundPGOAnalysis)
+      S->PGOAnalyses = std::move(PGOAnalyses);
   }
 
   return S.release();

>From b715a428f7cda48755a3bf9dbb0b862ec38f9c9a Mon Sep 17 00:00:00 2001
From: Micah Weston <micahsweston at gmail.com>
Date: Mon, 12 Feb 2024 15:12:57 -0500
Subject: [PATCH 2/2] fixup! [SHT_LLVM_BB_ADDR_MAP][obj2yaml] Implements
 PGOAnalysisMap for elf2yaml and tests.

Addresses reviewer feedback.
---
 .../obj2yaml/ELF/bb-addr-map-pgo-analysis-map.yaml  |  4 ++--
 llvm/tools/obj2yaml/elf2yaml.cpp                    | 13 ++++++++-----
 2 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/llvm/test/tools/obj2yaml/ELF/bb-addr-map-pgo-analysis-map.yaml b/llvm/test/tools/obj2yaml/ELF/bb-addr-map-pgo-analysis-map.yaml
index 3bb03e6efb8ec1..299bf463cf4bc9 100644
--- a/llvm/test/tools/obj2yaml/ELF/bb-addr-map-pgo-analysis-map.yaml
+++ b/llvm/test/tools/obj2yaml/ELF/bb-addr-map-pgo-analysis-map.yaml
@@ -200,8 +200,8 @@ Sections:
 # TRUNCATED-NEXT:        Content: {{([[:xdigit:]]{58})}}{{$}}
 # TRUNCATED-NEXT:        Content: {{([[:xdigit:]]{58})}}{{$}}
 
-## Check that obj2yaml will fail when original YAML does not provide a PGO
-## field that was enabled in the feature byte
+## Check that obj2yaml uses the "Content" tag when original YAML does not
+## provide a PGO field that was enabled in the feature byte
 
 # RUN: yaml2obj --docnum=3 %s -o %t4
 # RUN: obj2yaml %t4 | FileCheck %s --check-prefix=MISSING-FEC
diff --git a/llvm/tools/obj2yaml/elf2yaml.cpp b/llvm/tools/obj2yaml/elf2yaml.cpp
index e1fe004abecf51..6b9af906736c35 100644
--- a/llvm/tools/obj2yaml/elf2yaml.cpp
+++ b/llvm/tools/obj2yaml/elf2yaml.cpp
@@ -889,7 +889,7 @@ ELFDumper<ELFT>::dumpBBAddrMapSection(const Elf_Shdr *Shdr) {
   DataExtractor Data(Content, Obj.isLE(), ELFT::Is64Bits ? 8 : 4);
 
   std::vector<ELFYAML::BBAddrMapEntry> Entries;
-  bool FoundPGOAnalysis = false;
+  bool HasAnyPGOAnalysisMapEntry = false;
   std::vector<ELFYAML::PGOAnalysisMapEntry> PGOAnalyses;
   DataExtractor::Cursor Cur(0);
   uint8_t Version = 0;
@@ -945,7 +945,7 @@ ELFDumper<ELFT>::dumpBBAddrMapSection(const Elf_Shdr *Shdr) {
 
     ELFYAML::PGOAnalysisMapEntry &PGOAnalysis = PGOAnalyses.emplace_back();
     if (FeatureOrErr->hasPGOAnalysis()) {
-      FoundPGOAnalysis = true;
+      HasAnyPGOAnalysisMapEntry = true;
 
       if (FeatureOrErr->FuncEntryCount)
         PGOAnalysis.FuncEntryCount = Data.getULEB128(Cur);
@@ -955,13 +955,16 @@ ELFDumper<ELFT>::dumpBBAddrMapSection(const Elf_Shdr *Shdr) {
         for (uint64_t BlockIndex = 0; Cur && BlockIndex < TotalNumBlocks;
              ++BlockIndex) {
           auto &PGOBBEntry = PGOBBEntries.emplace_back();
-          if (FeatureOrErr->BBFreq)
+          if (FeatureOrErr->BBFreq) {
             PGOBBEntry.BBFreq = Data.getULEB128(Cur);
+            if (!Cur)
+              break;
+          }
 
           if (FeatureOrErr->BrProb) {
             auto &SuccEntries = PGOBBEntry.Successors.emplace();
             uint64_t SuccCount = Data.getULEB128(Cur);
-            for (uint64_t SuccIdx = 0; SuccIdx < SuccCount; ++SuccIdx) {
+            for (uint64_t SuccIdx = 0; Cur && SuccIdx < SuccCount; ++SuccIdx) {
               uint32_t ID = Data.getULEB128(Cur);
               uint32_t BrProb = Data.getULEB128(Cur);
               SuccEntries.push_back({ID, BrProb});
@@ -978,7 +981,7 @@ ELFDumper<ELFT>::dumpBBAddrMapSection(const Elf_Shdr *Shdr) {
     S->Content = yaml::BinaryRef(Content);
   } else {
     S->Entries = std::move(Entries);
-    if (FoundPGOAnalysis)
+    if (HasAnyPGOAnalysisMapEntry)
       S->PGOAnalyses = std::move(PGOAnalyses);
   }
 



More information about the llvm-commits mailing list