From: Amir Ayupov Date: Thu, 22 Dec 2022 00:31:26 +0000 (-0800) Subject: [BOLT] Check no-LBR samples in mayHaveProfileData X-Git-Tag: upstream/17.0.6~22228 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=6b05a62a6b10bcdfc777dee4761f273a5c883cba;p=platform%2Fupstream%2Fllvm.git [BOLT] Check no-LBR samples in mayHaveProfileData No-LBR mode wasn't tested and slipped when mayHaveProfileData was added for Lite mode. This enables processing of profiles collected without LBR and converted with `perf2bolt -nl` option. Test Plan: bin/llvm-lit -a tools/bolt/test/X86/nolbr.s https://github.com/rafaelauler/bolt-tests/pull/20 Reviewed By: #bolt, rafauler Differential Revision: https://reviews.llvm.org/D140256 --- diff --git a/bolt/lib/Profile/DataAggregator.cpp b/bolt/lib/Profile/DataAggregator.cpp index 4da1702..b320b44 100644 --- a/bolt/lib/Profile/DataAggregator.cpp +++ b/bolt/lib/Profile/DataAggregator.cpp @@ -646,7 +646,7 @@ void DataAggregator::processProfile(BinaryContext &BC) { // Mark all functions with registered events as having a valid profile. for (auto &BFI : BC.getBinaryFunctions()) { BinaryFunction &BF = BFI.second; - if (getBranchData(BF)) { + if (getBranchData(BF) || getFuncSampleData(BF.getNames())) { const auto Flags = opts::BasicAggregation ? BinaryFunction::PF_SAMPLE : BinaryFunction::PF_LBR; BF.markProfiled(Flags); diff --git a/bolt/lib/Profile/DataReader.cpp b/bolt/lib/Profile/DataReader.cpp index d6e031a..a2a7787 100644 --- a/bolt/lib/Profile/DataReader.cpp +++ b/bolt/lib/Profile/DataReader.cpp @@ -1331,7 +1331,8 @@ bool DataReader::mayHaveProfileData(const BinaryFunction &Function) { if (getBranchData(Function) || getMemData(Function)) return true; - if (getBranchDataForNames(Function.getNames()) || + if (getFuncSampleData(Function.getNames()) || + getBranchDataForNames(Function.getNames()) || getMemDataForNames(Function.getNames())) return true; diff --git a/bolt/test/X86/nolbr.s b/bolt/test/X86/nolbr.s new file mode 100644 index 0000000..bebb697 --- /dev/null +++ b/bolt/test/X86/nolbr.s @@ -0,0 +1,39 @@ +# This reproduces a bug where profile collected from perf without LBRs and +# converted into fdata-no-lbr format is reported to not contain profile for any +# functions. + +# REQUIRES: system-linux + +# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown \ +# RUN: %s -o %t.o +# RUN: link_fdata --no-lbr %s %t.o %t.fdata +# RUN: FileCheck %s --input-file %t.fdata --check-prefix=CHECK-FDATA +# RUN: llvm-strip --strip-unneeded %t.o +# RUN: %clang %cflags %t.o -o %t.exe -Wl,-q -nostdlib +# RUN: llvm-bolt %t.exe -o %t.out --data %t.fdata --dyno-stats -nl \ +# RUN: --print-only=_start 2>&1 | FileCheck %s --check-prefix=CHECK-BOLT + +# CHECK-FDATA: no_lbr +# CHECK-FDATA-NEXT: 1 _start [[#]] 1 + +# CHECK-BOLT: BOLT-INFO: pre-processing profile using branch profile reader +# CHECK-BOLT: BOLT-INFO: operating with basic samples profiling data (no LBR). +# CHECK-BOLT: BOLT-INFO: 1 out of 1 functions in the binary (100.0%) have non-empty execution profile + + .globl _start + .type _start, %function +_start: + pushq %rbp + movq %rsp, %rbp + cmpl $0x0, %eax +a: +# FDATA: 1 _start #a# 1 + je b + movl $0x0, %eax + jmp c +b: + movl $0x1, %eax +c: + popq %rbp + retq +.size _start, .-_start diff --git a/bolt/test/link_fdata.py b/bolt/test/link_fdata.py index e54125f..b87804d 100755 --- a/bolt/test/link_fdata.py +++ b/bolt/test/link_fdata.py @@ -18,6 +18,7 @@ parser.add_argument("objfile", help="Object file to extract symbol values from") parser.add_argument("output") parser.add_argument("prefix", nargs="?", default="FDATA", help="Custom FDATA prefix") parser.add_argument("--nmtool", default="nm", help="Path to nm tool") +parser.add_argument("--no-lbr", action='store_true') args = parser.parse_args() @@ -36,6 +37,10 @@ fdata_pat = re.compile(r"([01].*) (?P\d+) (?P\d+)") # [] preagg_pat = re.compile(r"(?P[BFf]) (?P.*)") +# No-LBR profile: +# +nolbr_pat = re.compile(r"([01].*) (?P\d+)") + # Replacement symbol: #symname# replace_pat = re.compile(r"#(?P[^#]+)#") @@ -51,6 +56,7 @@ with open(args.input, 'r') as f: profile_line = prefix_match.group(1) fdata_match = fdata_pat.match(profile_line) preagg_match = preagg_pat.match(profile_line) + nolbr_match = nolbr_pat.match(profile_line) if fdata_match: src_dst, execnt, mispred = fdata_match.groups() # Split by whitespaces not preceded by a backslash (negative lookbehind) @@ -59,6 +65,14 @@ with open(args.input, 'r') as f: # exactly matches the format. assert len(chunks) == 6, f"ERROR: wrong format/whitespaces must be escaped:\n{line}" exprs.append(('FDATA', (*chunks, execnt, mispred))) + elif nolbr_match: + loc, count = nolbr_match.groups() + # Split by whitespaces not preceded by a backslash (negative lookbehind) + chunks = re.split(r'(?