[llvm] 9692811 - [update_(llc_)test_checks.py] Support pre-processing commands

Alex Richardson via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 28 04:23:31 PDT 2021


Author: Alex Richardson
Date: 2021-04-28T12:19:19+01:00
New Revision: 9692811b264600b7fcb52a1f4fcf938d198567cb

URL: https://github.com/llvm/llvm-project/commit/9692811b264600b7fcb52a1f4fcf938d198567cb
DIFF: https://github.com/llvm/llvm-project/commit/9692811b264600b7fcb52a1f4fcf938d198567cb.diff

LOG: [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

Added: 
    llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/pre-process.ll
    llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/pre-process.ll.expected
    llvm/test/tools/UpdateTestChecks/update_llc_test_checks/pre-process.test
    llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/pre-process.ll
    llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/pre-process.ll.expected
    llvm/test/tools/UpdateTestChecks/update_test_checks/pre-process.test

Modified: 
    llvm/utils/UpdateTestChecks/common.py
    llvm/utils/update_llc_test_checks.py
    llvm/utils/update_test_checks.py

Removed: 
    


################################################################################
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 0000000000000..4f7f31375525c
--- /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 0000000000000..750c951aee8a9
--- /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 0000000000000..c60651c0a7f24
--- /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 0000000000000..c082e5e0cb7d4
--- /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_
diff erent_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 0000000000000..af98d6d54c8d6
--- /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_
diff erent_as(i8 addrspace(200)* %arg) addrspace(200) nounwind {
+; CHECK-AS200-LABEL: define {{[^@]+}}@test_zerogep_in_
diff erent_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_
diff erent_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_
diff erent_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_
diff erent_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 0000000000000..389c33b14cdc0
--- /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 45984751d6e77..449ccb07abcb4 100644
--- 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
@@ -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 614cd073213ae..0f1117bf3bbd9 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 4a55ac6b73941..e240c6ca2e504 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 = []
 


        


More information about the llvm-commits mailing list