[compiler-rt] [llvm] [lit] [compiler-rt] Add llvm-lit global command cache to speed up test config (PR #195888)

via llvm-commits llvm-commits at lists.llvm.org
Tue May 5 10:41:19 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-testing-tools

Author: Andrew Haberlandt (ndrewh)

<details>
<summary>Changes</summary>

Compiler-rt lit test discovery takes quite a while on Darwin (i.e. the time from when you launch llvm-lit to when the first test runs can be minutes for check-compiler-rt). This appears to be mostly due to subprocess calls during test configuration.

This adds a memoized command-runner to llvm-lit, so that lit.cfg.py scripts can re-use the result of feature-detection commands when running multiple test suites at once. I've adopted it for several subprocess calls in compiler-rt.

rdar://175893448

---
Full diff: https://github.com/llvm/llvm-project/pull/195888.diff


2 Files Affected:

- (modified) compiler-rt/test/lit.common.cfg.py (+9-30) 
- (modified) llvm/utils/lit/lit/util.py (+24-1) 


``````````diff
diff --git a/compiler-rt/test/lit.common.cfg.py b/compiler-rt/test/lit.common.cfg.py
index fef8f7ab297cc..b6eb8c08578fb 100644
--- a/compiler-rt/test/lit.common.cfg.py
+++ b/compiler-rt/test/lit.common.cfg.py
@@ -20,20 +20,8 @@ def get_path_from_clang(args, allow_failure):
         f"--target={config.target_triple}",
         *args,
     ]
-    path = None
-    try:
-        result = subprocess.run(
-            clang_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True
-        )
-        path = result.stdout.decode().strip()
-    except subprocess.CalledProcessError as e:
-        msg = f"Failed to run {clang_cmd}\nrc:{e.returncode}\nstdout:{e.stdout}\ne.stderr{e.stderr}"
-        if allow_failure:
-            lit_config.warning(msg)
-        else:
-            lit_config.fatal(msg)
-    return path, clang_cmd
-
+    path = lit.util.runCommandCached(clang_cmd, allow_failure, text=True)
+    return path.strip(), clang_cmd
 
 def find_compiler_libdir():
     """
@@ -592,10 +580,10 @@ def get_ios_commands_dir():
         # There is no simulator-specific sw_vers/sysctl, so we use the host OS version
         os_detection_prefix = []
 
-    darwin_os_version = subprocess.check_output(
-        os_detection_prefix + ["sw_vers", "-productVersion"], universal_newlines=True
+    darwin_os_version = lit.util.runCommandCached(
+        os_detection_prefix + ["sw_vers", "-productVersion"], universal_newlines=True, text=True
     )
-    darwin_os_version = tuple(int(x) for x in darwin_os_version.split("."))
+    darwin_os_version = tuple(int(x) for x in darwin_os_version.strip().split("."))
 
     if len(darwin_os_version) == 2:
         darwin_os_version = (darwin_os_version[0], darwin_os_version[1], 0)
@@ -609,8 +597,8 @@ def get_ios_commands_dir():
 
     # Detect x86_64h
     try:
-        output = subprocess.check_output(
-            os_detection_prefix + ["sysctl", "hw.cpusubtype"]
+        output = lit.util.runCommandCached(
+            os_detection_prefix + ["sysctl", "hw.cpusubtype"], text=True
         )
         output_re = re.match("^hw.cpusubtype: ([0-9]+)$", output)
         if output_re:
@@ -955,18 +943,9 @@ def is_windows_lto_supported():
     if lit.util.which("log"):
         # Querying the log can only done by a privileged user so
         # so check if we can query the log.
-        exit_code = -1
-        with open("/dev/null", "r") as f:
-            # Run a `log show` command the should finish fairly quickly and produce very little output.
-            exit_code = subprocess.call(
-                ["log", "show", "--last", "1m", "--predicate", "1 == 0"],
-                stdout=f,
-                stderr=f,
-            )
-        if exit_code == 0:
+        res = lit.util.runCommandCached(["log", "show", "--last", "1m", "--predicate", "1 == 0"], allow_failure=True)
+        if res is not None:
             config.available_features.add("darwin_log_cmd")
-        else:
-            lit_config.warning("log command found but cannot queried")
     else:
         lit_config.warning("log command not found. Some tests will be skipped.")
 elif config.android:
diff --git a/llvm/utils/lit/lit/util.py b/llvm/utils/lit/lit/util.py
index a800f1f6e1419..8fd296f460a02 100644
--- a/llvm/utils/lit/lit/util.py
+++ b/llvm/utils/lit/lit/util.py
@@ -12,7 +12,7 @@
 import subprocess
 import sys
 import threading
-
+import functools
 
 def pythonize_bool(value):
     if value is None:
@@ -441,3 +441,26 @@ def killProcessAndChildren(pid):
             psutilProc.kill()
         except psutil.NoSuchProcess:
             pass
+
+ at functools.cache
+def _runCommandCachedInner(cmd, allow_failure, **kwargs):
+    try:
+        result = subprocess.run(
+            cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True, **kwargs
+        )
+        return result.stdout
+    except subprocess.CalledProcessError as e:
+        msg = f"Failed to run {cmd}\nrc:{e.returncode}\nstdout:{e.stdout}\ne.stderr{e.stderr}"
+        if allow_failure:
+            lit_config.warning(msg)
+        else:
+            lit_config.fatal(msg)
+        return None
+
+def runCommandCached(cmd, allow_failure=False, **kwargs):
+    if type(cmd) is list:
+        cmd = tuple(cmd)
+    elif type(cmd) is str:
+        cmd = tuple([cmd])
+
+    return _runCommandCachedInner(cmd, allow_failure, **kwargs)

``````````

</details>


https://github.com/llvm/llvm-project/pull/195888


More information about the llvm-commits mailing list