From 9692811b264600b7fcb52a1f4fcf938d198567cb Mon Sep 17 00:00:00 2001 From: Alex Richardson Date: Wed, 21 Apr 2021 12:19:08 +0100 Subject: [PATCH] [update_(llc_)test_checks.py] Support pre-processing commands This has been rather useful in our downstream CHERI target where we want to run tests both with addrspace(0) and addrspace(200) pointers. With this patch we can prefix the opt command with `sed -e 's/addrspace(200)/addrspace(0)/g' -e 's/-A200-P200-G200//g'` to test both cases using the same IR input. Reviewed By: jdoerfert Differential Revision: https://reviews.llvm.org/D95137 --- .../update_llc_test_checks/Inputs/pre-process.ll | 15 +++++++++ .../Inputs/pre-process.ll.expected | 32 ++++++++++++++++++ .../update_llc_test_checks/pre-process.test | 10 ++++++ .../update_test_checks/Inputs/pre-process.ll | 18 ++++++++++ .../Inputs/pre-process.ll.expected | 39 ++++++++++++++++++++++ .../update_test_checks/pre-process.test | 6 ++++ llvm/utils/UpdateTestChecks/common.py | 15 ++++++++- llvm/utils/update_llc_test_checks.py | 20 ++++++----- llvm/utils/update_test_checks.py | 17 +++++++--- 9 files changed, 158 insertions(+), 14 deletions(-) create mode 100644 llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/pre-process.ll create mode 100644 llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/pre-process.ll.expected create mode 100644 llvm/test/tools/UpdateTestChecks/update_llc_test_checks/pre-process.test create mode 100644 llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/pre-process.ll create mode 100644 llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/pre-process.ll.expected create mode 100644 llvm/test/tools/UpdateTestChecks/update_test_checks/pre-process.test diff --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/pre-process.ll b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/pre-process.ll new file mode 100644 index 0000000..4f7f313 --- /dev/null +++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/pre-process.ll @@ -0,0 +1,15 @@ +; Test that update_llc_test_checks.py can run pre-processing commands. +; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s --check-prefix=CHECK-ADD +; RUN: sed 's/add /sub /g' %s | llc -mtriple=x86_64-unknown-unknown \ +; RUN: | FileCheck %s --check-prefix=CHECK-SUB +; Check that multiple pre-processing commands are handled +; RUN: sed 's/add /sub /g' %s | sed 's/i64 /i16 /g' | cat \ +; RUN: | llc -mtriple=x86_64-unknown-unknown | FileCheck %s --check-prefix=CHECK-SUB-I16 + +define i64 @test_add_constant(i64 %arg) nounwind { +entry: + %a1 = add i64 %arg, 1 + %a2 = add i64 %a1, 2 + %a3 = add i64 %a2, 3 + ret i64 %a3 +} diff --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/pre-process.ll.expected b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/pre-process.ll.expected new file mode 100644 index 0000000..750c951 --- /dev/null +++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/pre-process.ll.expected @@ -0,0 +1,32 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; Test that update_llc_test_checks.py can run pre-processing commands. +; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s --check-prefix=CHECK-ADD +; RUN: sed 's/add /sub /g' %s | llc -mtriple=x86_64-unknown-unknown \ +; RUN: | FileCheck %s --check-prefix=CHECK-SUB +; Check that multiple pre-processing commands are handled +; RUN: sed 's/add /sub /g' %s | sed 's/i64 /i16 /g' | cat \ +; RUN: | llc -mtriple=x86_64-unknown-unknown | FileCheck %s --check-prefix=CHECK-SUB-I16 + +define i64 @test_add_constant(i64 %arg) nounwind { +; CHECK-ADD-LABEL: test_add_constant: +; CHECK-ADD: # %bb.0: # %entry +; CHECK-ADD-NEXT: leaq 6(%rdi), %rax +; CHECK-ADD-NEXT: retq +; +; CHECK-SUB-LABEL: test_add_constant: +; CHECK-SUB: # %bb.0: # %entry +; CHECK-SUB-NEXT: leaq -6(%rdi), %rax +; CHECK-SUB-NEXT: retq +; +; CHECK-SUB-I16-LABEL: test_add_constant: +; CHECK-SUB-I16: # %bb.0: # %entry +; CHECK-SUB-I16-NEXT: # kill: def $edi killed $edi def $rdi +; CHECK-SUB-I16-NEXT: leal -6(%rdi), %eax +; CHECK-SUB-I16-NEXT: # kill: def $ax killed $ax killed $eax +; CHECK-SUB-I16-NEXT: retq +entry: + %a1 = add i64 %arg, 1 + %a2 = add i64 %a1, 2 + %a3 = add i64 %a2, 3 + ret i64 %a3 +} diff --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/pre-process.test b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/pre-process.test new file mode 100644 index 0000000..c60651c --- /dev/null +++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/pre-process.test @@ -0,0 +1,10 @@ +# REQUIRES: x86-registered-target +## Test that update_llc_test_checks.py can run pre-processing commands. + +## Test that update_test_checks.py can run pre-processing commands. +# RUN: cp -f %S/Inputs/pre-process.ll %t.ll && %update_llc_test_checks %t.ll +# RUN: diff -u %t.ll %S/Inputs/pre-process.ll.expected +## Check that running the script again does not change the result: +# RUN: %update_llc_test_checks %t.ll +# RUN: diff -u %t.ll %S/Inputs/pre-process.ll.expected + diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/pre-process.ll b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/pre-process.ll new file mode 100644 index 0000000..c082e5e --- /dev/null +++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/pre-process.ll @@ -0,0 +1,18 @@ +; Test that update_test_checks.py can run pre-processing commands. +; RUN: opt < %s -instsimplify -S | FileCheck %s --check-prefix=CHECK-AS200 +; RUN: sed -e 's/addrspace(200)/addrspace(0)/g' -e 's/-A200-P200-G200//g' %s \ +; RUN: | opt -instsimplify -S | FileCheck %s --check-prefix=CHECK-AS0 +; Check that multiple pre-processing commands are handled +; RUN: sed 's/addrspace(200)/addrspace(1)/g' %s | sed 's/-A1-P1-G1//g' \ +; RUN: | opt -instsimplify -S | FileCheck %s --check-prefix=CHECK-AS1 +; More than two commands should also be fine +; RUN: cat %s | cat | cat | cat | opt < %s -instsimplify -S \ +; RUN: | FileCheck %s --check-prefix=CHECK-AS200-NOOP-PRE-PROCESS + +target datalayout = "e-m:e-p200:128:128:128:64-p:64:64-A200-P200-G200" + +define i8 addrspace(200)* @test_zerogep_in_different_as(i8 addrspace(200)* %arg) addrspace(200) nounwind { +entry: + %ret = getelementptr inbounds i8, i8 addrspace(200)* %arg, i64 0 + ret i8 addrspace(200)* %ret +} diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/pre-process.ll.expected b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/pre-process.ll.expected new file mode 100644 index 0000000..af98d6d --- /dev/null +++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/pre-process.ll.expected @@ -0,0 +1,39 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature +; Test that update_test_checks.py can run pre-processing commands. +; RUN: opt < %s -instsimplify -S | FileCheck %s --check-prefix=CHECK-AS200 +; RUN: sed -e 's/addrspace(200)/addrspace(0)/g' -e 's/-A200-P200-G200//g' %s \ +; RUN: | opt -instsimplify -S | FileCheck %s --check-prefix=CHECK-AS0 +; Check that multiple pre-processing commands are handled +; RUN: sed 's/addrspace(200)/addrspace(1)/g' %s | sed 's/-A1-P1-G1//g' \ +; RUN: | opt -instsimplify -S | FileCheck %s --check-prefix=CHECK-AS1 +; More than two commands should also be fine +; RUN: cat %s | cat | cat | cat | opt < %s -instsimplify -S \ +; RUN: | FileCheck %s --check-prefix=CHECK-AS200-NOOP-PRE-PROCESS + +target datalayout = "e-m:e-p200:128:128:128:64-p:64:64-A200-P200-G200" + +define i8 addrspace(200)* @test_zerogep_in_different_as(i8 addrspace(200)* %arg) addrspace(200) nounwind { +; CHECK-AS200-LABEL: define {{[^@]+}}@test_zerogep_in_different_as +; CHECK-AS200-SAME: (i8 addrspace(200)* [[ARG:%.*]]) addrspace(200) #[[ATTR0:[0-9]+]] { +; CHECK-AS200-NEXT: entry: +; CHECK-AS200-NEXT: ret i8 addrspace(200)* [[ARG]] +; +; CHECK-AS0-LABEL: define {{[^@]+}}@test_zerogep_in_different_as +; CHECK-AS0-SAME: (i8* [[ARG:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-AS0-NEXT: entry: +; CHECK-AS0-NEXT: ret i8* [[ARG]] +; +; CHECK-AS1-LABEL: define {{[^@]+}}@test_zerogep_in_different_as +; CHECK-AS1-SAME: (i8 addrspace(1)* [[ARG:%.*]]) addrspace(1) #[[ATTR0:[0-9]+]] { +; CHECK-AS1-NEXT: entry: +; CHECK-AS1-NEXT: ret i8 addrspace(1)* [[ARG]] +; +; CHECK-AS200-NOOP-PRE-PROCESS-LABEL: define {{[^@]+}}@test_zerogep_in_different_as +; CHECK-AS200-NOOP-PRE-PROCESS-SAME: (i8 addrspace(200)* [[ARG:%.*]]) addrspace(200) #[[ATTR0:[0-9]+]] { +; CHECK-AS200-NOOP-PRE-PROCESS-NEXT: entry: +; CHECK-AS200-NOOP-PRE-PROCESS-NEXT: ret i8 addrspace(200)* [[ARG]] +; +entry: + %ret = getelementptr inbounds i8, i8 addrspace(200)* %arg, i64 0 + ret i8 addrspace(200)* %ret +} diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/pre-process.test b/llvm/test/tools/UpdateTestChecks/update_test_checks/pre-process.test new file mode 100644 index 0000000..389c33b --- /dev/null +++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/pre-process.test @@ -0,0 +1,6 @@ +## Test that update_test_checks.py can run pre-processing commands. +# RUN: cp -f %S/Inputs/pre-process.ll %t.ll && %update_test_checks --function-signature %t.ll +# RUN: diff -u %t.ll %S/Inputs/pre-process.ll.expected +## Check that running the script again does not change the result: +# RUN: %update_test_checks %t.ll +# RUN: diff -u %t.ll %S/Inputs/pre-process.ll.expected diff --git a/llvm/utils/UpdateTestChecks/common.py b/llvm/utils/UpdateTestChecks/common.py index 4598475..449ccb0 100644 --- a/llvm/utils/UpdateTestChecks/common.py +++ b/llvm/utils/UpdateTestChecks/common.py @@ -2,6 +2,7 @@ from __future__ import print_function import copy import glob +import os import re import subprocess import sys @@ -141,11 +142,23 @@ def should_add_line_to_output(input_line, prefix_set, skip_global_checks = False return True # Invoke the tool that is being tested. -def invoke_tool(exe, cmd_args, ir): +def invoke_tool(exe, cmd_args, ir, preprocess_cmd=None, verbose=False): with open(ir) as ir_file: # TODO Remove the str form which is used by update_test_checks.py and # update_llc_test_checks.py # The safer list form is used by update_cc_test_checks.py + if preprocess_cmd: + # Allow pre-processing the IR file (e.g. using sed): + assert isinstance(preprocess_cmd, str) # TODO: use a list instead of using shell + preprocess_cmd = preprocess_cmd.replace('%s', ir).strip() + if verbose: + print('Pre-processing input file: ', ir, " with command '", + preprocess_cmd, "'", sep="", file=sys.stderr) + # Python 2.7 doesn't have subprocess.DEVNULL: + with open(os.devnull, 'w') as devnull: + pp = subprocess.Popen(preprocess_cmd, shell=True, stdin=devnull, + stdout=subprocess.PIPE) + ir_file = pp.stdout if isinstance(cmd_args, list): stdout = subprocess.check_output([exe] + cmd_args, stdin=ir_file) else: diff --git a/llvm/utils/update_llc_test_checks.py b/llvm/utils/update_llc_test_checks.py index 614cd07..0f1117b 100755 --- a/llvm/utils/update_llc_test_checks.py +++ b/llvm/utils/update_llc_test_checks.py @@ -60,8 +60,13 @@ def main(): common.warn('Skipping unparseable RUN line: ' + l) continue - commands = [cmd.strip() for cmd in l.split('|', 1)] - llc_cmd = commands[0] + commands = [cmd.strip() for cmd in l.split('|')] + assert len(commands) >= 2 + preprocess_cmd = None + if len(commands) > 2: + preprocess_cmd = " | ".join(commands[:-2]) + llc_cmd = commands[-2] + filecheck_cmd = commands[-1] llc_tool = llc_cmd.split(' ')[0] triple_in_cmd = None @@ -74,9 +79,6 @@ def main(): if m: march_in_cmd = m.groups()[0] - filecheck_cmd = '' - if len(commands) > 1: - filecheck_cmd = commands[1] common.verify_filecheck_prefixes(filecheck_cmd) if llc_tool not in LLC_LIKE_TOOLS: common.warn('Skipping non-llc RUN line: ' + l) @@ -97,7 +99,8 @@ def main(): # FIXME: We should use multiple check prefixes to common check lines. For # now, we just ignore all but the last. - run_list.append((check_prefixes, llc_cmd_args, triple_in_cmd, march_in_cmd)) + run_list.append((check_prefixes, llc_tool, llc_cmd_args, preprocess_cmd, + triple_in_cmd, march_in_cmd)) if ti.path.endswith('.mir'): check_indent = ' ' @@ -113,12 +116,13 @@ def main(): 'replace_function_regex': []}), scrubber_args=[ti.args]) - for prefixes, llc_args, triple_in_cmd, march_in_cmd in run_list: + for prefixes, llc_tool, llc_args, preprocess_cmd, triple_in_cmd, march_in_cmd in run_list: common.debug('Extracted LLC cmd:', llc_tool, llc_args) common.debug('Extracted FileCheck prefixes:', str(prefixes)) raw_tool_output = common.invoke_tool(ti.args.llc_binary or llc_tool, - llc_args, ti.path) + llc_args, ti.path, preprocess_cmd, + verbose=ti.args.verbose) triple = triple_in_cmd or triple_in_ir if not triple: triple = asm.get_triple_from_march(march_in_cmd) diff --git a/llvm/utils/update_test_checks.py b/llvm/utils/update_test_checks.py index 4a55ac6..e240c6c 100755 --- a/llvm/utils/update_test_checks.py +++ b/llvm/utils/update_test_checks.py @@ -80,7 +80,13 @@ def main(): common.warn('Skipping unparseable RUN line: ' + l) continue - (tool_cmd, filecheck_cmd) = tuple([cmd.strip() for cmd in l.split('|', 1)]) + commands = [cmd.strip() for cmd in l.split('|')] + assert len(commands) >= 2 + preprocess_cmd = None + if len(commands) > 2: + preprocess_cmd = " | ".join(commands[:-2]) + tool_cmd = commands[-2] + filecheck_cmd = commands[-1] common.verify_filecheck_prefixes(filecheck_cmd) if not tool_cmd.startswith(opt_basename + ' '): common.warn('Skipping non-%s RUN line: %s' % (opt_basename, l)) @@ -101,7 +107,7 @@ def main(): # 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)) + prefix_list.append((check_prefixes, tool_cmd_args, preprocess_cmd)) global_vars_seen_dict = {} builder = common.FunctionTestBuilder( @@ -109,12 +115,13 @@ def main(): flags=ti.args, scrubber_args=[]) - for prefixes, opt_args in prefix_list: + for prefixes, opt_args, preprocess_cmd in prefix_list: common.debug('Extracted opt cmd: ' + opt_basename + ' ' + opt_args) common.debug('Extracted FileCheck prefixes: ' + str(prefixes)) raw_tool_output = common.invoke_tool(ti.args.opt_binary, opt_args, - ti.path) + ti.path, preprocess_cmd=preprocess_cmd, + verbose=ti.args.verbose) builder.process_run_line(common.OPT_FUNCTION_RE, common.scrub_body, raw_tool_output, prefixes) @@ -122,7 +129,7 @@ def main(): is_in_function = False is_in_function_start = False has_checked_pre_function_globals = False - prefix_set = set([prefix for prefixes, _ in prefix_list for prefix in prefixes]) + prefix_set = set([prefix for prefixes, _, _ in prefix_list for prefix in prefixes]) common.debug('Rewriting FileCheck prefixes:', str(prefix_set)) output_lines = [] -- 2.7.4