[Frontend] Remove unused includes (NFC) (#116927)
[llvm-project.git] / llvm / utils / update_llc_test_checks.py
blob3e9380d95e3f60ec18ca60ce2f4cd65edd086a8d
1 #!/usr/bin/env python3
3 """A test case update script.
5 This script is a utility to update LLVM 'llc' based test cases with new
6 FileCheck patterns. It can either update all of the tests in the file or
7 a single test function.
8 """
10 from __future__ import print_function
12 import argparse
13 import os # Used to advertise this file's name ("autogenerated_note").
15 from UpdateTestChecks import common
17 # llc is the only llc-like in the LLVM tree but downstream forks can add
18 # additional ones here if they have them.
19 LLC_LIKE_TOOLS = [
20 "llc",
24 def main():
25 parser = argparse.ArgumentParser(description=__doc__)
26 parser.add_argument(
27 "--llc-binary",
28 default=None,
29 help='The "llc" binary to use to generate the test case',
31 parser.add_argument("--function", help="The function in the test file to update")
32 parser.add_argument(
33 "--extra_scrub",
34 action="store_true",
35 help="Always use additional regex to further reduce diffs between various subtargets",
37 parser.add_argument(
38 "--x86_scrub_sp",
39 action="store_true",
40 default=True,
41 help="Use regex for x86 sp matching to reduce diffs between various subtargets",
43 parser.add_argument("--no_x86_scrub_sp", action="store_false", dest="x86_scrub_sp")
44 parser.add_argument(
45 "--x86_scrub_rip",
46 action="store_true",
47 default=False,
48 help="Use more regex for x86 rip matching to reduce diffs between various subtargets",
50 parser.add_argument(
51 "--no_x86_scrub_rip", action="store_false", dest="x86_scrub_rip"
53 parser.add_argument(
54 "--no_x86_scrub_mem_shuffle",
55 action="store_true",
56 default=False,
57 help="Reduce scrubbing shuffles with memory operands",
59 parser.add_argument(
60 "--tool",
61 default=None,
62 help="Treat the given tool name as an llc-like tool for which check lines should be generated",
64 parser.add_argument(
65 "--default-march",
66 default=None,
67 help="Set a default -march for when neither triple nor arch are found in a RUN line",
69 parser.add_argument("tests", nargs="+")
70 initial_args = common.parse_commandline_args(parser)
72 script_name = os.path.basename(__file__)
74 for ti in common.itertests(
75 initial_args.tests, parser, script_name="utils/" + script_name
77 triple_in_ir = None
78 for l in ti.input_lines:
79 m = common.TRIPLE_IR_RE.match(l)
80 if m:
81 triple_in_ir = m.groups()[0]
82 break
84 run_list = []
85 for l in ti.run_lines:
86 if "|" not in l:
87 common.warn("Skipping unparsable RUN line: " + l)
88 continue
90 commands = [cmd.strip() for cmd in l.split("|")]
91 assert len(commands) >= 2
92 preprocess_cmd = None
93 if len(commands) > 2:
94 preprocess_cmd = " | ".join(commands[:-2])
95 llc_cmd = commands[-2]
96 filecheck_cmd = commands[-1]
97 llc_tool = llc_cmd.split(" ")[0]
99 triple_in_cmd = None
100 m = common.TRIPLE_ARG_RE.search(llc_cmd)
101 if m:
102 triple_in_cmd = m.groups()[0]
104 march_in_cmd = ti.args.default_march
105 m = common.MARCH_ARG_RE.search(llc_cmd)
106 if m:
107 march_in_cmd = m.groups()[0]
109 m = common.DEBUG_ONLY_ARG_RE.search(llc_cmd)
110 if m and m.groups()[0] == "isel":
111 from UpdateTestChecks import isel as output_type
112 else:
113 from UpdateTestChecks import asm as output_type
115 common.verify_filecheck_prefixes(filecheck_cmd)
117 llc_like_tools = LLC_LIKE_TOOLS[:]
118 if ti.args.tool:
119 llc_like_tools.append(ti.args.tool)
120 if llc_tool not in llc_like_tools:
121 common.warn("Skipping non-llc RUN line: " + l)
122 continue
124 if not filecheck_cmd.startswith("FileCheck "):
125 common.warn("Skipping non-FileChecked RUN line: " + l)
126 continue
128 llc_cmd_args = llc_cmd[len(llc_tool) :].strip()
129 llc_cmd_args = llc_cmd_args.replace("< %s", "").replace("%s", "").strip()
130 if ti.path.endswith(".mir"):
131 llc_cmd_args += " -x mir"
132 check_prefixes = common.get_check_prefixes(filecheck_cmd)
134 # FIXME: We should use multiple check prefixes to common check lines. For
135 # now, we just ignore all but the last.
136 run_list.append(
138 check_prefixes,
139 llc_tool,
140 llc_cmd_args,
141 preprocess_cmd,
142 triple_in_cmd,
143 march_in_cmd,
147 if ti.path.endswith(".mir"):
148 check_indent = " "
149 else:
150 check_indent = ""
152 ginfo = common.make_asm_generalizer(version=1)
153 builder = common.FunctionTestBuilder(
154 run_list=run_list,
155 flags=type(
157 (object,),
159 "verbose": ti.args.verbose,
160 "filters": ti.args.filters,
161 "function_signature": False,
162 "check_attributes": False,
163 "replace_value_regex": [],
166 scrubber_args=[ti.args],
167 path=ti.path,
168 ginfo=ginfo,
171 for (
172 prefixes,
173 llc_tool,
174 llc_args,
175 preprocess_cmd,
176 triple_in_cmd,
177 march_in_cmd,
178 ) in run_list:
179 common.debug("Extracted LLC cmd:", llc_tool, llc_args)
180 common.debug("Extracted FileCheck prefixes:", str(prefixes))
182 raw_tool_output = common.invoke_tool(
183 ti.args.llc_binary or llc_tool,
184 llc_args,
185 ti.path,
186 preprocess_cmd,
187 verbose=ti.args.verbose,
189 triple = triple_in_cmd or triple_in_ir
190 if not triple:
191 triple = common.get_triple_from_march(march_in_cmd)
193 scrubber, function_re = output_type.get_run_handler(triple)
194 builder.process_run_line(function_re, scrubber, raw_tool_output, prefixes)
195 builder.processed_prefixes(prefixes)
197 func_dict = builder.finish_and_get_func_dict()
198 global_vars_seen_dict = {}
200 is_in_function = False
201 is_in_function_start = False
202 func_name = None
203 prefix_set = set([prefix for p in run_list for prefix in p[0]])
204 common.debug("Rewriting FileCheck prefixes:", str(prefix_set))
205 output_lines = []
207 include_generated_funcs = common.find_arg_in_test(
209 lambda args: ti.args.include_generated_funcs,
210 "--include-generated-funcs",
211 True,
214 generated_prefixes = []
215 if include_generated_funcs:
216 # Generate the appropriate checks for each function. We need to emit
217 # these in the order according to the generated output so that CHECK-LABEL
218 # works properly. func_order provides that.
220 # We can't predict where various passes might insert functions so we can't
221 # be sure the input function order is maintained. Therefore, first spit
222 # out all the source lines.
223 common.dump_input_lines(output_lines, ti, prefix_set, ";")
225 # Now generate all the checks.
226 generated_prefixes = common.add_checks_at_end(
227 output_lines,
228 run_list,
229 builder.func_order(),
230 check_indent + ";",
231 lambda my_output_lines, prefixes, func: output_type.add_checks(
232 my_output_lines,
233 check_indent + ";",
234 prefixes,
235 func_dict,
236 func,
237 ginfo,
238 global_vars_seen_dict,
239 is_filtered=builder.is_filtered(),
242 else:
243 for input_info in ti.iterlines(output_lines):
244 input_line = input_info.line
245 args = input_info.args
246 if is_in_function_start:
247 if input_line == "":
248 continue
249 if input_line.lstrip().startswith(";"):
250 m = common.CHECK_RE.match(input_line)
251 if not m or m.group(1) not in prefix_set:
252 output_lines.append(input_line)
253 continue
255 # Print out the various check lines here.
256 generated_prefixes.extend(
257 output_type.add_checks(
258 output_lines,
259 check_indent + ";",
260 run_list,
261 func_dict,
262 func_name,
263 ginfo,
264 global_vars_seen_dict,
265 is_filtered=builder.is_filtered(),
268 is_in_function_start = False
270 if is_in_function:
271 if common.should_add_line_to_output(input_line, prefix_set):
272 # This input line of the function body will go as-is into the output.
273 output_lines.append(input_line)
274 else:
275 continue
276 if input_line.strip() == "}":
277 is_in_function = False
278 continue
280 # If it's outside a function, it just gets copied to the output.
281 output_lines.append(input_line)
283 m = common.IR_FUNCTION_RE.match(input_line)
284 if not m:
285 continue
286 func_name = m.group(1)
287 if args.function is not None and func_name != args.function:
288 # When filtering on a specific function, skip all others.
289 continue
290 is_in_function = is_in_function_start = True
292 if ti.args.gen_unused_prefix_body:
293 output_lines.extend(
294 ti.get_checks_for_unused_prefixes(run_list, generated_prefixes)
297 common.debug("Writing %d lines to %s..." % (len(output_lines), ti.path))
298 with open(ti.path, "wb") as f:
299 f.writelines(["{}\n".format(l).encode("utf-8") for l in output_lines])
302 if __name__ == "__main__":
303 main()