[clang] 5a4033c - update-test-checks: safely handle tests with #if's

Nicolai Hähnle via cfe-commits cfe-commits at lists.llvm.org
Wed Jul 20 02:24:11 PDT 2022


Author: Nicolai Hähnle
Date: 2022-07-20T11:23:49+02:00
New Revision: 5a4033c36716de0cee75eb28b95cce44ae239cd9

URL: https://github.com/llvm/llvm-project/commit/5a4033c36716de0cee75eb28b95cce44ae239cd9
DIFF: https://github.com/llvm/llvm-project/commit/5a4033c36716de0cee75eb28b95cce44ae239cd9.diff

LOG: update-test-checks: safely handle tests with #if's

There is at least one Clang test (clang/test/CodeGen/arm_acle.c) which
has functions guarded by #if's that cause those functions to be compiled
only for a subset of RUN lines.

This results in a case where one RUN line has a body for the function
and another doesn't. Treat this case as a conflict for any prefixes that
the two RUN lines have in common.

This change exposed a bug where functions with '$' in the name weren't
properly recognized in ARM assembly (despite there being a test case
that was supposed to catch the problem!). This bug is fixed as well.

Differential Revision: https://reviews.llvm.org/D130089

Added: 
    clang/test/utils/update_cc_test_checks/Inputs/ifdef.c
    clang/test/utils/update_cc_test_checks/Inputs/ifdef.c.expected
    clang/test/utils/update_cc_test_checks/ifdef.test

Modified: 
    llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/arm_function_name.ll
    llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/arm_function_name.ll.expected
    llvm/utils/UpdateTestChecks/asm.py
    llvm/utils/UpdateTestChecks/common.py
    llvm/utils/update_analyze_test_checks.py
    llvm/utils/update_cc_test_checks.py
    llvm/utils/update_llc_test_checks.py
    llvm/utils/update_test_checks.py

Removed: 
    


################################################################################
diff  --git a/clang/test/utils/update_cc_test_checks/Inputs/ifdef.c b/clang/test/utils/update_cc_test_checks/Inputs/ifdef.c
new file mode 100644
index 0000000000000..79d73a2de4863
--- /dev/null
+++ b/clang/test/utils/update_cc_test_checks/Inputs/ifdef.c
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -triple=x86_64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK %s
+// RUN: %clang_cc1 -triple=x86_64-unknown-linux-gnu -emit-llvm -o - %s -DFOO | FileCheck -check-prefixes=CHECK,FOO %s
+
+#ifdef FOO
+int foo() {
+  return 1;
+}
+#endif
+
+int bar() {
+  return 2;
+}

diff  --git a/clang/test/utils/update_cc_test_checks/Inputs/ifdef.c.expected b/clang/test/utils/update_cc_test_checks/Inputs/ifdef.c.expected
new file mode 100644
index 0000000000000..c1fb72db9339e
--- /dev/null
+++ b/clang/test/utils/update_cc_test_checks/Inputs/ifdef.c.expected
@@ -0,0 +1,21 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple=x86_64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK %s
+// RUN: %clang_cc1 -triple=x86_64-unknown-linux-gnu -emit-llvm -o - %s -DFOO | FileCheck -check-prefixes=CHECK,FOO %s
+
+#ifdef FOO
+// FOO-LABEL: @foo(
+// FOO-NEXT:  entry:
+// FOO-NEXT:    ret i32 1
+//
+int foo() {
+  return 1;
+}
+#endif
+
+// CHECK-LABEL: @bar(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    ret i32 2
+//
+int bar() {
+  return 2;
+}

diff  --git a/clang/test/utils/update_cc_test_checks/ifdef.test b/clang/test/utils/update_cc_test_checks/ifdef.test
new file mode 100644
index 0000000000000..6e4c6319a31c9
--- /dev/null
+++ b/clang/test/utils/update_cc_test_checks/ifdef.test
@@ -0,0 +1,8 @@
+## Test that functions that are only compiled in a subset of RUN lines are
+## handled correctly
+
+# RUN: cp %S/Inputs/ifdef.c %t.c && %update_cc_test_checks %t.c
+# RUN: 
diff  -u %S/Inputs/ifdef.c.expected %t.c
+## Check that re-running update_cc_test_checks doesn't change the output
+# RUN: %update_cc_test_checks %t.c
+# RUN: 
diff  -u %S/Inputs/ifdef.c.expected %t.c

diff  --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/arm_function_name.ll b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/arm_function_name.ll
index fa03d8cc51cd9..5f3edb6edf478 100644
--- a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/arm_function_name.ll
+++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/arm_function_name.ll
@@ -1,9 +1,8 @@
 ; Check that we accept functions with '$' in the name.
-; TODO: This is not handled correcly on 32bit ARM and needs to be fixed.
 
-; RUN: llc -mtriple=armv7-unknown-linux < %s | FileCheck --prefix=LINUX %s
-; RUN: llc -mtriple=armv7-apple-darwin < %s | FileCheck --prefix=DARWIN %s
-; RUN: llc -mtriple=armv7-apple-ios < %s | FileCheck --prefix=IOS %s
+; RUN: llc -mtriple=armv7-unknown-linux < %s | FileCheck %s
+; RUN: llc -mtriple=armv7-apple-darwin < %s | FileCheck %s
+; RUN: llc -mtriple=armv7-apple-ios < %s | FileCheck %s
 
 define hidden i32 @"_Z54bar$ompvariant$bar"() {
 entry:

diff  --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/arm_function_name.ll.expected b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/arm_function_name.ll.expected
index e15d788ce34f4..6a8684f85575a 100644
--- a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/arm_function_name.ll.expected
+++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/arm_function_name.ll.expected
@@ -1,10 +1,9 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
 ; Check that we accept functions with '$' in the name.
-; TODO: This is not handled correcly on 32bit ARM and needs to be fixed.
 
-; RUN: llc -mtriple=armv7-unknown-linux < %s | FileCheck --prefix=LINUX %s
-; RUN: llc -mtriple=armv7-apple-darwin < %s | FileCheck --prefix=DARWIN %s
-; RUN: llc -mtriple=armv7-apple-ios < %s | FileCheck --prefix=IOS %s
+; RUN: llc -mtriple=armv7-unknown-linux < %s | FileCheck %s
+; RUN: llc -mtriple=armv7-apple-darwin < %s | FileCheck %s
+; RUN: llc -mtriple=armv7-apple-ios < %s | FileCheck %s
 
 define hidden i32 @"_Z54bar$ompvariant$bar"() {
 ; CHECK-LABEL: _Z54bar$ompvariant$bar:

diff  --git a/llvm/utils/UpdateTestChecks/asm.py b/llvm/utils/UpdateTestChecks/asm.py
index 953db74f3d840..821b2d0019075 100644
--- a/llvm/utils/UpdateTestChecks/asm.py
+++ b/llvm/utils/UpdateTestChecks/asm.py
@@ -23,10 +23,10 @@ class string:
     flags=(re.M | re.S))
 
 ASM_FUNCTION_ARM_RE = re.compile(
-    r'^(?P<func>[0-9a-zA-Z_]+):\n' # f: (name of function)
+    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
+    r'(?P<body>.*?)' # (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(
@@ -128,7 +128,8 @@ class string:
     flags=(re.M | re.S))
 
 ASM_FUNCTION_ARM_DARWIN_RE = re.compile(
-    r'^[ \t]*\.globl[ \t]*_(?P<func>[^ \t])[ \t]*@[ \t]--[ \t]Begin[ \t]function[ \t]"?(?P=func)"?'
+    r'@[ \t]--[ \t]Begin[ \t]function[ \t](?P<func>[^ \t]+?)\n'
+    r'^[ \t]*\.globl[ \t]*_(?P=func)[ \t]*'
     r'(?P<directives>.*?)'
     r'^_(?P=func):\n[ \t]*'
     r'(?P<body>.*?)'

diff  --git a/llvm/utils/UpdateTestChecks/common.py b/llvm/utils/UpdateTestChecks/common.py
index a1e883d8ea7dd..8e02488da985e 100644
--- a/llvm/utils/UpdateTestChecks/common.py
+++ b/llvm/utils/UpdateTestChecks/common.py
@@ -496,6 +496,7 @@ def __init__(self, run_list, flags, scrubber_args, path):
     self._func_dict = {}
     self._func_order = {}
     self._global_var_dict = {}
+    self._processed_prefixes = set()
     for tuple in run_list:
       for prefix in tuple[0]:
         self._func_dict.update({prefix:dict()})
@@ -584,30 +585,43 @@ def process_run_line(self, function_re, scrubber, raw_tool_output, prefixes, is_
                                    scrubbed_body)
 
         if func in self._func_dict[prefix]:
-          if (self._func_dict[prefix][func] is None or
-              str(self._func_dict[prefix][func]) != scrubbed_body or
-              self._func_dict[prefix][func].args_and_sig != args_and_sig or
-                  self._func_dict[prefix][func].attrs != attrs):
-            if (self._func_dict[prefix][func] is not None and
-                self._func_dict[prefix][func].is_same_except_arg_names(
+          if (self._func_dict[prefix][func] is not None and
+              (str(self._func_dict[prefix][func]) != scrubbed_body or
+               self._func_dict[prefix][func].args_and_sig != args_and_sig or
+               self._func_dict[prefix][func].attrs != attrs)):
+            if self._func_dict[prefix][func].is_same_except_arg_names(
                 scrubbed_extra,
                 args_and_sig,
                 attrs,
-                is_backend)):
+                is_backend):
               self._func_dict[prefix][func].scrub = scrubbed_extra
               self._func_dict[prefix][func].args_and_sig = args_and_sig
-              continue
             else:
               # This means a previous RUN line produced a body for this function
               # that is 
diff erent from the one produced by this current RUN line,
               # so the body can't be common accross RUN lines. We use None to
               # indicate that.
               self._func_dict[prefix][func] = None
-              continue
-
-        self._func_dict[prefix][func] = function_body(
-            scrubbed_body, scrubbed_extra, args_and_sig, attrs, func_name_separator)
-        self._func_order[prefix].append(func)
+        else:
+          if prefix not in self._processed_prefixes:
+            self._func_dict[prefix][func] = function_body(
+                scrubbed_body, scrubbed_extra, args_and_sig, attrs,
+                func_name_separator)
+            self._func_order[prefix].append(func)
+          else:
+            # An earlier RUN line used this check prefixes but didn't produce
+            # a body for this function. This happens in Clang tests that use
+            # preprocesser directives to exclude individual functions from some
+            # RUN lines.
+            self._func_dict[prefix][func] = None
+
+  def processed_prefixes(self, prefixes):
+    """
+    Mark a set of prefixes as having had at least one applicable RUN line fully
+    processed. This is used to filter out function bodies that don't have
+    outputs for all RUN lines.
+    """
+    self._processed_prefixes.update(prefixes)
 
   def get_failed_prefixes(self):
     # This returns the list of those prefixes that failed to match any function,

diff  --git a/llvm/utils/update_analyze_test_checks.py b/llvm/utils/update_analyze_test_checks.py
index c48e2db272833..168d358bc3d83 100755
--- a/llvm/utils/update_analyze_test_checks.py
+++ b/llvm/utils/update_analyze_test_checks.py
@@ -124,6 +124,8 @@ def main():
         common.warn('Don\'t know how to deal with this output')
         continue
 
+      builder.processed_prefixes(prefixes)
+
     func_dict = builder.finish_and_get_func_dict()
     is_in_function = False
     is_in_function_start = False

diff  --git a/llvm/utils/update_cc_test_checks.py b/llvm/utils/update_cc_test_checks.py
index 211892a4d682e..b9e91f19461b0 100755
--- a/llvm/utils/update_cc_test_checks.py
+++ b/llvm/utils/update_cc_test_checks.py
@@ -214,6 +214,7 @@ def get_function_body(builder, args, filename, clang_args, extra_commands,
     builder.process_run_line(
             common.OPT_FUNCTION_RE, common.scrub_body, raw_tool_output,
             prefixes, False)
+    builder.processed_prefixes(prefixes)
   else:
     print('The clang command line should include -emit-llvm as asm tests '
           'are discouraged in Clang testsuite.', file=sys.stderr)

diff  --git a/llvm/utils/update_llc_test_checks.py b/llvm/utils/update_llc_test_checks.py
index 66eb5d4e4f5e3..4ce5534a2b735 100755
--- a/llvm/utils/update_llc_test_checks.py
+++ b/llvm/utils/update_llc_test_checks.py
@@ -137,6 +137,7 @@ def main():
 
       scrubber, function_re = output_type.get_run_handler(triple)
       builder.process_run_line(function_re, scrubber, raw_tool_output, prefixes, True)
+      builder.processed_prefixes(prefixes)
 
     func_dict = builder.finish_and_get_func_dict()
     global_vars_seen_dict = {}

diff  --git a/llvm/utils/update_test_checks.py b/llvm/utils/update_test_checks.py
index c6d8d26f00758..f16103b892b06 100755
--- a/llvm/utils/update_test_checks.py
+++ b/llvm/utils/update_test_checks.py
@@ -120,6 +120,7 @@ def main():
                                            verbose=ti.args.verbose)
       builder.process_run_line(common.OPT_FUNCTION_RE, common.scrub_body,
               raw_tool_output, prefixes, False)
+      builder.processed_prefixes(prefixes)
 
     func_dict = builder.finish_and_get_func_dict()
     is_in_function = False


        


More information about the cfe-commits mailing list