-
Notifications
You must be signed in to change notification settings - Fork 12.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[utils] De-duplicate utils/update_{llc_,}test_checks.py
Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D42654 llvm-svn: 323718
- Loading branch information
Showing
5 changed files
with
296 additions
and
333 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,199 @@ | ||
| import re | ||
| import string | ||
|
|
||
| from . import common | ||
|
|
||
| # RegEx: this is where the magic happens. | ||
|
|
||
| ASM_FUNCTION_X86_RE = re.compile( | ||
| r'^_?(?P<func>[^:]+):[ \t]*#+[ \t]*@(?P=func)\n[^:]*?' | ||
| r'(?P<body>^##?[ \t]+[^:]+:.*?)\s*' | ||
| r'^\s*(?:[^:\n]+?:\s*\n\s*\.size|\.cfi_endproc|\.globl|\.comm|\.(?:sub)?section|#+ -- End function)', | ||
| flags=(re.M | re.S)) | ||
|
|
||
| ASM_FUNCTION_ARM_RE = re.compile( | ||
| r'^(?P<func>[0-9a-zA-Z_]+):\n' # f: (name of function) | ||
| r'\s+\.fnstart\n' # .fnstart | ||
| r'(?P<body>.*?)\n' # (body of the function) | ||
| r'.Lfunc_end[0-9]+:', # .Lfunc_end0: or # -- End function | ||
| flags=(re.M | re.S)) | ||
|
|
||
| ASM_FUNCTION_AARCH64_RE = re.compile( | ||
| r'^_?(?P<func>[^:]+):[ \t]*\/\/[ \t]*@(?P=func)\n' | ||
| r'[ \t]+.cfi_startproc\n' | ||
| r'(?P<body>.*?)\n' | ||
| # This list is incomplete | ||
| r'.Lfunc_end[0-9]+:\n', | ||
| flags=(re.M | re.S)) | ||
|
|
||
| ASM_FUNCTION_MIPS_RE = re.compile( | ||
| r'^_?(?P<func>[^:]+):[ \t]*#+[ \t]*@(?P=func)\n[^:]*?' # f: (name of func) | ||
| r'(?:^[ \t]+\.(frame|f?mask|set).*?\n)+' # Mips+LLVM standard asm prologue | ||
| r'(?P<body>.*?)\n' # (body of the function) | ||
| r'(?:^[ \t]+\.(set|end).*?\n)+' # Mips+LLVM standard asm epilogue | ||
| r'(\$|\.L)func_end[0-9]+:\n', # $func_end0: (mips32 - O32) or | ||
| # .Lfunc_end0: (mips64 - NewABI) | ||
| flags=(re.M | re.S)) | ||
|
|
||
| ASM_FUNCTION_PPC_RE = re.compile( | ||
| r'^_?(?P<func>[^:]+):[ \t]*#+[ \t]*@(?P=func)\n' | ||
| r'\.Lfunc_begin[0-9]+:\n' | ||
| r'(?:[ \t]+.cfi_startproc\n)?' | ||
| r'(?:\.Lfunc_[gl]ep[0-9]+:\n(?:[ \t]+.*?\n)*)*' | ||
| r'(?P<body>.*?)\n' | ||
| # This list is incomplete | ||
| r'(?:^[ \t]*(?:\.long[ \t]+[^\n]+|\.quad[ \t]+[^\n]+)\n)*' | ||
| r'.Lfunc_end[0-9]+:\n', | ||
| flags=(re.M | re.S)) | ||
|
|
||
| ASM_FUNCTION_RISCV_RE = re.compile( | ||
| r'^_?(?P<func>[^:]+):[ \t]*#+[ \t]*@(?P=func)\n[^:]*?' | ||
| r'(?P<body>^##?[ \t]+[^:]+:.*?)\s*' | ||
| r'.Lfunc_end[0-9]+:\n', | ||
| flags=(re.M | re.S)) | ||
|
|
||
| ASM_FUNCTION_SYSTEMZ_RE = re.compile( | ||
| r'^_?(?P<func>[^:]+):[ \t]*#+[ \t]*@(?P=func)\n' | ||
| r'[ \t]+.cfi_startproc\n' | ||
| r'(?P<body>.*?)\n' | ||
| r'.Lfunc_end[0-9]+:\n', | ||
| flags=(re.M | re.S)) | ||
|
|
||
|
|
||
| SCRUB_LOOP_COMMENT_RE = re.compile( | ||
| r'# =>This Inner Loop Header:.*|# in Loop:.*', flags=re.M) | ||
|
|
||
| SCRUB_X86_SHUFFLES_RE = ( | ||
| re.compile( | ||
| r'^(\s*\w+) [^#\n]+#+ ((?:[xyz]mm\d+|mem)( \{%k\d+\}( \{z\})?)? = .*)$', | ||
| flags=re.M)) | ||
| SCRUB_X86_SP_RE = re.compile(r'\d+\(%(esp|rsp)\)') | ||
| SCRUB_X86_RIP_RE = re.compile(r'[.\w]+\(%rip\)') | ||
| SCRUB_X86_LCP_RE = re.compile(r'\.LCPI[0-9]+_[0-9]+') | ||
| SCRUB_X86_RET_RE = re.compile(r'ret[l|q]') | ||
|
|
||
| def scrub_asm_x86(asm, args): | ||
| # Scrub runs of whitespace out of the assembly, but leave the leading | ||
| # whitespace in place. | ||
| asm = common.SCRUB_WHITESPACE_RE.sub(r' ', asm) | ||
| # Expand the tabs used for indentation. | ||
| asm = string.expandtabs(asm, 2) | ||
| # Detect shuffle asm comments and hide the operands in favor of the comments. | ||
| asm = SCRUB_X86_SHUFFLES_RE.sub(r'\1 {{.*#+}} \2', asm) | ||
| # Generically match the stack offset of a memory operand. | ||
| asm = SCRUB_X86_SP_RE.sub(r'{{[0-9]+}}(%\1)', asm) | ||
| # Generically match a RIP-relative memory operand. | ||
| asm = SCRUB_X86_RIP_RE.sub(r'{{.*}}(%rip)', asm) | ||
| # Generically match a LCP symbol. | ||
| asm = SCRUB_X86_LCP_RE.sub(r'{{\.LCPI.*}}', asm) | ||
| if args.x86_extra_scrub: | ||
| # Avoid generating different checks for 32- and 64-bit because of 'retl' vs 'retq'. | ||
| asm = SCRUB_X86_RET_RE.sub(r'ret{{[l|q]}}', asm) | ||
| # Strip kill operands inserted into the asm. | ||
| asm = common.SCRUB_KILL_COMMENT_RE.sub('', asm) | ||
| # Strip trailing whitespace. | ||
| asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm) | ||
| return asm | ||
|
|
||
| def scrub_asm_arm_eabi(asm, args): | ||
| # Scrub runs of whitespace out of the assembly, but leave the leading | ||
| # whitespace in place. | ||
| asm = common.SCRUB_WHITESPACE_RE.sub(r' ', asm) | ||
| # Expand the tabs used for indentation. | ||
| asm = string.expandtabs(asm, 2) | ||
| # Strip kill operands inserted into the asm. | ||
| asm = common.SCRUB_KILL_COMMENT_RE.sub('', asm) | ||
| # Strip trailing whitespace. | ||
| asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm) | ||
| return asm | ||
|
|
||
| def scrub_asm_powerpc64(asm, args): | ||
| # Scrub runs of whitespace out of the assembly, but leave the leading | ||
| # whitespace in place. | ||
| asm = common.SCRUB_WHITESPACE_RE.sub(r' ', asm) | ||
| # Expand the tabs used for indentation. | ||
| asm = string.expandtabs(asm, 2) | ||
| # Stripe unimportant comments | ||
| asm = SCRUB_LOOP_COMMENT_RE.sub(r'', asm) | ||
| # Strip trailing whitespace. | ||
| asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm) | ||
| return asm | ||
|
|
||
| def scrub_asm_mips(asm, args): | ||
| # Scrub runs of whitespace out of the assembly, but leave the leading | ||
| # whitespace in place. | ||
| asm = common.SCRUB_WHITESPACE_RE.sub(r' ', asm) | ||
| # Expand the tabs used for indentation. | ||
| asm = string.expandtabs(asm, 2) | ||
| # Strip trailing whitespace. | ||
| asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm) | ||
| return asm | ||
|
|
||
| def scrub_asm_riscv(asm, args): | ||
| # Scrub runs of whitespace out of the assembly, but leave the leading | ||
| # whitespace in place. | ||
| asm = common.SCRUB_WHITESPACE_RE.sub(r' ', asm) | ||
| # Expand the tabs used for indentation. | ||
| asm = string.expandtabs(asm, 2) | ||
| # Strip trailing whitespace. | ||
| asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm) | ||
| return asm | ||
|
|
||
| def scrub_asm_systemz(asm, args): | ||
| # Scrub runs of whitespace out of the assembly, but leave the leading | ||
| # whitespace in place. | ||
| asm = common.SCRUB_WHITESPACE_RE.sub(r' ', asm) | ||
| # Expand the tabs used for indentation. | ||
| asm = string.expandtabs(asm, 2) | ||
| # Strip trailing whitespace. | ||
| asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm) | ||
| return asm | ||
|
|
||
|
|
||
| def build_function_body_dictionary_for_triple(args, raw_tool_output, triple, prefixes, func_dict): | ||
| target_handlers = { | ||
| 'x86_64': (scrub_asm_x86, ASM_FUNCTION_X86_RE), | ||
| 'i686': (scrub_asm_x86, ASM_FUNCTION_X86_RE), | ||
| 'x86': (scrub_asm_x86, ASM_FUNCTION_X86_RE), | ||
| 'i386': (scrub_asm_x86, ASM_FUNCTION_X86_RE), | ||
| 'aarch64': (scrub_asm_arm_eabi, ASM_FUNCTION_AARCH64_RE), | ||
| 'arm-eabi': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE), | ||
| 'thumb-eabi': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE), | ||
| 'thumbv6': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE), | ||
| 'thumbv6-eabi': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE), | ||
| 'thumbv6t2': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE), | ||
| 'thumbv6t2-eabi': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE), | ||
| 'thumbv6m': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE), | ||
| 'thumbv6m-eabi': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE), | ||
| 'thumbv7': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE), | ||
| 'thumbv7-eabi': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE), | ||
| 'thumbv7m': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE), | ||
| 'thumbv7m-eabi': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE), | ||
| 'thumbv8-eabi': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE), | ||
| 'thumbv8m.base': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE), | ||
| 'thumbv8m.main': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE), | ||
| 'armv6': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE), | ||
| 'armv7': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE), | ||
| 'armv7-eabi': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE), | ||
| 'armeb-eabi': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE), | ||
| 'armv7eb-eabi': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE), | ||
| 'armv7eb': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE), | ||
| 'mips': (scrub_asm_mips, ASM_FUNCTION_MIPS_RE), | ||
| 'powerpc64': (scrub_asm_powerpc64, ASM_FUNCTION_PPC_RE), | ||
| 'powerpc64le': (scrub_asm_powerpc64, ASM_FUNCTION_PPC_RE), | ||
| 'riscv32': (scrub_asm_riscv, ASM_FUNCTION_RISCV_RE), | ||
| 'riscv64': (scrub_asm_riscv, ASM_FUNCTION_RISCV_RE), | ||
| 's390x': (scrub_asm_systemz, ASM_FUNCTION_SYSTEMZ_RE), | ||
| } | ||
| handlers = None | ||
| for prefix, s in target_handlers.items(): | ||
| if triple.startswith(prefix): | ||
| handlers = s | ||
| break | ||
| else: | ||
| raise KeyError('Triple %r is not supported' % (triple)) | ||
|
|
||
| scrubber, function_re = handlers | ||
| common.build_function_body_dictionary( | ||
| function_re, scrubber, [args], raw_tool_output, prefixes, | ||
| func_dict, args.verbose) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| import re | ||
| import subprocess | ||
|
|
||
| RUN_LINE_RE = re.compile('^\s*;\s*RUN:\s*(.*)$') | ||
| CHECK_PREFIX_RE = re.compile('--?check-prefix(?:es)?=(\S+)') | ||
| CHECK_RE = re.compile(r'^\s*;\s*([^:]+?)(?:-NEXT|-NOT|-DAG|-LABEL)?:') | ||
|
|
||
| IR_FUNCTION_RE = re.compile('^\s*define\s+(?:internal\s+)?[^@]*@(\w+)\s*\(') | ||
| TRIPLE_IR_RE = re.compile(r'^target\s+triple\s*=\s*"([^"]+)"$') | ||
| TRIPLE_ARG_RE = re.compile(r'-mtriple=([^ ]+)') | ||
|
|
||
| SCRUB_LEADING_WHITESPACE_RE = re.compile(r'^(\s+)') | ||
| SCRUB_WHITESPACE_RE = re.compile(r'(?!^(| \w))[ \t]+', flags=re.M) | ||
| SCRUB_TRAILING_WHITESPACE_RE = re.compile(r'[ \t]+$', flags=re.M) | ||
| SCRUB_KILL_COMMENT_RE = re.compile(r'^ *#+ +kill:.*\n') | ||
| SCRUB_LOOP_COMMENT_RE = re.compile( | ||
| r'# =>This Inner Loop Header:.*|# in Loop:.*', flags=re.M) | ||
|
|
||
| def should_add_line_to_output(input_line, prefix_set): | ||
| # Skip any blank comment lines in the IR. | ||
| if input_line.strip() == ';': | ||
| return False | ||
| # Skip any blank lines in the IR. | ||
| #if input_line.strip() == '': | ||
| # return False | ||
| # And skip any CHECK lines. We're building our own. | ||
| m = CHECK_RE.match(input_line) | ||
| if m and m.group(1) in prefix_set: | ||
| return False | ||
|
|
||
| return True | ||
|
|
||
| # Invoke the tool that is being tested. | ||
| def invoke_tool(exe, cmd_args, ir): | ||
| with open(ir) as ir_file: | ||
| stdout = subprocess.check_output(exe + ' ' + cmd_args, | ||
| shell=True, stdin=ir_file) | ||
| # Fix line endings to unix CR style. | ||
| stdout = stdout.replace('\r\n', '\n') | ||
| return stdout | ||
|
|
||
| # Build up a dictionary of all the function bodies. | ||
| def build_function_body_dictionary(function_re, scrubber, scrubber_args, raw_tool_output, prefixes, func_dict, verbose): | ||
| for m in function_re.finditer(raw_tool_output): | ||
| if not m: | ||
| continue | ||
| func = m.group('func') | ||
| scrubbed_body = scrubber(m.group('body'), *scrubber_args) | ||
| if func.startswith('stress'): | ||
| # We only use the last line of the function body for stress tests. | ||
| scrubbed_body = '\n'.join(scrubbed_body.splitlines()[-1:]) | ||
| if verbose: | ||
| print >>sys.stderr, 'Processing function: ' + func | ||
| for l in scrubbed_body.splitlines(): | ||
| print >>sys.stderr, ' ' + l | ||
| for prefix in prefixes: | ||
| if func in func_dict[prefix] and func_dict[prefix][func] != scrubbed_body: | ||
| if prefix == prefixes[-1]: | ||
| print >>sys.stderr, ('WARNING: Found conflicting asm under the ' | ||
| 'same prefix: %r!' % (prefix,)) | ||
| else: | ||
| func_dict[prefix][func] = None | ||
| continue | ||
|
|
||
| func_dict[prefix][func] = scrubbed_body |
Oops, something went wrong.