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 --- /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 --- /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 --- /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 --- /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 --- /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 update_test_checks.py can run sed as a pre-processing command. +; 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:#.*]] { +; 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:#.*]] { +; 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:#.*]] { +; 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:#.*]] { +; 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 --- /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 --- a/llvm/utils/UpdateTestChecks/common.py +++ b/llvm/utils/UpdateTestChecks/common.py @@ -2,6 +2,7 @@ import copy import glob +import os import re import subprocess import sys @@ -135,11 +136,23 @@ 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 --- a/llvm/utils/update_llc_test_checks.py +++ b/llvm/utils/update_llc_test_checks.py @@ -60,8 +60,13 @@ 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 @@ 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 @@ # 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 @@ '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 --- a/llvm/utils/update_test_checks.py +++ b/llvm/utils/update_test_checks.py @@ -80,7 +80,13 @@ 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 @@ # 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 @@ 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 @@ 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 = []