-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Change update_xxx_checks to continue on error when processing mutliple inputs #137728
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Example run with the modified script (while I am backporting commits to an older branch which lacks some IR syntax):
|
@llvm/pr-subscribers-testing-tools Author: Matthias Braun (MatzeB) ChangesChange llvm/utils/update_xxx_checks.py scripts to: Catch exceptions individually for each test. On exception print which test triggered the exception and continue with the remaining test updates. Patch is 95.56 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/137728.diff 7 Files Affected:
diff --git a/llvm/utils/update_analyze_test_checks.py b/llvm/utils/update_analyze_test_checks.py
index d356ebead0d81..6ecf51b88d819 100755
--- a/llvm/utils/update_analyze_test_checks.py
+++ b/llvm/utils/update_analyze_test_checks.py
@@ -31,6 +31,8 @@
from __future__ import print_function
+from sys import stderr
+from traceback import print_exc
import argparse
import os # Used to advertise this file's name ("autogenerated_note").
import sys
@@ -39,6 +41,158 @@
from UpdateTestChecks import common
+def update_test(opt_basename: str, ti: common.TestInfo):
+ triple_in_ir = None
+ for l in ti.input_lines:
+ m = common.TRIPLE_IR_RE.match(l)
+ if m:
+ triple_in_ir = m.groups()[0]
+ break
+
+ prefix_list = []
+ for l in ti.run_lines:
+ if "|" not in l:
+ common.warn("Skipping unparsable RUN line: " + l)
+ continue
+
+ (tool_cmd, filecheck_cmd) = tuple([cmd.strip() for cmd in l.split("|", 1)])
+ common.verify_filecheck_prefixes(filecheck_cmd)
+
+ if not tool_cmd.startswith(opt_basename + " "):
+ common.warn("WSkipping non-%s RUN line: %s" % (opt_basename, l))
+ continue
+
+ if not filecheck_cmd.startswith("FileCheck "):
+ common.warn("Skipping non-FileChecked RUN line: " + l)
+ continue
+
+ tool_cmd_args = tool_cmd[len(opt_basename) :].strip()
+ tool_cmd_args = tool_cmd_args.replace("< %s", "").replace("%s", "").strip()
+ check_prefixes = common.get_check_prefixes(filecheck_cmd)
+
+ # FIXME: We should use multiple check prefixes to common check lines. For
+ # now, we just ignore all but the last.
+ prefix_list.append((check_prefixes, tool_cmd_args))
+
+ ginfo = common.make_analyze_generalizer(version=1)
+ builder = common.FunctionTestBuilder(
+ run_list=prefix_list,
+ flags=type(
+ "",
+ (object,),
+ {
+ "verbose": ti.args.verbose,
+ "filters": ti.args.filters,
+ "function_signature": False,
+ "check_attributes": False,
+ "replace_value_regex": [],
+ },
+ ),
+ scrubber_args=[],
+ path=ti.path,
+ ginfo=ginfo,
+ )
+
+ for prefixes, opt_args in prefix_list:
+ common.debug("Extracted opt cmd:", opt_basename, opt_args, file=sys.stderr)
+ common.debug("Extracted FileCheck prefixes:", str(prefixes), file=sys.stderr)
+
+ raw_tool_outputs = common.invoke_tool(ti.args.opt_binary, opt_args, ti.path)
+
+ if re.search(r"Printing analysis ", raw_tool_outputs) is not None:
+ # Split analysis outputs by "Printing analysis " declarations.
+ for raw_tool_output in re.split(r"Printing analysis ", raw_tool_outputs):
+ builder.process_run_line(
+ common.ANALYZE_FUNCTION_RE,
+ common.scrub_body,
+ raw_tool_output,
+ prefixes,
+ )
+ elif (
+ re.search(r"(LV|LDist): Checking a loop in ", raw_tool_outputs) is not None
+ ):
+ for raw_tool_output in re.split(
+ r"(LV|LDist): Checking a loop in ", raw_tool_outputs
+ ):
+ builder.process_run_line(
+ common.LOOP_PASS_DEBUG_RE,
+ common.scrub_body,
+ raw_tool_output,
+ prefixes,
+ )
+ else:
+ common.warn("Don't know how to deal with this output")
+ continue
+
+ builder.processed_prefixes(prefixes)
+
+ func_dict = builder.finish_and_get_func_dict()
+ is_in_function = False
+ is_in_function_start = False
+ prefix_set = set([prefix for prefixes, _ in prefix_list for prefix in prefixes])
+ common.debug("Rewriting FileCheck prefixes:", str(prefix_set), file=sys.stderr)
+ output_lines = []
+
+ generated_prefixes = []
+ for input_info in ti.iterlines(output_lines):
+ input_line = input_info.line
+ args = input_info.args
+ if is_in_function_start:
+ if input_line == "":
+ continue
+ if input_line.lstrip().startswith(";"):
+ m = common.CHECK_RE.match(input_line)
+ if not m or m.group(1) not in prefix_set:
+ output_lines.append(input_line)
+ continue
+
+ # Print out the various check lines here.
+ generated_prefixes.extend(
+ common.add_analyze_checks(
+ output_lines,
+ ";",
+ prefix_list,
+ func_dict,
+ func_name,
+ ginfo,
+ is_filtered=builder.is_filtered(),
+ )
+ )
+ is_in_function_start = False
+
+ if is_in_function:
+ if common.should_add_line_to_output(input_line, prefix_set):
+ # This input line of the function body will go as-is into the output.
+ output_lines.append(input_line)
+ else:
+ continue
+ if input_line.strip() == "}":
+ is_in_function = False
+ continue
+
+ # If it's outside a function, it just gets copied to the output.
+ output_lines.append(input_line)
+
+ m = common.IR_FUNCTION_RE.match(input_line)
+ if not m:
+ continue
+ func_name = m.group(1)
+ if ti.args.function is not None and func_name != ti.args.function:
+ # When filtering on a specific function, skip all others.
+ continue
+ is_in_function = is_in_function_start = True
+
+ if ti.args.gen_unused_prefix_body:
+ output_lines.extend(
+ ti.get_checks_for_unused_prefixes(prefix_list, generated_prefixes)
+ )
+
+ common.debug("Writing %d lines to %s..." % (len(output_lines), ti.path))
+
+ with open(ti.path, "wb") as f:
+ f.writelines(["{}\n".format(l).encode("utf-8") for l in output_lines])
+
+
def main():
from argparse import RawTextHelpFormatter
@@ -61,163 +215,17 @@ def main():
common.error("Unexpected opt name: " + opt_basename)
sys.exit(1)
+ returncode = 0
for ti in common.itertests(
initial_args.tests, parser, script_name="utils/" + script_name
):
- triple_in_ir = None
- for l in ti.input_lines:
- m = common.TRIPLE_IR_RE.match(l)
- if m:
- triple_in_ir = m.groups()[0]
- break
-
- prefix_list = []
- for l in ti.run_lines:
- if "|" not in l:
- common.warn("Skipping unparsable RUN line: " + l)
- continue
-
- (tool_cmd, filecheck_cmd) = tuple([cmd.strip() for cmd in l.split("|", 1)])
- common.verify_filecheck_prefixes(filecheck_cmd)
-
- if not tool_cmd.startswith(opt_basename + " "):
- common.warn("WSkipping non-%s RUN line: %s" % (opt_basename, l))
- continue
-
- if not filecheck_cmd.startswith("FileCheck "):
- common.warn("Skipping non-FileChecked RUN line: " + l)
- continue
-
- tool_cmd_args = tool_cmd[len(opt_basename) :].strip()
- tool_cmd_args = tool_cmd_args.replace("< %s", "").replace("%s", "").strip()
- check_prefixes = common.get_check_prefixes(filecheck_cmd)
-
- # FIXME: We should use multiple check prefixes to common check lines. For
- # now, we just ignore all but the last.
- prefix_list.append((check_prefixes, tool_cmd_args))
-
- ginfo = common.make_analyze_generalizer(version=1)
- builder = common.FunctionTestBuilder(
- run_list=prefix_list,
- flags=type(
- "",
- (object,),
- {
- "verbose": ti.args.verbose,
- "filters": ti.args.filters,
- "function_signature": False,
- "check_attributes": False,
- "replace_value_regex": [],
- },
- ),
- scrubber_args=[],
- path=ti.path,
- ginfo=ginfo,
- )
-
- for prefixes, opt_args in prefix_list:
- common.debug("Extracted opt cmd:", opt_basename, opt_args, file=sys.stderr)
- common.debug(
- "Extracted FileCheck prefixes:", str(prefixes), file=sys.stderr
- )
-
- raw_tool_outputs = common.invoke_tool(ti.args.opt_binary, opt_args, ti.path)
-
- if re.search(r"Printing analysis ", raw_tool_outputs) is not None:
- # Split analysis outputs by "Printing analysis " declarations.
- for raw_tool_output in re.split(
- r"Printing analysis ", raw_tool_outputs
- ):
- builder.process_run_line(
- common.ANALYZE_FUNCTION_RE,
- common.scrub_body,
- raw_tool_output,
- prefixes,
- )
- elif (
- re.search(r"(LV|LDist): Checking a loop in ", raw_tool_outputs)
- is not None
- ):
- for raw_tool_output in re.split(
- r"(LV|LDist): Checking a loop in ", raw_tool_outputs
- ):
- builder.process_run_line(
- common.LOOP_PASS_DEBUG_RE,
- common.scrub_body,
- raw_tool_output,
- prefixes,
- )
- else:
- common.warn("Don't know how to deal with this output")
- continue
-
- builder.processed_prefixes(prefixes)
-
- func_dict = builder.finish_and_get_func_dict()
- is_in_function = False
- is_in_function_start = False
- prefix_set = set([prefix for prefixes, _ in prefix_list for prefix in prefixes])
- common.debug("Rewriting FileCheck prefixes:", str(prefix_set), file=sys.stderr)
- output_lines = []
-
- generated_prefixes = []
- for input_info in ti.iterlines(output_lines):
- input_line = input_info.line
- args = input_info.args
- if is_in_function_start:
- if input_line == "":
- continue
- if input_line.lstrip().startswith(";"):
- m = common.CHECK_RE.match(input_line)
- if not m or m.group(1) not in prefix_set:
- output_lines.append(input_line)
- continue
-
- # Print out the various check lines here.
- generated_prefixes.extend(
- common.add_analyze_checks(
- output_lines,
- ";",
- prefix_list,
- func_dict,
- func_name,
- ginfo,
- is_filtered=builder.is_filtered(),
- )
- )
- is_in_function_start = False
-
- if is_in_function:
- if common.should_add_line_to_output(input_line, prefix_set):
- # This input line of the function body will go as-is into the output.
- output_lines.append(input_line)
- else:
- continue
- if input_line.strip() == "}":
- is_in_function = False
- continue
-
- # If it's outside a function, it just gets copied to the output.
- output_lines.append(input_line)
-
- m = common.IR_FUNCTION_RE.match(input_line)
- if not m:
- continue
- func_name = m.group(1)
- if ti.args.function is not None and func_name != ti.args.function:
- # When filtering on a specific function, skip all others.
- continue
- is_in_function = is_in_function_start = True
-
- if ti.args.gen_unused_prefix_body:
- output_lines.extend(
- ti.get_checks_for_unused_prefixes(prefix_list, generated_prefixes)
- )
-
- common.debug("Writing %d lines to %s..." % (len(output_lines), ti.path))
-
- with open(ti.path, "wb") as f:
- f.writelines(["{}\n".format(l).encode("utf-8") for l in output_lines])
+ try:
+ update_test(opt_basename, ti)
+ except Exception:
+ stderr.write(f"Error: Failed to update test {ti.path}\n")
+ print_exc()
+ returncode = 1
+ return returncode
if __name__ == "__main__":
diff --git a/llvm/utils/update_cc_test_checks.py b/llvm/utils/update_cc_test_checks.py
index 7529d480b35dd..4102ee4ecbd22 100755
--- a/llvm/utils/update_cc_test_checks.py
+++ b/llvm/utils/update_cc_test_checks.py
@@ -14,6 +14,8 @@
from __future__ import print_function
+from sys import stderr
+from traceback import print_exc
import argparse
import collections
import json
@@ -302,257 +304,142 @@ def exec_run_line(exe):
sys.exit(3)
-def main():
- initial_args, parser = config()
- script_name = os.path.basename(__file__)
-
- for ti in common.itertests(
- initial_args.tests,
- parser,
- "utils/" + script_name,
- comment_prefix="//",
- argparse_callback=infer_dependent_args,
- ):
- # Build a list of filechecked and non-filechecked RUN lines.
- run_list = []
- line2func_list = collections.defaultdict(list)
-
- subs = {
- "%s": ti.path,
- "%t": tempfile.NamedTemporaryFile().name,
- "%S": os.path.dirname(ti.path),
- }
-
- for l in ti.run_lines:
- commands = [cmd.strip() for cmd in l.split("|")]
-
- triple_in_cmd = None
- m = common.TRIPLE_ARG_RE.search(commands[0])
- if m:
- triple_in_cmd = m.groups()[0]
-
- # Parse executable args.
- exec_args = shlex.split(commands[0])
- # Execute non-clang runline.
- if exec_args[0] not in SUBST:
- # Do lit-like substitutions.
- for s in subs:
- exec_args = [
- i.replace(s, subs[s]) if s in i else i for i in exec_args
- ]
- run_list.append((None, exec_args, None, None))
- continue
- # This is a clang runline, apply %clang substitution rule, do lit-like substitutions,
- # and append args.clang_args
- clang_args = exec_args
- clang_args[0:1] = SUBST[clang_args[0]]
- for s in subs:
- clang_args = [
- i.replace(s, subs[s]) if s in i else i for i in clang_args
- ]
- clang_args += ti.args.clang_args
-
- # Extract -check-prefix in FileCheck args
- filecheck_cmd = commands[-1]
- common.verify_filecheck_prefixes(filecheck_cmd)
- if not filecheck_cmd.startswith("FileCheck "):
- # Execute non-filechecked clang runline.
- exe = [ti.args.clang] + clang_args
- run_list.append((None, exe, None, None))
- continue
+def update_test(ti: common.TestInfo):
+ # Build a list of filechecked and non-filechecked RUN lines.
+ run_list = []
+ line2func_list = collections.defaultdict(list)
- check_prefixes = common.get_check_prefixes(filecheck_cmd)
- run_list.append((check_prefixes, clang_args, commands[1:-1], triple_in_cmd))
+ subs = {
+ "%s": ti.path,
+ "%t": tempfile.NamedTemporaryFile().name,
+ "%S": os.path.dirname(ti.path),
+ }
- # Execute clang, generate LLVM IR, and extract functions.
+ for l in ti.run_lines:
+ commands = [cmd.strip() for cmd in l.split("|")]
- # Store only filechecked runlines.
- filecheck_run_list = [i for i in run_list if i[0]]
- ginfo = common.make_ir_generalizer(
- ti.args.version, ti.args.check_globals == "none"
- )
- builder = common.FunctionTestBuilder(
- run_list=filecheck_run_list,
- flags=ti.args,
- scrubber_args=[],
- path=ti.path,
- ginfo=ginfo,
- )
+ triple_in_cmd = None
+ m = common.TRIPLE_ARG_RE.search(commands[0])
+ if m:
+ triple_in_cmd = m.groups()[0]
- for prefixes, args, extra_commands, triple_in_cmd in run_list:
- # Execute non-filechecked runline.
- if not prefixes:
- print(
- "NOTE: Executing non-FileChecked RUN line: " + " ".join(args),
- file=sys.stderr,
- )
- exec_run_line(args)
- continue
+ # Parse executable args.
+ exec_args = shlex.split(commands[0])
+ # Execute non-clang runline.
+ if exec_args[0] not in SUBST:
+ # Do lit-like substitutions.
+ for s in subs:
+ exec_args = [i.replace(s, subs[s]) if s in i else i for i in exec_args]
+ run_list.append((None, exec_args, None, None))
+ continue
+ # This is a clang runline, apply %clang substitution rule, do lit-like substitutions,
+ # and append args.clang_args
+ clang_args = exec_args
+ clang_args[0:1] = SUBST[clang_args[0]]
+ for s in subs:
+ clang_args = [i.replace(s, subs[s]) if s in i else i for i in clang_args]
+ clang_args += ti.args.clang_args
+
+ # Extract -check-prefix in FileCheck args
+ filecheck_cmd = commands[-1]
+ common.verify_filecheck_prefixes(filecheck_cmd)
+ if not filecheck_cmd.startswith("FileCheck "):
+ # Execute non-filechecked clang runline.
+ exe = [ti.args.clang] + clang_args
+ run_list.append((None, exe, None, None))
+ continue
+
+ check_prefixes = common.get_check_prefixes(filecheck_cmd)
+ run_list.append((check_prefixes, clang_args, commands[1:-1], triple_in_cmd))
+
+ # Execute clang, generate LLVM IR, and extract functions.
+
+ # Store only filechecked runlines.
+ filecheck_run_list = [i for i in run_list if i[0]]
+ ginfo = common.make_ir_generalizer(ti.args.version, ti.args.check_globals == "none")
+ builder = common.FunctionTestBuilder(
+ run_list=filecheck_run_list,
+ flags=ti.args,
+ scrubber_args=[],
+ path=ti.path,
+ ginfo=ginfo,
+ )
- clang_args = args
- common.debug("Extracted clang cmd: clang {}".format(clang_args))
- common.debug("Extracted FileCheck prefixes: {}".format(prefixes))
-
- # Invoke external tool and extract function bodies.
- raw_tool_output = common.invoke_tool(ti.args.clang, clang_args, ti.path)
- get_function_body(
- builder,
- ti.args,
- ti.path,
- clang_args,
- extra_commands,
- prefixes,
- raw_tool_output,
+ for prefixes, args, extra_commands, triple_in_cmd in run_list:
+ # Execute non-filechecked runline.
+ if not prefixes:
+ print(
+ "NOTE: Executing non-FileChecked RUN line: " + " ".join(args),
+ file=sys.stderr,
)
-
- # Invoke clang -Xclang -ast-dump=json to get mapping from start lines to
- # mangled names. Forward all clang args for now.
- for k, v in get_line2func_list(
- ti.args, clang_args, common.get_globals_name_prefix(raw_tool_output)
- ).items():
- line2func_list[k].extend(v)
-
- func_dict = builder.finish_and_get_func_dict()
- global_vars_seen_dict = {}
- prefix_set = set([prefix for p in filecheck_run_list for prefix in p[0]])
- output_lines = []
- has_checked_pre_function_globals = False
-
- include_generated_funcs = common.find_arg_in_t...
[truncated]
|
28d596e
to
8d0800f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, and thanks for doing this! :) I was slightly afraid when looking at the diff at first, but ignoring whitespaces makes it surprisingly concise!
There are some test failures in update_mc_tests
though, so I guess you want to look at those before merging.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, save a couple small differences between tests in the if __name__ == '__main__'
code
This is something I didn't even realize was a limitation, but I've probably been a little confused by at some points, so thank you for the fix!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Thank you! |
…e inputs (llvm#137728) Change llvm/utils/update_xxx_checks.py scripts to: Catch exceptions individually for each test. On exception print which test triggered the exception and continue with the remaining test updates.
…e inputs (llvm#137728) Change llvm/utils/update_xxx_checks.py scripts to: Catch exceptions individually for each test. On exception print which test triggered the exception and continue with the remaining test updates.
…e inputs (llvm#137728) Change llvm/utils/update_xxx_checks.py scripts to: Catch exceptions individually for each test. On exception print which test triggered the exception and continue with the remaining test updates.
…e inputs (llvm#137728) Change llvm/utils/update_xxx_checks.py scripts to: Catch exceptions individually for each test. On exception print which test triggered the exception and continue with the remaining test updates.
Change llvm/utils/update_xxx_checks.py scripts to:
Catch exceptions individually for each test. On exception print which test triggered the exception and continue with the remaining test updates.