diff --git a/bolt/lib/Core/HashUtilities.cpp b/bolt/lib/Core/HashUtilities.cpp --- a/bolt/lib/Core/HashUtilities.cpp +++ b/bolt/lib/Core/HashUtilities.cpp @@ -106,8 +106,6 @@ std::string hashBlock(BinaryContext &BC, const BinaryBasicBlock &BB, OperandHashFuncTy OperandHashFunc) { - assert(BB.size() > 0 && "computing hash over an empty basic block"); - const bool IsX86 = BC.isX86(); // The hash is computed by creating a string of all instruction opcodes and diff --git a/bolt/lib/Passes/BinaryPasses.cpp b/bolt/lib/Passes/BinaryPasses.cpp --- a/bolt/lib/Passes/BinaryPasses.cpp +++ b/bolt/lib/Passes/BinaryPasses.cpp @@ -1317,6 +1317,7 @@ void PrintProgramStats::runOnFunctions(BinaryContext &BC) { uint64_t NumRegularFunctions = 0; uint64_t NumStaleProfileFunctions = 0; + uint64_t NumAllStaleFunctions = 0; uint64_t NumInferredFunctions = 0; uint64_t NumNonSimpleProfiledFunctions = 0; uint64_t NumUnknownControlFlowFunctions = 0; @@ -1360,6 +1361,7 @@ if (Function.hasInferredProfile()) { ++NumInferredFunctions; InferredSampleCount += SampleCount; + ++NumAllStaleFunctions; } } else { if (opts::ReportStaleFuncs) { @@ -1369,6 +1371,7 @@ } ++NumStaleProfileFunctions; StaleSampleCount += SampleCount; + ++NumAllStaleFunctions; } } BC.NumProfiledFuncs = ProfiledFunctions.size(); @@ -1416,6 +1419,13 @@ } } if (NumInferredFunctions) { + const float PctAllStale = + NumAllStaleFunctions / (float)NumAllProfiledFunctions * 100.0f; + outs() << "BOLT-INFO: " << NumAllStaleFunctions + << format(" (%.1f%% of all profiled)", PctAllStale) << " function" + << (NumAllStaleFunctions == 1 ? "" : "s") + << " have invalid (possibly stale) profile." + " Use -report-stale to see the list.\n"; outs() << format("BOLT-INFO: inferred profile for %d (%.2f%% of all " "profiled) functions responsible for %.2f%% samples\n", NumInferredFunctions, diff --git a/bolt/test/X86/Inputs/blarge_profile_stale.yaml b/bolt/test/X86/Inputs/blarge_profile_stale.yaml new file mode 100644 --- /dev/null +++ b/bolt/test/X86/Inputs/blarge_profile_stale.yaml @@ -0,0 +1,51 @@ +--- +header: + profile-version: 1 + binary-name: '/data/users/spupyrev/llvm-upstream/build/tools/bolt/test/X86/Output/reader-yaml.test.tmp.exe' + binary-build-id: '' + profile-flags: [ lbr ] + profile-origin: branch profile reader + profile-events: '' +functions: + - name: SolveCubic + fid: 6 + hash: 0xC6E9098E973BBE19 + exec: 151 + nblocks: 18 + blocks: + - bid: 0 + insns: 43 + hash: 0x8A41C5F60CF1B879 + exec: 151 + succ: [ { bid: 1, cnt: 4, mis: 2 }, { bid: 11, cnt: 0 } ] + - bid: 1 + insns: 7 + hash: 0x6D641B0E41067EE6 + succ: [ { bid: 10, cnt: 0 }, { bid: 2, cnt: 0 } ] + - bid: 13 + insns: 26 + hash: 0x2C528DB7C11E0C22 + succ: [ { bid: 15, cnt: 89 }, { bid: 14, cnt: 0 } ] + - bid: 15 + insns: 9 + hash: 0x7A5F8FF268495B78 + - name: usqrt + fid: 7 + hash: 0x8B62B1F9AD81EA35 + exec: 20 + nblocks: 6 + blocks: + - bid: 0 + insns: 4 + hash: 0xF5818B6ACA0B4B1A + exec: 20 + succ: [ { bid: 1, cnt: 0 } ] + - bid: 1 + insns: 9 + hash: 0x388CD0AB1361C40C + succ: [ { bid: 3, cnt: 320, mis: 171 }, { bid: 2, cnt: 0 } ] + - bid: 3 + insns: 2 + hash: 0xB096EE55E872A023 + succ: [ { bid: 1, cnt: 300, mis: 33 }, { bid: 4, cnt: 20 } ] +... diff --git a/bolt/test/X86/reader-stale-yaml.test b/bolt/test/X86/reader-stale-yaml.test new file mode 100644 --- /dev/null +++ b/bolt/test/X86/reader-stale-yaml.test @@ -0,0 +1,39 @@ +# This script checks that YamlProfileReader in llvm-bolt is reading data +# correctly and stale data is corrected. + +RUN: yaml2obj %p/Inputs/blarge.yaml &> %t.exe +RUN: llvm-bolt %t.exe -o /dev/null --b %p/Inputs/blarge_profile_stale.yaml --print-cfg --print-only=usqrt --infer-stale-profile=1 \ +RUN: 2>&1 | FileCheck %s -check-prefix=CHECK + +# Verify that yaml reader works as expected. +CHECK: pre-processing profile using YAML profile reader + +# Verify the inferred counts of "usqrt" that has stale profile: +# - the function has nblocks=6 in the profile, which makes it stale +# - block with bid=0 has an incorrect (missing) count, which is inferred +CHECK: Binary Function "usqrt" after building cfg { +CHECK: State : CFG constructed +CHECK: Address : 0x401170 +CHECK: Size : 0x43 +CHECK: Section : .text +CHECK: IsSimple : 1 +CHECK: BB Count : 5 +CHECK: Exec Count : 20 +CHECK: RawBranchCount : 640 +CHECK: } + +# Verify block counts. +CHECK: .LBB01 (4 instructions, align : 1) +CHECK: Successors: .Ltmp[[#BB13:]] (mispreds: 0, count: 20) +CHECK: .Ltmp[[#BB13:]] (9 instructions, align : 1) +CHECK: Successors: .Ltmp[[#BB12:]] (mispreds: 0, count: 320), .LFT[[#BB0:]] (mispreds: 0, count: 0) +CHECK: .LFT[[#BB0:]] (2 instructions, align : 1) +CHECK: Successors: .Ltmp[[#BB12:]] (mispreds: 0, count: 0) +CHECK: .Ltmp[[#BB12:]] (2 instructions, align : 1) +CHECK: Successors: .Ltmp[[#BB13:]] (mispreds: 0, count: 300), .LFT[[#BB1:]] (mispreds: 0, count: 20) +CHECK: .LFT[[#BB1:]] (2 instructions, align : 1) + +# Check the overal inference stats. +CHECK: 2 out of 7 functions in the binary (28.6%) have non-empty execution profile +CHECK: 1 (50.0% of all profiled) function have invalid (possibly stale) profile +CHECK: inferred profile for 1 (50.00% of all profiled) functions responsible for 87.31% samples