From 58d80150442eb2fab0044b2aa46472120605ddd5 Mon Sep 17 00:00:00 2001
From: Sergey Fedorov <vital.had@gmail.com>
Date: Sun, 14 Dec 2025 02:37:21 +0800
Subject: [PATCH] Compat fixes for llvm-7

Revert b97a33b1cb90326ccfa1c8a9882e50cd9e6de80f

Revert 7d872f538efc5cb3786c3aa0a6654bae7a67ec63

See also 6e17a5c5fd086ebe6f57216fb3ce5d1d8d6c83e5

Revert b51bcc72d9fce469ccdcd75676d8bd35f41e5614

attributes.rs part is skipped, since llvm_target_features was removed in 72fb4379d56b93b9bd0149649a74fb4b5465ec18 and 7e443c4282df6daa9c92be7d1008c974cc5ede00

Revert 8b8e706008111fa3865e8da76eeddabfbf9851f0

Revert 8506bb006040cf8e8cb004202706c81e62ddacee
---
 compiler/rustc_codegen_llvm/src/attributes.rs |  21 +-
 compiler/rustc_codegen_llvm/src/back/write.rs |   4 +
 compiler/rustc_codegen_llvm/src/context.rs    |  17 ++
 .../src/debuginfo/metadata.rs                 |  18 +-
 compiler/rustc_codegen_llvm/src/intrinsic.rs  |  49 +++-
 compiler/rustc_codegen_llvm/src/llvm_util.rs  |  18 +-
 compiler/rustc_llvm/build.rs                  |  26 ++-
 .../llvm-wrapper/ArchiveWrapper.cpp           |   4 +
 .../rustc_llvm/llvm-wrapper/PassWrapper.cpp   | 120 +++++++++-
 .../rustc_llvm/llvm-wrapper/RustWrapper.cpp   | 210 +++++++++++++++++-
 compiler/rustc_llvm/src/lib.rs                |   5 +-
 library/core/src/num/dec2flt/algorithm.rs     |  10 +-
 library/profiler_builtins/build.rs            |   4 +-
 library/std/src/os/fortanix_sgx/arch.rs       |   6 +-
 library/std/src/sys/sgx/abi/mem.rs            |   5 +-
 src/bootstrap/native.rs                       |   4 +-
 src/test/codegen/abi-efiapi.rs                |   1 +
 src/test/codegen/enum-debug-clike.rs          |  12 +-
 src/test/codegen/enum-debug-niche-2.rs        |   7 +-
 src/test/codegen/enum-debug-niche.rs          |   6 +-
 src/test/codegen/enum-debug-tagged.rs         |   6 +-
 src/test/codegen/force-frame-pointers.rs      |   1 +
 src/test/codegen/force-unwind-tables.rs       |   1 +
 src/test/codegen/instrument-mcount.rs         |   3 +-
 .../simd-intrinsic-transmute-array.rs         |   1 +
 src/test/debuginfo/borrowed-enum.rs           |   3 +-
 src/test/debuginfo/enum-thinlto.rs            |   3 +-
 src/test/debuginfo/generator-objects.rs       |   3 +-
 .../generic-enum-with-different-disr-sizes.rs |   3 +-
 .../debuginfo/generic-struct-style-enum.rs    |   3 +-
 .../debuginfo/generic-tuple-style-enum.rs     |   3 +-
 src/test/debuginfo/issue-57822.rs             |   3 +-
 src/test/debuginfo/recursive-struct.rs        |   3 +-
 src/test/debuginfo/struct-style-enum.rs       |   3 +-
 src/test/debuginfo/tuple-style-enum.rs        |   3 +-
 src/test/debuginfo/unique-enum.rs             |   3 +-
 .../new-llvm-pass-manager-thin-lto.rs         |   1 +
 ...intrinsic-generic-arithmetic-saturating.rs |   1 +
 .../simd/simd-intrinsic-generic-reduction.rs  |   1 +
 39 files changed, 528 insertions(+), 67 deletions(-)

diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs
index f1c45d8dc36..65db02d85d1 100644
--- a/compiler/rustc_codegen_llvm/src/attributes.rs
+++ b/compiler/rustc_codegen_llvm/src/attributes.rs
@@ -71,12 +71,21 @@ fn naked(val: &'ll Value, is_naked: bool) {
 
 pub fn set_frame_pointer_elimination(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
     if cx.sess().must_not_eliminate_frame_pointers() {
-        llvm::AddFunctionAttrStringValue(
-            llfn,
-            llvm::AttributePlace::Function,
-            cstr!("frame-pointer"),
-            cstr!("all"),
-        );
+        if llvm_util::get_version() >= (8, 0, 0) {
+            llvm::AddFunctionAttrStringValue(
+                llfn,
+                llvm::AttributePlace::Function,
+                cstr!("frame-pointer"),
+                cstr!("all"),
+            );
+        } else {
+            llvm::AddFunctionAttrStringValue(
+                llfn,
+                llvm::AttributePlace::Function,
+                cstr!("no-frame-pointer-elim"),
+                cstr!("true"),
+            );
+        }
     }
 }
 
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index 5b4a187a1d5..8e1a7c0e5e1 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -407,6 +407,10 @@ fn get_pgo_use_path(config: &ModuleConfig) -> Option<CString> {
 }
 
 pub(crate) fn should_use_new_llvm_pass_manager(config: &ModuleConfig) -> bool {
+    // We only support the new pass manager starting with LLVM 9.
+    if llvm_util::get_version() < (9, 0, 0) {
+        return false;
+    }
     // The new pass manager is disabled by default.
     config.new_llvm_pass_manager.unwrap_or(false)
 }
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index 6aa952462fa..5b69d42c03e 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -101,6 +101,15 @@ fn to_llvm_tls_model(tls_model: TlsModel) -> llvm::ThreadLocalMode {
     }
 }
 
+fn strip_function_ptr_alignment(data_layout: String) -> String {
+    // FIXME: Make this more general.
+    data_layout.replace("-Fi8-", "-")
+}
+
+fn strip_x86_address_spaces(data_layout: String) -> String {
+    data_layout.replace("-p270:32:32-p271:32:32-p272:64:64-", "-")
+}
+
 fn strip_powerpc64_vectors(data_layout: String) -> String {
     data_layout.replace("-v256:256:256-v512:512:512", "")
 }
@@ -115,6 +124,14 @@ pub unsafe fn create_module(
     let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx);
 
     let mut target_data_layout = sess.target.data_layout.clone();
+    if llvm_util::get_version() < (9, 0, 0) {
+        target_data_layout = strip_function_ptr_alignment(target_data_layout);
+    }
+    if llvm_util::get_version() < (10, 0, 0)
+        && (sess.target.arch == "x86" || sess.target.arch == "x86_64")
+    {
+        target_data_layout = strip_x86_address_spaces(target_data_layout);
+    }
     if llvm_util::get_version() < (12, 0, 0) && sess.target.arch == "powerpc64" {
         target_data_layout = strip_powerpc64_vectors(target_data_layout);
     }
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index 1e70664e64d..a51acaa6161 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -16,6 +16,7 @@
     DIArray, DICompositeType, DIDescriptor, DIFile, DIFlags, DILexicalBlock, DIScope, DIType,
     DebugEmissionKind,
 };
+use crate::llvm_util;
 use crate::value::Value;
 
 use cstr::cstr;
@@ -1402,11 +1403,22 @@ fn prepare_union_metadata(
 // Enums
 //=-----------------------------------------------------------------------------
 
-/// DWARF variant support is only available starting in LLVM 8, but
-/// on MSVC we have to use the fallback mode, because LLVM doesn't
-/// lower variant parts to PDB.
+/// DWARF variant support is only available starting in LLVM 8.
+/// Although the earlier enum debug info output did not work properly
+/// in all situations, it is better for the time being to continue to
+/// sometimes emit the old style rather than emit something completely
+/// useless when rust is compiled against LLVM 6 or older. LLVM 7
+/// contains an early version of the DWARF variant support, and will
+/// crash when handling the new debug info format. This function
+/// decides which representation will be emitted.
 fn use_enum_fallback(cx: &CodegenCx<'_, '_>) -> bool {
+    // On MSVC we have to use the fallback mode, because LLVM doesn't
+    // lower variant parts to PDB.
     cx.sess().target.is_like_msvc
+        // LLVM version 7 did not release with an important bug fix;
+        // but the required patch is in the LLVM 8.  Rust LLVM reports
+        // 8 as well.
+        || llvm_util::get_version() < (8, 0, 0)
 }
 
 // FIXME(eddyb) maybe precompute this? Right now it's computed once
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index 22d513d66d1..b3e1d405d7e 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -2,6 +2,7 @@
 use crate::builder::Builder;
 use crate::context::CodegenCx;
 use crate::llvm;
+use crate::llvm_util;
 use crate::type_::Type;
 use crate::type_of::LayoutLlvmExt;
 use crate::va_arg::emit_va_arg;
@@ -270,14 +271,46 @@ fn codegen_intrinsic_call(
                             let is_add = name == sym::saturating_add;
                             let lhs = args[0].immediate();
                             let rhs = args[1].immediate();
-                            let llvm_name = &format!(
-                                "llvm.{}{}.sat.i{}",
-                                if signed { 's' } else { 'u' },
-                                if is_add { "add" } else { "sub" },
-                                width
-                            );
-                            let llfn = self.get_intrinsic(llvm_name);
-                            self.call(llfn, &[lhs, rhs], None)
+                            if llvm_util::get_version() >= (8, 0, 0) {
+                                let llvm_name = &format!(
+                                    "llvm.{}{}.sat.i{}",
+                                    if signed { 's' } else { 'u' },
+                                    if is_add { "add" } else { "sub" },
+                                    width
+                                );
+                                let llfn = self.get_intrinsic(llvm_name);
+                                self.call(llfn, &[lhs, rhs], None)
+                            } else {
+                                let llvm_name = &format!(
+                                    "llvm.{}{}.with.overflow.i{}",
+                                    if signed { 's' } else { 'u' },
+                                    if is_add { "add" } else { "sub" },
+                                    width
+                                );
+                                let llfn = self.get_intrinsic(llvm_name);
+                                let pair = self.call(llfn, &[lhs, rhs], None);
+                                let val = self.extract_value(pair, 0);
+                                let overflow = self.extract_value(pair, 1);
+                                let llty = self.type_ix(width);
+
+                                let limit = if signed {
+                                    let limit_lo = self
+                                        .const_uint_big(llty, (i128::MIN >> (128 - width)) as u128);
+                                    let limit_hi = self
+                                        .const_uint_big(llty, (i128::MAX >> (128 - width)) as u128);
+                                    let neg = self.icmp(
+                                        IntPredicate::IntSLT,
+                                        val,
+                                        self.const_uint(llty, 0),
+                                    );
+                                    self.select(neg, limit_hi, limit_lo)
+                                } else if is_add {
+                                    self.const_uint_big(llty, u128::MAX >> (128 - width))
+                                } else {
+                                    self.const_uint(llty, 0)
+                                };
+                                self.select(overflow, limit, val)
+                            }
                         }
                         _ => bug!(),
                     },
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 0dd3d2ae15b..6d2ddd50c7d 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -95,10 +95,12 @@ fn llvm_arg_to_arg_name(full_arg: &str) -> &str {
             add("-enable-machine-outliner=never", false);
         }
 
-        match sess.opts.debugging_opts.merge_functions.unwrap_or(sess.target.merge_functions) {
-            MergeFunctions::Disabled | MergeFunctions::Trampolines => {}
-            MergeFunctions::Aliases => {
-                add("-mergefunc-use-aliases", false);
+        if llvm_util::get_version() >= (8, 0, 0) {
+            match sess.opts.debugging_opts.merge_functions.unwrap_or(sess.target.merge_functions) {
+                MergeFunctions::Disabled | MergeFunctions::Trampolines => {}
+                MergeFunctions::Aliases => {
+                    add("-mergefunc-use-aliases", false);
+                }
             }
         }
 
@@ -118,7 +120,7 @@ fn llvm_arg_to_arg_name(full_arg: &str) -> &str {
         }
     }
 
-    if sess.opts.debugging_opts.llvm_time_trace {
+    if sess.opts.debugging_opts.llvm_time_trace && llvm_util::get_version() >= (9, 0, 0) {
         // time-trace is not thread safe and running it in parallel will cause seg faults.
         if !sess.opts.debugging_opts.no_parallel_llvm {
             bug!("`-Z llvm-time-trace` requires `-Z no-parallel-llvm")
@@ -136,8 +138,10 @@ fn llvm_arg_to_arg_name(full_arg: &str) -> &str {
 
 pub fn time_trace_profiler_finish(file_name: &str) {
     unsafe {
-        let file_name = CString::new(file_name).unwrap();
-        llvm::LLVMTimeTraceProfilerFinish(file_name.as_ptr());
+        if llvm_util::get_version() >= (9, 0, 0) {
+            let file_name = CString::new(file_name).unwrap();
+            llvm::LLVMTimeTraceProfilerFinish(file_name.as_ptr());
+        }
     }
 }
 
diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs
index 452d1b19a18..a4c7747381e 100644
--- a/compiler/rustc_llvm/build.rs
+++ b/compiler/rustc_llvm/build.rs
@@ -70,7 +70,7 @@ fn main() {
     let host = env::var("HOST").expect("HOST was not set");
     let is_crossed = target != host;
 
-    let optional_components = &[
+    let mut optional_components = vec![
         "x86",
         "arm",
         "aarch64",
@@ -85,10 +85,26 @@ fn main() {
         "sparc",
         "nvptx",
         "hexagon",
-        "riscv",
-        "bpf",
     ];
 
+    let mut version_cmd = Command::new(&llvm_config);
+    version_cmd.arg("--version");
+    let version_output = output(&mut version_cmd);
+    let mut parts = version_output.split('.').take(2).filter_map(|s| s.parse::<u32>().ok());
+    let (major, _minor) = if let (Some(major), Some(minor)) = (parts.next(), parts.next()) {
+        (major, minor)
+    } else {
+        (7, 0)
+    };
+
+    if major > 6 {
+        optional_components.push("riscv");
+    }
+
+    if major > 9 {
+        optional_components.push("bpf");
+    }
+
     let required_components = &[
         "ipo",
         "bitreader",
@@ -114,6 +130,10 @@ fn main() {
         println!("cargo:rustc-cfg=llvm_component=\"{}\"", component);
     }
 
+    if major >= 9 {
+        println!("cargo:rustc-cfg=llvm_has_msp430_asm_parser");
+    }
+
     // Link in our own LLVM shims, compiled with the same flags as LLVM
     let mut cmd = Command::new(&llvm_config);
     cmd.arg("--cxxflags");
diff --git a/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp
index 97541e615da..2797fe8df4a 100644
--- a/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp
@@ -91,7 +91,11 @@ extern "C" void LLVMRustDestroyArchive(LLVMRustArchiveRef RustArchive) {
 extern "C" LLVMRustArchiveIteratorRef
 LLVMRustArchiveIteratorNew(LLVMRustArchiveRef RustArchive) {
   Archive *Archive = RustArchive->getBinary();
+#if LLVM_VERSION_GE(10, 0)
   std::unique_ptr<Error> Err = std::make_unique<Error>(Error::success());
+#else
+  std::unique_ptr<Error> Err = llvm::make_unique<Error>(Error::success());
+#endif
   auto Cur = Archive->child_begin(*Err);
   if (*Err) {
     LLVMRustSetLastError(toString(std::move(*Err)).c_str());
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index 3595e37cf96..9e3e9e35ee4 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -17,7 +17,9 @@
 #include "llvm/Object/ObjectFile.h"
 #include "llvm/Object/IRObjectFile.h"
 #include "llvm/Passes/PassBuilder.h"
+#if LLVM_VERSION_GE(9, 0)
 #include "llvm/Passes/StandardInstrumentations.h"
+#endif
 #include "llvm/Support/CBindingWrapping.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Host.h"
@@ -30,14 +32,20 @@
 #include "llvm-c/Transforms/PassManagerBuilder.h"
 
 #include "llvm/Transforms/Instrumentation.h"
+#if LLVM_VERSION_GE(9, 0)
 #include "llvm/Transforms/Instrumentation/AddressSanitizer.h"
 #include "llvm/Support/TimeProfiler.h"
+#endif
 #include "llvm/Transforms/Instrumentation/GCOVProfiler.h"
 #include "llvm/Transforms/Instrumentation/InstrProfiling.h"
+#if LLVM_VERSION_GE(8, 0)
 #include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
 #include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
 #include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
+#endif
+#if LLVM_VERSION_GE(9, 0)
 #include "llvm/Transforms/Utils/CanonicalizeAliases.h"
+#endif
 #include "llvm/Transforms/Utils/NameAnonGlobals.h"
 
 using namespace llvm;
@@ -67,18 +75,24 @@ extern "C" void LLVMInitializePasses() {
 }
 
 extern "C" void LLVMTimeTraceProfilerInitialize() {
+#if LLVM_VERSION_GE(10, 0)
   timeTraceProfilerInitialize(
       /* TimeTraceGranularity */ 0,
       /* ProcName */ "rustc");
+#elif LLVM_VERSION_GE(9, 0)
+  timeTraceProfilerInitialize();
+#endif
 }
 
 extern "C" void LLVMTimeTraceProfilerFinish(const char* FileName) {
+#if LLVM_VERSION_GE(9, 0)
   StringRef FN(FileName);
   std::error_code EC;
   raw_fd_ostream OS(FN, EC, sys::fs::CD_CreateAlways);
 
   timeTraceProfilerWrite(OS);
   timeTraceProfilerCleanup();
+#endif
 }
 
 enum class LLVMRustPassKind {
@@ -119,25 +133,41 @@ extern "C" LLVMPassRef LLVMRustCreateAddressSanitizerFunctionPass(bool Recover)
 extern "C" LLVMPassRef LLVMRustCreateModuleAddressSanitizerPass(bool Recover) {
   const bool CompileKernel = false;
 
+#if LLVM_VERSION_GE(9, 0)
   return wrap(createModuleAddressSanitizerLegacyPassPass(CompileKernel, Recover));
+#else
+  return wrap(createAddressSanitizerModulePass(CompileKernel, Recover));
+#endif
 }
 
 extern "C" LLVMPassRef LLVMRustCreateMemorySanitizerPass(int TrackOrigins, bool Recover) {
+#if LLVM_VERSION_GE(9, 0)
   const bool CompileKernel = false;
 
   return wrap(createMemorySanitizerLegacyPassPass(
       MemorySanitizerOptions{TrackOrigins, Recover, CompileKernel}));
+#elif LLVM_VERSION_GE(8, 0)
+  return wrap(createMemorySanitizerLegacyPassPass(TrackOrigins, Recover));
+#else
+  return wrap(createMemorySanitizerPass(TrackOrigins, Recover));
+#endif
 }
 
 extern "C" LLVMPassRef LLVMRustCreateThreadSanitizerPass() {
+#if LLVM_VERSION_GE(8, 0)
   return wrap(createThreadSanitizerLegacyPassPass());
+#else
+  return wrap(createThreadSanitizerPass());
+#endif
 }
 
+#if LLVM_VERSION_GE(8, 0)
 extern "C" LLVMPassRef LLVMRustCreateHWAddressSanitizerPass(bool Recover) {
   const bool CompileKernel = false;
 
   return wrap(createHWAddressSanitizerLegacyPassPass(CompileKernel, Recover));
 }
+#endif
 
 extern "C" LLVMRustPassKind LLVMRustPassKind(LLVMPassRef RustPass) {
   assert(RustPass);
@@ -173,8 +203,10 @@ void LLVMRustAddLastExtensionPasses(
   // so they are run for optimized and non-optimized builds.
   unwrap(PMBR)->addExtension(PassManagerBuilder::EP_OptimizerLast,
                              AddExtensionPasses);
+#if LLVM_VERSION_GE(9, 0)
   unwrap(PMBR)->addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
                              AddExtensionPasses);
+#endif
 }
 
 #ifdef LLVM_COMPONENT_X86
@@ -284,7 +316,11 @@ enum class LLVMRustCodeModel {
 static Optional<CodeModel::Model> fromRust(LLVMRustCodeModel Model) {
   switch (Model) {
   case LLVMRustCodeModel::Tiny:
+#if LLVM_VERSION_GE(9, 0)
     return CodeModel::Tiny;
+#else
+    return CodeModel::Small;
+#endif
   case LLVMRustCodeModel::Small:
     return CodeModel::Small;
   case LLVMRustCodeModel::Kernel:
@@ -392,7 +428,11 @@ extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef TM) {
   const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
   const Triple::ArchType HostArch = Triple(sys::getProcessTriple()).getArch();
   const Triple::ArchType TargetArch = Target->getTargetTriple().getArch();
+#if LLVM_VERSION_GE(9, 0)
   const ArrayRef<SubtargetSubTypeKV> CPUTable = MCInfo->getCPUTable();
+#else
+  const ArrayRef<SubtargetFeatureKV> CPUTable = MCInfo->getCPUTable();
+#endif
   unsigned MaxCPULen = getLongestEntryLength(CPUTable);
 
   printf("Available CPUs for this target:\n");
@@ -591,6 +631,7 @@ enum class LLVMRustFileType {
   ObjectFile,
 };
 
+#if LLVM_VERSION_GE(10, 0)
 static CodeGenFileType fromRust(LLVMRustFileType Type) {
   switch (Type) {
   case LLVMRustFileType::AssemblyFile:
@@ -601,6 +642,18 @@ static CodeGenFileType fromRust(LLVMRustFileType Type) {
     report_fatal_error("Bad FileType.");
   }
 }
+#else
+static TargetMachine::CodeGenFileType fromRust(LLVMRustFileType Type) {
+  switch (Type) {
+  case LLVMRustFileType::AssemblyFile:
+    return TargetMachine::CGFT_AssemblyFile;
+  case LLVMRustFileType::ObjectFile:
+    return TargetMachine::CGFT_ObjectFile;
+  default:
+    report_fatal_error("Bad FileType.");
+  }
+}
+#endif
 
 extern "C" LLVMRustResult
 LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR,
@@ -649,6 +702,8 @@ extern "C" typedef void (*LLVMRustSelfProfileBeforePassCallback)(void*, // LlvmS
                                                       const char*);     // IR name
 extern "C" typedef void (*LLVMRustSelfProfileAfterPassCallback)(void*); // LlvmSelfProfiler
 
+#if LLVM_VERSION_GE(9, 0)
+
 std::string LLVMRustwrappedIrGetName(const llvm::Any &WrappedIr) {
   if (any_isa<const Module *>(WrappedIr))
     return any_cast<const Module *>(WrappedIr)->getName().str();
@@ -717,6 +772,8 @@ void LLVMSelfProfileInitializeCallbacks(
       });
 }
 
+#endif
+
 enum class LLVMRustOptStage {
   PreLinkNoLTO,
   PreLinkThinLTO,
@@ -732,8 +789,10 @@ struct LLVMRustSanitizerOptions {
   bool SanitizeMemoryRecover;
   int  SanitizeMemoryTrackOrigins;
   bool SanitizeThread;
+#if LLVM_VERSION_GE(8, 0)
   bool SanitizeHWAddress;
   bool SanitizeHWAddressRecover;
+#endif
 };
 
 extern "C" LLVMRustResult
@@ -752,6 +811,7 @@ LLVMRustOptimizeWithNewPassManager(
     LLVMRustSelfProfileBeforePassCallback BeforePassCallback,
     LLVMRustSelfProfileAfterPassCallback AfterPassCallback,
     const char *ExtraPasses, size_t ExtraPassesLen) {
+#if LLVM_VERSION_GE(9, 0)
   Module *TheModule = unwrap(ModuleRef);
   TargetMachine *TM = unwrap(TMRef);
   PassBuilder::OptimizationLevel OptLevel = fromRust(OptLevelRust);
@@ -876,11 +936,13 @@ LLVMRustOptimizeWithNewPassManager(
         }
       );
 #else
+#if LLVM_VERSION_GE(10, 0)
       PipelineStartEPCallbacks.push_back(
         [Options](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) {
           MPM.addPass(MemorySanitizerPass(Options));
         }
       );
+#endif
       OptimizerLastEPCallbacks.push_back(
         [Options](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) {
           FPM.addPass(MemorySanitizerPass(Options));
@@ -898,11 +960,13 @@ LLVMRustOptimizeWithNewPassManager(
         }
       );
 #else
+#if LLVM_VERSION_GE(10, 0)
       PipelineStartEPCallbacks.push_back(
         [](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) {
           MPM.addPass(ThreadSanitizerPass());
         }
       );
+#endif
       OptimizerLastEPCallbacks.push_back(
         [](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) {
           FPM.addPass(ThreadSanitizerPass());
@@ -944,6 +1008,7 @@ LLVMRustOptimizeWithNewPassManager(
       );
 #endif
     }
+#if LLVM_VERSION_GE(8, 0)
     if (SanitizerOptions->SanitizeHWAddress) {
 #if LLVM_VERSION_GE(11, 0)
       OptimizerLastEPCallbacks.push_back(
@@ -961,6 +1026,7 @@ LLVMRustOptimizeWithNewPassManager(
       );
 #endif
     }
+#endif
   }
 
 #if LLVM_VERSION_GE(13, 0)
@@ -997,11 +1063,13 @@ LLVMRustOptimizeWithNewPassManager(
 
       MPM.addPass(AlwaysInlinerPass(EmitLifetimeMarkers));
 
+# if LLVM_VERSION_GE(10, 0)
       if (PGOOpt) {
         PB.addPGOInstrPassesForO0(
             MPM, DebugPassManager, PGOOpt->Action == PGOOptions::IRInstr,
             /*IsCS=*/false, PGOOpt->ProfileFile, PGOOpt->ProfileRemappingFile);
       }
+# endif
 #endif
     } else {
 #if LLVM_VERSION_GE(12, 0)
@@ -1093,6 +1161,11 @@ LLVMRustOptimizeWithNewPassManager(
 
   MPM.run(*TheModule, MAM);
   return LLVMRustResult::Success;
+#else
+  // The new pass manager has been available for a long time,
+  // but we don't bother supporting it on old LLVM versions.
+  report_fatal_error("New pass manager only supported since LLVM 9");
+#endif
 }
 
 // Callback to demangle function name
@@ -1158,10 +1231,18 @@ public:
     const Value *Value;
     if (const CallInst *CI = dyn_cast<CallInst>(I)) {
       Name = "call";
+#if LLVM_VERSION_GE(8, 0)
       Value = CI->getCalledOperand();
+#else
+      Value = CI->getCalledValue();
+#endif
     } else if (const InvokeInst* II = dyn_cast<InvokeInst>(I)) {
       Name = "invoke";
+#if LLVM_VERSION_GE(8, 0)
       Value = II->getCalledOperand();
+#else
+      Value = II->getCalledValue();
+#endif
     } else {
       // Could demangle more operations, e. g.
       // `store %place, @function`.
@@ -1284,7 +1365,9 @@ extern "C" void LLVMRustSetModuleCodeModel(LLVMModuleRef M,
   auto CM = fromRust(Model);
   if (!CM.hasValue())
     return;
+#if LLVM_VERSION_GE(9, 0)
   unwrap(M)->setCodeModel(*CM);
+#endif
 }
 
 // Here you'll find an implementation of ThinLTO as used by the Rust compiler
@@ -1381,7 +1464,11 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules,
                           int num_modules,
                           const char **preserved_symbols,
                           int num_symbols) {
+#if LLVM_VERSION_GE(10, 0)
   auto Ret = std::make_unique<LLVMRustThinLTOData>();
+#else
+  auto Ret = llvm::make_unique<LLVMRustThinLTOData>();
+#endif
 
   // Load each module's summary and merge it into one combined index
   for (int i = 0; i < num_modules; i++) {
@@ -1414,11 +1501,15 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules,
   auto deadIsPrevailing = [&](GlobalValue::GUID G) {
     return PrevailingType::Unknown;
   };
+#if LLVM_VERSION_GE(8, 0)
   // We don't have a complete picture in our use of ThinLTO, just our immediate
   // crate, so we need `ImportEnabled = false` to limit internalization.
   // Otherwise, we sometimes lose `static` values -- see #60184.
   computeDeadSymbolsWithConstProp(Ret->Index, Ret->GUIDPreservedSymbols,
                                   deadIsPrevailing, /* ImportEnabled = */ false);
+#else
+  computeDeadSymbols(Ret->Index, Ret->GUIDPreservedSymbols, deadIsPrevailing);
+#endif
   ComputeCrossModuleImport(
     Ret->Index,
     Ret->ModuleToDefinedGVSummaries,
@@ -1455,9 +1546,13 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules,
   lto::Config conf;
   thinLTOResolvePrevailingInIndex(conf, Ret->Index, isPrevailing, recordNewLinkage,
                                   Ret->GUIDPreservedSymbols);
-#else
+#elif LLVM_VERSION_GE(9, 0)
   thinLTOResolvePrevailingInIndex(Ret->Index, isPrevailing, recordNewLinkage,
                                   Ret->GUIDPreservedSymbols);
+#elif LLVM_VERSION_GE(8, 0)
+  thinLTOResolvePrevailingInIndex(Ret->Index, isPrevailing, recordNewLinkage);
+#else
+  thinLTOResolveWeakForLinkerInIndex(Ret->Index, isPrevailing, recordNewLinkage);
 #endif
   // Here we calculate an `ExportedGUIDs` set for use in the `isExported`
   // callback below. This callback below will dictate the linkage for all
@@ -1474,6 +1569,7 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules,
         ExportedGUIDs.insert(GUID);
     }
   }
+#if LLVM_VERSION_GE(10, 0)
   auto isExported = [&](StringRef ModuleIdentifier, ValueInfo VI) {
     const auto &ExportList = Ret->ExportLists.find(ModuleIdentifier);
     return (ExportList != Ret->ExportLists.end() &&
@@ -1481,6 +1577,15 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules,
       ExportedGUIDs.count(VI.getGUID());
   };
   thinLTOInternalizeAndPromoteInIndex(Ret->Index, isExported, isPrevailing);
+#else
+  auto isExported = [&](StringRef ModuleIdentifier, GlobalValue::GUID GUID) {
+    const auto &ExportList = Ret->ExportLists.find(ModuleIdentifier);
+    return (ExportList != Ret->ExportLists.end() &&
+      ExportList->second.count(GUID)) ||
+      ExportedGUIDs.count(GUID);
+  };
+  thinLTOInternalizeAndPromoteInIndex(Ret->Index, isExported);
+#endif
 
   return Ret.release();
 }
@@ -1535,7 +1640,11 @@ extern "C" bool
 LLVMRustPrepareThinLTOResolveWeak(const LLVMRustThinLTOData *Data, LLVMModuleRef M) {
   Module &Mod = *unwrap(M);
   const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(Mod.getModuleIdentifier());
+#if LLVM_VERSION_GE(8, 0)
   thinLTOResolvePrevailingInModule(Mod, DefinedGlobals);
+#else
+  thinLTOResolveWeakForLinkerModule(Mod, DefinedGlobals);
+#endif
   return true;
 }
 
@@ -1637,7 +1746,11 @@ struct LLVMRustThinLTOBuffer {
 
 extern "C" LLVMRustThinLTOBuffer*
 LLVMRustThinLTOBufferCreate(LLVMModuleRef M) {
+#if LLVM_VERSION_GE(10, 0)
   auto Ret = std::make_unique<LLVMRustThinLTOBuffer>();
+#else
+  auto Ret = llvm::make_unique<LLVMRustThinLTOBuffer>();
+#endif
   {
     raw_string_ostream OS(Ret->data);
     {
@@ -1776,6 +1889,7 @@ LLVMRustThinLTOPatchDICompileUnit(LLVMModuleRef Mod, DICompileUnit *Unit) {
 // used during the normal linker-plugin incremental thin-LTO process.
 extern "C" void
 LLVMRustComputeLTOCacheKey(RustStringRef KeyOut, const char *ModId, LLVMRustThinLTOData *Data) {
+#if LLVM_VERSION_GE(9, 0)
   SmallString<40> Key;
   llvm::lto::Config conf;
   const auto &ImportList = Data->ImportLists.lookup(ModId);
@@ -1798,4 +1912,8 @@ LLVMRustComputeLTOCacheKey(RustStringRef KeyOut, const char *ModId, LLVMRustThin
   );
 
   LLVMRustStringWriteImpl(KeyOut, Key.c_str(), Key.size());
+#else
+  // computeLTOCacheKey doesn't exist in LLVM 7
+  LLVMRustStringWriteImpl(KeyOut, "", 0);
+#endif
 }
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index 9b757eb40c1..a62ce96d9bd 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -114,7 +114,9 @@ extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M,
   return wrap(unwrap(M)
                   ->getOrInsertFunction(StringRef(Name, NameLen),
                                         unwrap<FunctionType>(FunctionTy))
+#if LLVM_VERSION_GE(9, 0)
                   .getCallee()
+#endif
   );
 }
 
@@ -196,74 +198,175 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
   case InaccessibleMemOnly:
     return Attribute::InaccessibleMemOnly;
   case SanitizeHWAddress:
+#if LLVM_VERSION_GE(8, 0)
     return Attribute::SanitizeHWAddress;
+#else
+    report_fatal_error("SanitizeHWAddress not supported in LLVM < 8");
+#endif
   case WillReturn:
+#if LLVM_VERSION_GE(9, 0)
     return Attribute::WillReturn;
+#else
+    report_fatal_error("WillReturn not supported in LLVM < 9");
+#endif
   }
   report_fatal_error("bad AttributeKind");
 }
 
+#if LLVM_VERSION_GE(9, 0)
+  #define LLVM_CALL_INST_OR_INVOKE_BASE CallBase
+#else
+  // For LLVM < 9, we need to handle CallInst and InvokeInst separately
+  #define LLVM_CALL_INST_OR_INVOKE_BASE Instruction
+#endif
+
 extern "C" void LLVMRustAddCallSiteAttribute(LLVMValueRef Instr, unsigned Index,
                                              LLVMRustAttribute RustAttr) {
+#if LLVM_VERSION_GE(9, 0)
   CallBase *Call = unwrap<CallBase>(Instr);
   Attribute Attr = Attribute::get(Call->getContext(), fromRust(RustAttr));
   Call->addAttribute(Index, Attr);
+#else
+  Instruction *I = unwrap<Instruction>(Instr);
+  Attribute Attr = Attribute::get(I->getContext(), fromRust(RustAttr));
+  if (CallInst *CI = dyn_cast<CallInst>(I)) {
+    CI->addAttribute(Index, Attr);
+  } else if (InvokeInst *II = dyn_cast<InvokeInst>(I)) {
+    II->addAttribute(Index, Attr);
+  }
+#endif
 }
 
 extern "C" void LLVMRustAddCallSiteAttrString(LLVMValueRef Instr, unsigned Index,
                                               const char *Name) {
+#if LLVM_VERSION_GE(9, 0)
   CallBase *Call = unwrap<CallBase>(Instr);
   Attribute Attr = Attribute::get(Call->getContext(), Name);
   Call->addAttribute(Index, Attr);
+#else
+  Instruction *I = unwrap<Instruction>(Instr);
+  Attribute Attr = Attribute::get(I->getContext(), Name);
+  if (CallInst *CI = dyn_cast<CallInst>(I)) {
+    CI->addAttribute(Index, Attr);
+  } else if (InvokeInst *II = dyn_cast<InvokeInst>(I)) {
+    II->addAttribute(Index, Attr);
+  }
+#endif
 }
 
-
 extern "C" void LLVMRustAddAlignmentCallSiteAttr(LLVMValueRef Instr,
                                                  unsigned Index,
                                                  uint32_t Bytes) {
+#if LLVM_VERSION_GE(9, 0)
   CallBase *Call = unwrap<CallBase>(Instr);
   AttrBuilder B;
   B.addAlignmentAttr(Bytes);
   Call->setAttributes(Call->getAttributes().addAttributes(
       Call->getContext(), Index, B));
+#else
+  Instruction *I = unwrap<Instruction>(Instr);
+  AttrBuilder B;
+  B.addAlignmentAttr(Bytes);
+  if (CallInst *CI = dyn_cast<CallInst>(I)) {
+    CI->setAttributes(CI->getAttributes().addAttributes(
+        CI->getContext(), Index, B));
+  } else if (InvokeInst *II = dyn_cast<InvokeInst>(I)) {
+    II->setAttributes(II->getAttributes().addAttributes(
+        II->getContext(), Index, B));
+  }
+#endif
 }
 
 extern "C" void LLVMRustAddDereferenceableCallSiteAttr(LLVMValueRef Instr,
                                                        unsigned Index,
                                                        uint64_t Bytes) {
+#if LLVM_VERSION_GE(9, 0)
   CallBase *Call = unwrap<CallBase>(Instr);
   AttrBuilder B;
   B.addDereferenceableAttr(Bytes);
   Call->setAttributes(Call->getAttributes().addAttributes(
       Call->getContext(), Index, B));
+#else
+  Instruction *I = unwrap<Instruction>(Instr);
+  AttrBuilder B;
+  B.addDereferenceableAttr(Bytes);
+  if (CallInst *CI = dyn_cast<CallInst>(I)) {
+    CI->setAttributes(CI->getAttributes().addAttributes(
+        CI->getContext(), Index, B));
+  } else if (InvokeInst *II = dyn_cast<InvokeInst>(I)) {
+    II->setAttributes(II->getAttributes().addAttributes(
+        II->getContext(), Index, B));
+  }
+#endif
 }
 
 extern "C" void LLVMRustAddDereferenceableOrNullCallSiteAttr(LLVMValueRef Instr,
                                                              unsigned Index,
                                                              uint64_t Bytes) {
+#if LLVM_VERSION_GE(9, 0)
   CallBase *Call = unwrap<CallBase>(Instr);
   AttrBuilder B;
   B.addDereferenceableOrNullAttr(Bytes);
   Call->setAttributes(Call->getAttributes().addAttributes(
       Call->getContext(), Index, B));
+#else
+  Instruction *I = unwrap<Instruction>(Instr);
+  AttrBuilder B;
+  B.addDereferenceableOrNullAttr(Bytes);
+  if (CallInst *CI = dyn_cast<CallInst>(I)) {
+    CI->setAttributes(CI->getAttributes().addAttributes(
+        CI->getContext(), Index, B));
+  } else if (InvokeInst *II = dyn_cast<InvokeInst>(I)) {
+    II->setAttributes(II->getAttributes().addAttributes(
+        II->getContext(), Index, B));
+  }
+#endif
 }
 
 extern "C" void LLVMRustAddByValCallSiteAttr(LLVMValueRef Instr, unsigned Index,
                                              LLVMTypeRef Ty) {
+#if LLVM_VERSION_GE(9, 0)
   CallBase *Call = unwrap<CallBase>(Instr);
   Attribute Attr = Attribute::getWithByValType(Call->getContext(), unwrap(Ty));
   Call->addAttribute(Index, Attr);
+#elif LLVM_VERSION_GE(8, 0)
+  Instruction *I = unwrap<Instruction>(Instr);
+  Attribute Attr = Attribute::get(I->getContext(), Attribute::ByVal);
+  if (CallInst *CI = dyn_cast<CallInst>(I)) {
+    CI->addAttribute(Index, Attr);
+  } else if (InvokeInst *II = dyn_cast<InvokeInst>(I)) {
+    II->addAttribute(Index, Attr);
+  }
+#else
+  Instruction *I = unwrap<Instruction>(Instr);
+  Attribute Attr = Attribute::get(I->getContext(), Attribute::ByVal);
+  if (CallInst *CI = dyn_cast<CallInst>(I)) {
+    CI->addAttribute(Index, Attr);
+  } else if (InvokeInst *II = dyn_cast<InvokeInst>(I)) {
+    II->addAttribute(Index, Attr);
+  }
+#endif
 }
 
 extern "C" void LLVMRustAddStructRetCallSiteAttr(LLVMValueRef Instr, unsigned Index,
                                                  LLVMTypeRef Ty) {
-  CallBase *Call = unwrap<CallBase>(Instr);
 #if LLVM_VERSION_GE(12, 0)
+  CallBase *Call = unwrap<CallBase>(Instr);
   Attribute Attr = Attribute::getWithStructRetType(Call->getContext(), unwrap(Ty));
-#else
+  Call->addAttribute(Index, Attr);
+#elif LLVM_VERSION_GE(9, 0)
+  CallBase *Call = unwrap<CallBase>(Instr);
   Attribute Attr = Attribute::get(Call->getContext(), Attribute::StructRet);
-#endif
   Call->addAttribute(Index, Attr);
+#else
+  Instruction *I = unwrap<Instruction>(Instr);
+  Attribute Attr = Attribute::get(I->getContext(), Attribute::StructRet);
+  if (CallInst *CI = dyn_cast<CallInst>(I)) {
+    CI->addAttribute(Index, Attr);
+  } else if (InvokeInst *II = dyn_cast<InvokeInst>(I)) {
+    II->addAttribute(Index, Attr);
+  }
+#endif
 }
 
 extern "C" void LLVMRustAddFunctionAttribute(LLVMValueRef Fn, unsigned Index,
@@ -303,7 +406,11 @@ extern "C" void LLVMRustAddDereferenceableOrNullAttr(LLVMValueRef Fn,
 extern "C" void LLVMRustAddByValAttr(LLVMValueRef Fn, unsigned Index,
                                      LLVMTypeRef Ty) {
   Function *F = unwrap<Function>(Fn);
+#if LLVM_VERSION_GE(9, 0)
   Attribute Attr = Attribute::getWithByValType(F->getContext(), unwrap(Ty));
+#else
+  Attribute Attr = Attribute::get(F->getContext(), Attribute::ByVal);
+#endif
   F->addAttribute(Index, Attr);
 }
 
@@ -533,6 +640,11 @@ static DINode::DIFlags fromRust(LLVMRustDIFlags Flags) {
   if (isSet(Flags & LLVMRustDIFlags::FlagAppleBlock)) {
     Result |= DINode::DIFlags::FlagAppleBlock;
   }
+#if LLVM_VERSION_LT(10, 0)
+  if (isSet(Flags & LLVMRustDIFlags::FlagBlockByrefStruct)) {
+    Result |= DINode::DIFlags::FlagBlockByrefStruct;
+  }
+#endif
   if (isSet(Flags & LLVMRustDIFlags::FlagVirtual)) {
     Result |= DINode::DIFlags::FlagVirtual;
   }
@@ -612,6 +724,7 @@ inline LLVMRustDISPFlags virtuality(LLVMRustDISPFlags F) {
   return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(F) & 0x3);
 }
 
+#if LLVM_VERSION_GE(8, 0)
 static DISubprogram::DISPFlags fromRust(LLVMRustDISPFlags SPFlags) {
   DISubprogram::DISPFlags Result = DISubprogram::DISPFlags::SPFlagZero;
 
@@ -636,12 +749,15 @@ static DISubprogram::DISPFlags fromRust(LLVMRustDISPFlags SPFlags) {
   if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagOptimized)) {
     Result |= DISubprogram::DISPFlags::SPFlagOptimized;
   }
+#if LLVM_VERSION_GE(9, 0)
   if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagMainSubprogram)) {
     Result |= DISubprogram::DISPFlags::SPFlagMainSubprogram;
   }
+#endif
 
   return Result;
 }
+#endif
 
 enum class LLVMRustDebugEmissionKind {
   NoDebug,
@@ -763,8 +879,13 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
     LLVMMetadataRef Decl) {
   DITemplateParameterArray TParams =
       DITemplateParameterArray(unwrap<MDTuple>(TParam));
+#if LLVM_VERSION_GE(8, 0)
   DISubprogram::DISPFlags llvmSPFlags = fromRust(SPFlags);
   DINode::DIFlags llvmFlags = fromRust(Flags);
+#if LLVM_VERSION_LT(9, 0)
+  if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagMainSubprogram))
+    llvmFlags |= DINode::DIFlags::FlagMainSubprogram;
+#endif
   DISubprogram *Sub = Builder->createFunction(
       unwrapDI<DIScope>(Scope),
       StringRef(Name, NameLen),
@@ -772,6 +893,22 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
       unwrapDI<DIFile>(File), LineNo,
       unwrapDI<DISubroutineType>(Ty), ScopeLine, llvmFlags,
       llvmSPFlags, TParams, unwrapDIPtr<DISubprogram>(Decl));
+#else
+  bool IsLocalToUnit = isSet(SPFlags & LLVMRustDISPFlags::SPFlagLocalToUnit);
+  bool IsDefinition = isSet(SPFlags & LLVMRustDISPFlags::SPFlagDefinition);
+  bool IsOptimized = isSet(SPFlags & LLVMRustDISPFlags::SPFlagOptimized);
+  DINode::DIFlags llvmFlags = fromRust(Flags);
+  if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagMainSubprogram))
+    llvmFlags |= DINode::DIFlags::FlagMainSubprogram;
+  DISubprogram *Sub = Builder->createFunction(
+      unwrapDI<DIScope>(Scope),
+      StringRef(Name, NameLen),
+      StringRef(LinkageName, LinkageNameLen),
+      unwrapDI<DIFile>(File), LineNo,
+      unwrapDI<DISubroutineType>(Ty), IsLocalToUnit, IsDefinition,
+      ScopeLine, llvmFlags, IsOptimized, TParams,
+      unwrapDIPtr<DISubprogram>(Decl));
+#endif
   if (MaybeFn)
     unwrap<Function>(MaybeFn)->setSubprogram(Sub);
   return wrap(Sub);
@@ -897,9 +1034,13 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
       unwrapDI<DIDescriptor>(Context), StringRef(Name, NameLen),
       StringRef(LinkageName, LinkageNameLen),
       unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), IsLocalToUnit,
+#if LLVM_VERSION_GE(10, 0)
       /* isDefined */ true,
+#endif
       InitExpr, unwrapDIPtr<MDNode>(Decl),
+#if LLVM_VERSION_GE(8, 0)
       /* templateParams */ nullptr,
+#endif
       AlignInBits);
 
   InitVal->setMetadata("dbg", VarExpr);
@@ -1097,7 +1238,11 @@ extern "C" void LLVMRustUnpackOptimizationDiagnostic(
   if (loc.isValid()) {
     *Line = loc.getLine();
     *Column = loc.getColumn();
+#if LLVM_VERSION_GE(8, 0)
     FilenameOS << loc.getAbsolutePath();
+#else
+    FilenameOS << loc.getFilename();
+#endif
   }
 
   RawRustStringOstream MessageOS(MessageOut);
@@ -1400,8 +1545,18 @@ extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMValueRef Fn,
   FunctionType *FTy = cast<FunctionType>(Callee->getType()->getPointerElementType());
   unsigned Len = Bundle ? 1 : 0;
   ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
+#if LLVM_VERSION_GE(8, 0)
   return wrap(unwrap(B)->CreateCall(
       FTy, Callee, makeArrayRef(unwrap(Args), NumArgs), Bundles));
+#else
+  if (Len > 0) {
+    return wrap(unwrap(B)->CreateCall(
+        Callee, makeArrayRef(unwrap(Args), NumArgs), Bundles));
+  } else {
+    return wrap(unwrap(B)->CreateCall(
+        Callee, makeArrayRef(unwrap(Args), NumArgs)));
+  }
+#endif
 }
 
 extern "C" LLVMValueRef LLVMRustGetInstrProfIncrementIntrinsic(LLVMModuleRef M) {
@@ -1413,28 +1568,47 @@ extern "C" LLVMValueRef LLVMRustBuildMemCpy(LLVMBuilderRef B,
                                             LLVMValueRef Dst, unsigned DstAlign,
                                             LLVMValueRef Src, unsigned SrcAlign,
                                             LLVMValueRef Size, bool IsVolatile) {
+#if LLVM_VERSION_GE(10, 0)
   return wrap(unwrap(B)->CreateMemCpy(
       unwrap(Dst), MaybeAlign(DstAlign),
       unwrap(Src), MaybeAlign(SrcAlign),
       unwrap(Size), IsVolatile));
+#else
+  return wrap(unwrap(B)->CreateMemCpy(
+      unwrap(Dst), DstAlign,
+      unwrap(Src), SrcAlign,
+      unwrap(Size), IsVolatile));
+#endif
 }
 
 extern "C" LLVMValueRef LLVMRustBuildMemMove(LLVMBuilderRef B,
                                              LLVMValueRef Dst, unsigned DstAlign,
                                              LLVMValueRef Src, unsigned SrcAlign,
                                              LLVMValueRef Size, bool IsVolatile) {
+#if LLVM_VERSION_GE(10, 0)
   return wrap(unwrap(B)->CreateMemMove(
       unwrap(Dst), MaybeAlign(DstAlign),
       unwrap(Src), MaybeAlign(SrcAlign),
       unwrap(Size), IsVolatile));
+#else
+  return wrap(unwrap(B)->CreateMemMove(
+      unwrap(Dst), DstAlign,
+      unwrap(Src), SrcAlign,
+      unwrap(Size), IsVolatile));
+#endif
 }
 
 extern "C" LLVMValueRef LLVMRustBuildMemSet(LLVMBuilderRef B,
                                             LLVMValueRef Dst, unsigned DstAlign,
                                             LLVMValueRef Val,
                                             LLVMValueRef Size, bool IsVolatile) {
+#if LLVM_VERSION_GE(10, 0)
   return wrap(unwrap(B)->CreateMemSet(
       unwrap(Dst), unwrap(Val), unwrap(Size), MaybeAlign(DstAlign), IsVolatile));
+#else
+  return wrap(unwrap(B)->CreateMemSet(
+      unwrap(Dst), unwrap(Val), unwrap(Size), DstAlign, IsVolatile));
+#endif
 }
 
 extern "C" LLVMValueRef
@@ -1446,9 +1620,21 @@ LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,
   FunctionType *FTy = cast<FunctionType>(Callee->getType()->getPointerElementType());
   unsigned Len = Bundle ? 1 : 0;
   ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
+#if LLVM_VERSION_GE(8, 0)
   return wrap(unwrap(B)->CreateInvoke(FTy, Callee, unwrap(Then), unwrap(Catch),
                                       makeArrayRef(unwrap(Args), NumArgs),
                                       Bundles, Name));
+#else
+  if (Len > 0) {
+    return wrap(unwrap(B)->CreateInvoke(Callee, unwrap(Then), unwrap(Catch),
+                                        makeArrayRef(unwrap(Args), NumArgs),
+                                        Bundles, Name));
+  } else {
+    return wrap(unwrap(B)->CreateInvoke(Callee, unwrap(Then), unwrap(Catch),
+                                        makeArrayRef(unwrap(Args), NumArgs),
+                                        Name));
+  }
+#endif
 }
 
 extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B,
@@ -1624,7 +1810,11 @@ struct LLVMRustModuleBuffer {
 
 extern "C" LLVMRustModuleBuffer*
 LLVMRustModuleBufferCreate(LLVMModuleRef M) {
+#if LLVM_VERSION_GE(10, 0)
   auto Ret = std::make_unique<LLVMRustModuleBuffer>();
+#else
+  auto Ret = llvm::make_unique<LLVMRustModuleBuffer>();
+#endif
   {
     raw_string_ostream OS(Ret->data);
     {
@@ -1744,6 +1934,7 @@ extern "C" LLVMRustResult LLVMRustWriteImportLibrary(
   ConvertedExports.reserve(NumExports);
 
   for (size_t i = 0; i < NumExports; ++i) {
+#if LLVM_VERSION_GE(8, 0)
     ConvertedExports.push_back(llvm::object::COFFShortExport{
       Exports[i].name,  // Name
       std::string{},    // ExtName
@@ -1755,6 +1946,17 @@ extern "C" LLVMRustResult LLVMRustWriteImportLibrary(
       false,            // Private
       false             // Constant
     });
+#else
+    llvm::object::COFFShortExport exp;
+    exp.Name = Exports[i].name;
+    exp.ExtName = "";
+    exp.Ordinal = 0;
+    exp.Noname = false;
+    exp.Data = false;
+    exp.Private = false;
+    exp.Constant = false;
+    ConvertedExports.push_back(exp);
+#endif
   }
 
   auto Error = llvm::object::writeImportLibrary(
diff --git a/compiler/rustc_llvm/src/lib.rs b/compiler/rustc_llvm/src/lib.rs
index 122627eb500..dc21f75ec80 100644
--- a/compiler/rustc_llvm/src/lib.rs
+++ b/compiler/rustc_llvm/src/lib.rs
@@ -125,7 +125,10 @@ fn init() { }
         LLVMInitializeMSP430TargetInfo,
         LLVMInitializeMSP430Target,
         LLVMInitializeMSP430TargetMC,
-        LLVMInitializeMSP430AsmPrinter,
+        LLVMInitializeMSP430AsmPrinter
+    );
+    init_target!(
+        all(llvm_component = "msp430", llvm_has_msp430_asm_parser),
         LLVMInitializeMSP430AsmParser
     );
     init_target!(
diff --git a/library/core/src/num/dec2flt/algorithm.rs b/library/core/src/num/dec2flt/algorithm.rs
index 313b6870ac9..38554b460cd 100644
--- a/library/core/src/num/dec2flt/algorithm.rs
+++ b/library/core/src/num/dec2flt/algorithm.rs
@@ -62,9 +62,10 @@ fn set_cw(cw: u16) {
         // any `u16`
         unsafe {
             asm!(
-                "fldcw word ptr [{}]",
+                "fldcw ({})",
                 in(reg) &cw,
-                options(nostack),
+                // We are using ATT syntax to support LLVM 8 and LLVM 9.
+                options(att_syntax, nostack),
             )
         }
     }
@@ -86,9 +87,10 @@ pub fn set_precision<T>() -> FPUControlWord {
         // any `u16`
         unsafe {
             asm!(
-                "fnstcw word ptr [{}]",
+                "fnstcw ({})",
                 in(reg) &mut cw,
-                options(nostack),
+                // We are using ATT syntax to support LLVM 8 and LLVM 9.
+                options(att_syntax, nostack),
             )
         }
 
diff --git a/library/profiler_builtins/build.rs b/library/profiler_builtins/build.rs
index 1b1f11798d7..2de6db762b2 100644
--- a/library/profiler_builtins/build.rs
+++ b/library/profiler_builtins/build.rs
@@ -24,11 +24,13 @@ fn main() {
         "InstrProfilingPlatformLinux.c",
         "InstrProfilingPlatformOther.c",
         "InstrProfilingPlatformWindows.c",
-        "InstrProfilingRuntime.cpp",
         "InstrProfilingUtil.c",
         "InstrProfilingValue.c",
         "InstrProfilingVersionVar.c",
         "InstrProfilingWriter.c",
+        // This file was renamed in LLVM 10.
+        "InstrProfilingRuntime.cc",
+        "InstrProfilingRuntime.cpp",
         // These files were added in LLVM 11.
         "InstrProfilingInternal.c",
         "InstrProfilingBiasVar.c",
diff --git a/library/std/src/os/fortanix_sgx/arch.rs b/library/std/src/os/fortanix_sgx/arch.rs
index b0170e67446..971cf1ee726 100644
--- a/library/std/src/os/fortanix_sgx/arch.rs
+++ b/library/std/src/os/fortanix_sgx/arch.rs
@@ -39,7 +39,8 @@
             inout(reg) request => _,
             inlateout("eax") ENCLU_EGETKEY => error,
             in("rcx") out.as_mut_ptr(),
-            options(nostack),
+            // NOTE(#76738): ATT syntax is used to support LLVM 8 and 9.
+            options(att_syntax, nostack),
         );
 
         match error {
@@ -71,7 +72,8 @@ pub fn ereport(
             in("eax") ENCLU_EREPORT,
             in("rcx") reportdata,
             in("rdx") report.as_mut_ptr(),
-            options(preserves_flags, nostack),
+            // NOTE(#76738): ATT syntax is used to support LLVM 8 and 9.
+            options(att_syntax, preserves_flags, nostack),
         );
 
         report.assume_init()
diff --git a/library/std/src/sys/sgx/abi/mem.rs b/library/std/src/sys/sgx/abi/mem.rs
index 1e743894a9f..3753fdd3536 100644
--- a/library/std/src/sys/sgx/abi/mem.rs
+++ b/library/std/src/sys/sgx/abi/mem.rs
@@ -36,9 +36,10 @@ pub fn image_base() -> u64 {
     let base: u64;
     unsafe {
         asm!(
-            "lea {}, qword ptr [rip + IMAGE_BASE]",
+            "lea IMAGE_BASE(%rip), {}",
             lateout(reg) base,
-            options(nostack, preserves_flags, nomem, pure),
+            // NOTE(#76738): ATT syntax is used to support LLVM 8 and 9.
+            options(att_syntax, nostack, preserves_flags, nomem, pure),
         )
     };
     base
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index 449fdb87b02..d4b3f8b7831 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -347,11 +347,11 @@ fn check_llvm_version(builder: &Builder<'_>, llvm_config: &Path) {
     let version = output(cmd.arg("--version"));
     let mut parts = version.split('.').take(2).filter_map(|s| s.parse::<u32>().ok());
     if let (Some(major), Some(_minor)) = (parts.next(), parts.next()) {
-        if major >= 10 {
+        if major >= 7 {
             return;
         }
     }
-    panic!("\n\nbad LLVM version: {}, need >=10.0\n\n", version)
+    panic!("\n\nbad LLVM version: {}, need >=7.0\n\n", version)
 }
 
 fn configure_cmake(
diff --git a/src/test/codegen/abi-efiapi.rs b/src/test/codegen/abi-efiapi.rs
index 613b0bf50e5..19bbf840045 100644
--- a/src/test/codegen/abi-efiapi.rs
+++ b/src/test/codegen/abi-efiapi.rs
@@ -1,6 +1,7 @@
 // Checks if the correct annotation for the efiapi ABI is passed to llvm.
 
 // revisions:x86_64 i686 aarch64 arm riscv
+// min-llvm-version: 9.0
 // needs-llvm-components: aarch64 arm riscv
 
 //[x86_64] compile-flags: --target x86_64-unknown-uefi
diff --git a/src/test/codegen/enum-debug-clike.rs b/src/test/codegen/enum-debug-clike.rs
index 1e369a2c4e6..6ac01d05603 100644
--- a/src/test/codegen/enum-debug-clike.rs
+++ b/src/test/codegen/enum-debug-clike.rs
@@ -1,13 +1,17 @@
-// This tests that debug info for "c-like" enums is properly emitted.
-// This is ignored for the fallback mode on MSVC due to problems with PDB.
+// This test depends on a patch that was committed to upstream LLVM
+// before 7.0, then backported to the Rust LLVM fork.  It tests that
+// debug info for "c-like" enums is properly emitted.
 
-//
 // ignore-msvc
+// min-system-llvm-version 8.0
 
 // compile-flags: -g -C no-prepopulate-passes
 
+// DIFlagFixedEnum was deprecated in 8.0, renamed to DIFlagEnumClass.
+// We match either for compatibility.
+
 // CHECK-LABEL: @main
-// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_enumeration_type,{{.*}}name: "E",{{.*}}flags: DIFlagEnumClass,{{.*}}
+// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_enumeration_type,{{.*}}name: "E",{{.*}}flags: {{(DIFlagEnumClass|DIFlagFixedEnum)}},{{.*}}
 // CHECK: {{.*}}DIEnumerator{{.*}}name: "A",{{.*}}value: {{[0-9].*}}
 // CHECK: {{.*}}DIEnumerator{{.*}}name: "B",{{.*}}value: {{[0-9].*}}
 // CHECK: {{.*}}DIEnumerator{{.*}}name: "C",{{.*}}value: {{[0-9].*}}
diff --git a/src/test/codegen/enum-debug-niche-2.rs b/src/test/codegen/enum-debug-niche-2.rs
index 9c72ad9d248..6143ba7f556 100644
--- a/src/test/codegen/enum-debug-niche-2.rs
+++ b/src/test/codegen/enum-debug-niche-2.rs
@@ -1,8 +1,9 @@
-// This tests that optimized enum debug info accurately reflects the enum layout.
-// This is ignored for the fallback mode on MSVC due to problems with PDB.
+// This test depends on a patch that was committed to upstream LLVM
+// before 7.0, then backported to the Rust LLVM fork.  It tests that
+// optimized enum debug info accurately reflects the enum layout.
 
-//
 // ignore-msvc
+// min-system-llvm-version 8.0
 
 // compile-flags: -g -C no-prepopulate-passes
 
diff --git a/src/test/codegen/enum-debug-niche.rs b/src/test/codegen/enum-debug-niche.rs
index b718a6854dd..737335a5081 100644
--- a/src/test/codegen/enum-debug-niche.rs
+++ b/src/test/codegen/enum-debug-niche.rs
@@ -1,7 +1,9 @@
-// This tests that optimized enum debug info accurately reflects the enum layout.
-// This is ignored for the fallback mode on MSVC due to problems with PDB.
+// This test depends on a patch that was committed to upstream LLVM
+// before 7.0, then backported to the Rust LLVM fork.  It tests that
+// optimized enum debug info accurately reflects the enum layout.
 
 // ignore-msvc
+// min-system-llvm-version 8.0
 
 // compile-flags: -g -C no-prepopulate-passes
 
diff --git a/src/test/codegen/enum-debug-tagged.rs b/src/test/codegen/enum-debug-tagged.rs
index 095c49ac3ac..e3b5e62d4ba 100644
--- a/src/test/codegen/enum-debug-tagged.rs
+++ b/src/test/codegen/enum-debug-tagged.rs
@@ -1,6 +1,8 @@
-// This tests that debug info for tagged (ordinary) enums is properly emitted.
-// This is ignored for the fallback mode on MSVC due to problems with PDB.
+// This test depends on a patch that was committed to upstream LLVM
+// before 7.0, then backported to the Rust LLVM fork.  It tests that
+// debug info for tagged (ordinary) enums is properly emitted.
 
+// min-system-llvm-version 8.0
 // ignore-msvc
 
 // compile-flags: -g -C no-prepopulate-passes
diff --git a/src/test/codegen/force-frame-pointers.rs b/src/test/codegen/force-frame-pointers.rs
index 637c4234654..4c94a601f33 100644
--- a/src/test/codegen/force-frame-pointers.rs
+++ b/src/test/codegen/force-frame-pointers.rs
@@ -1,3 +1,4 @@
+// min-llvm-version 8.0
 // compile-flags: -C no-prepopulate-passes -C force-frame-pointers=y
 
 #![crate_type="lib"]
diff --git a/src/test/codegen/force-unwind-tables.rs b/src/test/codegen/force-unwind-tables.rs
index 4c0a5602c6d..eba4a7469f9 100644
--- a/src/test/codegen/force-unwind-tables.rs
+++ b/src/test/codegen/force-unwind-tables.rs
@@ -1,3 +1,4 @@
+// min-llvm-version: 8.0
 // compile-flags: -C no-prepopulate-passes -C force-unwind-tables=y
 
 #![crate_type="lib"]
diff --git a/src/test/codegen/instrument-mcount.rs b/src/test/codegen/instrument-mcount.rs
index b26076e7a7b..e4e6d5ca2b8 100644
--- a/src/test/codegen/instrument-mcount.rs
+++ b/src/test/codegen/instrument-mcount.rs
@@ -1,4 +1,5 @@
-//
+// min-llvm-version 8.0
+// ignore-tidy-linelength
 // compile-flags: -Z instrument-mcount
 
 #![crate_type = "lib"]
diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs
index 7d9b0d2a77b..63b1ebdad9e 100644
--- a/src/test/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs
+++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs
@@ -1,5 +1,6 @@
 //
 // compile-flags: -C no-prepopulate-passes
+// min-llvm-version 8.0
 
 #![crate_type = "lib"]
 
diff --git a/src/test/debuginfo/borrowed-enum.rs b/src/test/debuginfo/borrowed-enum.rs
index f3e465dc652..273e6b9b977 100644
--- a/src/test/debuginfo/borrowed-enum.rs
+++ b/src/test/debuginfo/borrowed-enum.rs
@@ -1,4 +1,5 @@
-// Require a gdb or lldb that can read DW_TAG_variant_part.
+// Require LLVM with DW_TAG_variant_part and a gdb or lldb that can read it.
+// min-system-llvm-version: 8.0
 // min-gdb-version: 8.2
 // rust-lldb
 
diff --git a/src/test/debuginfo/enum-thinlto.rs b/src/test/debuginfo/enum-thinlto.rs
index b10e04a4a9e..de8dfb12dc4 100644
--- a/src/test/debuginfo/enum-thinlto.rs
+++ b/src/test/debuginfo/enum-thinlto.rs
@@ -1,4 +1,5 @@
-// Require a gdb that can read DW_TAG_variant_part.
+// Require LLVM with DW_TAG_variant_part and a gdb that can read it.
+// min-system-llvm-version: 8.0
 // min-gdb-version: 8.2
 
 // compile-flags:-g -Z thinlto
diff --git a/src/test/debuginfo/generator-objects.rs b/src/test/debuginfo/generator-objects.rs
index 1beed1c835d..2c36adc1621 100644
--- a/src/test/debuginfo/generator-objects.rs
+++ b/src/test/debuginfo/generator-objects.rs
@@ -1,4 +1,5 @@
-// Require a gdb that can read DW_TAG_variant_part.
+// Require LLVM with DW_TAG_variant_part and a gdb that can read it.
+// min-system-llvm-version: 8.0
 // min-gdb-version: 8.2
 
 // LLDB without native Rust support cannot read DW_TAG_variant_part,
diff --git a/src/test/debuginfo/generic-enum-with-different-disr-sizes.rs b/src/test/debuginfo/generic-enum-with-different-disr-sizes.rs
index adcb04da30d..72d38a6f045 100644
--- a/src/test/debuginfo/generic-enum-with-different-disr-sizes.rs
+++ b/src/test/debuginfo/generic-enum-with-different-disr-sizes.rs
@@ -1,7 +1,8 @@
 // ignore-lldb: FIXME(#27089)
 // min-lldb-version: 310
 
-// Require a gdb that can read DW_TAG_variant_part.
+// Require LLVM with DW_TAG_variant_part and a gdb that can read it.
+// min-system-llvm-version: 8.0
 // min-gdb-version: 8.2
 
 // compile-flags:-g
diff --git a/src/test/debuginfo/generic-struct-style-enum.rs b/src/test/debuginfo/generic-struct-style-enum.rs
index 764330ae27f..3fae6a239a4 100644
--- a/src/test/debuginfo/generic-struct-style-enum.rs
+++ b/src/test/debuginfo/generic-struct-style-enum.rs
@@ -1,6 +1,7 @@
 // min-lldb-version: 310
 
-// Require a gdb that can read DW_TAG_variant_part.
+// Require LLVM with DW_TAG_variant_part and a gdb that can read it.
+// min-system-llvm-version: 8.0
 // min-gdb-version: 8.2
 
 // compile-flags:-g
diff --git a/src/test/debuginfo/generic-tuple-style-enum.rs b/src/test/debuginfo/generic-tuple-style-enum.rs
index 60362e54e7d..5b57750718d 100644
--- a/src/test/debuginfo/generic-tuple-style-enum.rs
+++ b/src/test/debuginfo/generic-tuple-style-enum.rs
@@ -1,4 +1,5 @@
-// Require a gdb or lldb that can read DW_TAG_variant_part.
+// Require LLVM with DW_TAG_variant_part and a gdb and lldb that can read it.
+// min-system-llvm-version: 8.0
 // min-gdb-version: 8.2
 // rust-lldb
 
diff --git a/src/test/debuginfo/issue-57822.rs b/src/test/debuginfo/issue-57822.rs
index 6b2b12edda5..59985db1c3d 100644
--- a/src/test/debuginfo/issue-57822.rs
+++ b/src/test/debuginfo/issue-57822.rs
@@ -1,7 +1,8 @@
 // This test makes sure that the LLDB pretty printer does not throw an exception
 // for nested closures and generators.
 
-// Require a gdb that can read DW_TAG_variant_part.
+// Require LLVM with DW_TAG_variant_part and a gdb that can read it.
+// min-system-llvm-version: 8.0
 // min-gdb-version: 8.2
 
 // compile-flags:-g
diff --git a/src/test/debuginfo/recursive-struct.rs b/src/test/debuginfo/recursive-struct.rs
index c0bd6736701..4f75ef4fa9b 100644
--- a/src/test/debuginfo/recursive-struct.rs
+++ b/src/test/debuginfo/recursive-struct.rs
@@ -1,6 +1,7 @@
 // ignore-lldb
 
-// Require a gdb that can read DW_TAG_variant_part.
+// Require LLVM with DW_TAG_variant_part and a gdb that can read it.
+// min-system-llvm-version: 8.0
 // min-gdb-version: 8.2
 
 // compile-flags:-g
diff --git a/src/test/debuginfo/struct-style-enum.rs b/src/test/debuginfo/struct-style-enum.rs
index 3d819e36898..465471010ba 100644
--- a/src/test/debuginfo/struct-style-enum.rs
+++ b/src/test/debuginfo/struct-style-enum.rs
@@ -1,4 +1,5 @@
-// Require a gdb or lldb that can read DW_TAG_variant_part.
+// Require LLVM with DW_TAG_variant_part and a gdb and lldb that can read it.
+// min-system-llvm-version: 8.0
 // min-gdb-version: 8.2
 // rust-lldb
 
diff --git a/src/test/debuginfo/tuple-style-enum.rs b/src/test/debuginfo/tuple-style-enum.rs
index 39ead172e65..d26fc08f202 100644
--- a/src/test/debuginfo/tuple-style-enum.rs
+++ b/src/test/debuginfo/tuple-style-enum.rs
@@ -1,4 +1,5 @@
-// Require a gdb or lldb that can read DW_TAG_variant_part.
+// Require LLVM with DW_TAG_variant_part and a gdb and lldb that can read it.
+// min-system-llvm-version: 8.0
 // min-gdb-version: 8.2
 // rust-lldb
 
diff --git a/src/test/debuginfo/unique-enum.rs b/src/test/debuginfo/unique-enum.rs
index 9d938b6e369..2be94574943 100644
--- a/src/test/debuginfo/unique-enum.rs
+++ b/src/test/debuginfo/unique-enum.rs
@@ -1,4 +1,5 @@
-// Require a gdb or lldb that can read DW_TAG_variant_part.
+// Require LLVM with DW_TAG_variant_part and a gdb and lldb that can read it.
+// min-system-llvm-version: 8.0
 // min-gdb-version: 8.2
 // rust-lldb
 
diff --git a/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs b/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs
index 1542c7f3118..9439df266d5 100644
--- a/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs
+++ b/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs
@@ -2,6 +2,7 @@
 // being run when compiling with new LLVM pass manager and ThinLTO.
 // Note: The issue occurred only on non-zero opt-level.
 //
+// min-llvm-version: 9.0
 // needs-sanitizer-support
 // needs-sanitizer-address
 //
diff --git a/src/test/ui/simd/simd-intrinsic-generic-arithmetic-saturating.rs b/src/test/ui/simd/simd-intrinsic-generic-arithmetic-saturating.rs
index c11d14b99d4..f4627028cfa 100644
--- a/src/test/ui/simd/simd-intrinsic-generic-arithmetic-saturating.rs
+++ b/src/test/ui/simd/simd-intrinsic-generic-arithmetic-saturating.rs
@@ -1,5 +1,6 @@
 // run-pass
 // ignore-emscripten
+// min-llvm-version 8.0
 
 #![allow(non_camel_case_types)]
 #![feature(repr_simd, platform_intrinsics)]
diff --git a/src/test/ui/simd/simd-intrinsic-generic-reduction.rs b/src/test/ui/simd/simd-intrinsic-generic-reduction.rs
index 7193fb3527f..8b5afeac0bc 100644
--- a/src/test/ui/simd/simd-intrinsic-generic-reduction.rs
+++ b/src/test/ui/simd/simd-intrinsic-generic-reduction.rs
@@ -2,6 +2,7 @@
 #![allow(non_camel_case_types)]
 
 // ignore-emscripten
+// min-system-llvm-version: 9.0
 
 // Test that the simd_reduce_{op} intrinsics produce the correct results.
 
