Mercurial > hg > CbC > CbC_llvm
view polly/test/update_check.py @ 266:00f31e85ec16 default tip
Added tag current for changeset 31d058e83c98
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Sat, 14 Oct 2023 10:13:55 +0900 |
parents | 1f2b6ac9f198 |
children |
line wrap: on
line source
#!/usr/bin/env python3 # -*- coding: UTF-8 -*- # Polly/LLVM update_check.py # Update lit FileCheck files by replacing the 'CHECK:' lines by the actual output of the 'RUN:' command. import argparse import os import subprocess import shlex import re polly_src_dir = """@POLLY_SOURCE_DIR@""" polly_lib_dir = """@POLLY_LIB_DIR@""" shlibext = """@LLVM_SHLIBEXT@""" llvm_tools_dir = """@LLVM_TOOLS_DIR@""" llvm_polly_link_into_tools = not """@LLVM_POLLY_LINK_INTO_TOOLS@""".lower() in { "", "0", "n", "no", "off", "false", "notfound", "llvm_polly_link_into_tools-notfound", } runre = re.compile(r"\s*\;\s*RUN\s*\:(?P<tool>.*)") filecheckre = re.compile(r"\s*(?P<tool>.*)\|\s*(?P<filecheck>FileCheck\s[^|]*)") emptyline = re.compile(r"\s*(\;\s*)?") commentline = re.compile(r"\s*(\;.*)?") def ltrim_emptylines(lines, meta=None): while len(lines) and emptyline.fullmatch(lines[0]): del lines[0] if meta is not None: del meta[0] def rtrim_emptylines(lines): while len(lines) and emptyline.fullmatch(lines[-1]): del lines[-1] def trim_emptylines(lines): ltrim_emptylines(lines) rtrim_emptylines(lines) def complete_exename(path, filename): complpath = os.path.join(path, filename) if os.path.isfile(complpath): return complpath elif os.path.isfile(complpath + ".exe"): return complpath + ".exe" return filename def indention(line): for i, c in enumerate(line): if c != " " and c != "\t": return i return None def common_indent(lines): indentions = (indention(line) for line in lines) indentions = (indent for indent in indentions if indent is not None) return min(indentions, default=0) funcre = re.compile(r"^ Function: \S*$") regionre = re.compile(r"^ Region: \S*$") depthre = re.compile(r"^ Max Loop Depth: .*") paramre = re.compile(r" [0-9a-z-A-Z_]+\: .*") def classyfier1(lines): i = iter(lines) line = i.__next__() while True: if line.startswith( "Printing analysis 'Polly - Calculate dependences' for region: " ): yield {"PrintingDependenceInfo"} elif line.startswith("remark: "): yield {"Remark"} elif funcre.fullmatch(line): yield {"Function"} elif regionre.fullmatch(line): yield {"Region"} elif depthre.fullmatch(line): yield {"MaxLoopDepth"} elif line == " Invariant Accesses: {": while True: yield {"InvariantAccesses"} if line == " }": break line = i.__next__() elif line == " Context:": yield {"Context"} line = i.__next__() yield {"Context"} elif line == " Assumed Context:": yield {"AssumedContext"} line = i.__next__() yield {"AssumedContext"} elif line == " Invalid Context:": yield {"InvalidContext"} line = i.__next__() yield {"InvalidContext"} elif line == " Boundary Context:": yield {"BoundaryContext"} line = i.__next__() yield {"BoundaryContext"} line = i.__next__() while paramre.fullmatch(line): yield {"Param"} line = i.__next__() continue elif line == " Arrays {": while True: yield {"Arrays"} if line == " }": break line = i.__next__() elif line == " Arrays (Bounds as pw_affs) {": while True: yield {"PwAffArrays"} if line == " }": break line = i.__next__() elif line.startswith(" Alias Groups ("): while True: yield {"AliasGroups"} line = i.__next__() if not line.startswith(" "): break continue elif line == " Statements {": while True: yield {"Statements"} if line == " }": break line = i.__next__() elif line == " RAW dependences:": yield {"RAWDep", "BasicDep", "Dep", "DepInfo"} line = i.__next__() while line.startswith(" "): yield {"RAWDep", "BasicDep", "Dep", "DepInfo"} line = i.__next__() continue elif line == " WAR dependences:": yield {"WARDep", "BasicDep", "Dep", "DepInfo"} line = i.__next__() while line.startswith(" "): yield {"WARDep", "BasicDep", "Dep", "DepInfo"} line = i.__next__() continue elif line == " WAW dependences:": yield {"WAWDep", "BasicDep", "Dep", "DepInfo"} line = i.__next__() while line.startswith(" "): yield {"WAWDep", "BasicDep", "Dep", "DepInfo"} line = i.__next__() continue elif line == " Reduction dependences:": yield {"RedDep", "Dep", "DepInfo"} line = i.__next__() while line.startswith(" "): yield {"RedDep", "Dep", "DepInfo"} line = i.__next__() continue elif line == " Transitive closure of reduction dependences:": yield {"TransitiveClosureDep", "DepInfo"} line = i.__next__() while line.startswith(" "): yield {"TransitiveClosureDep", "DepInfo"} line = i.__next__() continue elif line.startswith("New access function '"): yield {"NewAccessFunction"} elif line == "Schedule before flattening {": while True: yield {"ScheduleBeforeFlattening"} if line == "}": break line = i.__next__() elif line == "Schedule after flattening {": while True: yield {"ScheduleAfterFlattening"} if line == "}": break line = i.__next__() else: yield set() line = i.__next__() def classyfier2(lines): i = iter(lines) line = i.__next__() while True: if funcre.fullmatch(line): while line.startswith(" "): yield {"FunctionDetail"} line = i.__next__() continue elif line.startswith( "Printing analysis 'Polly - Generate an AST from the SCoP (isl)' for region: " ): yield {"PrintingIslAst"} line = i.__next__() while not line.startswith("Printing analysis"): yield {"AstDetail"} line = i.__next__() continue else: yield set() line = i.__next__() replrepl = {"{{": "{{[{][{]}}", "}}": "{{[}][}]}}", "[[": "{{\[\[}}", "]]": "{{\]\]}}"} replre = re.compile("|".join(re.escape(k) for k in replrepl.keys())) def main(): parser = argparse.ArgumentParser(description="Update CHECK lines") parser.add_argument( "testfile", help="File to update (absolute or relative to --testdir)" ) parser.add_argument( "--check-style", choices=["CHECK", "CHECK-NEXT"], default="CHECK-NEXT", help="What kind of checks lines to generate", ) parser.add_argument( "--check-position", choices=["end", "before-content", "autodetect"], default="autodetect", help="Where to add the CHECK lines into the file; 'autodetect' searches for the first 'CHECK' line ind inserts it there", ) parser.add_argument( "--check-include", action="append", default=[], help="What parts of the output lines to check; use syntax 'CHECK=include' to apply to one CHECK-prefix only (by default, everything)", ) parser.add_argument( "--check-label-include", action="append", default=[], help="Use CHECK-LABEL for these includes", ) parser.add_argument( "--check-part-newline", action="store_true", help="Add empty line between different check parts", ) parser.add_argument( "--prefix-only", action="append", default=None, help="Update only these prefixes (default: all)", ) parser.add_argument("--bindir", help="Location of the opt program") parser.add_argument("--testdir", help="Root dir for unit tests") parser.add_argument( "--inplace", "-i", action="store_true", help="Replace input file" ) parser.add_argument("--output", "-o", help="Write changed input to this file") known = parser.parse_args() if not known.inplace and known.output is None: print("Must specify what to do with output (--output or --inplace)") exit(1) if known.inplace and known.output is not None: print("--inplace and --output are mutually exclusive") exit(1) outfile = known.output filecheckparser = argparse.ArgumentParser(add_help=False) filecheckparser.add_argument("-check-prefix", "--check-prefix", default="CHECK") filename = known.testfile for dir in [".", known.testdir, os.path.join(polly_src_dir, "test"), polly_src_dir]: if not dir: continue testfilename = os.path.join(dir, filename) if os.path.isfile(testfilename): filename = testfilename break if known.inplace: outfile = filename allchecklines = [] checkprefixes = [] with open(filename, "r") as file: oldlines = [line.rstrip("\r\n") for line in file.readlines()] runlines = [] for line in oldlines: m = runre.match(line) if m: runlines.append(m.group("tool")) continuation = "" newrunlines = [] for line in runlines: if line.endswith("\\"): continuation += line[:-2] + " " else: newrunlines.append(continuation + line) continuation = "" if continuation: newrunlines.append(continuation) for line in newrunlines: m = filecheckre.match(line) if not m: continue tool, filecheck = m.group("tool", "filecheck") filecheck = shlex.split(filecheck) tool = shlex.split(tool) if known.bindir is not None: tool[0] = complete_exename(known.bindir, tool[0]) if os.path.isdir(llvm_tools_dir): tool[0] = complete_exename(llvm_tools_dir, tool[0]) check_prefix = filecheckparser.parse_known_args(filecheck)[0].check_prefix if known.prefix_only is not None and not check_prefix in known.prefix_only: continue if check_prefix in checkprefixes: continue checkprefixes.append(check_prefix) newtool = [] optstderr = None for toolarg in tool: toolarg = toolarg.replace("%s", filename) toolarg = toolarg.replace("%S", os.path.dirname(filename)) if toolarg == "%loadPolly": if not llvm_polly_link_into_tools: newtool += [ "-load", os.path.join(polly_lib_dir, "LLVMPolly" + shlibext), ] newtool.append("-polly-process-unprofitable") newtool.append("-polly-remarks-minimal") elif toolarg == "2>&1": optstderr = subprocess.STDOUT else: newtool.append(toolarg) tool = newtool inpfile = None i = 1 while i < len(tool): if tool[i] == "<": inpfile = tool[i + 1] del tool[i : i + 2] continue i += 1 if inpfile: with open(inpfile) as inp: retlines = subprocess.check_output( tool, universal_newlines=True, stdin=inp, stderr=optstderr ) else: retlines = subprocess.check_output( tool, universal_newlines=True, stderr=optstderr ) retlines = [line.replace("\t", " ") for line in retlines.splitlines()] check_include = [] for checkme in known.check_include + known.check_label_include: parts = checkme.split("=") if len(parts) == 2: if parts[0] == check_prefix: check_include.append(parts[1]) else: check_include.append(checkme) if check_include: filtered_retlines = [] classified_retlines = [] lastmatch = None for line, kind in ( (line, class1.union(class2)) for line, class1, class2 in zip( retlines, classyfier1(retlines), classyfier2(retlines) ) ): match = kind.intersection(check_include) if match: if lastmatch != match: filtered_retlines.append("") classified_retlines.append({"Separator"}) filtered_retlines.append(line) classified_retlines.append(kind) lastmatch = match retlines = filtered_retlines else: classified_retlines = (set() for line in retlines) rtrim_emptylines(retlines) ltrim_emptylines(retlines, classified_retlines) retlines = [ replre.sub(lambda m: replrepl[m.group(0)], line) for line in retlines ] indent = common_indent(retlines) retlines = [line[indent:] for line in retlines] checklines = [] previous_was_empty = True for line, kind in zip(retlines, classified_retlines): if line: if known.check_style == "CHECK" and known.check_label_include: if not kind.isdisjoint(known.check_label_include): checklines.append("; " + check_prefix + "-LABEL: " + line) else: checklines.append("; " + check_prefix + ": " + line) elif known.check_style == "CHECK": checklines.append("; " + check_prefix + ": " + line) elif known.check_label_include and known.check_label_include: if not kind.isdisjoint(known.check_label_include): checklines.append("; " + check_prefix + "-LABEL: " + line) elif previous_was_empty: checklines.append("; " + check_prefix + ": " + line) else: checklines.append("; " + check_prefix + "-NEXT: " + line) else: if previous_was_empty: checklines.append("; " + check_prefix + ": " + line) else: checklines.append("; " + check_prefix + "-NEXT: " + line) previous_was_empty = False else: if not "Separator" in kind or known.check_part_newline: checklines.append(";") previous_was_empty = True allchecklines.append(checklines) if not checkprefixes: return checkre = re.compile( r"^\s*\;\s*(" + "|".join([re.escape(s) for s in checkprefixes]) + ")(\-NEXT|\-DAG|\-NOT|\-LABEL|\-SAME)?\s*\:" ) firstcheckline = None firstnoncommentline = None headerlines = [] newlines = [] uptonowlines = [] emptylines = [] lastwascheck = False for line in oldlines: if checkre.match(line): if firstcheckline is None: firstcheckline = len(newlines) + len(emptylines) if not lastwascheck: uptonowlines += emptylines emptylines = [] lastwascheck = True elif emptyline.fullmatch(line): emptylines.append(line) else: newlines += uptonowlines newlines += emptylines newlines.append(line) emptylines = [] uptonowlines = [] lastwascheck = False for i, line in enumerate(newlines): if not commentline.fullmatch(line): firstnoncommentline = i break with open(outfile, "w", newline="") as file: def writelines(lines): for line in lines: file.write(line) file.write("\n") if firstcheckline is not None and known.check_position == "autodetect": writelines(newlines[:firstcheckline]) writelines(uptonowlines) for i, checklines in enumerate(allchecklines): if i != 0: file.write("\n") writelines(checklines) writelines(newlines[firstcheckline:]) writelines(emptylines) elif ( firstnoncommentline is not None and known.check_position == "before-content" ): headerlines = newlines[:firstnoncommentline] rtrim_emptylines(headerlines) contentlines = newlines[firstnoncommentline:] ltrim_emptylines(contentlines) writelines(headerlines) for checklines in allchecklines: file.write("\n") writelines(checklines) file.write("\n") writelines(contentlines) writelines(uptonowlines) writelines(emptylines) else: writelines(newlines) rtrim_emptylines(newlines) for checklines in allchecklines: file.write("\n\n") writelines(checklines) if __name__ == "__main__": main()