Fangrui Song | e0b9a4a | 2019-11-26 10:40:52 -0800 | [diff] [blame] | 1 | #!/usr/bin/env python3 |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 2 | |
| 3 | """Updates FileCheck checks in MIR tests. |
| 4 | |
| 5 | This script is a utility to update MIR based tests with new FileCheck |
| 6 | patterns. |
| 7 | |
| 8 | The checks added by this script will cover the entire body of each |
| 9 | function it handles. Virtual registers used are given names via |
| 10 | FileCheck patterns, so if you do want to check a subset of the body it |
| 11 | should be straightforward to trim out the irrelevant parts. None of |
Gaëtan Bossu | e29f77d | 2022-12-08 20:49:04 +0100 | [diff] [blame] | 12 | the YAML metadata will be checked, other than function names, and fixedStack |
| 13 | if the --print-fixed-stack option is used. |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 14 | |
| 15 | If there are multiple llc commands in a test, the full set of checks |
| 16 | will be repeated for each different check pattern. Checks for patterns |
| 17 | that are common between different commands will be left as-is by |
| 18 | default, or removed if the --remove-common-prefixes flag is provided. |
| 19 | """ |
| 20 | |
| 21 | from __future__ import print_function |
| 22 | |
| 23 | import argparse |
| 24 | import collections |
Simon Pilgrim | 2fa1863 | 2019-03-05 10:44:37 +0000 | [diff] [blame] | 25 | import glob |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 26 | import os |
| 27 | import re |
| 28 | import subprocess |
| 29 | import sys |
| 30 | |
Justin Bogner | 2589a0b | 2018-02-28 00:56:24 +0000 | [diff] [blame] | 31 | from UpdateTestChecks import common |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 32 | |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 33 | MIR_FUNC_NAME_RE = re.compile(r" *name: *(?P<func>[A-Za-z0-9_.-]+)") |
| 34 | MIR_BODY_BEGIN_RE = re.compile(r" *body: *\|") |
| 35 | MIR_BASIC_BLOCK_RE = re.compile(r" *bb\.[0-9]+.*:$") |
Jay Foad | 92b54b8 | 2023-09-18 12:14:46 +0100 | [diff] [blame] | 36 | VREG_RE = re.compile(r"(%[0-9]+)(?:\.[a-z0-9_]+)?(?::[a-z0-9_]+)?(?:\([<>a-z0-9 ]+\))?") |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 37 | MI_FLAGS_STR = ( |
| 38 | r"(frame-setup |frame-destroy |nnan |ninf |nsz |arcp |contract |afn " |
| 39 | r"|reassoc |nuw |nsw |exact |nofpexcept |nomerge )*" |
| 40 | ) |
Jay Foad | 92b54b8 | 2023-09-18 12:14:46 +0100 | [diff] [blame] | 41 | VREG_DEF_FLAGS_STR = r"(?:dead |undef )*" |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 42 | VREG_DEF_RE = re.compile( |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 43 | r"^ *(?P<vregs>{2}{0}(?:, {2}{0})*) = " |
| 44 | r"{1}(?P<opcode>[A-Zt][A-Za-z0-9_]+)".format( |
| 45 | VREG_RE.pattern, MI_FLAGS_STR, VREG_DEF_FLAGS_STR |
| 46 | ) |
| 47 | ) |
| 48 | MIR_PREFIX_DATA_RE = re.compile(r"^ *(;|bb.[0-9].*: *$|[a-z]+:( |$)|$)") |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 49 | |
Justin Bogner | 3a7928a | 2017-12-19 00:49:04 +0000 | [diff] [blame] | 50 | IR_FUNC_NAME_RE = re.compile( |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 51 | r"^\s*define\s+(?:internal\s+)?[^@]*@(?P<func>[A-Za-z0-9_.]+)\s*\(" |
| 52 | ) |
| 53 | IR_PREFIX_DATA_RE = re.compile(r"^ *(;|$)") |
Justin Bogner | 3a7928a | 2017-12-19 00:49:04 +0000 | [diff] [blame] | 54 | |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 55 | MIR_FUNC_RE = re.compile( |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 56 | r"^---$" |
| 57 | r"\n" |
| 58 | r"^ *name: *(?P<func>[A-Za-z0-9_.-]+)$" |
| 59 | r".*?" |
Jay Foad | 0f3446c | 2023-06-14 11:44:41 +0100 | [diff] [blame] | 60 | r"(?:^ *fixedStack: *(\[\])? *\n" |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 61 | r"(?P<fixedStack>.*?)\n?" |
| 62 | r"^ *stack:" |
Jay Foad | 0f3446c | 2023-06-14 11:44:41 +0100 | [diff] [blame] | 63 | r".*?)?" |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 64 | r"^ *body: *\|\n" |
| 65 | r"(?P<body>.*?)\n" |
| 66 | r"^\.\.\.$", |
| 67 | flags=(re.M | re.S), |
| 68 | ) |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 69 | |
Justin Bogner | 2589a0b | 2018-02-28 00:56:24 +0000 | [diff] [blame] | 70 | |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 71 | class LLC: |
| 72 | def __init__(self, bin): |
| 73 | self.bin = bin |
| 74 | |
| 75 | def __call__(self, args, ir): |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 76 | if ir.endswith(".mir"): |
| 77 | args = "{} -x mir".format(args) |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 78 | with open(ir) as ir_file: |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 79 | stdout = subprocess.check_output( |
| 80 | "{} {}".format(self.bin, args), shell=True, stdin=ir_file |
| 81 | ) |
Simon Pilgrim | ff4c7c2 | 2019-03-02 11:14:01 +0000 | [diff] [blame] | 82 | if sys.version_info[0] > 2: |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 83 | stdout = stdout.decode() |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 84 | # Fix line endings to unix CR style. |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 85 | stdout = stdout.replace("\r\n", "\n") |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 86 | return stdout |
| 87 | |
| 88 | |
| 89 | class Run: |
| 90 | def __init__(self, prefixes, cmd_args, triple): |
| 91 | self.prefixes = prefixes |
| 92 | self.cmd_args = cmd_args |
| 93 | self.triple = triple |
| 94 | |
| 95 | def __getitem__(self, index): |
| 96 | return [self.prefixes, self.cmd_args, self.triple][index] |
| 97 | |
| 98 | |
| 99 | def log(msg, verbose=True): |
| 100 | if verbose: |
| 101 | print(msg, file=sys.stderr) |
| 102 | |
| 103 | |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 104 | def find_triple_in_ir(lines, verbose=False): |
| 105 | for l in lines: |
Justin Bogner | 2589a0b | 2018-02-28 00:56:24 +0000 | [diff] [blame] | 106 | m = common.TRIPLE_IR_RE.match(l) |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 107 | if m: |
| 108 | return m.group(1) |
| 109 | return None |
| 110 | |
| 111 | |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 112 | def build_run_list(test, run_lines, verbose=False): |
| 113 | run_list = [] |
| 114 | all_prefixes = [] |
| 115 | for l in run_lines: |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 116 | if "|" not in l: |
| 117 | common.warn("Skipping unparsable RUN line: " + l) |
David Bolvansky | 2572160 | 2019-08-07 14:44:50 +0000 | [diff] [blame] | 118 | continue |
| 119 | |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 120 | commands = [cmd.strip() for cmd in l.split("|", 1)] |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 121 | llc_cmd = commands[0] |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 122 | filecheck_cmd = commands[1] if len(commands) > 1 else "" |
David Bolvansky | beca1b6 | 2019-07-29 17:41:00 +0000 | [diff] [blame] | 123 | common.verify_filecheck_prefixes(filecheck_cmd) |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 124 | |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 125 | if not llc_cmd.startswith("llc "): |
| 126 | common.warn("Skipping non-llc RUN line: {}".format(l), test_file=test) |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 127 | continue |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 128 | if not filecheck_cmd.startswith("FileCheck "): |
| 129 | common.warn( |
| 130 | "Skipping non-FileChecked RUN line: {}".format(l), test_file=test |
| 131 | ) |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 132 | continue |
| 133 | |
| 134 | triple = None |
Justin Bogner | 2589a0b | 2018-02-28 00:56:24 +0000 | [diff] [blame] | 135 | m = common.TRIPLE_ARG_RE.search(llc_cmd) |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 136 | if m: |
| 137 | triple = m.group(1) |
| 138 | # If we find -march but not -mtriple, use that. |
Justin Bogner | 2589a0b | 2018-02-28 00:56:24 +0000 | [diff] [blame] | 139 | m = common.MARCH_ARG_RE.search(llc_cmd) |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 140 | if m and not triple: |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 141 | triple = "{}--".format(m.group(1)) |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 142 | |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 143 | cmd_args = llc_cmd[len("llc") :].strip() |
| 144 | cmd_args = cmd_args.replace("< %s", "").replace("%s", "").strip() |
Shengchen Kan | e1af2a2 | 2023-02-04 09:35:32 +0800 | [diff] [blame] | 145 | check_prefixes = common.get_check_prefixes(filecheck_cmd) |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 146 | all_prefixes += check_prefixes |
| 147 | |
| 148 | run_list.append(Run(check_prefixes, cmd_args, triple)) |
| 149 | |
Nicolai Hähnle | 333bccf | 2022-05-25 01:57:14 +0200 | [diff] [blame] | 150 | # Sort prefixes that are shared between run lines before unshared prefixes. |
| 151 | # This causes us to prefer printing shared prefixes. |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 152 | for run in run_list: |
Nicolai Hähnle | 333bccf | 2022-05-25 01:57:14 +0200 | [diff] [blame] | 153 | run.prefixes.sort(key=lambda prefix: -all_prefixes.count(prefix)) |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 154 | |
Nicolai Hähnle | 333bccf | 2022-05-25 01:57:14 +0200 | [diff] [blame] | 155 | return run_list |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 156 | |
| 157 | |
| 158 | def find_functions_with_one_bb(lines, verbose=False): |
| 159 | result = [] |
| 160 | cur_func = None |
| 161 | bbs = 0 |
| 162 | for line in lines: |
Justin Bogner | e1fa9ae3f | 2017-12-18 23:31:55 +0000 | [diff] [blame] | 163 | m = MIR_FUNC_NAME_RE.match(line) |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 164 | if m: |
| 165 | if bbs == 1: |
| 166 | result.append(cur_func) |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 167 | cur_func = m.group("func") |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 168 | bbs = 0 |
Justin Bogner | e1fa9ae3f | 2017-12-18 23:31:55 +0000 | [diff] [blame] | 169 | m = MIR_BASIC_BLOCK_RE.match(line) |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 170 | if m: |
| 171 | bbs += 1 |
| 172 | if bbs == 1: |
| 173 | result.append(cur_func) |
| 174 | return result |
| 175 | |
| 176 | |
Gaëtan Bossu | e29f77d | 2022-12-08 20:49:04 +0100 | [diff] [blame] | 177 | class FunctionInfo: |
| 178 | def __init__(self, body, fixedStack): |
| 179 | self.body = body |
| 180 | self.fixedStack = fixedStack |
| 181 | |
| 182 | def __eq__(self, other): |
| 183 | if not isinstance(other, FunctionInfo): |
| 184 | return False |
| 185 | return self.body == other.body and self.fixedStack == other.fixedStack |
| 186 | |
| 187 | |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 188 | def build_function_info_dictionary( |
| 189 | test, raw_tool_output, triple, prefixes, func_dict, verbose |
| 190 | ): |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 191 | for m in MIR_FUNC_RE.finditer(raw_tool_output): |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 192 | func = m.group("func") |
| 193 | fixedStack = m.group("fixedStack") |
| 194 | body = m.group("body") |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 195 | if verbose: |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 196 | log("Processing function: {}".format(func)) |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 197 | for l in body.splitlines(): |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 198 | log(" {}".format(l)) |
Nicolai Hähnle | 333bccf | 2022-05-25 01:57:14 +0200 | [diff] [blame] | 199 | |
| 200 | # Vreg mangling |
| 201 | mangled = [] |
| 202 | vreg_map = {} |
| 203 | for func_line in body.splitlines(keepends=True): |
| 204 | m = VREG_DEF_RE.match(func_line) |
| 205 | if m: |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 206 | for vreg in VREG_RE.finditer(m.group("vregs")): |
Jay Foad | eebfa2f | 2023-09-15 13:10:45 +0100 | [diff] [blame] | 207 | if vreg.group(1) in vreg_map: |
| 208 | name = vreg_map[vreg.group(1)] |
| 209 | else: |
| 210 | name = mangle_vreg(m.group("opcode"), vreg_map.values()) |
| 211 | vreg_map[vreg.group(1)] = name |
Nicolai Hähnle | 333bccf | 2022-05-25 01:57:14 +0200 | [diff] [blame] | 212 | func_line = func_line.replace( |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 213 | vreg.group(1), "[[{}:%[0-9]+]]".format(name), 1 |
| 214 | ) |
Nicolai Hähnle | 333bccf | 2022-05-25 01:57:14 +0200 | [diff] [blame] | 215 | for number, name in vreg_map.items(): |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 216 | func_line = re.sub( |
| 217 | r"{}\b".format(number), "[[{}]]".format(name), func_line |
| 218 | ) |
Nicolai Hähnle | 333bccf | 2022-05-25 01:57:14 +0200 | [diff] [blame] | 219 | mangled.append(func_line) |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 220 | body = "".join(mangled) |
Nicolai Hähnle | 333bccf | 2022-05-25 01:57:14 +0200 | [diff] [blame] | 221 | |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 222 | for prefix in prefixes: |
Gaëtan Bossu | e29f77d | 2022-12-08 20:49:04 +0100 | [diff] [blame] | 223 | info = FunctionInfo(body, fixedStack) |
Nicolai Hähnle | 333bccf | 2022-05-25 01:57:14 +0200 | [diff] [blame] | 224 | if func in func_dict[prefix]: |
Gaëtan Bossu | e29f77d | 2022-12-08 20:49:04 +0100 | [diff] [blame] | 225 | if func_dict[prefix][func] != info: |
Nicolai Hähnle | 333bccf | 2022-05-25 01:57:14 +0200 | [diff] [blame] | 226 | func_dict[prefix][func] = None |
| 227 | else: |
Gaëtan Bossu | e29f77d | 2022-12-08 20:49:04 +0100 | [diff] [blame] | 228 | func_dict[prefix][func] = info |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 229 | |
| 230 | |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 231 | def add_checks_for_function( |
| 232 | test, output_lines, run_list, func_dict, func_name, single_bb, args |
| 233 | ): |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 234 | printed_prefixes = set() |
| 235 | for run in run_list: |
| 236 | for prefix in run.prefixes: |
| 237 | if prefix in printed_prefixes: |
Nicolai Hähnle | 333bccf | 2022-05-25 01:57:14 +0200 | [diff] [blame] | 238 | break |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 239 | if not func_dict[prefix][func_name]: |
| 240 | continue |
Eddie Phillips | e7ed55a | 2023-07-06 11:48:56 +0100 | [diff] [blame] | 241 | if printed_prefixes: |
| 242 | # Add some space between different check prefixes. |
| 243 | indent = len(output_lines[-1]) - len(output_lines[-1].lstrip(" ")) |
| 244 | output_lines.append(" "*indent + ";") |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 245 | printed_prefixes.add(prefix) |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 246 | log("Adding {} lines for {}".format(prefix, func_name), args.verbose) |
| 247 | add_check_lines( |
| 248 | test, |
| 249 | output_lines, |
| 250 | prefix, |
| 251 | func_name, |
| 252 | single_bb, |
| 253 | func_dict[prefix][func_name], |
| 254 | args, |
| 255 | ) |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 256 | break |
Nicolai Hähnle | 333bccf | 2022-05-25 01:57:14 +0200 | [diff] [blame] | 257 | else: |
| 258 | common.warn( |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 259 | "Found conflicting asm for function: {}".format(func_name), |
| 260 | test_file=test, |
| 261 | ) |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 262 | return output_lines |
| 263 | |
| 264 | |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 265 | def add_check_lines( |
| 266 | test, output_lines, prefix, func_name, single_bb, func_info: FunctionInfo, args |
| 267 | ): |
Gaëtan Bossu | e29f77d | 2022-12-08 20:49:04 +0100 | [diff] [blame] | 268 | func_body = func_info.body.splitlines() |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 269 | if single_bb: |
| 270 | # Don't bother checking the basic block label for a single BB |
| 271 | func_body.pop(0) |
| 272 | |
| 273 | if not func_body: |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 274 | common.warn( |
| 275 | "Function has no instructions to check: {}".format(func_name), |
| 276 | test_file=test, |
| 277 | ) |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 278 | return |
| 279 | |
| 280 | first_line = func_body[0] |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 281 | indent = len(first_line) - len(first_line.lstrip(" ")) |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 282 | # A check comment, indented the appropriate amount |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 283 | check = "{:>{}}; {}".format("", indent, prefix) |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 284 | |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 285 | output_lines.append("{}-LABEL: name: {}".format(check, func_name)) |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 286 | |
Gaëtan Bossu | e29f77d | 2022-12-08 20:49:04 +0100 | [diff] [blame] | 287 | if args.print_fixed_stack: |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 288 | output_lines.append("{}: fixedStack:".format(check)) |
Gaëtan Bossu | e29f77d | 2022-12-08 20:49:04 +0100 | [diff] [blame] | 289 | for stack_line in func_info.fixedStack.splitlines(): |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 290 | filecheck_directive = check + "-NEXT" |
| 291 | output_lines.append("{}: {}".format(filecheck_directive, stack_line)) |
Gaëtan Bossu | e29f77d | 2022-12-08 20:49:04 +0100 | [diff] [blame] | 292 | |
| 293 | first_check = True |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 294 | for func_line in func_body: |
| 295 | if not func_line.strip(): |
Alex Richardson | 19b7f39 | 2021-09-20 12:33:33 +0100 | [diff] [blame] | 296 | # The mir printer prints leading whitespace so we can't use CHECK-EMPTY: |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 297 | output_lines.append(check + "-NEXT: {{" + func_line + "$}}") |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 298 | continue |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 299 | filecheck_directive = check if first_check else check + "-NEXT" |
Alex Richardson | 19b7f39 | 2021-09-20 12:33:33 +0100 | [diff] [blame] | 300 | first_check = False |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 301 | check_line = "{}: {}".format(filecheck_directive, func_line[indent:]).rstrip() |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 302 | output_lines.append(check_line) |
| 303 | |
| 304 | |
| 305 | def mangle_vreg(opcode, current_names): |
| 306 | base = opcode |
| 307 | # Simplify some common prefixes and suffixes |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 308 | if opcode.startswith("G_"): |
| 309 | base = base[len("G_") :] |
| 310 | if opcode.endswith("_PSEUDO"): |
| 311 | base = base[: len("_PSEUDO")] |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 312 | # Shorten some common opcodes with long-ish names |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 313 | base = dict( |
| 314 | IMPLICIT_DEF="DEF", |
| 315 | GLOBAL_VALUE="GV", |
| 316 | CONSTANT="C", |
| 317 | FCONSTANT="C", |
| 318 | MERGE_VALUES="MV", |
| 319 | UNMERGE_VALUES="UV", |
| 320 | INTRINSIC="INT", |
| 321 | INTRINSIC_W_SIDE_EFFECTS="INT", |
| 322 | INSERT_VECTOR_ELT="IVEC", |
| 323 | EXTRACT_VECTOR_ELT="EVEC", |
| 324 | SHUFFLE_VECTOR="SHUF", |
| 325 | ).get(base, base) |
Justin Bogner | a217847 | 2017-10-18 15:37:09 +0000 | [diff] [blame] | 326 | # Avoid ambiguity when opcodes end in numbers |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 327 | if len(base.rstrip("0123456789")) < len(base): |
| 328 | base += "_" |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 329 | |
| 330 | i = 0 |
| 331 | for name in current_names: |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 332 | if name.rstrip("0123456789") == base: |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 333 | i += 1 |
| 334 | if i: |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 335 | return "{}{}".format(base, i) |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 336 | return base |
| 337 | |
| 338 | |
| 339 | def should_add_line_to_output(input_line, prefix_set): |
Eddie Phillips | e7ed55a | 2023-07-06 11:48:56 +0100 | [diff] [blame] | 340 | # Skip any check lines that we're handling as well as comments |
Justin Bogner | 2589a0b | 2018-02-28 00:56:24 +0000 | [diff] [blame] | 341 | m = common.CHECK_RE.match(input_line) |
Eddie Phillips | e7ed55a | 2023-07-06 11:48:56 +0100 | [diff] [blame] | 342 | if (m and m.group(1) in prefix_set) or re.search("^[ \t]*;", input_line): |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 343 | return False |
| 344 | return True |
| 345 | |
| 346 | |
Gaëtan Bossu | c7f0bc3 | 2022-12-08 21:50:02 +0100 | [diff] [blame] | 347 | def update_test_file(args, test, autogenerated_note): |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 348 | with open(test) as fd: |
| 349 | input_lines = [l.rstrip() for l in fd] |
| 350 | |
David Bolvansky | 2572160 | 2019-08-07 14:44:50 +0000 | [diff] [blame] | 351 | triple_in_ir = find_triple_in_ir(input_lines, args.verbose) |
Alex Richardson | 8a057a4 | 2019-12-02 10:50:23 +0000 | [diff] [blame] | 352 | run_lines = common.find_run_lines(test, input_lines) |
Nicolai Hähnle | 333bccf | 2022-05-25 01:57:14 +0200 | [diff] [blame] | 353 | run_list = build_run_list(test, run_lines, args.verbose) |
David Bolvansky | 2572160 | 2019-08-07 14:44:50 +0000 | [diff] [blame] | 354 | |
| 355 | simple_functions = find_functions_with_one_bb(input_lines, args.verbose) |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 356 | |
| 357 | func_dict = {} |
| 358 | for run in run_list: |
| 359 | for prefix in run.prefixes: |
| 360 | func_dict.update({prefix: dict()}) |
| 361 | for prefixes, llc_args, triple_in_cmd in run_list: |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 362 | log("Extracted LLC cmd: llc {}".format(llc_args), args.verbose) |
| 363 | log("Extracted FileCheck prefixes: {}".format(prefixes), args.verbose) |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 364 | |
Gaëtan Bossu | c7f0bc3 | 2022-12-08 21:50:02 +0100 | [diff] [blame] | 365 | raw_tool_output = args.llc_binary(llc_args, test) |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 366 | if not triple_in_cmd and not triple_in_ir: |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 367 | common.warn("No triple found: skipping file", test_file=test) |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 368 | return |
| 369 | |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 370 | build_function_info_dictionary( |
| 371 | test, |
| 372 | raw_tool_output, |
| 373 | triple_in_cmd or triple_in_ir, |
| 374 | prefixes, |
| 375 | func_dict, |
| 376 | args.verbose, |
| 377 | ) |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 378 | |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 379 | state = "toplevel" |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 380 | func_name = None |
| 381 | prefix_set = set([prefix for run in run_list for prefix in run.prefixes]) |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 382 | log("Rewriting FileCheck prefixes: {}".format(prefix_set), args.verbose) |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 383 | |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 384 | output_lines = [] |
| 385 | output_lines.append(autogenerated_note) |
| 386 | |
| 387 | for input_line in input_lines: |
| 388 | if input_line == autogenerated_note: |
| 389 | continue |
| 390 | |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 391 | if state == "toplevel": |
Justin Bogner | 3a7928a | 2017-12-19 00:49:04 +0000 | [diff] [blame] | 392 | m = IR_FUNC_NAME_RE.match(input_line) |
| 393 | if m: |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 394 | state = "ir function prefix" |
| 395 | func_name = m.group("func") |
| 396 | if input_line.rstrip("| \r\n") == "---": |
| 397 | state = "document" |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 398 | output_lines.append(input_line) |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 399 | elif state == "document": |
Justin Bogner | e1fa9ae3f | 2017-12-18 23:31:55 +0000 | [diff] [blame] | 400 | m = MIR_FUNC_NAME_RE.match(input_line) |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 401 | if m: |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 402 | state = "mir function metadata" |
| 403 | func_name = m.group("func") |
| 404 | if input_line.strip() == "...": |
| 405 | state = "toplevel" |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 406 | func_name = None |
| 407 | if should_add_line_to_output(input_line, prefix_set): |
| 408 | output_lines.append(input_line) |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 409 | elif state == "mir function metadata": |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 410 | if should_add_line_to_output(input_line, prefix_set): |
| 411 | output_lines.append(input_line) |
Justin Bogner | e1fa9ae3f | 2017-12-18 23:31:55 +0000 | [diff] [blame] | 412 | m = MIR_BODY_BEGIN_RE.match(input_line) |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 413 | if m: |
| 414 | if func_name in simple_functions: |
| 415 | # If there's only one block, put the checks inside it |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 416 | state = "mir function prefix" |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 417 | continue |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 418 | state = "mir function body" |
| 419 | add_checks_for_function( |
| 420 | test, |
| 421 | output_lines, |
| 422 | run_list, |
| 423 | func_dict, |
| 424 | func_name, |
| 425 | single_bb=False, |
| 426 | args=args, |
| 427 | ) |
| 428 | elif state == "mir function prefix": |
Justin Bogner | e1fa9ae3f | 2017-12-18 23:31:55 +0000 | [diff] [blame] | 429 | m = MIR_PREFIX_DATA_RE.match(input_line) |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 430 | if not m: |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 431 | state = "mir function body" |
| 432 | add_checks_for_function( |
| 433 | test, |
| 434 | output_lines, |
| 435 | run_list, |
| 436 | func_dict, |
| 437 | func_name, |
| 438 | single_bb=True, |
| 439 | args=args, |
| 440 | ) |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 441 | |
| 442 | if should_add_line_to_output(input_line, prefix_set): |
| 443 | output_lines.append(input_line) |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 444 | elif state == "mir function body": |
| 445 | if input_line.strip() == "...": |
| 446 | state = "toplevel" |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 447 | func_name = None |
| 448 | if should_add_line_to_output(input_line, prefix_set): |
| 449 | output_lines.append(input_line) |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 450 | elif state == "ir function prefix": |
Justin Bogner | 3a7928a | 2017-12-19 00:49:04 +0000 | [diff] [blame] | 451 | m = IR_PREFIX_DATA_RE.match(input_line) |
| 452 | if not m: |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 453 | state = "ir function body" |
| 454 | add_checks_for_function( |
| 455 | test, |
| 456 | output_lines, |
| 457 | run_list, |
| 458 | func_dict, |
| 459 | func_name, |
| 460 | single_bb=False, |
| 461 | args=args, |
| 462 | ) |
Justin Bogner | 3a7928a | 2017-12-19 00:49:04 +0000 | [diff] [blame] | 463 | |
| 464 | if should_add_line_to_output(input_line, prefix_set): |
| 465 | output_lines.append(input_line) |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 466 | elif state == "ir function body": |
| 467 | if input_line.strip() == "}": |
| 468 | state = "toplevel" |
Justin Bogner | 3a7928a | 2017-12-19 00:49:04 +0000 | [diff] [blame] | 469 | func_name = None |
| 470 | if should_add_line_to_output(input_line, prefix_set): |
| 471 | output_lines.append(input_line) |
| 472 | |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 473 | log("Writing {} lines to {}...".format(len(output_lines), test), args.verbose) |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 474 | |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 475 | with open(test, "wb") as fd: |
| 476 | fd.writelines(["{}\n".format(l).encode("utf-8") for l in output_lines]) |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 477 | |
| 478 | |
| 479 | def main(): |
| 480 | parser = argparse.ArgumentParser( |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 481 | description=__doc__, formatter_class=argparse.RawTextHelpFormatter |
| 482 | ) |
| 483 | parser.add_argument( |
| 484 | "--llc-binary", |
| 485 | default="llc", |
| 486 | type=LLC, |
| 487 | help='The "llc" binary to generate the test case with', |
| 488 | ) |
| 489 | parser.add_argument( |
| 490 | "--print-fixed-stack", |
| 491 | action="store_true", |
| 492 | help="Add check lines for fixedStack", |
| 493 | ) |
| 494 | parser.add_argument("tests", nargs="+") |
Alex Richardson | 0d25697 | 2019-11-20 13:19:48 +0000 | [diff] [blame] | 495 | args = common.parse_commandline_args(parser) |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 496 | |
Gaëtan Bossu | c7f0bc3 | 2022-12-08 21:50:02 +0100 | [diff] [blame] | 497 | script_name = os.path.basename(__file__) |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 498 | for ti in common.itertests(args.tests, parser, script_name="utils/" + script_name): |
Justin Bogner | b745be5 | 2017-10-18 22:36:08 +0000 | [diff] [blame] | 499 | try: |
Gaëtan Bossu | c7f0bc3 | 2022-12-08 21:50:02 +0100 | [diff] [blame] | 500 | update_test_file(ti.args, ti.path, ti.test_autogenerated_note) |
Justin Bogner | b745be5 | 2017-10-18 22:36:08 +0000 | [diff] [blame] | 501 | except Exception: |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 502 | common.warn("Error processing file", test_file=ti.path) |
Justin Bogner | b745be5 | 2017-10-18 22:36:08 +0000 | [diff] [blame] | 503 | raise |
Justin Bogner | 8fdac76 | 2017-10-18 02:20:31 +0000 | [diff] [blame] | 504 | |
| 505 | |
Tobias Hieta | 3c76287 | 2023-05-15 11:02:42 +0200 | [diff] [blame] | 506 | if __name__ == "__main__": |
| 507 | main() |