diff --git a/llvm/include/llvm/CodeGen/CommandFlags.h b/llvm/include/llvm/CodeGen/CommandFlags.h index d5448d781363d4a..000aed782a80574 100644 --- a/llvm/include/llvm/CodeGen/CommandFlags.h +++ b/llvm/include/llvm/CodeGen/CommandFlags.h @@ -136,6 +136,8 @@ bool getEmitCallSiteInfo(); bool getEnableMachineFunctionSplitter(); +bool getEnableStaticDataPartitioning(); + bool getEnableDebugEntryValues(); bool getValueTrackingVariableLocations(); diff --git a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h index 3e2cd05387926c2..10f0594c267aeee 100644 --- a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -76,6 +76,9 @@ class TargetLoweringObjectFileELF : public TargetLoweringObjectFile { MCSection *getSectionForJumpTable(const Function &F, const TargetMachine &TM) const override; + MCSection * + getSectionForJumpTable(const Function &F, const TargetMachine &TM, + const MachineJumpTableEntry *JTE) const override; MCSection *getSectionForLSDA(const Function &F, const MCSymbol &FnSym, const TargetMachine &TM) const override; diff --git a/llvm/include/llvm/Target/TargetLoweringObjectFile.h b/llvm/include/llvm/Target/TargetLoweringObjectFile.h index b523d6a47b41af3..a5ed1b29dc1bce9 100644 --- a/llvm/include/llvm/Target/TargetLoweringObjectFile.h +++ b/llvm/include/llvm/Target/TargetLoweringObjectFile.h @@ -21,6 +21,7 @@ namespace llvm { struct Align; +struct MachineJumpTableEntry; class Constant; class DataLayout; class Function; @@ -135,6 +136,10 @@ class TargetLoweringObjectFile : public MCObjectFileInfo { virtual MCSection *getSectionForJumpTable(const Function &F, const TargetMachine &TM) const; + virtual MCSection * + getSectionForJumpTable(const Function &F, const TargetMachine &TM, + const MachineJumpTableEntry *JTE) const; + virtual MCSection *getSectionForLSDA(const Function &, const MCSymbol &, const TargetMachine &) const { return LSDASection; diff --git a/llvm/include/llvm/Target/TargetMachine.h b/llvm/include/llvm/Target/TargetMachine.h index 9bdb110bd36839b..4a54c706c0cb6a0 100644 --- a/llvm/include/llvm/Target/TargetMachine.h +++ b/llvm/include/llvm/Target/TargetMachine.h @@ -305,6 +305,10 @@ class TargetMachine { return Options.FunctionSections; } + bool getEnableStaticDataPartitioning() const { + return Options.EnableStaticDataPartitioning; + } + /// Return true if visibility attribute should not be emitted in XCOFF, /// corresponding to -mignore-xcoff-visibility. bool getIgnoreXCOFFVisibility() const { diff --git a/llvm/include/llvm/Target/TargetOptions.h b/llvm/include/llvm/Target/TargetOptions.h index 88f253805ca99ce..fd8dad4f6f79127 100644 --- a/llvm/include/llvm/Target/TargetOptions.h +++ b/llvm/include/llvm/Target/TargetOptions.h @@ -145,7 +145,8 @@ namespace llvm { TrapUnreachable(false), NoTrapAfterNoreturn(false), TLSSize(0), EmulatedTLS(false), EnableTLSDESC(false), EnableIPRA(false), EmitStackSizeSection(false), EnableMachineOutliner(false), - EnableMachineFunctionSplitter(false), SupportsDefaultOutlining(false), + EnableMachineFunctionSplitter(false), + EnableStaticDataPartitioning(false), SupportsDefaultOutlining(false), EmitAddrsig(false), BBAddrMap(false), EmitCallSiteInfo(false), SupportsDebugEntryValues(false), EnableDebugEntryValues(false), ValueTrackingVariableLocations(false), ForceDwarfFrameSection(false), @@ -312,6 +313,9 @@ namespace llvm { /// Enables the MachineFunctionSplitter pass. unsigned EnableMachineFunctionSplitter : 1; + /// Enables the StaticDataSplitter pass. + unsigned EnableStaticDataPartitioning : 1; + /// Set if the target supports default outlining behaviour. unsigned SupportsDefaultOutlining : 1; diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index c21915673f643db..44b10c3ef997267 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -2853,7 +2853,6 @@ void AsmPrinter::emitConstantPool() { // Print assembly representations of the jump tables used by the current // function. void AsmPrinter::emitJumpTableInfo() { - const DataLayout &DL = MF->getDataLayout(); const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); if (!MJTI) return; if (MJTI->getEntryKind() == MachineJumpTableInfo::EK_Inline) return; @@ -2869,11 +2868,26 @@ void AsmPrinter::emitJumpTableInfo() { MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference64, F); - SmallVector JumpTableIndices; + if (!TM.Options.EnableStaticDataPartitioning) { + emitJumpTableImpl(*MJTI, llvm::to_vector(llvm::seq(JT.size())), + JTInDiffSection); + return; + } + + SmallVector HotJumpTableIndices, ColdJumpTableIndices; + // When static data partitioning is enabled, collect jump table entries that + // go into the same section together to reduce the amount of section switch + // statements. for (unsigned JTI = 0, JTSize = JT.size(); JTI < JTSize; ++JTI) { - JumpTableIndices.push_back(JTI); + if (JT[JTI].Hotness == MachineFunctionDataHotness::Cold) { + ColdJumpTableIndices.push_back(JTI); + } else { + HotJumpTableIndices.push_back(JTI); + } } - emitJumpTableImpl(*MJTI, JumpTableIndices, JTInDiffSection); + + emitJumpTableImpl(*MJTI, HotJumpTableIndices, JTInDiffSection); + emitJumpTableImpl(*MJTI, ColdJumpTableIndices, JTInDiffSection); } void AsmPrinter::emitJumpTableImpl(const MachineJumpTableInfo &MJTI, @@ -2885,7 +2899,13 @@ void AsmPrinter::emitJumpTableImpl(const MachineJumpTableInfo &MJTI, const TargetLoweringObjectFile &TLOF = getObjFileLowering(); const Function &F = MF->getFunction(); const std::vector &JT = MJTI.getJumpTables(); - MCSection *JumpTableSection = TLOF.getSectionForJumpTable(F, TM); + MCSection *JumpTableSection = nullptr; + if (TM.Options.EnableStaticDataPartitioning) { + JumpTableSection = + TLOF.getSectionForJumpTable(F, TM, &JT[JumpTableIndices.front()]); + } else { + JumpTableSection = TLOF.getSectionForJumpTable(F, TM); + } const DataLayout &DL = MF->getDataLayout(); if (JTInDiffSection) { diff --git a/llvm/lib/CodeGen/CommandFlags.cpp b/llvm/lib/CodeGen/CommandFlags.cpp index d180cfcea658c21..023656cde0089ea 100644 --- a/llvm/lib/CodeGen/CommandFlags.cpp +++ b/llvm/lib/CodeGen/CommandFlags.cpp @@ -103,6 +103,7 @@ CGOPT(bool, EnableStackSizeSection) CGOPT(bool, EnableAddrsig) CGOPT(bool, EmitCallSiteInfo) CGOPT(bool, EnableMachineFunctionSplitter) +CGOPT(bool, EnableStaticDataPartitioning) CGOPT(bool, EnableDebugEntryValues) CGOPT(bool, ForceDwarfFrameSection) CGOPT(bool, XRayFunctionIndex) @@ -480,6 +481,12 @@ codegen::RegisterCodeGenFlags::RegisterCodeGenFlags() { cl::init(false)); CGBINDOPT(EnableMachineFunctionSplitter); + static cl::opt EnableStaticDataPartitioning( + "partition-static-data-sections", + cl::desc("Partition data sections using profile information."), + cl::init(false)); + CGBINDOPT(EnableStaticDataPartitioning); + static cl::opt ForceDwarfFrameSection( "force-dwarf-frame-section", cl::desc("Always emit a debug frame section."), cl::init(false)); @@ -586,6 +593,7 @@ codegen::InitTargetOptionsFromCodeGenFlags(const Triple &TheTriple) { Options.ExceptionModel = getExceptionModel(); Options.EmitStackSizeSection = getEnableStackSizeSection(); Options.EnableMachineFunctionSplitter = getEnableMachineFunctionSplitter(); + Options.EnableStaticDataPartitioning = getEnableStaticDataPartitioning(); Options.EmitAddrsig = getEnableAddrsig(); Options.EmitCallSiteInfo = getEmitCallSiteInfo(); Options.EnableDebugEntryValues = getEnableDebugEntryValues(); diff --git a/llvm/lib/CodeGen/StaticDataSplitter.cpp b/llvm/lib/CodeGen/StaticDataSplitter.cpp index 25f02fde8a4b8ac..e5bf0a5a3a255f6 100644 --- a/llvm/lib/CodeGen/StaticDataSplitter.cpp +++ b/llvm/lib/CodeGen/StaticDataSplitter.cpp @@ -35,19 +35,11 @@ using namespace llvm; #define DEBUG_TYPE "static-data-splitter" -STATISTIC(NumHotJumpTables, "Number of hot jump tables seen"); -STATISTIC(NumColdJumpTables, "Number of cold jump tables seen"); +STATISTIC(NumHotJumpTables, "Number of hot jump tables seen."); +STATISTIC(NumColdJumpTables, "Number of cold jump tables seen."); STATISTIC(NumUnknownJumpTables, - "Number of jump tables with unknown hotness. Option " - "-static-data-default-hotness specifies the hotness."); - -static cl::opt StaticDataDefaultHotness( - "static-data-default-hotness", cl::Hidden, - cl::desc("This option specifies the hotness of static data when profile " - "information is unavailable"), - cl::init(MachineFunctionDataHotness::Hot), - cl::values(clEnumValN(MachineFunctionDataHotness::Hot, "hot", "Hot"), - clEnumValN(MachineFunctionDataHotness::Cold, "cold", "Cold"))); + "Number of jump tables with unknown hotness. They are from functions " + "without profile information."); class StaticDataSplitter : public MachineFunctionPass { const MachineBranchProbabilityInfo *MBPI = nullptr; @@ -156,13 +148,6 @@ bool StaticDataSplitter::splitJumpTables(MachineFunction &MF) { if (ProfileAvailable) return splitJumpTablesWithProfiles(MF, *MJTI); - // If function profile is unavailable (e.g., module not instrumented, or new - // code paths lacking samples), -static-data-default-hotness specifies the - // hotness. - for (size_t JTI = 0; JTI < MJTI->getJumpTables().size(); JTI++) - MF.getJumpTableInfo()->updateJumpTableEntryHotness( - JTI, StaticDataDefaultHotness); - return true; } diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp index 6ab6d18213ba43e..3c2c7c8c9fed69a 100644 --- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -24,6 +24,7 @@ #include "llvm/CodeGen/BasicBlockSectionUtils.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineModuleInfoImpls.h" #include "llvm/IR/Comdat.h" @@ -648,7 +649,8 @@ static StringRef getSectionPrefixForGlobal(SectionKind Kind, bool IsLarge) { static SmallString<128> getELFSectionNameForGlobal(const GlobalObject *GO, SectionKind Kind, Mangler &Mang, const TargetMachine &TM, - unsigned EntrySize, bool UniqueSectionName) { + unsigned EntrySize, bool UniqueSectionName, + const MachineJumpTableEntry *JTE) { SmallString<128> Name = getSectionPrefixForGlobal(Kind, TM.isLargeGlobalValue(GO)); if (Kind.isMergeableCString()) { @@ -669,7 +671,19 @@ getELFSectionNameForGlobal(const GlobalObject *GO, SectionKind Kind, bool HasPrefix = false; if (const auto *F = dyn_cast(GO)) { - if (std::optional Prefix = F->getSectionPrefix()) { + // Jump table hotness takes precedence over its enclosing function's hotness + // if it's known. The function's section prefix is used if jump table entry + // hotness is unknown. + if (JTE && JTE->Hotness != MachineFunctionDataHotness::Unknown) { + if (JTE->Hotness == MachineFunctionDataHotness::Hot) { + raw_svector_ostream(Name) << ".hot"; + } else { + assert(JTE->Hotness == MachineFunctionDataHotness::Cold && + "Hotness must be cold"); + raw_svector_ostream(Name) << ".unlikely"; + } + HasPrefix = true; + } else if (std::optional Prefix = F->getSectionPrefix()) { raw_svector_ostream(Name) << '.' << *Prefix; HasPrefix = true; } @@ -767,8 +781,8 @@ calcUniqueIDUpdateFlagsAndSize(const GlobalObject *GO, StringRef SectionName, // implicitly for this symbol e.g. .rodata.str1.1, then we don't need // to unique the section as the entry size for this symbol will be // compatible with implicitly created sections. - SmallString<128> ImplicitSectionNameStem = - getELFSectionNameForGlobal(GO, Kind, Mang, TM, EntrySize, false); + SmallString<128> ImplicitSectionNameStem = getELFSectionNameForGlobal( + GO, Kind, Mang, TM, EntrySize, false, /*MJTE=*/nullptr); if (SymbolMergeable && Ctx.isELFImplicitMergeableSectionNamePrefix(SectionName) && SectionName.starts_with(ImplicitSectionNameStem)) @@ -874,7 +888,8 @@ MCSection *TargetLoweringObjectFileELF::getExplicitSectionGlobal( static MCSectionELF *selectELFSectionForGlobal( MCContext &Ctx, const GlobalObject *GO, SectionKind Kind, Mangler &Mang, const TargetMachine &TM, bool EmitUniqueSection, unsigned Flags, - unsigned *NextUniqueID, const MCSymbolELF *AssociatedSymbol) { + unsigned *NextUniqueID, const MCSymbolELF *AssociatedSymbol, + const MachineJumpTableEntry *MJTE = nullptr) { auto [Group, IsComdat, ExtraFlags] = getGlobalObjectInfo(GO, TM); Flags |= ExtraFlags; @@ -893,7 +908,7 @@ static MCSectionELF *selectELFSectionForGlobal( } } SmallString<128> Name = getELFSectionNameForGlobal( - GO, Kind, Mang, TM, EntrySize, UniqueSectionName); + GO, Kind, Mang, TM, EntrySize, UniqueSectionName, MJTE); // Use 0 as the unique ID for execute-only text. if (Kind.isExecuteOnly()) @@ -967,17 +982,23 @@ MCSection *TargetLoweringObjectFileELF::getUniqueSectionForFunction( MCSection *TargetLoweringObjectFileELF::getSectionForJumpTable( const Function &F, const TargetMachine &TM) const { + return getSectionForJumpTable(F, TM, /*JTE=*/nullptr); +} + +MCSection *TargetLoweringObjectFileELF::getSectionForJumpTable( + const Function &F, const TargetMachine &TM, + const MachineJumpTableEntry *JTE) const { // If the function can be removed, produce a unique section so that // the table doesn't prevent the removal. const Comdat *C = F.getComdat(); bool EmitUniqueSection = TM.getFunctionSections() || C; - if (!EmitUniqueSection) + if (!EmitUniqueSection && !TM.getEnableStaticDataPartitioning()) return ReadOnlySection; return selectELFSectionForGlobal(getContext(), &F, SectionKind::getReadOnly(), getMangler(), TM, EmitUniqueSection, ELF::SHF_ALLOC, &NextUniqueID, - /* AssociatedSymbol */ nullptr); + /* AssociatedSymbol */ nullptr, JTE); } MCSection *TargetLoweringObjectFileELF::getSectionForLSDA( diff --git a/llvm/lib/CodeGen/TargetPassConfig.cpp b/llvm/lib/CodeGen/TargetPassConfig.cpp index 847a1aef39c5655..b3046ce83ac5a5d 100644 --- a/llvm/lib/CodeGen/TargetPassConfig.cpp +++ b/llvm/lib/CodeGen/TargetPassConfig.cpp @@ -1255,7 +1255,7 @@ void TargetPassConfig::addMachinePasses() { } } addPass(createMachineFunctionSplitterPass()); - if (SplitStaticData) + if (SplitStaticData || TM->Options.EnableStaticDataPartitioning) addPass(createStaticDataSplitterPass()); } // We run the BasicBlockSections pass if either we need BB sections or BB diff --git a/llvm/lib/Target/TargetLoweringObjectFile.cpp b/llvm/lib/Target/TargetLoweringObjectFile.cpp index 4fe9d13d0622659..02c101055d9f36f 100644 --- a/llvm/lib/Target/TargetLoweringObjectFile.cpp +++ b/llvm/lib/Target/TargetLoweringObjectFile.cpp @@ -348,6 +348,12 @@ TargetLoweringObjectFile::SectionForGlobal(const GlobalObject *GO, MCSection *TargetLoweringObjectFile::getSectionForJumpTable( const Function &F, const TargetMachine &TM) const { + return getSectionForJumpTable(F, TM, /*JTE=*/nullptr); +} + +MCSection *TargetLoweringObjectFile::getSectionForJumpTable( + const Function &F, const TargetMachine &TM, + const MachineJumpTableEntry *JTE) const { Align Alignment(1); return getSectionForConstant(F.getDataLayout(), SectionKind::getReadOnly(), /*C=*/nullptr, diff --git a/llvm/test/CodeGen/X86/jump-table-partition.ll b/llvm/test/CodeGen/X86/jump-table-partition.ll index 8c7e726576bceb2..0d76f8a5a91ed9a 100644 --- a/llvm/test/CodeGen/X86/jump-table-partition.ll +++ b/llvm/test/CodeGen/X86/jump-table-partition.ll @@ -6,18 +6,55 @@ ; RUN: llc -mtriple=x86_64-unknown-linux-gnu -stop-after=finalize-isel -min-jump-table-entries=2 %s -o %t.mir ; RUN: llc -mtriple=x86_64-unknown-linux-gnu --run-pass=static-data-splitter -stats -x mir %t.mir -o - 2>&1 | FileCheck %s --check-prefix=STAT -; Tests stat messages are expected. -; COM: Update test to verify section suffixes when target-lowering and assembler changes are implemented. -; COM: Also run static-data-splitter pass with -static-data-default-hotness=cold and check data section suffix. - + ; @foo has 2 hot and 2 cold jump tables. + ; The two jump tables with unknown hotness come from @func_without_profile and + ; @bar respectively. ; STAT: 2 static-data-splitter - Number of cold jump tables seen ; STAT: 2 static-data-splitter - Number of hot jump tables seen -; STAT: 1 static-data-splitter - Number of jump tables with unknown hotness - -; In function @foo, the 2 switch instructions to jt0.* and jt1.* get lowered to hot jump tables, -; and the 2 switch instructions to jt2.* and jt3.* get lowered to cold jump tables. - -; @func_without_profile doesn't have profiles. It's jump table hotness is unknown. +; STAT: 2 static-data-splitter - Number of jump tables with unknown hotness + +; RUN: llc -mtriple=x86_64-unknown-linux-gnu -enable-split-machine-functions \ +; RUN: -partition-static-data-sections=true -function-sections=true \ +; RUN: -min-jump-table-entries=2 -unique-section-names=false \ +; RUN: %s -o - 2>&1 | FileCheck %s --check-prefixes=NUM,JT + +; Section names will optionally have `.` if -function-sections is enabled. +; RUN: llc -mtriple=x86_64-unknown-linux-gnu -enable-split-machine-functions \ +; RUN: -partition-static-data-sections=true -function-sections=true \ +; RUN: -min-jump-table-entries=2 %s -o - 2>&1 | FileCheck %s --check-prefixes=FUNC,JT + +; RUN: llc -mtriple=x86_64-unknown-linux-gnu -enable-split-machine-functions \ +; RUN: -partition-static-data-sections=true -function-sections=false \ +; RUN: -min-jump-table-entries=2 %s -o - 2>&1 | FileCheck %s --check-prefixes=FUNCLESS,JT + +; In function @foo, the 2 switch instructions to jt0.* and jt1.* are placed in +; hot-prefixed sections, and the 2 switch instructions to jt2.* and jt3.* are +; placed in cold-prefixed sections. +; NUM: .section .rodata.hot.,"a",@progbits,unique,2 +; FUNC: .section .rodata.hot.foo,"a",@progbits +; FUNCLESS: .section .rodata.hot.,"a",@progbits +; JT: .LJTI0_0: +; JT: .LJTI0_2: +; NUM: .section .rodata.unlikely.,"a",@progbits,unique,3 +; FUNC: .section .rodata.unlikely.foo,"a",@progbits +; FUNCLESS: .section .rodata.unlikely.,"a",@progbits +; JT: .LJTI0_1: +; JT: .LJTI0_3: + +; @func_without_profile simulates the functions without profile information +; (e.g., not instrumented or not profiled), its jump tables are placed in +; sections without hot or unlikely prefixes. +; NUM: .section .rodata,"a",@progbits,unique,5 +; FUNC: .section .rodata.func_without_profile,"a",@progbits +; FUNCLESS: .section .rodata,"a",@progbits +; JT: .LJTI1_0: + +; @bar doesn't have profile information and it has a section prefix. +; Tests that its jump tables are placed in sections with function prefixes. +; NUM: .section .rodata.bar_prefix.,"a",@progbits,unique,7 +; FUNC: .section .rodata.bar_prefix.bar +; FUNCLESS: .section .rodata.bar_prefix.,"a" +; JT: .LJTI2_0 target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" @@ -31,6 +68,7 @@ target triple = "x86_64-unknown-linux-gnu" @default = private constant [8 x i8] c"default\00" @jt3 = private constant [4 x i8] c"jt3\00" +; jt0 and jt2 are hot. jt1 and jt3 are cold. define i32 @foo(i32 %num) !prof !13 { entry: %mod3 = sdiv i32 %num, 3 @@ -53,9 +91,9 @@ jt0.default: jt0.epilog: %zero = icmp eq i32 %num, 0 - br i1 %zero, label %cold, label %hot, !prof !15 + br i1 %zero, label %hot, label %cold, !prof !17 -cold: +hot: %c2 = call i32 @transform(i32 %num) switch i32 %c2, label %jt2.default [ i32 1, label %jt2.bb1 @@ -76,9 +114,9 @@ jt2.default: jt2.epilog: %c2cmp = icmp ne i32 %c2, 0 - br i1 %c2cmp, label %return, label %jt3.prologue, !prof !16 + br i1 %c2cmp, label %return, label %jt3.prologue, !prof !18 -hot: +cold: %c1 = call i32 @compute(i32 %num) switch i32 %c1, label %jt1.default [ i32 1, label %jt1.bb1 @@ -150,6 +188,29 @@ sw.epilog: ret void } +define void @bar(i32 %num) !section_prefix !20 { +entry: + switch i32 %num, label %sw.default [ + i32 1, label %sw.bb + i32 2, label %sw.bb1 + ] + +sw.bb: + call i32 @puts(ptr @str.10) + br label %sw.epilog + +sw.bb1: + call i32 @puts(ptr @str.9) + br label %sw.epilog + +sw.default: + call i32 @puts(ptr @str.11) + br label %sw.epilog + +sw.epilog: + ret void +} + declare i32 @puts(ptr) declare i32 @printf(ptr, ...) declare i32 @compute(i32) @@ -173,5 +234,9 @@ declare i32 @cleanup(i32) !12 = !{i32 999999, i64 1, i32 9} !13 = !{!"function_entry_count", i64 100000} !14 = !{!"branch_weights", i32 60000, i32 20000, i32 20000} -!15 = !{!"branch_weights", i32 1, i32 99999} -!16 = !{!"branch_weights", i32 99998, i32 1} +!15 = !{!"function_entry_count", i64 1} +!16 = !{!"branch_weights", i32 1, i32 0, i32 0, i32 0, i32 0, i32 0} +!17 = !{!"branch_weights", i32 99999, i32 1} +!18 = !{!"branch_weights", i32 99998, i32 1} +!19 = !{!"branch_weights", i32 97000, i32 1000, i32 1000, i32 1000} +!20 = !{!"function_section_prefix", !"bar_prefix"}