xref: /llvm-project/llvm/utils/bugpoint_gisel_reducer.py (revision b71edfaa4ec3c998aadb35255ce2f60bba2940b0)
11b55f1f8SVolkan Keles#!/usr/bin/env python
21b55f1f8SVolkan Keles
31b55f1f8SVolkan Keles"""Reduces GlobalISel failures.
41b55f1f8SVolkan Keles
51b55f1f8SVolkan KelesThis script is a utility to reduce tests that GlobalISel
61b55f1f8SVolkan Kelesfails to compile.
71b55f1f8SVolkan Keles
81b55f1f8SVolkan KelesIt runs llc to get the error message using a regex and creates
91b55f1f8SVolkan Kelesa custom command to check that specific error. Then, it runs bugpoint
101b55f1f8SVolkan Keleswith the custom command.
111b55f1f8SVolkan Keles
121b55f1f8SVolkan Keles"""
131b55f1f8SVolkan Kelesfrom __future__ import print_function
141b55f1f8SVolkan Kelesimport argparse
151b55f1f8SVolkan Kelesimport re
161b55f1f8SVolkan Kelesimport subprocess
171b55f1f8SVolkan Kelesimport sys
181b55f1f8SVolkan Kelesimport tempfile
191b55f1f8SVolkan Kelesimport os
201b55f1f8SVolkan Keles
211b55f1f8SVolkan Keles
221b55f1f8SVolkan Kelesdef log(msg):
231b55f1f8SVolkan Keles    print(msg)
241b55f1f8SVolkan Keles
251b55f1f8SVolkan Keles
261b55f1f8SVolkan Kelesdef hr():
27*b71edfaaSTobias Hieta    log("-" * 50)
281b55f1f8SVolkan Keles
291b55f1f8SVolkan Keles
301b55f1f8SVolkan Kelesdef log_err(msg):
31*b71edfaaSTobias Hieta    print("ERROR: {}".format(msg), file=sys.stderr)
321b55f1f8SVolkan Keles
331b55f1f8SVolkan Keles
341b55f1f8SVolkan Kelesdef check_path(path):
351b55f1f8SVolkan Keles    if not os.path.exists(path):
36*b71edfaaSTobias Hieta        log_err("{} does not exist.".format(path))
371b55f1f8SVolkan Keles        raise
381b55f1f8SVolkan Keles    return path
391b55f1f8SVolkan Keles
401b55f1f8SVolkan Keles
411b55f1f8SVolkan Kelesdef check_bin(build_dir, bin_name):
42*b71edfaaSTobias Hieta    file_name = "{}/bin/{}".format(build_dir, bin_name)
431b55f1f8SVolkan Keles    return check_path(file_name)
441b55f1f8SVolkan Keles
451b55f1f8SVolkan Keles
461b55f1f8SVolkan Kelesdef run_llc(llc, irfile):
47*b71edfaaSTobias Hieta    pr = subprocess.Popen(
48*b71edfaaSTobias Hieta        [llc, "-o", "-", "-global-isel", "-pass-remarks-missed=gisel", irfile],
491b55f1f8SVolkan Keles        stdout=subprocess.PIPE,
50*b71edfaaSTobias Hieta        stderr=subprocess.PIPE,
51*b71edfaaSTobias Hieta    )
521b55f1f8SVolkan Keles    out, err = pr.communicate()
531b55f1f8SVolkan Keles    res = pr.wait()
541b55f1f8SVolkan Keles    if res == 0:
551b55f1f8SVolkan Keles        return 0
561b55f1f8SVolkan Keles    re_err = re.compile(
57*b71edfaaSTobias Hieta        r"LLVM ERROR: ([a-z\s]+):.*(G_INTRINSIC[_A-Z]* <intrinsic:@[a-zA-Z0-9\.]+>|G_[A-Z_]+)"
58*b71edfaaSTobias Hieta    )
591b55f1f8SVolkan Keles    match = re_err.match(err)
601b55f1f8SVolkan Keles    if not match:
611b55f1f8SVolkan Keles        return 0
621b55f1f8SVolkan Keles    else:
631b55f1f8SVolkan Keles        return [match.group(1), match.group(2)]
641b55f1f8SVolkan Keles
651b55f1f8SVolkan Keles
661b55f1f8SVolkan Kelesdef run_bugpoint(bugpoint_bin, llc_bin, opt_bin, tmp, ir_file):
67*b71edfaaSTobias Hieta    compileCmd = "-compile-command={} -c {} {}".format(
68*b71edfaaSTobias Hieta        os.path.realpath(__file__), llc_bin, tmp
69*b71edfaaSTobias Hieta    )
70*b71edfaaSTobias Hieta    pr = subprocess.Popen(
71*b71edfaaSTobias Hieta        [
72*b71edfaaSTobias Hieta            bugpoint_bin,
73*b71edfaaSTobias Hieta            "-compile-custom",
741b55f1f8SVolkan Keles            compileCmd,
75*b71edfaaSTobias Hieta            "-opt-command={}".format(opt_bin),
76*b71edfaaSTobias Hieta            ir_file,
77*b71edfaaSTobias Hieta        ]
78*b71edfaaSTobias Hieta    )
791b55f1f8SVolkan Keles    res = pr.wait()
801b55f1f8SVolkan Keles    if res != 0:
811b55f1f8SVolkan Keles        log_err("Unable to reduce the test.")
821b55f1f8SVolkan Keles        raise
831b55f1f8SVolkan Keles
841b55f1f8SVolkan Keles
851b55f1f8SVolkan Kelesdef run_bugpoint_check():
861b55f1f8SVolkan Keles    path_to_llc = sys.argv[2]
871b55f1f8SVolkan Keles    path_to_err = sys.argv[3]
881b55f1f8SVolkan Keles    path_to_ir = sys.argv[4]
89*b71edfaaSTobias Hieta    with open(path_to_err, "r") as f:
901b55f1f8SVolkan Keles        err = f.read()
911b55f1f8SVolkan Keles        res = run_llc(path_to_llc, path_to_ir)
921b55f1f8SVolkan Keles        if res == 0:
931b55f1f8SVolkan Keles            return 0
94*b71edfaaSTobias Hieta        log("GlobalISed failed, {}: {}".format(res[0], res[1]))
95*b71edfaaSTobias Hieta        if res != err.split(";"):
961b55f1f8SVolkan Keles            return 0
971b55f1f8SVolkan Keles        else:
981b55f1f8SVolkan Keles            return 1
991b55f1f8SVolkan Keles
1001b55f1f8SVolkan Keles
1011b55f1f8SVolkan Kelesdef main():
1021b55f1f8SVolkan Keles    # Check if this is called by bugpoint.
103*b71edfaaSTobias Hieta    if len(sys.argv) == 5 and sys.argv[1] == "-c":
1041b55f1f8SVolkan Keles        sys.exit(run_bugpoint_check())
1051b55f1f8SVolkan Keles
1061b55f1f8SVolkan Keles    # Parse arguments.
1071b55f1f8SVolkan Keles    parser = argparse.ArgumentParser(
108*b71edfaaSTobias Hieta        description=__doc__, formatter_class=argparse.RawTextHelpFormatter
109*b71edfaaSTobias Hieta    )
110*b71edfaaSTobias Hieta    parser.add_argument("BuildDir", help="Path to LLVM build directory")
111*b71edfaaSTobias Hieta    parser.add_argument("IRFile", help="Path to the input IR file")
1121b55f1f8SVolkan Keles    args = parser.parse_args()
1131b55f1f8SVolkan Keles
1141b55f1f8SVolkan Keles    # Check if the binaries exist.
1151b55f1f8SVolkan Keles    build_dir = check_path(args.BuildDir)
1161b55f1f8SVolkan Keles    ir_file = check_path(args.IRFile)
117*b71edfaaSTobias Hieta    llc_bin = check_bin(build_dir, "llc")
118*b71edfaaSTobias Hieta    opt_bin = check_bin(build_dir, "opt")
119*b71edfaaSTobias Hieta    bugpoint_bin = check_bin(build_dir, "bugpoint")
1201b55f1f8SVolkan Keles
1211b55f1f8SVolkan Keles    # Run llc to see if GlobalISel fails.
122*b71edfaaSTobias Hieta    log("Running llc...")
1231b55f1f8SVolkan Keles    res = run_llc(llc_bin, ir_file)
1241b55f1f8SVolkan Keles    if res == 0:
1251b55f1f8SVolkan Keles        log_err("Expected failure")
1261b55f1f8SVolkan Keles        raise
1271b55f1f8SVolkan Keles    hr()
128*b71edfaaSTobias Hieta    log("GlobalISel failed, {}: {}.".format(res[0], res[1]))
1291b55f1f8SVolkan Keles    tmp = tempfile.NamedTemporaryFile()
130*b71edfaaSTobias Hieta    log("Writing error to {} for bugpoint.".format(tmp.name))
131*b71edfaaSTobias Hieta    tmp.write(";".join(res))
1321b55f1f8SVolkan Keles    tmp.flush()
1331b55f1f8SVolkan Keles    hr()
1341b55f1f8SVolkan Keles
1351b55f1f8SVolkan Keles    # Run bugpoint.
136*b71edfaaSTobias Hieta    log("Running bugpoint...")
1371b55f1f8SVolkan Keles    run_bugpoint(bugpoint_bin, llc_bin, opt_bin, tmp.name, ir_file)
1381b55f1f8SVolkan Keles    hr()
139*b71edfaaSTobias Hieta    log("Done!")
1401b55f1f8SVolkan Keles    hr()
141*b71edfaaSTobias Hieta    output_file = "bugpoint-reduced-simplified.bc"
142*b71edfaaSTobias Hieta    log("Run llvm-dis to disassemble the output:")
143*b71edfaaSTobias Hieta    log("$ {}/bin/llvm-dis -o - {}".format(build_dir, output_file))
144*b71edfaaSTobias Hieta    log("Run llc to reproduce the problem:")
145*b71edfaaSTobias Hieta    log(
146*b71edfaaSTobias Hieta        "$ {}/bin/llc -o - -global-isel "
147*b71edfaaSTobias Hieta        "-pass-remarks-missed=gisel {}".format(build_dir, output_file)
148*b71edfaaSTobias Hieta    )
1491b55f1f8SVolkan Keles
1501b55f1f8SVolkan Keles
151*b71edfaaSTobias Hietaif __name__ == "__main__":
1521b55f1f8SVolkan Keles    main()
153