diff --git a/hadrian/src/Settings/Builders/RunTest.hs b/hadrian/src/Settings/Builders/RunTest.hs
index c10e93aae0f8b5adf2091b571f4f3d105be0f3e5..d6615a264edb3785776e2cd673ddb3c6bd05161d 100644
--- a/hadrian/src/Settings/Builders/RunTest.hs
+++ b/hadrian/src/Settings/Builders/RunTest.hs
@@ -70,7 +70,6 @@ runTestBuilderArgs = builder RunTest ? do
     withSMP             <- getBooleanSetting TestGhcWithSMP
     debugged            <- getBooleanSetting TestGhcDebugged
     keepFiles           <- expr (testKeepFiles <$> userSetting defaultTestArgs)
-    withLlvm            <- expr (not . null <$> settingsFileSetting SettingsFileSetting_LlcCommand)
 
     accept <- expr (testAccept <$> userSetting defaultTestArgs)
     (acceptPlatform, acceptOS) <- expr . liftIO $
@@ -125,8 +124,6 @@ runTestBuilderArgs = builder RunTest ? do
             , arg "-e", arg $ asBool "config.have_profiling=" (hasLibWay profiling)
             , arg "-e", arg $ asBool "config.have_fast_bignum=" (bignumBackend /= "native" && not bignumCheck)
             , arg "-e", arg $ asBool "ghc_with_smp=" withSMP
-            , arg "-e", arg $ asBool "ghc_with_llvm=" withLlvm
-
 
             , arg "-e", arg $ "config.ghc_dynamic_by_default=" ++ show hasDynamicByDefault
             , arg "-e", arg $ "config.ghc_dynamic=" ++ show hasDynamic
diff --git a/testsuite/config/ghc b/testsuite/config/ghc
index 4f053eb50f4cf548e7a2285390cfa821f1b07b5f..c54ac6b3858489833ba4bdb356abd88ddefc5bdd 100644
--- a/testsuite/config/ghc
+++ b/testsuite/config/ghc
@@ -64,10 +64,6 @@ else:
 if (config.have_profiling and ghc_with_threaded_rts):
     config.run_ways.append('profthreaded')
 
-if (ghc_with_llvm and not config.unregisterised):
-    config.compile_ways.append('optllvm')
-    config.run_ways.append('optllvm')
-
 # WinIO I/O manager for Windows
 if windows:
     winio_ways = ['winio', 'winio_threaded']
@@ -195,6 +191,17 @@ def get_compiler_info():
 
     config.have_ncg = compilerInfoDict.get("Have native code generator", "NO") == "YES"
 
+    # Detect whether an LLVM toolhain is available
+    llc_path = compilerInfoDict.get("LLVM llc command")
+    config.have_llvm = shutil.which(llc_path) is not None
+    if config.unregisterised:
+        print("Unregisterised build; skipping LLVM ways...")
+    elif config.have_llvm:
+        config.compile_ways.append('optllvm')
+        config.run_ways.append('optllvm')
+    else:
+        print("Failed to find `llc` command; skipping LLVM ways...")
+
     # Whether GHC itself was built using the LLVM backend. We need to know this
     # since some tests in ext-interp fail when stage2 ghc is built using
     # LLVM. See #16087.
diff --git a/testsuite/driver/testglobals.py b/testsuite/driver/testglobals.py
index c358a660d977f35531e7b89697388d8a0538e734..629a496330c67fd942c2a89a5b2556befefb889c 100644
--- a/testsuite/driver/testglobals.py
+++ b/testsuite/driver/testglobals.py
@@ -115,6 +115,9 @@ class TestConfig:
         self.way_flags = {}  # type: Dict[WayName, List[str]]
         self.way_rts_flags = {}  # type: Dict[WayName, List[str]]
 
+        # Do we have a functional LLVM toolchain?
+        self.have_llvm = False
+
         # Do we have vanilla libraries?
         self.have_vanilla = False
 
diff --git a/testsuite/mk/test.mk b/testsuite/mk/test.mk
index 35d31229038b9356239e4f88a2199493d791fa3b..8a32ee6a428f54fb947783cd5e14422541942f33 100644
--- a/testsuite/mk/test.mk
+++ b/testsuite/mk/test.mk
@@ -194,18 +194,6 @@ else
 RUNTEST_OPTS += -e ghc_with_smp=False
 endif
 
-# Does the LLVM backend work?
-ifeq "$(LLC)" ""
-RUNTEST_OPTS += -e ghc_with_llvm=False
-else ifeq "$(TargetARCH_CPP)" "powerpc"
-RUNTEST_OPTS += -e ghc_with_llvm=False
-else ifneq "$(LLC)" "llc"
-# If we have a real detected value for LLVM, then it really ought to work
-RUNTEST_OPTS += -e ghc_with_llvm=True
-else
-RUNTEST_OPTS += -e ghc_with_llvm=False
-endif
-
 ifeq "$(WINDOWS)" "YES"
 RUNTEST_OPTS += -e windows=True
 else