Skip to content
This repository was archived by the owner on Jul 1, 2023. It is now read-only.

Commit 81e6eca

Browse files
aaupovfacebook-github-bot
authored andcommitted
Wrapper script: support for no-output tests and heatmap mode
Summary: - Added an option `skip_binary_cmp` to support invocations that don't output a binary - Minor fixes for heatmap mode, timeout, log comparison - Rearranged in-line config example to be copy-pasteable Reviewed By: rafaelauler Differential Revision: D26822016 fbshipit-source-id: cd6cbc00440
1 parent 2af45be commit 81e6eca

File tree

1 file changed

+45
-32
lines changed

1 file changed

+45
-32
lines changed

utils/llvm-bolt-wrapper.py

Lines changed: 45 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,18 @@
2323
# read options from config file llvm-bolt-wrapper.ini in script CWD
2424
#
2525
# [config]
26-
# base_bolt = /full/path/to/llvm-bolt.real # mandatory
27-
# cmp_bolt = /full/path/to/other/llvm-bolt # mandatory
28-
# verbose # optional, defaults to False
29-
# keep_tmp # optional, defaults to False
30-
# no_minimize # optional, defaults to False
31-
# run_sequentially # optional, defaults to False
32-
# compare_output # optional, defaults to False
33-
# timing_file = timing1.log # optional, defaults to timing.log
26+
# # mandatory
27+
# base_bolt = /full/path/to/llvm-bolt.real
28+
# cmp_bolt = /full/path/to/other/llvm-bolt
29+
# # optional, default to False
30+
# verbose
31+
# keep_tmp
32+
# no_minimize
33+
# run_sequentially
34+
# compare_output
35+
# skip_binary_cmp
36+
# # optional, defaults to timing.log in CWD
37+
# timing_file = timing1.log
3438

3539
cfg = configparser.ConfigParser(allow_no_value = True)
3640
cfgs = cfg.read("llvm-bolt-wrapper.ini")
@@ -56,6 +60,7 @@ def get_cfg(key):
5660
NO_MINIMIZE = get_cfg('no_minimize')
5761
RUN_SEQUENTIALLY = get_cfg('run_sequentially')
5862
COMPARE_OUTPUT = get_cfg('compare_output')
63+
SKIP_BINARY_CMP = get_cfg('skip_binary_cmp')
5964
TIMING_FILE = cfg['config'].get('timing_file', 'timing.log')
6065

6166
# perf2bolt mode
@@ -75,6 +80,8 @@ def get_cfg(key):
7580
'BOLT-INFO: BOLT version',
7681
'^Args: ',
7782
'^BOLT-DEBUG:',
83+
'BOLT-INFO:.*data.*output data',
84+
'WARNING: reading perf data directly',
7885
]
7986

8087
def run_cmd(cmd):
@@ -124,26 +131,26 @@ def write_to(txt, filename, mode='w'):
124131
def wait(proc):
125132
try:
126133
out, err = proc.communicate(timeout=9000)
127-
except TimeoutExpired:
134+
except subprocess.TimeoutExpired:
128135
proc.kill()
129136
out, err = proc.communicate()
130137
return out, err
131138

132-
def compare_logs(main, cmp):
139+
def compare_logs(main, cmp, skip_end=0):
133140
'''
134141
Compares logs but allows for certain lines to be excluded from comparison.
135142
Returns None on success, mismatch otherwise.
136143
'''
137-
for main_line, cmp_line in zip(main.splitlines(), cmp.splitlines()):
138-
if main_line != cmp_line:
144+
for lhs, rhs in list(zip(main.splitlines(), cmp.splitlines()))[:-skip_end]:
145+
if lhs != rhs:
139146
# check skip patterns
140147
for skip in SKIP_MATCH:
141148
# both lines must contain the pattern
142-
if re.search(skip, main_line) and re.search(skip, cmp_line):
149+
if re.search(skip, lhs) and re.search(skip, rhs):
143150
break
144151
# otherwise return mismatching lines
145152
else:
146-
return (main_line, cmp_line)
153+
return (lhs, rhs)
147154
return None
148155

149156
def fmt_cmp(cmp_tuple):
@@ -196,18 +203,18 @@ def main():
196203
args = prepend_dash(args)
197204

198205
# run both BOLT binaries
199-
main_bolt = run_bolt(BASE_BOLT, args + unknownargs)
206+
main_bolt = run_bolt(BASE_BOLT, unknownargs + args)
200207
if RUN_SEQUENTIALLY:
201208
main_out, main_err = wait(main_bolt)
202-
cmp_bolt = run_bolt(CMP_BOLT, cmp_args + unknownargs)
209+
cmp_bolt = run_bolt(CMP_BOLT, unknownargs + cmp_args)
203210
else:
204-
cmp_bolt = run_bolt(CMP_BOLT, cmp_args + unknownargs)
211+
cmp_bolt = run_bolt(CMP_BOLT, unknownargs + cmp_args)
205212
main_out, main_err = wait(main_bolt)
206213
cmp_out, cmp_err = wait(cmp_bolt)
207214

208215
# compare logs
209216
out = compare_logs(main_out, cmp_out)
210-
err = compare_logs(main_err, cmp_err)
217+
err = compare_logs(main_err, cmp_err, skip_end=1) # skips the line with time
211218
if (main_bolt.returncode != cmp_bolt.returncode or
212219
(COMPARE_OUTPUT and (out or err))):
213220
print(tmp)
@@ -225,20 +232,26 @@ def main():
225232
# report binary timing as csv: output binary; base bolt real; cmp bolt real
226233
report_real_time(main_binary, main_err, cmp_err)
227234

228-
cmp_proc = subprocess.run(['cmp', main_binary, cmp_binary],
229-
capture_output=True, text=True)
230-
if cmp_proc.returncode:
231-
# check if ELF headers match
232-
hdr = compare_headers(main_binary, cmp_binary)
233-
if hdr:
234-
print(fmt_cmp(hdr))
235-
write_to(fmt_cmp(hdr), os.path.join(tmp, 'headers.txt'))
236-
exit("headers mismatch")
237-
# check which section has the first mismatch
238-
mismatch_offset = parse_cmp_offset(cmp_proc.stdout)
239-
print(mismatch_offset)
240-
# since headers match, check which section this offset falls into
241-
exit("binaries mismatch")
235+
if not SKIP_BINARY_CMP:
236+
cmp_proc = subprocess.run(['cmp', main_binary, cmp_binary],
237+
capture_output=True, text=True)
238+
if cmp_proc.returncode:
239+
# check if output is an ELF file (magic bytes)
240+
with open(main_binary, 'rb') as f:
241+
magic = f.read(4)
242+
if magic != b'\x7fELF':
243+
exit("output mismatch")
244+
# check if ELF headers match
245+
hdr = compare_headers(main_binary, cmp_binary)
246+
if hdr:
247+
print(fmt_cmp(hdr))
248+
write_to(fmt_cmp(hdr), os.path.join(tmp, 'headers.txt'))
249+
exit("headers mismatch")
250+
# check which section has the first mismatch
251+
mismatch_offset = parse_cmp_offset(cmp_proc.stdout)
252+
print(mismatch_offset)
253+
# since headers match, check which section this offset falls into
254+
exit("binaries mismatch")
242255

243256
# temp files are only cleaned on success
244257
if not KEEP_TMP:

0 commit comments

Comments
 (0)