Skip to content

Commit 6ad693e

Browse files
[mca] update_mca_test_checks.py helpers to manage llvm-mca -scheduling-info new option
When using llvm-mca -scheduling-info and if assembly test contains comments with reference values of scheduling info: <MicroOps> <Latency> <Forward Latency> <Throughput> <Units> To check coherency between llvm-mca -scheduling-info output and scheduling references in comment, use --check-sched-info. Exit with error if found deferences and report them. This is usefull to check new scheduling info patches as we can specify source documentation references for each instructions and so be able to understand easier differences. Example of comment in AArch64/Neoverse/V1-scheduling-info.s: abs D15, D23 // ABS <V><d>, <V><n> \\ ASIMD arith, basic \\ 1 2 2 4.0 V1UnitV llvm-mca -scheduling-info output: 1 2 2 4.00 - ABSv1i64 V1UnitSVE01, V1UnitV, abs d15, d23 // ABS <V><d>, <V><n> \\ ASIMD arith, basic \\ 1 2 2 4.0 V1UnitV update_mca_test_checks.py is searching for 4 values at the begining and after comment // and compare these values. Values order must be the same as llvm-mca output. And it will check that all resources in comment (reference) is included in llvm-mca output. It is possible to update source test scheduling information references using -update-sched-info option. If you want to update test source references and llvm-mca output references, you have to run two times update_mca_test_checks.py -update-sched-info. First time to update scheduling information references and second time to update llvm-mca new output reference.
1 parent 1f2ab0d commit 6ad693e

File tree

1 file changed

+183
-0
lines changed

1 file changed

+183
-0
lines changed

llvm/utils/update_mca_test_checks.py

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import os
1313
import sys
1414
import warnings
15+
import re
1516

1617
from UpdateTestChecks import common
1718

@@ -64,6 +65,18 @@ def _get_parser():
6465
default="llvm-mca",
6566
help="the binary to use to generate the test case " "(default: llvm-mca)",
6667
)
68+
parser.add_argument(
69+
"--check-sched-info",
70+
action="store_true",
71+
help="check scheduling info if references are given "
72+
"in comment after each instruction",
73+
)
74+
parser.add_argument(
75+
"--update-sched-info",
76+
action="store_true",
77+
help="updating scheduling info references given "
78+
"in comment after each instruction",
79+
)
6780
parser.add_argument("tests", metavar="<test-path>", nargs="+")
6881
return parser
6982

@@ -245,6 +258,156 @@ def _align_matching_blocks(all_blocks, farthest_indexes):
245258
return False
246259

247260

261+
def _check_sched_values(line, scheds, units, err, updates):
262+
"""Check for scheduling values differences
263+
between values reported by llvm-mca with -scheduling-info option
264+
and values in comment at the end of assembly instruction line (//).
265+
Reference units must be included in the list reported by llvm-mca.
266+
"""
267+
268+
_err = []
269+
# Got zip of llvm output and values from comment
270+
infos = ["MicroOps", "Latency", "Forward latency", "Throughput"]
271+
sched_info = zip(infos, scheds[0].split(), scheds[1].split())
272+
for si in sched_info:
273+
if float(si[1]) != float(si[2]):
274+
updates.add("sched")
275+
_err.append(
276+
"\t=> {} LLVM value {} != reference value in comment {}\n".format(
277+
si[0], si[1], si[2]
278+
)
279+
)
280+
281+
for u in units[1]:
282+
if not u in units[0]:
283+
updates.add("units")
284+
_err.append(
285+
"\t=> LLVM units {} != reference units in comment {}\n".format(
286+
units[0], units[1]
287+
)
288+
)
289+
break
290+
291+
if len(_err) > 0:
292+
err.append("{}\n{}".format(line, "".join(_err)))
293+
return True
294+
295+
return False
296+
297+
298+
def _replace_values(oldvalue, newvalue):
299+
"""Replacing values with the same format (spaces)
300+
than oldvalue
301+
"""
302+
303+
fmt = re.sub("[0-9.]+", "{}", oldvalue)
304+
return fmt.format(*newvalue.split())
305+
306+
307+
def _has_comment(line, cmt_format):
308+
"""Returns True if line contains C++ or C style
309+
comment. Set cmt_format first and optional second
310+
comment caracters.
311+
"""
312+
313+
cpp_comment = re.search("\/\/", line)
314+
c_comment = re.search("\/\*", line)
315+
if "//" in line:
316+
cmt_format.append("//")
317+
return True
318+
319+
if "/*" in line:
320+
cmt_format.append("/*")
321+
cmt_format.append("*/")
322+
return True
323+
324+
return False
325+
326+
327+
def _sched_info(raw_tool_output, test_path, check_sched_info, update_sched_info):
328+
"""Check scheduling info if passed in assembly comment after each
329+
instructions.
330+
331+
Recognized form is:
332+
1 | 2 | 2 | 4.00 | ABSv1i64 | V1UnitV, | abs d15, d23
333+
// ABS <V><d>, <V><n> \\ ASIMD arith, basic \\ 1 2 2 4.0 V1UnitV
334+
335+
Format:
336+
[1] // [2] \\ [3] \\ [4]
337+
[1]: <llvm-mca output> <asm instruction>
338+
[2]: <Architecture description>
339+
[3]: <Scheduling info reference>
340+
[4]: <micro ops> <latency> <forward latency> <throughput> <units>
341+
342+
<llvm-mca output> with -scheduling-info option:
343+
<MicroOps> | <latency> | <fwd latency> | <throughput> |
344+
<side effect> | <llvm opcode> <units>
345+
346+
The goal is to check [4] regarding llvm-mca output with -scheduling-info [1]
347+
option. It will allow to check scheduling info easily when
348+
doing code review of scheduling info merge requests.
349+
If a difference is found, the comment should be fixed and checked
350+
against documentation.
351+
"""
352+
353+
scheduling_info = re.compile(
354+
"(^\s+|\\\\\s+)([0-9]+[\s|]+[0-9]+" "[\s|]+[0-9]+[\s|]+\s+[0-9.]+)"
355+
)
356+
units_info = re.compile(
357+
"(^\s+|\\\\\s+)[0-9]+[\s|]+[0-9]+" "[\s|]+[0-9]+[\s|]+\s+[0-9.]+[\s|]+([^|*/]+)"
358+
)
359+
360+
fixes = {}
361+
err = []
362+
instr_idx = 0
363+
for b in raw_tool_output.split("\n\n"):
364+
for line in b.splitlines():
365+
cmt_format = []
366+
if _has_comment(line, cmt_format):
367+
scheds = scheduling_info.findall(line)
368+
scheds = [s[1].replace("|", "") for s in scheds]
369+
if len(scheds) == 2:
370+
cmt = cmt_format[0] + line.split(cmt_format[0])[1]
371+
units = units_info.findall(line)
372+
c_units = [re.sub("\s", "", u[1]).split(",") for u in units]
373+
updates = set()
374+
if _check_sched_values(line, scheds, c_units, err, updates):
375+
if update_sched_info:
376+
if "sched" in updates:
377+
cmt = cmt.replace(
378+
scheds[1], _replace_values(scheds[1], scheds[0])
379+
)
380+
if "units" in updates:
381+
cmt = cmt.replace(units[1][1], units[0][1])
382+
383+
fixes[instr_idx] = cmt
384+
instr_idx = instr_idx + 1
385+
386+
if update_sched_info:
387+
with open(test_path) as f:
388+
# Overwrite test with new fixed comments if any.
389+
# Test file will be read again just before writing final checking
390+
output_lines = []
391+
instr_idx = 0
392+
393+
for line in f:
394+
out = line.rstrip()
395+
cmt_format = []
396+
if _has_comment(line, cmt_format) and not re.match("^#", line):
397+
if fixes.get(instr_idx) is not None:
398+
out = line.split(cmt_format[0])[0] + fixes[instr_idx]
399+
400+
instr_idx = instr_idx + 1
401+
402+
output_lines.append(out)
403+
404+
with open(test_path, "wb") as f:
405+
f.writelines(["{}\n".format(l).encode("utf-8") for l in output_lines])
406+
407+
if check_sched_info:
408+
if len(err) > 0:
409+
raise Error("{}".format("".join(err)))
410+
248411
def _get_block_infos(run_infos, test_path, args, common_prefix): # noqa
249412
"""For each run line, run the tool with the specified args and collect the
250413
output. We use the concept of 'blocks' for uniquing, where a block is
@@ -289,6 +452,20 @@ def _block_key(tool_args, prefixes):
289452
line if line.strip() else "" for line in raw_tool_output.splitlines()
290453
)
291454

455+
# Check if -scheduling-info passed to llvm-mca to check comments if any
456+
if "-scheduling-info" in tool_args:
457+
_sched_info(
458+
raw_tool_output,
459+
test_path,
460+
args.check_sched_info,
461+
args.update_sched_info,
462+
)
463+
else:
464+
if args.check_sched_info:
465+
_warn("--check-sched-info: ignored: need llvm-mca -scheduling-info")
466+
if args.update_sched_info:
467+
_warn("--update-sched-info: ignored: need llvm-mca -scheduling-info")
468+
292469
# Split blocks, stripping all trailing whitespace, but keeping preceding
293470
# whitespace except for newlines so that columns will line up visually.
294471
all_blocks[key] = [
@@ -550,6 +727,12 @@ def update_test_file(args, test_path, autogenerated_note):
550727
run_infos = _get_run_infos(run_lines, args)
551728
common_prefix, prefix_pad = _get_useful_prefix_info(run_infos)
552729
block_infos = _get_block_infos(run_infos, test_path, args, common_prefix)
730+
731+
if args.update_sched_info:
732+
# Read again input lines in case of changes (scheduling info updates in comments)
733+
with open(test_path) as f:
734+
input_lines = [l.rstrip() for l in f]
735+
553736
_write_output(
554737
test_path,
555738
input_lines,

0 commit comments

Comments
 (0)