diff --git a/Cargo.lock b/Cargo.lock
index 529e17b158fc8..4c02b21dd71e9 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3433,7 +3433,6 @@ version = "0.0.0"
 dependencies = [
  "rustc_ast",
  "rustc_span",
- "tracing",
 ]
 
 [[package]]
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index d0732b35b6e9e..565488ab6a52d 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -2006,7 +2006,7 @@ bitflags::bitflags! {
     }
 }
 
-#[derive(Clone, PartialEq, PartialOrd, Encodable, Decodable, Debug, Hash, HashStable_Generic)]
+#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Hash, HashStable_Generic)]
 pub enum InlineAsmTemplatePiece {
     String(String),
     Placeholder { operand_idx: usize, modifier: Option<char>, span: Span },
@@ -2211,7 +2211,7 @@ pub enum IsAuto {
     No,
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Encodable, Decodable, Debug)]
 #[derive(HashStable_Generic)]
 pub enum Unsafe {
     Yes(Span),
diff --git a/compiler/rustc_ast_pretty/Cargo.toml b/compiler/rustc_ast_pretty/Cargo.toml
index 29f2be4cf4648..5ad8714e9fec9 100644
--- a/compiler/rustc_ast_pretty/Cargo.toml
+++ b/compiler/rustc_ast_pretty/Cargo.toml
@@ -7,6 +7,5 @@ edition = "2021"
 doctest = false
 
 [dependencies]
-tracing = "0.1"
 rustc_span = { path = "../rustc_span" }
 rustc_ast = { path = "../rustc_ast" }
diff --git a/compiler/rustc_ast_pretty/src/pp.rs b/compiler/rustc_ast_pretty/src/pp.rs
index ad9d15f1ce345..25437f8b53a94 100644
--- a/compiler/rustc_ast_pretty/src/pp.rs
+++ b/compiler/rustc_ast_pretty/src/pp.rs
@@ -138,7 +138,6 @@ use ring::RingBuffer;
 use std::borrow::Cow;
 use std::collections::VecDeque;
 use std::fmt;
-use tracing::debug;
 
 /// How to break. Described in more detail in the module docs.
 #[derive(Clone, Copy, PartialEq)]
@@ -193,22 +192,6 @@ impl fmt::Display for Token {
     }
 }
 
-fn buf_str(buf: &RingBuffer<BufEntry>, left: usize, right: usize, lim: usize) -> String {
-    let mut i = left;
-    let mut l = lim;
-    let mut s = String::from("[");
-    while i != right && l != 0 {
-        l -= 1;
-        if i != left {
-            s.push_str(", ");
-        }
-        s.push_str(&format!("{}={}", buf[i].size, &buf[i].token));
-        i += 1;
-    }
-    s.push(']');
-    s
-}
-
 #[derive(Copy, Clone)]
 enum PrintStackBreak {
     Fits,
@@ -267,7 +250,6 @@ impl Default for BufEntry {
 impl Printer {
     pub fn new() -> Self {
         let linewidth = 78;
-        debug!("Printer::new {}", linewidth);
         let mut buf = RingBuffer::new();
         buf.advance_right();
         Printer {
@@ -310,16 +292,13 @@ impl Printer {
         } else {
             self.advance_right();
         }
-        debug!("pp Begin({})/buffer Vec<{},{}>", b.offset, self.left, self.right);
         self.scan_push(BufEntry { token: Token::Begin(b), size: -self.right_total });
     }
 
     fn scan_end(&mut self) {
         if self.scan_stack.is_empty() {
-            debug!("pp End/print Vec<{},{}>", self.left, self.right);
             self.print_end();
         } else {
-            debug!("pp End/buffer Vec<{},{}>", self.left, self.right);
             self.advance_right();
             self.scan_push(BufEntry { token: Token::End, size: -1 });
         }
@@ -334,7 +313,6 @@ impl Printer {
         } else {
             self.advance_right();
         }
-        debug!("pp Break({})/buffer Vec<{},{}>", b.offset, self.left, self.right);
         self.check_stack(0);
         self.scan_push(BufEntry { token: Token::Break(b), size: -self.right_total });
         self.right_total += b.blank_space;
@@ -342,10 +320,8 @@ impl Printer {
 
     fn scan_string(&mut self, s: Cow<'static, str>) {
         if self.scan_stack.is_empty() {
-            debug!("pp String('{}')/print Vec<{},{}>", s, self.left, self.right);
             self.print_string(s);
         } else {
-            debug!("pp String('{}')/buffer Vec<{},{}>", s, self.left, self.right);
             self.advance_right();
             let len = s.len() as isize;
             self.buf[self.right] = BufEntry { token: Token::String(s), size: len };
@@ -355,18 +331,8 @@ impl Printer {
     }
 
     fn check_stream(&mut self) {
-        debug!(
-            "check_stream Vec<{}, {}> with left_total={}, right_total={}",
-            self.left, self.right, self.left_total, self.right_total
-        );
         if self.right_total - self.left_total > self.space {
-            debug!(
-                "scan window is {}, longer than space on line ({})",
-                self.right_total - self.left_total,
-                self.space
-            );
             if Some(&self.left) == self.scan_stack.back() {
-                debug!("setting {} to infinity and popping", self.left);
                 let scanned = self.scan_pop_bottom();
                 self.buf[scanned].size = SIZE_INFINITY;
             }
@@ -378,7 +344,6 @@ impl Printer {
     }
 
     fn scan_push(&mut self, entry: BufEntry) {
-        debug!("scan_push {}", self.right);
         self.buf[self.right] = entry;
         self.scan_stack.push_front(self.right);
     }
@@ -401,11 +366,6 @@ impl Printer {
     }
 
     fn advance_left(&mut self) {
-        debug!(
-            "advance_left Vec<{},{}>, sizeof({})={}",
-            self.left, self.right, self.left, self.buf[self.left].size
-        );
-
         let mut left_size = self.buf[self.left].size;
 
         while left_size >= 0 {
@@ -465,14 +425,12 @@ impl Printer {
     }
 
     fn print_newline(&mut self, amount: isize) {
-        debug!("NEWLINE {}", amount);
         self.out.push('\n');
         self.pending_indentation = 0;
         self.indent(amount);
     }
 
     fn indent(&mut self, amount: isize) {
-        debug!("INDENT {}", amount);
         self.pending_indentation += amount;
     }
 
@@ -485,17 +443,14 @@ impl Printer {
     fn print_begin(&mut self, b: BeginToken, l: isize) {
         if l > self.space {
             let col = self.margin - self.space + b.offset;
-            debug!("print Begin -> push broken block at col {}", col);
             self.print_stack
                 .push(PrintStackElem { offset: col, pbreak: PrintStackBreak::Broken(b.breaks) });
         } else {
-            debug!("print Begin -> push fitting block");
             self.print_stack.push(PrintStackElem { offset: 0, pbreak: PrintStackBreak::Fits });
         }
     }
 
     fn print_end(&mut self) {
-        debug!("print End -> pop End");
         self.print_stack.pop().unwrap();
     }
 
@@ -503,22 +458,18 @@ impl Printer {
         let top = self.get_top();
         match top.pbreak {
             PrintStackBreak::Fits => {
-                debug!("print Break({}) in fitting block", b.blank_space);
                 self.space -= b.blank_space;
                 self.indent(b.blank_space);
             }
             PrintStackBreak::Broken(Breaks::Consistent) => {
-                debug!("print Break({}+{}) in consistent block", top.offset, b.offset);
                 self.print_newline(top.offset + b.offset);
                 self.space = self.margin - (top.offset + b.offset);
             }
             PrintStackBreak::Broken(Breaks::Inconsistent) => {
                 if l > self.space {
-                    debug!("print Break({}+{}) w/ newline in inconsistent", top.offset, b.offset);
                     self.print_newline(top.offset + b.offset);
                     self.space = self.margin - (top.offset + b.offset);
                 } else {
-                    debug!("print Break({}) w/o newline in inconsistent", b.blank_space);
                     self.indent(b.blank_space);
                     self.space -= b.blank_space;
                 }
@@ -528,7 +479,6 @@ impl Printer {
 
     fn print_string(&mut self, s: Cow<'static, str>) {
         let len = s.len() as isize;
-        debug!("print String({})", s);
         // assert!(len <= space);
         self.space -= len;
 
@@ -545,8 +495,6 @@ impl Printer {
     }
 
     fn print(&mut self, token: Token, l: isize) {
-        debug!("print {} {} (remaining line space={})", token, l, self.space);
-        debug!("{}", buf_str(&self.buf, self.left, self.right, 6));
         match token {
             Token::Begin(b) => self.print_begin(b, l),
             Token::End => self.print_end(),
diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs
index 2fb5a0f9faf82..5703a72c686e5 100644
--- a/compiler/rustc_codegen_llvm/src/back/archive.rs
+++ b/compiler/rustc_codegen_llvm/src/back/archive.rs
@@ -1,6 +1,7 @@
 //! A helper class for dealing with static archives
 
-use std::ffi::{CStr, CString};
+use std::env;
+use std::ffi::{CStr, CString, OsString};
 use std::io;
 use std::mem;
 use std::path::{Path, PathBuf};
@@ -158,54 +159,127 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
             output_path.with_extension("lib")
         };
 
-        // we've checked for \0 characters in the library name already
-        let dll_name_z = CString::new(lib_name).unwrap();
-        // All import names are Rust identifiers and therefore cannot contain \0 characters.
-        // FIXME: when support for #[link_name] implemented, ensure that import.name values don't
-        // have any \0 characters
-        let import_name_and_ordinal_vector: Vec<(CString, Option<u16>)> = dll_imports
+        let mingw_gnu_toolchain = self.config.sess.target.llvm_target.ends_with("pc-windows-gnu");
+
+        let import_name_and_ordinal_vector: Vec<(String, Option<u16>)> = dll_imports
             .iter()
             .map(|import: &DllImport| {
                 if self.config.sess.target.arch == "x86" {
-                    (LlvmArchiveBuilder::i686_decorated_name(import), import.ordinal)
+                    (
+                        LlvmArchiveBuilder::i686_decorated_name(import, mingw_gnu_toolchain),
+                        import.ordinal,
+                    )
                 } else {
-                    (CString::new(import.name.to_string()).unwrap(), import.ordinal)
+                    (import.name.to_string(), import.ordinal)
                 }
             })
             .collect();
 
-        let output_path_z = rustc_fs_util::path_to_c_string(&output_path);
+        if mingw_gnu_toolchain {
+            // The binutils linker used on -windows-gnu targets cannot read the import
+            // libraries generated by LLVM: in our attempts, the linker produced an .EXE
+            // that loaded but crashed with an AV upon calling one of the imported
+            // functions.  Therefore, use binutils to create the import library instead,
+            // by writing a .DEF file to the temp dir and calling binutils's dlltool.
+            let def_file_path =
+                tmpdir.as_ref().join(format!("{}_imports", lib_name)).with_extension("def");
+
+            let def_file_content = format!(
+                "EXPORTS\n{}",
+                import_name_and_ordinal_vector
+                    .into_iter()
+                    .map(|(name, ordinal)| {
+                        match ordinal {
+                            Some(n) => format!("{} @{} NONAME", name, n),
+                            None => name,
+                        }
+                    })
+                    .collect::<Vec<String>>()
+                    .join("\n")
+            );
 
-        tracing::trace!("invoking LLVMRustWriteImportLibrary");
-        tracing::trace!("  dll_name {:#?}", dll_name_z);
-        tracing::trace!("  output_path {}", output_path.display());
-        tracing::trace!(
-            "  import names: {}",
-            dll_imports.iter().map(|import| import.name.to_string()).collect::<Vec<_>>().join(", "),
-        );
+            match std::fs::write(&def_file_path, def_file_content) {
+                Ok(_) => {}
+                Err(e) => {
+                    self.config.sess.fatal(&format!("Error writing .DEF file: {}", e));
+                }
+            };
 
-        let ffi_exports: Vec<LLVMRustCOFFShortExport> = import_name_and_ordinal_vector
-            .iter()
-            .map(|(name_z, ordinal)| LLVMRustCOFFShortExport::new(name_z.as_ptr(), *ordinal))
-            .collect();
-        let result = unsafe {
-            crate::llvm::LLVMRustWriteImportLibrary(
-                dll_name_z.as_ptr(),
-                output_path_z.as_ptr(),
-                ffi_exports.as_ptr(),
-                ffi_exports.len(),
-                llvm_machine_type(&self.config.sess.target.arch) as u16,
-                !self.config.sess.target.is_like_msvc,
-            )
-        };
+            let dlltool = find_binutils_dlltool(self.config.sess);
+            let result = std::process::Command::new(dlltool)
+                .args([
+                    "-d",
+                    def_file_path.to_str().unwrap(),
+                    "-D",
+                    lib_name,
+                    "-l",
+                    output_path.to_str().unwrap(),
+                ])
+                .output();
+
+            match result {
+                Err(e) => {
+                    self.config.sess.fatal(&format!("Error calling dlltool: {}", e.to_string()));
+                }
+                Ok(output) if !output.status.success() => self.config.sess.fatal(&format!(
+                    "Dlltool could not create import library: {}\n{}",
+                    String::from_utf8_lossy(&output.stdout),
+                    String::from_utf8_lossy(&output.stderr)
+                )),
+                _ => {}
+            }
+        } else {
+            // we've checked for \0 characters in the library name already
+            let dll_name_z = CString::new(lib_name).unwrap();
+
+            let output_path_z = rustc_fs_util::path_to_c_string(&output_path);
+
+            tracing::trace!("invoking LLVMRustWriteImportLibrary");
+            tracing::trace!("  dll_name {:#?}", dll_name_z);
+            tracing::trace!("  output_path {}", output_path.display());
+            tracing::trace!(
+                "  import names: {}",
+                dll_imports
+                    .iter()
+                    .map(|import| import.name.to_string())
+                    .collect::<Vec<_>>()
+                    .join(", "),
+            );
 
-        if result == crate::llvm::LLVMRustResult::Failure {
-            self.config.sess.fatal(&format!(
-                "Error creating import library for {}: {}",
-                lib_name,
-                llvm::last_error().unwrap_or("unknown LLVM error".to_string())
-            ));
-        }
+            // All import names are Rust identifiers and therefore cannot contain \0 characters.
+            // FIXME: when support for #[link_name] is implemented, ensure that the import names
+            // still don't contain any \0 characters.  Also need to check that the names don't
+            // contain substrings like " @" or "NONAME" that are keywords or otherwise reserved
+            // in definition files.
+            let cstring_import_name_and_ordinal_vector: Vec<(CString, Option<u16>)> =
+                import_name_and_ordinal_vector
+                    .into_iter()
+                    .map(|(name, ordinal)| (CString::new(name).unwrap(), ordinal))
+                    .collect();
+
+            let ffi_exports: Vec<LLVMRustCOFFShortExport> = cstring_import_name_and_ordinal_vector
+                .iter()
+                .map(|(name_z, ordinal)| LLVMRustCOFFShortExport::new(name_z.as_ptr(), *ordinal))
+                .collect();
+            let result = unsafe {
+                crate::llvm::LLVMRustWriteImportLibrary(
+                    dll_name_z.as_ptr(),
+                    output_path_z.as_ptr(),
+                    ffi_exports.as_ptr(),
+                    ffi_exports.len(),
+                    llvm_machine_type(&self.config.sess.target.arch) as u16,
+                    !self.config.sess.target.is_like_msvc,
+                )
+            };
+
+            if result == crate::llvm::LLVMRustResult::Failure {
+                self.config.sess.fatal(&format!(
+                    "Error creating import library for {}: {}",
+                    lib_name,
+                    llvm::last_error().unwrap_or("unknown LLVM error".to_string())
+                ));
+            }
+        };
 
         self.add_archive(&output_path, |_| false).unwrap_or_else(|e| {
             self.config.sess.fatal(&format!(
@@ -332,22 +406,61 @@ impl<'a> LlvmArchiveBuilder<'a> {
         }
     }
 
-    fn i686_decorated_name(import: &DllImport) -> CString {
+    fn i686_decorated_name(import: &DllImport, mingw: bool) -> String {
         let name = import.name;
-        // We verified during construction that `name` does not contain any NULL characters, so the
-        // conversion to CString is guaranteed to succeed.
-        CString::new(match import.calling_convention {
-            DllCallingConvention::C => format!("_{}", name),
-            DllCallingConvention::Stdcall(arg_list_size) => format!("_{}@{}", name, arg_list_size),
+        let prefix = if mingw { "" } else { "_" };
+
+        match import.calling_convention {
+            DllCallingConvention::C => format!("{}{}", prefix, name),
+            DllCallingConvention::Stdcall(arg_list_size) => {
+                format!("{}{}@{}", prefix, name, arg_list_size)
+            }
             DllCallingConvention::Fastcall(arg_list_size) => format!("@{}@{}", name, arg_list_size),
             DllCallingConvention::Vectorcall(arg_list_size) => {
                 format!("{}@@{}", name, arg_list_size)
             }
-        })
-        .unwrap()
+        }
     }
 }
 
 fn string_to_io_error(s: String) -> io::Error {
     io::Error::new(io::ErrorKind::Other, format!("bad archive: {}", s))
 }
+
+fn find_binutils_dlltool(sess: &Session) -> OsString {
+    assert!(sess.target.options.is_like_windows && !sess.target.options.is_like_msvc);
+    if let Some(dlltool_path) = &sess.opts.debugging_opts.dlltool {
+        return dlltool_path.clone().into_os_string();
+    }
+
+    let mut tool_name: OsString = if sess.host.arch != sess.target.arch {
+        // We are cross-compiling, so we need the tool with the prefix matching our target
+        if sess.target.arch == "x86" {
+            "i686-w64-mingw32-dlltool"
+        } else {
+            "x86_64-w64-mingw32-dlltool"
+        }
+    } else {
+        // We are not cross-compiling, so we just want `dlltool`
+        "dlltool"
+    }
+    .into();
+
+    if sess.host.options.is_like_windows {
+        // If we're compiling on Windows, add the .exe suffix
+        tool_name.push(".exe");
+    }
+
+    // NOTE: it's not clear how useful it is to explicitly search PATH.
+    for dir in env::split_paths(&env::var_os("PATH").unwrap_or_default()) {
+        let full_path = dir.join(&tool_name);
+        if full_path.is_file() {
+            return full_path.into_os_string();
+        }
+    }
+
+    // The user didn't specify the location of the dlltool binary, and we weren't able
+    // to find the appropriate one on the PATH.  Just return the name of the tool
+    // and let the invocation fail with a hopefully useful error message.
+    tool_name
+}
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 5217fa2758f79..8a9450c20dda4 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -731,27 +731,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
     }
 
     fn fptoui_sat(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> Option<&'ll Value> {
-        if !self.fptoint_sat_broken_in_llvm() {
-            let src_ty = self.cx.val_ty(val);
-            let float_width = self.cx.float_width(src_ty);
-            let int_width = self.cx.int_width(dest_ty);
-            let name = format!("llvm.fptoui.sat.i{}.f{}", int_width, float_width);
-            return Some(self.call_intrinsic(&name, &[val]));
-        }
-
-        None
+        self.fptoint_sat(false, val, dest_ty)
     }
 
     fn fptosi_sat(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> Option<&'ll Value> {
-        if !self.fptoint_sat_broken_in_llvm() {
-            let src_ty = self.cx.val_ty(val);
-            let float_width = self.cx.float_width(src_ty);
-            let int_width = self.cx.int_width(dest_ty);
-            let name = format!("llvm.fptosi.sat.i{}.f{}", int_width, float_width);
-            return Some(self.call_intrinsic(&name, &[val]));
-        }
-
-        None
+        self.fptoint_sat(true, val, dest_ty)
     }
 
     fn fptoui(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
@@ -1455,4 +1439,43 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
             _ => false,
         }
     }
+
+    fn fptoint_sat(
+        &mut self,
+        signed: bool,
+        val: &'ll Value,
+        dest_ty: &'ll Type,
+    ) -> Option<&'ll Value> {
+        if !self.fptoint_sat_broken_in_llvm() {
+            let src_ty = self.cx.val_ty(val);
+            let (float_ty, int_ty, vector_length) = if self.cx.type_kind(src_ty) == TypeKind::Vector
+            {
+                assert_eq!(self.cx.vector_length(src_ty), self.cx.vector_length(dest_ty));
+                (
+                    self.cx.element_type(src_ty),
+                    self.cx.element_type(dest_ty),
+                    Some(self.cx.vector_length(src_ty)),
+                )
+            } else {
+                (src_ty, dest_ty, None)
+            };
+            let float_width = self.cx.float_width(float_ty);
+            let int_width = self.cx.int_width(int_ty);
+
+            let instr = if signed { "fptosi" } else { "fptoui" };
+            let name = if let Some(vector_length) = vector_length {
+                format!(
+                    "llvm.{}.sat.v{}i{}.v{}f{}",
+                    instr, vector_length, int_width, vector_length, float_width
+                )
+            } else {
+                format!("llvm.{}.sat.i{}.f{}", instr, int_width, float_width)
+            };
+            let f =
+                self.declare_cfn(&name, llvm::UnnamedAddr::No, self.type_func(&[src_ty], dest_ty));
+            Some(self.call(self.type_func(&[src_ty], dest_ty), f, &[val], None))
+        } else {
+            None
+        }
+    }
 }
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index cebb6d13c4e9f..5adfa18035a0e 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -1688,7 +1688,7 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
     bitwise_red!(simd_reduce_all: vector_reduce_and, true);
     bitwise_red!(simd_reduce_any: vector_reduce_or, true);
 
-    if name == sym::simd_cast {
+    if name == sym::simd_cast || name == sym::simd_as {
         require_simd!(ret_ty, "return");
         let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
         require!(
@@ -1714,14 +1714,26 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
         let (in_style, in_width) = match in_elem.kind() {
             // vectors of pointer-sized integers should've been
             // disallowed before here, so this unwrap is safe.
-            ty::Int(i) => (Style::Int(true), i.bit_width().unwrap()),
-            ty::Uint(u) => (Style::Int(false), u.bit_width().unwrap()),
+            ty::Int(i) => (
+                Style::Int(true),
+                i.normalize(bx.tcx().sess.target.pointer_width).bit_width().unwrap(),
+            ),
+            ty::Uint(u) => (
+                Style::Int(false),
+                u.normalize(bx.tcx().sess.target.pointer_width).bit_width().unwrap(),
+            ),
             ty::Float(f) => (Style::Float, f.bit_width()),
             _ => (Style::Unsupported, 0),
         };
         let (out_style, out_width) = match out_elem.kind() {
-            ty::Int(i) => (Style::Int(true), i.bit_width().unwrap()),
-            ty::Uint(u) => (Style::Int(false), u.bit_width().unwrap()),
+            ty::Int(i) => (
+                Style::Int(true),
+                i.normalize(bx.tcx().sess.target.pointer_width).bit_width().unwrap(),
+            ),
+            ty::Uint(u) => (
+                Style::Int(false),
+                u.normalize(bx.tcx().sess.target.pointer_width).bit_width().unwrap(),
+            ),
             ty::Float(f) => (Style::Float, f.bit_width()),
             _ => (Style::Unsupported, 0),
         };
@@ -1748,10 +1760,10 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
                 });
             }
             (Style::Float, Style::Int(out_is_signed)) => {
-                return Ok(if out_is_signed {
-                    bx.fptosi(args[0].immediate(), llret_ty)
-                } else {
-                    bx.fptoui(args[0].immediate(), llret_ty)
+                return Ok(match (out_is_signed, name == sym::simd_as) {
+                    (false, false) => bx.fptoui(args[0].immediate(), llret_ty),
+                    (true, false) => bx.fptosi(args[0].immediate(), llret_ty),
+                    (_, true) => bx.cast_float_to_int(out_is_signed, args[0].immediate(), llret_ty),
                 });
             }
             (Style::Float, Style::Float) => {
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index 679c45767018d..68decce82ab52 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -3,11 +3,10 @@ use super::place::PlaceRef;
 use super::{FunctionCx, LocalRef};
 
 use crate::base;
-use crate::common::{self, IntPredicate, RealPredicate};
+use crate::common::{self, IntPredicate};
 use crate::traits::*;
 use crate::MemFlags;
 
-use rustc_apfloat::{ieee, Float, Round, Status};
 use rustc_middle::mir;
 use rustc_middle::ty::cast::{CastTy, IntTy};
 use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
@@ -368,10 +367,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                                 bx.inttoptr(usize_llval, ll_t_out)
                             }
                             (CastTy::Float, CastTy::Int(IntTy::I)) => {
-                                cast_float_to_int(&mut bx, true, llval, ll_t_in, ll_t_out)
+                                bx.cast_float_to_int(true, llval, ll_t_out)
                             }
                             (CastTy::Float, CastTy::Int(_)) => {
-                                cast_float_to_int(&mut bx, false, llval, ll_t_in, ll_t_out)
+                                bx.cast_float_to_int(false, llval, ll_t_out)
                             }
                             _ => bug!("unsupported cast: {:?} to {:?}", operand.layout.ty, cast.ty),
                         };
@@ -768,146 +767,3 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         // (*) this is only true if the type is suitable
     }
 }
-
-fn cast_float_to_int<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
-    bx: &mut Bx,
-    signed: bool,
-    x: Bx::Value,
-    float_ty: Bx::Type,
-    int_ty: Bx::Type,
-) -> Bx::Value {
-    if let Some(false) = bx.cx().sess().opts.debugging_opts.saturating_float_casts {
-        return if signed { bx.fptosi(x, int_ty) } else { bx.fptoui(x, int_ty) };
-    }
-
-    let try_sat_result = if signed { bx.fptosi_sat(x, int_ty) } else { bx.fptoui_sat(x, int_ty) };
-    if let Some(try_sat_result) = try_sat_result {
-        return try_sat_result;
-    }
-
-    let int_width = bx.cx().int_width(int_ty);
-    let float_width = bx.cx().float_width(float_ty);
-    // LLVM's fpto[su]i returns undef when the input x is infinite, NaN, or does not fit into the
-    // destination integer type after rounding towards zero. This `undef` value can cause UB in
-    // safe code (see issue #10184), so we implement a saturating conversion on top of it:
-    // Semantically, the mathematical value of the input is rounded towards zero to the next
-    // mathematical integer, and then the result is clamped into the range of the destination
-    // integer type. Positive and negative infinity are mapped to the maximum and minimum value of
-    // the destination integer type. NaN is mapped to 0.
-    //
-    // Define f_min and f_max as the largest and smallest (finite) floats that are exactly equal to
-    // a value representable in int_ty.
-    // They are exactly equal to int_ty::{MIN,MAX} if float_ty has enough significand bits.
-    // Otherwise, int_ty::MAX must be rounded towards zero, as it is one less than a power of two.
-    // int_ty::MIN, however, is either zero or a negative power of two and is thus exactly
-    // representable. Note that this only works if float_ty's exponent range is sufficiently large.
-    // f16 or 256 bit integers would break this property. Right now the smallest float type is f32
-    // with exponents ranging up to 127, which is barely enough for i128::MIN = -2^127.
-    // On the other hand, f_max works even if int_ty::MAX is greater than float_ty::MAX. Because
-    // we're rounding towards zero, we just get float_ty::MAX (which is always an integer).
-    // This already happens today with u128::MAX = 2^128 - 1 > f32::MAX.
-    let int_max = |signed: bool, int_width: u64| -> u128 {
-        let shift_amount = 128 - int_width;
-        if signed { i128::MAX as u128 >> shift_amount } else { u128::MAX >> shift_amount }
-    };
-    let int_min = |signed: bool, int_width: u64| -> i128 {
-        if signed { i128::MIN >> (128 - int_width) } else { 0 }
-    };
-
-    let compute_clamp_bounds_single = |signed: bool, int_width: u64| -> (u128, u128) {
-        let rounded_min = ieee::Single::from_i128_r(int_min(signed, int_width), Round::TowardZero);
-        assert_eq!(rounded_min.status, Status::OK);
-        let rounded_max = ieee::Single::from_u128_r(int_max(signed, int_width), Round::TowardZero);
-        assert!(rounded_max.value.is_finite());
-        (rounded_min.value.to_bits(), rounded_max.value.to_bits())
-    };
-    let compute_clamp_bounds_double = |signed: bool, int_width: u64| -> (u128, u128) {
-        let rounded_min = ieee::Double::from_i128_r(int_min(signed, int_width), Round::TowardZero);
-        assert_eq!(rounded_min.status, Status::OK);
-        let rounded_max = ieee::Double::from_u128_r(int_max(signed, int_width), Round::TowardZero);
-        assert!(rounded_max.value.is_finite());
-        (rounded_min.value.to_bits(), rounded_max.value.to_bits())
-    };
-
-    let mut float_bits_to_llval = |bits| {
-        let bits_llval = match float_width {
-            32 => bx.cx().const_u32(bits as u32),
-            64 => bx.cx().const_u64(bits as u64),
-            n => bug!("unsupported float width {}", n),
-        };
-        bx.bitcast(bits_llval, float_ty)
-    };
-    let (f_min, f_max) = match float_width {
-        32 => compute_clamp_bounds_single(signed, int_width),
-        64 => compute_clamp_bounds_double(signed, int_width),
-        n => bug!("unsupported float width {}", n),
-    };
-    let f_min = float_bits_to_llval(f_min);
-    let f_max = float_bits_to_llval(f_max);
-    // To implement saturation, we perform the following steps:
-    //
-    // 1. Cast x to an integer with fpto[su]i. This may result in undef.
-    // 2. Compare x to f_min and f_max, and use the comparison results to select:
-    //  a) int_ty::MIN if x < f_min or x is NaN
-    //  b) int_ty::MAX if x > f_max
-    //  c) the result of fpto[su]i otherwise
-    // 3. If x is NaN, return 0.0, otherwise return the result of step 2.
-    //
-    // This avoids resulting undef because values in range [f_min, f_max] by definition fit into the
-    // destination type. It creates an undef temporary, but *producing* undef is not UB. Our use of
-    // undef does not introduce any non-determinism either.
-    // More importantly, the above procedure correctly implements saturating conversion.
-    // Proof (sketch):
-    // If x is NaN, 0 is returned by definition.
-    // Otherwise, x is finite or infinite and thus can be compared with f_min and f_max.
-    // This yields three cases to consider:
-    // (1) if x in [f_min, f_max], the result of fpto[su]i is returned, which agrees with
-    //     saturating conversion for inputs in that range.
-    // (2) if x > f_max, then x is larger than int_ty::MAX. This holds even if f_max is rounded
-    //     (i.e., if f_max < int_ty::MAX) because in those cases, nextUp(f_max) is already larger
-    //     than int_ty::MAX. Because x is larger than int_ty::MAX, the return value of int_ty::MAX
-    //     is correct.
-    // (3) if x < f_min, then x is smaller than int_ty::MIN. As shown earlier, f_min exactly equals
-    //     int_ty::MIN and therefore the return value of int_ty::MIN is correct.
-    // QED.
-
-    let int_max = bx.cx().const_uint_big(int_ty, int_max(signed, int_width));
-    let int_min = bx.cx().const_uint_big(int_ty, int_min(signed, int_width) as u128);
-    let zero = bx.cx().const_uint(int_ty, 0);
-
-    // Step 1 ...
-    let fptosui_result = if signed { bx.fptosi(x, int_ty) } else { bx.fptoui(x, int_ty) };
-    let less_or_nan = bx.fcmp(RealPredicate::RealULT, x, f_min);
-    let greater = bx.fcmp(RealPredicate::RealOGT, x, f_max);
-
-    // Step 2: We use two comparisons and two selects, with %s1 being the
-    // result:
-    //     %less_or_nan = fcmp ult %x, %f_min
-    //     %greater = fcmp olt %x, %f_max
-    //     %s0 = select %less_or_nan, int_ty::MIN, %fptosi_result
-    //     %s1 = select %greater, int_ty::MAX, %s0
-    // Note that %less_or_nan uses an *unordered* comparison. This
-    // comparison is true if the operands are not comparable (i.e., if x is
-    // NaN). The unordered comparison ensures that s1 becomes int_ty::MIN if
-    // x is NaN.
-    //
-    // Performance note: Unordered comparison can be lowered to a "flipped"
-    // comparison and a negation, and the negation can be merged into the
-    // select. Therefore, it not necessarily any more expensive than an
-    // ordered ("normal") comparison. Whether these optimizations will be
-    // performed is ultimately up to the backend, but at least x86 does
-    // perform them.
-    let s0 = bx.select(less_or_nan, int_min, fptosui_result);
-    let s1 = bx.select(greater, int_max, s0);
-
-    // Step 3: NaN replacement.
-    // For unsigned types, the above step already yielded int_ty::MIN == 0 if x is NaN.
-    // Therefore we only need to execute this step for signed integer types.
-    if signed {
-        // LLVM has no isNaN predicate, so we use (x == x) instead
-        let cmp = bx.fcmp(RealPredicate::RealOEQ, x, x);
-        bx.select(cmp, s1, zero)
-    } else {
-        s1
-    }
-}
diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs
index 48d88095855d1..5a06fb4610587 100644
--- a/compiler/rustc_codegen_ssa/src/traits/builder.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs
@@ -1,18 +1,21 @@
 use super::abi::AbiBuilderMethods;
 use super::asm::AsmBuilderMethods;
+use super::consts::ConstMethods;
 use super::coverageinfo::CoverageInfoBuilderMethods;
 use super::debuginfo::DebugInfoBuilderMethods;
 use super::intrinsic::IntrinsicCallMethods;
-use super::type_::ArgAbiMethods;
+use super::misc::MiscMethods;
+use super::type_::{ArgAbiMethods, BaseTypeMethods};
 use super::{HasCodegen, StaticBuilderMethods};
 
 use crate::common::{
-    AtomicOrdering, AtomicRmwBinOp, IntPredicate, RealPredicate, SynchronizationScope,
+    AtomicOrdering, AtomicRmwBinOp, IntPredicate, RealPredicate, SynchronizationScope, TypeKind,
 };
 use crate::mir::operand::OperandRef;
 use crate::mir::place::PlaceRef;
 use crate::MemFlags;
 
+use rustc_apfloat::{ieee, Float, Round, Status};
 use rustc_middle::ty::layout::{HasParamEnv, TyAndLayout};
 use rustc_middle::ty::Ty;
 use rustc_span::Span;
@@ -202,6 +205,179 @@ pub trait BuilderMethods<'a, 'tcx>:
     fn intcast(&mut self, val: Self::Value, dest_ty: Self::Type, is_signed: bool) -> Self::Value;
     fn pointercast(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
 
+    fn cast_float_to_int(
+        &mut self,
+        signed: bool,
+        x: Self::Value,
+        dest_ty: Self::Type,
+    ) -> Self::Value {
+        let in_ty = self.cx().val_ty(x);
+        let (float_ty, int_ty) = if self.cx().type_kind(dest_ty) == TypeKind::Vector
+            && self.cx().type_kind(in_ty) == TypeKind::Vector
+        {
+            (self.cx().element_type(in_ty), self.cx().element_type(dest_ty))
+        } else {
+            (in_ty, dest_ty)
+        };
+        assert!(matches!(self.cx().type_kind(float_ty), TypeKind::Float | TypeKind::Double));
+        assert_eq!(self.cx().type_kind(int_ty), TypeKind::Integer);
+
+        if let Some(false) = self.cx().sess().opts.debugging_opts.saturating_float_casts {
+            return if signed { self.fptosi(x, dest_ty) } else { self.fptoui(x, dest_ty) };
+        }
+
+        let try_sat_result =
+            if signed { self.fptosi_sat(x, dest_ty) } else { self.fptoui_sat(x, dest_ty) };
+        if let Some(try_sat_result) = try_sat_result {
+            return try_sat_result;
+        }
+
+        let int_width = self.cx().int_width(int_ty);
+        let float_width = self.cx().float_width(float_ty);
+        // LLVM's fpto[su]i returns undef when the input x is infinite, NaN, or does not fit into the
+        // destination integer type after rounding towards zero. This `undef` value can cause UB in
+        // safe code (see issue #10184), so we implement a saturating conversion on top of it:
+        // Semantically, the mathematical value of the input is rounded towards zero to the next
+        // mathematical integer, and then the result is clamped into the range of the destination
+        // integer type. Positive and negative infinity are mapped to the maximum and minimum value of
+        // the destination integer type. NaN is mapped to 0.
+        //
+        // Define f_min and f_max as the largest and smallest (finite) floats that are exactly equal to
+        // a value representable in int_ty.
+        // They are exactly equal to int_ty::{MIN,MAX} if float_ty has enough significand bits.
+        // Otherwise, int_ty::MAX must be rounded towards zero, as it is one less than a power of two.
+        // int_ty::MIN, however, is either zero or a negative power of two and is thus exactly
+        // representable. Note that this only works if float_ty's exponent range is sufficiently large.
+        // f16 or 256 bit integers would break this property. Right now the smallest float type is f32
+        // with exponents ranging up to 127, which is barely enough for i128::MIN = -2^127.
+        // On the other hand, f_max works even if int_ty::MAX is greater than float_ty::MAX. Because
+        // we're rounding towards zero, we just get float_ty::MAX (which is always an integer).
+        // This already happens today with u128::MAX = 2^128 - 1 > f32::MAX.
+        let int_max = |signed: bool, int_width: u64| -> u128 {
+            let shift_amount = 128 - int_width;
+            if signed { i128::MAX as u128 >> shift_amount } else { u128::MAX >> shift_amount }
+        };
+        let int_min = |signed: bool, int_width: u64| -> i128 {
+            if signed { i128::MIN >> (128 - int_width) } else { 0 }
+        };
+
+        let compute_clamp_bounds_single = |signed: bool, int_width: u64| -> (u128, u128) {
+            let rounded_min =
+                ieee::Single::from_i128_r(int_min(signed, int_width), Round::TowardZero);
+            assert_eq!(rounded_min.status, Status::OK);
+            let rounded_max =
+                ieee::Single::from_u128_r(int_max(signed, int_width), Round::TowardZero);
+            assert!(rounded_max.value.is_finite());
+            (rounded_min.value.to_bits(), rounded_max.value.to_bits())
+        };
+        let compute_clamp_bounds_double = |signed: bool, int_width: u64| -> (u128, u128) {
+            let rounded_min =
+                ieee::Double::from_i128_r(int_min(signed, int_width), Round::TowardZero);
+            assert_eq!(rounded_min.status, Status::OK);
+            let rounded_max =
+                ieee::Double::from_u128_r(int_max(signed, int_width), Round::TowardZero);
+            assert!(rounded_max.value.is_finite());
+            (rounded_min.value.to_bits(), rounded_max.value.to_bits())
+        };
+        // To implement saturation, we perform the following steps:
+        //
+        // 1. Cast x to an integer with fpto[su]i. This may result in undef.
+        // 2. Compare x to f_min and f_max, and use the comparison results to select:
+        //  a) int_ty::MIN if x < f_min or x is NaN
+        //  b) int_ty::MAX if x > f_max
+        //  c) the result of fpto[su]i otherwise
+        // 3. If x is NaN, return 0.0, otherwise return the result of step 2.
+        //
+        // This avoids resulting undef because values in range [f_min, f_max] by definition fit into the
+        // destination type. It creates an undef temporary, but *producing* undef is not UB. Our use of
+        // undef does not introduce any non-determinism either.
+        // More importantly, the above procedure correctly implements saturating conversion.
+        // Proof (sketch):
+        // If x is NaN, 0 is returned by definition.
+        // Otherwise, x is finite or infinite and thus can be compared with f_min and f_max.
+        // This yields three cases to consider:
+        // (1) if x in [f_min, f_max], the result of fpto[su]i is returned, which agrees with
+        //     saturating conversion for inputs in that range.
+        // (2) if x > f_max, then x is larger than int_ty::MAX. This holds even if f_max is rounded
+        //     (i.e., if f_max < int_ty::MAX) because in those cases, nextUp(f_max) is already larger
+        //     than int_ty::MAX. Because x is larger than int_ty::MAX, the return value of int_ty::MAX
+        //     is correct.
+        // (3) if x < f_min, then x is smaller than int_ty::MIN. As shown earlier, f_min exactly equals
+        //     int_ty::MIN and therefore the return value of int_ty::MIN is correct.
+        // QED.
+
+        let float_bits_to_llval = |bx: &mut Self, bits| {
+            let bits_llval = match float_width {
+                32 => bx.cx().const_u32(bits as u32),
+                64 => bx.cx().const_u64(bits as u64),
+                n => bug!("unsupported float width {}", n),
+            };
+            bx.bitcast(bits_llval, float_ty)
+        };
+        let (f_min, f_max) = match float_width {
+            32 => compute_clamp_bounds_single(signed, int_width),
+            64 => compute_clamp_bounds_double(signed, int_width),
+            n => bug!("unsupported float width {}", n),
+        };
+        let f_min = float_bits_to_llval(self, f_min);
+        let f_max = float_bits_to_llval(self, f_max);
+        let int_max = self.cx().const_uint_big(int_ty, int_max(signed, int_width));
+        let int_min = self.cx().const_uint_big(int_ty, int_min(signed, int_width) as u128);
+        let zero = self.cx().const_uint(int_ty, 0);
+
+        // If we're working with vectors, constants must be "splatted": the constant is duplicated
+        // into each lane of the vector.  The algorithm stays the same, we are just using the
+        // same constant across all lanes.
+        let maybe_splat = |bx: &mut Self, val| {
+            if bx.cx().type_kind(dest_ty) == TypeKind::Vector {
+                bx.vector_splat(bx.vector_length(dest_ty), val)
+            } else {
+                val
+            }
+        };
+        let f_min = maybe_splat(self, f_min);
+        let f_max = maybe_splat(self, f_max);
+        let int_max = maybe_splat(self, int_max);
+        let int_min = maybe_splat(self, int_min);
+        let zero = maybe_splat(self, zero);
+
+        // Step 1 ...
+        let fptosui_result = if signed { self.fptosi(x, dest_ty) } else { self.fptoui(x, dest_ty) };
+        let less_or_nan = self.fcmp(RealPredicate::RealULT, x, f_min);
+        let greater = self.fcmp(RealPredicate::RealOGT, x, f_max);
+
+        // Step 2: We use two comparisons and two selects, with %s1 being the
+        // result:
+        //     %less_or_nan = fcmp ult %x, %f_min
+        //     %greater = fcmp olt %x, %f_max
+        //     %s0 = select %less_or_nan, int_ty::MIN, %fptosi_result
+        //     %s1 = select %greater, int_ty::MAX, %s0
+        // Note that %less_or_nan uses an *unordered* comparison. This
+        // comparison is true if the operands are not comparable (i.e., if x is
+        // NaN). The unordered comparison ensures that s1 becomes int_ty::MIN if
+        // x is NaN.
+        //
+        // Performance note: Unordered comparison can be lowered to a "flipped"
+        // comparison and a negation, and the negation can be merged into the
+        // select. Therefore, it not necessarily any more expensive than an
+        // ordered ("normal") comparison. Whether these optimizations will be
+        // performed is ultimately up to the backend, but at least x86 does
+        // perform them.
+        let s0 = self.select(less_or_nan, int_min, fptosui_result);
+        let s1 = self.select(greater, int_max, s0);
+
+        // Step 3: NaN replacement.
+        // For unsigned types, the above step already yielded int_ty::MIN == 0 if x is NaN.
+        // Therefore we only need to execute this step for signed integer types.
+        if signed {
+            // LLVM has no isNaN predicate, so we use (x == x) instead
+            let cmp = self.fcmp(RealPredicate::RealOEQ, x, x);
+            self.select(cmp, s1, zero)
+        } else {
+            s1
+        }
+    }
+
     fn icmp(&mut self, op: IntPredicate, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
     fn fcmp(&mut self, op: RealPredicate, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
 
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 816e770f01252..0e27a82b2b13b 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -646,6 +646,7 @@ fn test_debugging_options_tracking_hash() {
     untracked!(borrowck, String::from("other"));
     untracked!(deduplicate_diagnostics, false);
     untracked!(dep_tasks, true);
+    untracked!(dlltool, Some(PathBuf::from("custom_dlltool.exe")));
     untracked!(dont_buffer_diagnostics, true);
     untracked!(dump_dep_graph, true);
     untracked!(dump_mir, Some(String::from("abc")));
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index 639d2e617c77a..13cd8e4a046b0 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -274,11 +274,6 @@ impl Collector<'_> {
                     span,
                     "`#[link(...)]` with `kind = \"raw-dylib\"` only supported on Windows",
                 );
-            } else if !self.tcx.sess.target.options.is_like_msvc {
-                self.tcx.sess.span_warn(
-                    span,
-                    "`#[link(...)]` with `kind = \"raw-dylib\"` not supported on windows-gnu",
-                );
             }
 
             if lib_name.as_str().contains('\0') {
diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs
index 51e4afaf2204a..fafd847a1cbaa 100644
--- a/compiler/rustc_middle/src/mir/terminator.rs
+++ b/compiler/rustc_middle/src/mir/terminator.rs
@@ -105,7 +105,7 @@ impl<'a> Iterator for SwitchTargetsIter<'a> {
 
 impl<'a> ExactSizeIterator for SwitchTargetsIter<'a> {}
 
-#[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, PartialOrd)]
+#[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq)]
 pub enum TerminatorKind<'tcx> {
     /// Block should have one successor in the graph; we jump there.
     Goto { target: BasicBlock },
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index d6c35dfef8888..19a73732fcac3 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -36,6 +36,7 @@ impl<'tcx> Const<'tcx> {
         Self::from_opt_const_arg_anon_const(tcx, ty::WithOptConstParam::unknown(def_id))
     }
 
+    #[instrument(skip(tcx), level = "debug")]
     pub fn from_opt_const_arg_anon_const(
         tcx: TyCtxt<'tcx>,
         def: ty::WithOptConstParam<LocalDefId>,
@@ -51,6 +52,7 @@ impl<'tcx> Const<'tcx> {
         };
 
         let expr = &tcx.hir().body(body_id).value;
+        debug!(?expr);
 
         let ty = tcx.type_of(def.def_id_for_type_of());
 
@@ -67,11 +69,21 @@ impl<'tcx> Const<'tcx> {
         }
     }
 
+    #[instrument(skip(tcx), level = "debug")]
     fn try_eval_lit_or_param(
         tcx: TyCtxt<'tcx>,
         ty: Ty<'tcx>,
         expr: &'tcx hir::Expr<'tcx>,
     ) -> Option<&'tcx Self> {
+        // Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments
+        // currently have to be wrapped in curly brackets, so it's necessary to special-case.
+        let expr = match &expr.kind {
+            hir::ExprKind::Block(block, _) if block.stmts.is_empty() && block.expr.is_some() => {
+                block.expr.as_ref().unwrap()
+            }
+            _ => expr,
+        };
+
         let lit_input = match expr.kind {
             hir::ExprKind::Lit(ref lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }),
             hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => match expr.kind {
@@ -97,15 +109,6 @@ impl<'tcx> Const<'tcx> {
             }
         }
 
-        // Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments
-        // currently have to be wrapped in curly brackets, so it's necessary to special-case.
-        let expr = match &expr.kind {
-            hir::ExprKind::Block(block, _) if block.stmts.is_empty() && block.expr.is_some() => {
-                block.expr.as_ref().unwrap()
-            }
-            _ => expr,
-        };
-
         use hir::{def::DefKind::ConstParam, def::Res, ExprKind, Path, QPath};
         match expr.kind {
             ExprKind::Path(QPath::Resolved(_, &Path { res: Res::Def(ConstParam, def_id), .. })) => {
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index 4e60b7593c651..48502112e3a71 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -139,22 +139,46 @@ impl<'a> Parser<'a> {
         style: PathStyle,
         ty_generics: Option<&Generics>,
     ) -> PResult<'a, Path> {
-        maybe_whole!(self, NtPath, |path| {
+        let reject_generics_if_mod_style = |parser: &Parser<'_>, path: &Path| {
+            // Ensure generic arguments don't end up in attribute paths, such as:
+            //
+            //     macro_rules! m {
+            //         ($p:path) => { #[$p] struct S; }
+            //     }
+            //
+            //     m!(inline<u8>); //~ ERROR: unexpected generic arguments in path
+            //
             if style == PathStyle::Mod && path.segments.iter().any(|segment| segment.args.is_some())
             {
-                self.struct_span_err(
-                    path.segments
-                        .iter()
-                        .filter_map(|segment| segment.args.as_ref())
-                        .map(|arg| arg.span())
-                        .collect::<Vec<_>>(),
-                    "unexpected generic arguments in path",
-                )
-                .emit();
+                parser
+                    .struct_span_err(
+                        path.segments
+                            .iter()
+                            .filter_map(|segment| segment.args.as_ref())
+                            .map(|arg| arg.span())
+                            .collect::<Vec<_>>(),
+                        "unexpected generic arguments in path",
+                    )
+                    .emit();
             }
+        };
+
+        maybe_whole!(self, NtPath, |path| {
+            reject_generics_if_mod_style(self, &path);
             path
         });
 
+        if let token::Interpolated(nt) = &self.token.kind {
+            if let token::NtTy(ty) = &**nt {
+                if let ast::TyKind::Path(None, path) = &ty.kind {
+                    let path = path.clone();
+                    self.bump();
+                    reject_generics_if_mod_style(self, &path);
+                    return Ok(path);
+                }
+            }
+        }
+
         let lo = self.token.span;
         let mut segments = Vec::new();
         let mod_sep_ctxt = self.token.span.ctxt();
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 0b9623d1c7d6f..c48d8d689c10e 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -1161,6 +1161,8 @@ options! {
     dep_tasks: bool = (false, parse_bool, [UNTRACKED],
         "print tasks that execute and the color their dep node gets (requires debug build) \
         (default: no)"),
+    dlltool: Option<PathBuf> = (None, parse_opt_pathbuf, [UNTRACKED],
+        "import library generation tool (windows-gnu only)"),
     dont_buffer_diagnostics: bool = (false, parse_bool, [UNTRACKED],
         "emit diagnostics rather than buffering (breaks NLL error downgrading, sorting) \
         (default: no)"),
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index af87399ac95dc..702e359466079 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1223,6 +1223,7 @@ symbols! {
         simd,
         simd_add,
         simd_and,
+        simd_as,
         simd_bitmask,
         simd_cast,
         simd_ceil,
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index d174e00df77a9..af3540386f9fc 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -53,6 +53,7 @@ pub fn add_placeholder_note(err: &mut rustc_errors::DiagnosticBuilder<'_>) {
 /// If there are types that satisfy both impls, invokes `on_overlap`
 /// with a suitably-freshened `ImplHeader` with those types
 /// substituted. Otherwise, invokes `no_overlap`.
+#[instrument(skip(tcx, skip_leak_check, on_overlap, no_overlap), level = "debug")]
 pub fn overlapping_impls<F1, F2, R>(
     tcx: TyCtxt<'_>,
     impl1_def_id: DefId,
@@ -65,12 +66,6 @@ where
     F1: FnOnce(OverlapResult<'_>) -> R,
     F2: FnOnce() -> R,
 {
-    debug!(
-        "overlapping_impls(\
-           impl1_def_id={:?}, \
-           impl2_def_id={:?})",
-        impl1_def_id, impl2_def_id,
-    );
     // Before doing expensive operations like entering an inference context, do
     // a quick check via fast_reject to tell if the impl headers could possibly
     // unify.
@@ -85,6 +80,7 @@ where
     .any(|(ty1, ty2)| {
         let t1 = fast_reject::simplify_type(tcx, ty1, SimplifyParams::No, StripReferences::No);
         let t2 = fast_reject::simplify_type(tcx, ty2, SimplifyParams::No, StripReferences::No);
+
         if let (Some(t1), Some(t2)) = (t1, t2) {
             // Simplified successfully
             t1 != t2
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index ab732f510ff92..cd2e0f18e0cc0 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -117,9 +117,8 @@ pub fn translate_substs<'a, 'tcx>(
 /// Specialization is determined by the sets of types to which the impls apply;
 /// `impl1` specializes `impl2` if it applies to a subset of the types `impl2` applies
 /// to.
+#[instrument(skip(tcx), level = "debug")]
 pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId, DefId)) -> bool {
-    debug!("specializes({:?}, {:?})", impl1_def_id, impl2_def_id);
-
     // The feature gate should prevent introducing new specializations, but not
     // taking advantage of upstream ones.
     let features = tcx.features();
diff --git a/compiler/rustc_typeck/src/check/intrinsic.rs b/compiler/rustc_typeck/src/check/intrinsic.rs
index 6314f2aba4efe..4c612ed5be51a 100644
--- a/compiler/rustc_typeck/src/check/intrinsic.rs
+++ b/compiler/rustc_typeck/src/check/intrinsic.rs
@@ -453,7 +453,7 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
         sym::simd_scatter => (3, vec![param(0), param(1), param(2)], tcx.mk_unit()),
         sym::simd_insert => (2, vec![param(0), tcx.types.u32, param(1)], param(0)),
         sym::simd_extract => (2, vec![param(0), tcx.types.u32], param(1)),
-        sym::simd_cast => (2, vec![param(0)], param(1)),
+        sym::simd_cast | sym::simd_as => (2, vec![param(0)], param(1)),
         sym::simd_bitmask => (2, vec![param(0)], param(1)),
         sym::simd_select | sym::simd_select_bitmask => {
             (2, vec![param(0), param(1), param(1)], param(1))
diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs
index 85ceede5b9e3a..0b8ed0cc174b4 100644
--- a/library/core/src/num/f32.rs
+++ b/library/core/src/num/f32.rs
@@ -675,7 +675,7 @@ impl f32 {
     /// Returns the maximum of the two numbers.
     ///
     /// Follows the IEEE-754 2008 semantics for maxNum, except for handling of signaling NaNs.
-    /// This matches the behavior of libm’s fmin.
+    /// This matches the behavior of libm’s fmax.
     ///
     /// ```
     /// let x = 1.0f32;
diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs
index 4049c95b130f2..5a3cd2a4b9260 100644
--- a/library/core/src/num/f64.rs
+++ b/library/core/src/num/f64.rs
@@ -691,7 +691,7 @@ impl f64 {
     /// Returns the maximum of the two numbers.
     ///
     /// Follows the IEEE-754 2008 semantics for maxNum, except for handling of signaling NaNs.
-    /// This matches the behavior of libm’s fmin.
+    /// This matches the behavior of libm’s fmax.
     ///
     /// ```
     /// let x = 1.0_f64;
diff --git a/library/stdarch b/library/stdarch
index 1d5d0e8b0e313..11c98f6eb9c4b 160000
--- a/library/stdarch
+++ b/library/stdarch
@@ -1 +1 @@
-Subproject commit 1d5d0e8b0e3134dc781adb98057e38ffdf200df2
+Subproject commit 11c98f6eb9c4ba48b2362ad4960343b312d056b8
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index 865e14f694dcc..2455d56bd2b3f 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -554,16 +554,8 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
             extra_scripts: &[],
             static_extra_scripts: &[],
         };
-        let sidebar = if let Some(ref version) = self.shared.cache.crate_version {
-            format!(
-                "<h2 class=\"location\">Crate {}</h2>\
-                     <div class=\"block version\">\
-                         <p>Version {}</p>\
-                     </div>\
-                     <a id=\"all-types\" href=\"index.html\"><p>Back to index</p></a>",
-                crate_name,
-                Escape(version),
-            )
+        let sidebar = if self.shared.cache.crate_version.is_some() {
+            format!("<h2 class=\"location\">Crate {}</h2>", crate_name)
         } else {
             String::new()
         };
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index a79b3e8ed084b..29a793f3110b1 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -1744,13 +1744,6 @@ fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) {
             buffer,
             "<h2 class=\"location\"><a href=\"#\">{}{}</a></h2>",
             match *it.kind {
-                clean::StructItem(..) => "Struct ",
-                clean::TraitItem(..) => "Trait ",
-                clean::PrimitiveItem(..) => "Primitive Type ",
-                clean::UnionItem(..) => "Union ",
-                clean::EnumItem(..) => "Enum ",
-                clean::TypedefItem(..) => "Type Definition ",
-                clean::ForeignTypeItem => "Foreign Type ",
                 clean::ModuleItem(..) =>
                     if it.is_crate() {
                         "Crate "
@@ -1763,26 +1756,14 @@ fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) {
         );
     }
 
+    buffer.write_str("<div class=\"sidebar-elems\">");
     if it.is_crate() {
+        write!(buffer, "<div class=\"block\"><ul>");
         if let Some(ref version) = cx.cache().crate_version {
-            write!(
-                buffer,
-                "<div class=\"block version\">\
-                     <div class=\"narrow-helper\"></div>\
-                     <p>Version {}</p>\
-                 </div>",
-                Escape(version),
-            );
+            write!(buffer, "<li class=\"version\">Version {}</li>", Escape(version));
         }
-    }
-
-    buffer.write_str("<div class=\"sidebar-elems\">");
-    if it.is_crate() {
-        write!(
-            buffer,
-            "<a id=\"all-types\" href=\"all.html\"><p>See all {}'s items</p></a>",
-            it.name.as_ref().expect("crates always have a name"),
-        );
+        write!(buffer, "<li><a id=\"all-types\" href=\"all.html\">All Items</a></li>");
+        buffer.write_str("</div></ul>");
     }
 
     match *it.kind {
@@ -1806,7 +1787,7 @@ fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) {
     // to navigate the documentation (though slightly inefficiently).
 
     if !it.is_mod() {
-        buffer.write_str("<h2 class=\"location\">Other items in<br>");
+        buffer.write_str("<h2 class=\"location\">In ");
         for (i, name) in cx.current.iter().take(parentlen).enumerate() {
             if i > 0 {
                 buffer.write_str("::<wbr>");
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index bfdce74de67da..dbc068ce6b13b 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -169,8 +169,7 @@ h1.fqn {
 	section hierarchies. */
 h2,
 .top-doc h3,
-.top-doc h4,
-.sidebar .others h3 {
+.top-doc h4 {
 	border-bottom: 1px solid;
 }
 h3.code-header {
@@ -206,7 +205,11 @@ div.impl-items > div {
 }
 
 h1, h2, h3, h4, h5, h6,
-.sidebar, a.source, .search-input, .search-results .result-name,
+.sidebar,
+.mobile-topbar,
+a.source,
+.search-input,
+.search-results .result-name,
 .content table td:first-child > a,
 .item-left > a,
 .out-of-band,
@@ -261,6 +264,11 @@ textarea {
 	margin: 0;
 }
 
+button {
+	/* Buttons on Safari have different default padding than other platforms. Make them the same. */
+	padding: 1px 6px;
+}
+
 /* end tweaks for normalize.css 8 */
 
 .rustdoc {
@@ -359,15 +367,25 @@ nav.sub {
 }
 
 .sidebar {
-	width: 200px;
+	font-size: 0.9rem;
+	width: 250px;
+	min-width: 200px;
 	overflow-y: scroll;
 	position: sticky;
-	min-width: 200px;
 	height: 100vh;
 	top: 0;
 	left: 0;
 }
 
+.sidebar-elems,
+.sidebar > .location {
+	padding-left: 24px;
+}
+
+.sidebar .location {
+	overflow-wrap: anywhere;
+}
+
 .rustdoc.source .sidebar {
 	width: 50px;
 	min-width: 0px;
@@ -396,6 +414,10 @@ nav.sub {
 	visibility: visible;
 }
 
+#all-types {
+	margin-top: 1em;
+}
+
 /* Improve the scrollbar display on firefox */
 * {
 	scrollbar-width: initial;
@@ -415,48 +437,28 @@ nav.sub {
 	-webkit-box-shadow: inset 0;
 }
 
-.sidebar .block > ul > li {
-	margin-right: -10px;
-}
-
 /* Everything else */
 
 .hidden {
 	display: none !important;
 }
 
-.logo-container {
+.sidebar .logo-container {
 	display: flex;
 	margin-top: 10px;
 	margin-bottom: 10px;
 	justify-content: center;
 }
 
+.version {
+	overflow-wrap: break-word;
+}
+
 .logo-container > img {
 	height: 100px;
 	width: 100px;
 }
 
-.sidebar .location {
-	border: 1px solid;
-	font-size: 1.0625rem;
-	margin: 30px 10px 20px 10px;
-	text-align: center;
-	word-wrap: break-word;
-	font-weight: inherit;
-	padding: 0;
-}
-
-.sidebar .version {
-	font-size: 0.9375rem;
-	text-align: center;
-	border-bottom: 1px solid;
-	overflow-wrap: break-word;
-	overflow-wrap: anywhere;
-	word-wrap: break-word; /* deprecated */
-	word-break: break-word; /* Chrome, non-standard */
-}
-
 .location:empty {
 	border: none;
 }
@@ -470,48 +472,45 @@ nav.sub {
 
 .block {
 	padding: 0;
-	margin-bottom: 14px;
-}
-.block h2, .block h3 {
-	text-align: center;
 }
 .block ul, .block li {
-	margin: 0 10px;
 	padding: 0;
 	list-style: none;
 }
 
 .block a {
 	display: block;
+	padding: 0.3em;
+	margin-left: -0.3em;
+
 	text-overflow: ellipsis;
 	overflow: hidden;
-	line-height: 15px;
-	padding: 7px 5px;
-	font-size: 0.875rem;
-	font-weight: 300;
-	transition: border 500ms ease-out;
 }
 
-.sidebar-title {
-	border-top: 1px solid;
-	border-bottom: 1px solid;
-	text-align: center;
-	font-size: 1.0625rem;
-	margin-bottom: 5px;
-	font-weight: inherit;
+.sidebar h2 {
+	border-bottom: none;
+	font-weight: 500;
 	padding: 0;
+	margin: 0;
+	margin-top: 1rem;
+	margin-bottom: 1rem;
 }
 
-.sidebar-links {
-	margin-bottom: 15px;
+.sidebar h3 {
+	font-size: 1.1rem;
+	font-weight: 500;
+	padding: 0;
+	margin: 0;
+	margin-top: 0.5rem;
+	margin-bottom: 0.25rem;
 }
 
-.sidebar-links > a {
-	padding-left: 10px;
-	width: 100%;
+.sidebar-links,
+.block {
+	margin-bottom: 2em;
 }
 
-.sidebar-menu {
+.mobile-topbar {
 	display: none;
 }
 
@@ -784,13 +783,12 @@ nav.sub {
 	margin-top: 0;
 }
 
-nav:not(.sidebar) {
+nav.sub {
 	flex-grow: 1;
-	border-bottom: 1px solid;
 	padding-bottom: 10px;
 	margin-bottom: 25px;
 }
-.source nav:not(.sidebar).sub {
+.source nav.sub {
 	margin-left: 32px;
 }
 nav.main {
@@ -1395,18 +1393,6 @@ pre.rust {
 	margin-left: 5px;
 }
 
-#all-types {
-	text-align: center;
-	border: 1px solid;
-	margin: 0 10px;
-	margin-bottom: 10px;
-	display: block;
-	border-radius: 7px;
-}
-#all-types > p {
-	margin: 5px 0;
-}
-
 #sidebar-toggle {
 	position: sticky;
 	top: 0;
@@ -1752,8 +1738,12 @@ details.rustdoc-toggle[open] > summary.hideme::after {
 }
 
 @media (max-width: 700px) {
-	body {
+	.rustdoc {
 		padding-top: 0px;
+		/* Sidebar should overlay main content, rather than pushing main content to the right.
+		   Turn off `display: flex` on the body element. */
+		display: block;
+		scroll-margin-top: 45px;
 	}
 
 	main {
@@ -1761,134 +1751,110 @@ details.rustdoc-toggle[open] > summary.hideme::after {
 		padding-top: 0px;
 	}
 
-	/* Space is at a premium on mobile, so remove the theme-picker icon. */
-	#theme-picker {
-		display: none;
-		width: 0;
-	}
-
 	.rustdoc {
 		flex-direction: column;
 	}
 
-	.rustdoc:not(.source) > .sidebar {
-		width: 100%;
-		height: 45px;
-		min-height: 40px;
-		max-height: 45px;
-		margin: 0;
-		padding: 0 15px;
-		position: static;
-		z-index: 11;
-		overflow-y: hidden;
+	/* Hide the logo and item name from the sidebar. Those are displayed
+	   in the mobile-topbar instead. */
+	.sidebar .sidebar-logo,
+	.sidebar .location {
+		display: none;
 	}
 
-	.rustdoc.source > .sidebar {
+	.sidebar-elems {
+		margin-top: 1em;
+	}
+
+	.sidebar {
 		position: fixed;
-		top: 0;
-		left: 0;
+		top: 45px;
+		/* Hide the sidebar offscreen while not in use. Doing this instead of display: none means
+		   the sidebar stays visible for screen readers, which is useful for navigation. */
+		left: -1000px;
+		margin-left: 0;
+		background-color: rgba(0,0,0,0);
 		margin: 0;
+		padding: 0;
+		padding-left: 15px;
 		z-index: 11;
-		width: 0;
 	}
 
-	.sidebar.mobile {
-		position: sticky !important;
+	/* The source view uses a different design for the sidebar toggle, and doesn't have a topbar,
+	   so don't bump down the main content or the sidebar. */
+	.source main,
+	.source .sidebar {
 		top: 0;
+		padding: 0;
+	}
+
+	.sidebar.shown,
+	.sidebar.expanded,
+	.sidebar:focus-within {
 		left: 0;
-		width: 100%;
-		margin-left: 0;
-		background-color: rgba(0,0,0,0);
 	}
 
-	.sidebar > .location {
-		float: right;
-		margin: 0px;
-		margin-top: 2px;
-		padding: 3px 10px 1px 10px;
-		min-height: 39px;
-		background: inherit;
-		text-align: left;
-		font-size: 1.5rem;
+	.rustdoc.source > .sidebar {
+		position: fixed;
+		margin: 0;
+		z-index: 11;
+		width: 0;
 	}
 
-	.sidebar .location:empty {
-		padding: 0;
+	.mobile-topbar .location {
+		border: none;
+		margin: 0;
+		margin-left: auto;
+		padding: 0.3em;
+		padding-right: 0.6em;
+		text-overflow: ellipsis;
+		overflow-x: hidden;
 	}
 
-	.rustdoc:not(.source) .sidebar .logo-container {
-		width: 35px;
-		height: 35px;
-		margin-top: 5px;
-		margin-bottom: 5px;
-		float: left;
-		margin-left: 50px;
+	.mobile-topbar .logo-container {
+		max-height: 45px;
 	}
 
-	.sidebar .logo-container > img {
+	.mobile-topbar .logo-container > img {
 		max-width: 35px;
 		max-height: 35px;
+		margin-left: 20px;
+		margin-top: 5px;
+		margin-bottom: 5px;
 	}
 
-	.sidebar-menu {
-		position: fixed;
+	.mobile-topbar {
+		display: flex;
+		flex-direction: row;
+		position: sticky;
 		z-index: 10;
 		font-size: 2rem;
 		cursor: pointer;
-		width: 45px;
+		height: 45px;
+		width: 100%;
 		left: 0;
 		top: 0;
-		text-align: center;
-		display: block;
-		border-bottom: 1px solid;
-		border-right: 1px solid;
-		height: 45px;
 	}
 
-	.rustdoc.source > .sidebar > .sidebar-menu {
+	.source .mobile-topbar {
 		display: none;
 	}
 
-	/* We do NOT hide this element so that alternative device readers still have this information
-	   available. */
-	.sidebar-elems {
-		position: fixed;
-		z-index: 1;
-		top: 45px;
-		bottom: 0;
-		width: 246px;
-		/* We move the sidebar to the left by its own width so it doesn't appear. */
-		left: -246px;
-		overflow-y: auto;
-		border-right: 1px solid;
-	}
-
-	.sidebar > .block.version {
-		overflow: hidden;
-		border-bottom: none;
-		margin-bottom: 0;
-		height: 100%;
-		padding-left: 12px;
-	}
-	.sidebar > .block.version > div.narrow-helper {
-		float: left;
-		width: 1px;
-		height: 100%;
-	}
-	.sidebar > .block.version > p {
-		/* hide Version text if too narrow */
-		margin: 0;
-		min-width: 55px;
-		/* vertically center */
-		display: flex;
-		align-items: center;
-		height: 100%;
+	.sidebar-menu-toggle {
+		width: 45px;
+		border: none;
 	}
 
 	.source nav:not(.sidebar).sub {
 		margin-left: 32px;
 	}
 
+	/* Space is at a premium on mobile, so remove the theme-picker icon. */
+	#theme-picker {
+		display: none;
+		width: 0;
+	}
+
 	.content {
 		margin-left: 0px;
 	}
@@ -1925,28 +1891,6 @@ details.rustdoc-toggle[open] > summary.hideme::after {
 		height: 50px;
 	}
 
-	.show-it, .sidebar-elems:focus-within {
-		z-index:  2;
-		left: 0;
-	}
-
-	.show-it > .block.items {
-		margin: 8px 0;
-	}
-
-	.show-it > .block.items > ul {
-		margin: 0;
-	}
-
-	.show-it > .block.items > ul > li {
-		text-align: center;
-		margin: 2px 0;
-	}
-
-	.show-it > .block.items > ul > li > a {
-		font-size: 1.3125rem;
-	}
-
 	/* Because of ios, we need to actually have a full height sidebar title so the
 	 * actual sidebar can show up. But then we need to make it transparent so we don't
 	 * hide content. The filler just allows to create the background for the sidebar
@@ -1967,10 +1911,6 @@ details.rustdoc-toggle[open] > summary.hideme::after {
 		left: -11px;
 	}
 
-	#all-types {
-		margin: 10px;
-	}
-
 	.sidebar.expanded #sidebar-toggle {
 		font-size: 1.5rem;
 	}
diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css
index 885fe7c09a973..82a2be67ceb0c 100644
--- a/src/librustdoc/html/static/css/themes/ayu.css
+++ b/src/librustdoc/html/static/css/themes/ayu.css
@@ -57,7 +57,7 @@ pre, .rustdoc.source .example-wrap {
 	background-color: #191f26;
 }
 
-.sidebar {
+.sidebar, .mobile-topbar, .sidebar-menu-toggle {
 	background-color: #14191f;
 }
 
@@ -100,12 +100,6 @@ pre, .rustdoc.source .example-wrap {
 	background-color: #14191f;
 }
 
-.sidebar .location {
-	border-color: #000;
-	background-color: #0f1419;
-	color: #fff;
-}
-
 .sidebar-elems .location {
 	color: #ff7733;
 }
@@ -114,15 +108,6 @@ pre, .rustdoc.source .example-wrap {
 	color: #fff;
 }
 
-.sidebar .version {
-	border-bottom-color: #424c57;
-}
-
-.sidebar-title {
-	border-top-color: #5c6773;
-	border-bottom-color: #5c6773;
-}
-
 .block a:hover {
 	background: transparent;
 	color: #ffb44c;
@@ -228,7 +213,8 @@ a.anchor,
 .small-section-header a,
 #source-sidebar a,
 pre.rust a,
-.sidebar a,
+.sidebar h2 a,
+.sidebar h3 a,
 .in-band a {
 	color: #c5c5c5;
 }
@@ -581,13 +567,6 @@ kbd {
 	}
 }
 
-#all-types {
-	background-color: #14191f;
-}
-#all-types:hover {
-	background-color: rgba(70, 70, 70, 0.33);
-}
-
 .search-results .result-name span.alias {
 	color: #c5c5c5;
 }
diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css
index 71af77978328f..761bf50dd36b1 100644
--- a/src/librustdoc/html/static/css/themes/dark.css
+++ b/src/librustdoc/html/static/css/themes/dark.css
@@ -28,7 +28,7 @@ pre, .rustdoc.source .example-wrap {
 	background-color: #2A2A2A;
 }
 
-.sidebar {
+.sidebar, .mobile-topbar, .sidebar-menu-toggle {
 	background-color: #505050;
 }
 
@@ -69,21 +69,6 @@ pre, .rustdoc.source .example-wrap {
 	background-color: #565656;
 }
 
-.sidebar .location {
-	border-color: #fff;
-	background: #575757;
-	color: #DDD;
-}
-
-.sidebar .version {
-	border-bottom-color: #DDD;
-}
-
-.sidebar-title {
-	border-top-color: #777;
-	border-bottom-color: #777;
-}
-
 .block a:hover {
 	background: #444;
 }
@@ -186,7 +171,8 @@ a.anchor,
 .small-section-header a,
 #source-sidebar a,
 pre.rust a,
-.sidebar a,
+.sidebar h2 a,
+.sidebar h3 a,
 .in-band a {
 	color: #ddd;
 }
@@ -453,13 +439,6 @@ kbd {
 	}
 }
 
-#all-types {
-	background-color: #505050;
-}
-#all-types:hover {
-	background-color: #606060;
-}
-
 .search-results .result-name span.alias {
 	color: #fff;
 }
diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css
index e462fd16237f2..7cca7d4004b5e 100644
--- a/src/librustdoc/html/static/css/themes/light.css
+++ b/src/librustdoc/html/static/css/themes/light.css
@@ -30,7 +30,7 @@ pre, .rustdoc.source .example-wrap {
 	background-color: #F5F5F5;
 }
 
-.sidebar {
+.sidebar, .mobile-topbar, .sidebar-menu-toggle {
 	background-color: #F5F5F5;
 }
 
@@ -69,21 +69,6 @@ pre, .rustdoc.source .example-wrap {
 	background-color: #f1f1f1;
 }
 
-.sidebar .location {
-	border-color: #000;
-	background-color: #fff;
-	color: #333;
-}
-
-.sidebar .version {
-	border-bottom-color: #DDD;
-}
-
-.sidebar-title {
-	border-top-color: #777;
-	border-bottom-color: #777;
-}
-
 .block a:hover {
 	background: #F5F5F5;
 }
@@ -183,7 +168,8 @@ a.anchor,
 .small-section-header a,
 #source-sidebar a,
 pre.rust a,
-.sidebar a,
+.sidebar h2 a,
+.sidebar h3 a,
 .in-band a {
 	color: #000;
 }
@@ -440,13 +426,6 @@ kbd {
 	}
 }
 
-#all-types {
-	background-color: #fff;
-}
-#all-types:hover {
-	background-color: #f9f9f9;
-}
-
 .search-results .result-name span.alias {
 	color: #000;
 }
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index e7d1eedd35871..161b95d99930e 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -67,6 +67,13 @@ function resourcePath(basename, extension) {
             ty: sidebarVars.attributes["data-ty"].value,
             relpath: sidebarVars.attributes["data-relpath"].value,
         };
+        // FIXME: It would be nicer to generate this text content directly in HTML,
+        // but with the current code it's hard to get the right information in the right place.
+        var mobileLocationTitle = document.querySelector(".mobile-topbar h2.location");
+        var locationTitle = document.querySelector(".sidebar h2.location");
+        if (mobileLocationTitle && locationTitle) {
+            mobileLocationTitle.innerText = locationTitle.innerText;
+        }
     }
 }());
 
@@ -309,37 +316,6 @@ function hideThemeButtonState() {
         return null;
     }
 
-    function showSidebar() {
-        var elems = document.getElementsByClassName("sidebar-elems")[0];
-        if (elems) {
-            addClass(elems, "show-it");
-        }
-        var sidebar = document.getElementsByClassName("sidebar")[0];
-        if (sidebar) {
-            addClass(sidebar, "mobile");
-            var filler = document.getElementById("sidebar-filler");
-            if (!filler) {
-                var div = document.createElement("div");
-                div.id = "sidebar-filler";
-                sidebar.appendChild(div);
-            }
-        }
-    }
-
-    function hideSidebar() {
-        var elems = document.getElementsByClassName("sidebar-elems")[0];
-        if (elems) {
-            removeClass(elems, "show-it");
-        }
-        var sidebar = document.getElementsByClassName("sidebar")[0];
-        removeClass(sidebar, "mobile");
-        var filler = document.getElementById("sidebar-filler");
-        if (filler) {
-            filler.remove();
-        }
-        document.getElementsByTagName("body")[0].style.marginTop = "";
-    }
-
     var toggleAllDocsId = "toggle-all-docs";
     var main = document.getElementById(MAIN_ID);
     var savedHash = "";
@@ -374,7 +350,8 @@ function hideThemeButtonState() {
 
     function onHashChange(ev) {
         // If we're in mobile mode, we should hide the sidebar in any case.
-        hideSidebar();
+        var sidebar = document.getElementsByClassName("sidebar")[0];
+        removeClass(sidebar, "shown");
         handleHashes(ev);
     }
 
@@ -866,6 +843,11 @@ function hideThemeButtonState() {
         });
     }());
 
+    function hideSidebar() {
+        var sidebar = document.getElementsByClassName("sidebar")[0];
+        removeClass(sidebar, "shown");
+    }
+
     function handleClick(id, f) {
         var elem = document.getElementById(id);
         if (elem) {
@@ -906,16 +888,16 @@ function hideThemeButtonState() {
         };
     });
 
-    var sidebar_menu = document.getElementsByClassName("sidebar-menu")[0];
-    if (sidebar_menu) {
-        sidebar_menu.onclick = function() {
+    var sidebar_menu_toggle = document.getElementsByClassName("sidebar-menu-toggle")[0];
+    if (sidebar_menu_toggle) {
+        sidebar_menu_toggle.addEventListener("click", function() {
             var sidebar = document.getElementsByClassName("sidebar")[0];
-            if (hasClass(sidebar, "mobile")) {
-                hideSidebar();
+            if (!hasClass(sidebar, "shown")) {
+                addClass(sidebar, "shown");
             } else {
-                showSidebar();
+                removeClass(sidebar, "shown");
             }
-        };
+        });
     }
 
     var buildHelperPopup = function() {
diff --git a/src/librustdoc/html/static/js/source-script.js b/src/librustdoc/html/static/js/source-script.js
index 81dc0b2fb1eb9..498f60e9f25ae 100644
--- a/src/librustdoc/html/static/js/source-script.js
+++ b/src/librustdoc/html/static/js/source-script.js
@@ -139,7 +139,7 @@ function createSourceSidebar() {
                                       currentFile, hasFoundFile);
     });
 
-    container.insertBefore(sidebar, document.querySelector(".sidebar-logo").nextSibling);
+    container.appendChild(sidebar);
     // Focus on the current file in the source files sidebar.
     var selected_elem = sidebar.getElementsByClassName("selected")[0];
     if (typeof selected_elem !== "undefined") {
diff --git a/src/librustdoc/templates/page.html b/src/librustdoc/templates/page.html
index 1ef001ec2b719..1322b854b7fc7 100644
--- a/src/librustdoc/templates/page.html
+++ b/src/librustdoc/templates/page.html
@@ -72,8 +72,20 @@
     </div> {#- -#}
     <![endif]--> {#- -#}
     {{- layout.external_html.before_content|safe -}}
+    <nav class="mobile-topbar"> {#- -#}
+        <button class="sidebar-menu-toggle">&#9776;</button> {#- -#}
+        <a class="sidebar-logo" href="{{page.root_path|safe}}{{krate_with_trailing_slash|safe}}index.html"> {#- -#}
+            <div class="logo-container"> {#- -#}
+            {%- if !layout.logo.is_empty() -%}
+                <img src="{{layout.logo}}" alt="logo"> {#- -#}
+            {%- else -%}
+                <img class="rust-logo" src="{{static_root_path|safe}}rust-logo{{page.resource_suffix}}.svg" alt="logo"> {#- -#}
+            {%- endif -%}
+            </div>
+        </a> {#- -#}
+        <h2 class="location"></h2>
+    </nav>
     <nav class="sidebar"> {#- -#}
-        <div class="sidebar-menu" role="button">&#9776;</div> {#- -#}
         <a class="sidebar-logo" href="{{page.root_path|safe}}{{krate_with_trailing_slash|safe}}index.html"> {#- -#}
             <div class="logo-container"> {#- -#}
                 {%- if !layout.logo.is_empty()  %}
diff --git a/src/test/run-make/raw-dylib-c/Makefile b/src/test/run-make/raw-dylib-c/Makefile
index 26ab4d34764d1..166305672e6f2 100644
--- a/src/test/run-make/raw-dylib-c/Makefile
+++ b/src/test/run-make/raw-dylib-c/Makefile
@@ -1,14 +1,19 @@
 # Test the behavior of #[link(.., kind = "raw-dylib")] on windows-msvc
 
-# only-windows-msvc
+# only-windows
 
 -include ../../run-make-fulldeps/tools.mk
 
 all:
 	$(call COMPILE_OBJ,"$(TMPDIR)"/extern_1.obj,extern_1.c)
 	$(call COMPILE_OBJ,"$(TMPDIR)"/extern_2.obj,extern_2.c)
+ifdef IS_MSVC
 	$(CC) "$(TMPDIR)"/extern_1.obj -link -dll -out:"$(TMPDIR)"/extern_1.dll
 	$(CC) "$(TMPDIR)"/extern_2.obj -link -dll -out:"$(TMPDIR)"/extern_2.dll
+else
+	$(CC) "$(TMPDIR)"/extern_1.obj -shared -o "$(TMPDIR)"/extern_1.dll
+	$(CC) "$(TMPDIR)"/extern_2.obj -shared -o "$(TMPDIR)"/extern_2.dll
+endif
 	$(RUSTC) --crate-type lib --crate-name raw_dylib_test lib.rs
 	$(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
 	"$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt
diff --git a/src/test/run-make/raw-dylib-link-ordinal/Makefile b/src/test/run-make/raw-dylib-link-ordinal/Makefile
index 04b257d063204..0e84a749b0578 100644
--- a/src/test/run-make/raw-dylib-link-ordinal/Makefile
+++ b/src/test/run-make/raw-dylib-link-ordinal/Makefile
@@ -1,12 +1,16 @@
 # Test the behavior of #[link(.., kind = "raw-dylib")] and #[link_ordinal] on windows-msvc
 
-# only-windows-msvc
+# only-windows
 
 -include ../../run-make-fulldeps/tools.mk
 
 all:
 	$(call COMPILE_OBJ,"$(TMPDIR)"/exporter.obj,exporter.c)
+ifdef IS_MSVC
 	$(CC) "$(TMPDIR)"/exporter.obj exporter.def -link -dll -out:"$(TMPDIR)"/exporter.dll
+else
+	$(CC) "$(TMPDIR)"/exporter.obj exporter.def -shared -o "$(TMPDIR)"/exporter.dll
+endif
 	$(RUSTC) --crate-type lib --crate-name raw_dylib_test lib.rs
 	$(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
 	"$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt
diff --git a/src/test/run-make/raw-dylib-stdcall-ordinal/Makefile b/src/test/run-make/raw-dylib-stdcall-ordinal/Makefile
new file mode 100644
index 0000000000000..69f62669d6291
--- /dev/null
+++ b/src/test/run-make/raw-dylib-stdcall-ordinal/Makefile
@@ -0,0 +1,23 @@
+# Test the behavior of #[link(.., kind = "raw-dylib")], #[link_ordinal], and alternative calling conventions on i686 windows.
+
+# only-x86
+# only-windows
+
+-include ../../run-make-fulldeps/tools.mk
+
+all:
+	$(call COMPILE_OBJ,"$(TMPDIR)"/exporter.obj,exporter.c)
+ifdef IS_MSVC
+	$(CC) "$(TMPDIR)"/exporter.obj exporter-msvc.def -link -dll -out:"$(TMPDIR)"/exporter.dll
+else
+	$(CC) "$(TMPDIR)"/exporter.obj exporter-gnu.def -shared -o "$(TMPDIR)"/exporter.dll
+endif
+	$(RUSTC) --crate-type lib --crate-name raw_dylib_test lib.rs
+	$(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
+	"$(TMPDIR)"/driver > "$(TMPDIR)"/actual_output.txt
+
+ifdef RUSTC_BLESS_TEST
+	cp "$(TMPDIR)"/actual_output.txt expected_output.txt
+else
+	$(DIFF) expected_output.txt "$(TMPDIR)"/actual_output.txt
+endif
diff --git a/src/test/run-make/raw-dylib-stdcall-ordinal/driver.rs b/src/test/run-make/raw-dylib-stdcall-ordinal/driver.rs
new file mode 100644
index 0000000000000..4059ede11fc96
--- /dev/null
+++ b/src/test/run-make/raw-dylib-stdcall-ordinal/driver.rs
@@ -0,0 +1,5 @@
+extern crate raw_dylib_test;
+
+fn main() {
+    raw_dylib_test::library_function();
+}
diff --git a/src/test/run-make/raw-dylib-stdcall-ordinal/expected_output.txt b/src/test/run-make/raw-dylib-stdcall-ordinal/expected_output.txt
new file mode 100644
index 0000000000000..20157763745f8
--- /dev/null
+++ b/src/test/run-make/raw-dylib-stdcall-ordinal/expected_output.txt
@@ -0,0 +1,2 @@
+exported_function_stdcall(6)
+exported_function_fastcall(125)
diff --git a/src/test/run-make/raw-dylib-stdcall-ordinal/exporter-gnu.def b/src/test/run-make/raw-dylib-stdcall-ordinal/exporter-gnu.def
new file mode 100644
index 0000000000000..8d28d714b7e64
--- /dev/null
+++ b/src/test/run-make/raw-dylib-stdcall-ordinal/exporter-gnu.def
@@ -0,0 +1,4 @@
+LIBRARY exporter
+EXPORTS
+    exported_function_stdcall@4 @15 NONAME
+    @exported_function_fastcall@4 @18 NONAME
\ No newline at end of file
diff --git a/src/test/run-make/raw-dylib-stdcall-ordinal/exporter-msvc.def b/src/test/run-make/raw-dylib-stdcall-ordinal/exporter-msvc.def
new file mode 100644
index 0000000000000..5a4c79a58edfd
--- /dev/null
+++ b/src/test/run-make/raw-dylib-stdcall-ordinal/exporter-msvc.def
@@ -0,0 +1,4 @@
+LIBRARY exporter
+EXPORTS
+    _exported_function_stdcall@4 @15 NONAME
+    @exported_function_fastcall@4 @18 NONAME
\ No newline at end of file
diff --git a/src/test/run-make/raw-dylib-stdcall-ordinal/exporter.c b/src/test/run-make/raw-dylib-stdcall-ordinal/exporter.c
new file mode 100644
index 0000000000000..1fb45bf010ff2
--- /dev/null
+++ b/src/test/run-make/raw-dylib-stdcall-ordinal/exporter.c
@@ -0,0 +1,11 @@
+#include <stdio.h>
+
+void __stdcall exported_function_stdcall(int i) {
+    printf("exported_function_stdcall(%d)\n", i);
+    fflush(stdout);
+}
+
+void __fastcall exported_function_fastcall(int i) {
+    printf("exported_function_fastcall(%d)\n", i);
+    fflush(stdout);
+}
diff --git a/src/test/run-make/raw-dylib-stdcall-ordinal/lib.rs b/src/test/run-make/raw-dylib-stdcall-ordinal/lib.rs
new file mode 100644
index 0000000000000..07dd3d7be9b90
--- /dev/null
+++ b/src/test/run-make/raw-dylib-stdcall-ordinal/lib.rs
@@ -0,0 +1,20 @@
+#![feature(raw_dylib)]
+
+#[link(name = "exporter", kind = "raw-dylib")]
+extern "stdcall" {
+    #[link_ordinal(15)]
+    fn imported_function_stdcall(i: i32);
+}
+
+#[link(name = "exporter", kind = "raw-dylib")]
+extern "fastcall" {
+    #[link_ordinal(18)]
+    fn imported_function_fastcall(i: i32);
+}
+
+pub fn library_function() {
+    unsafe {
+        imported_function_stdcall(6);
+        imported_function_fastcall(125);
+    }
+}
diff --git a/src/test/rustdoc-gui/anchors.goml b/src/test/rustdoc-gui/anchors.goml
index e6758287d8cb2..2d48d21dc1b05 100644
--- a/src/test/rustdoc-gui/anchors.goml
+++ b/src/test/rustdoc-gui/anchors.goml
@@ -20,7 +20,7 @@ assert-css: (".srclink", {"text-decoration": "underline solid rgb(56, 115, 173)"
 
 assert-css: ("#top-doc-prose-title", {"color": "rgb(0, 0, 0)"})
 
-assert-css: (".sidebar a", {"color": "rgb(0, 0, 0)"})
+assert-css: (".sidebar a", {"color": "rgb(56, 115, 173)"})
 assert-css: (".in-band a", {"color": "rgb(0, 0, 0)"})
 
 // We move the cursor over the "Implementations" title so the anchor is displayed.
diff --git a/src/test/rustdoc-gui/code-blocks-overflow.goml b/src/test/rustdoc-gui/code-blocks-overflow.goml
index ee4dad444e932..f93f3f0aefc51 100644
--- a/src/test/rustdoc-gui/code-blocks-overflow.goml
+++ b/src/test/rustdoc-gui/code-blocks-overflow.goml
@@ -5,4 +5,4 @@ size: (1080, 600)
 assert-count: (".docblock > .example-wrap", 2)
 assert: ".docblock > .example-wrap > .language-txt"
 assert: ".docblock > .example-wrap > .rust-example-rendered"
-assert-css: (".docblock > .example-wrap > pre", {"width": "796px", "overflow-x": "auto"}, ALL)
+assert-css: (".docblock > .example-wrap > pre", {"width": "785.25px", "overflow-x": "auto"}, ALL)
diff --git a/src/test/rustdoc-gui/docblock-table-overflow.goml b/src/test/rustdoc-gui/docblock-table-overflow.goml
index 1b3006155d8b6..a9af88189a67d 100644
--- a/src/test/rustdoc-gui/docblock-table-overflow.goml
+++ b/src/test/rustdoc-gui/docblock-table-overflow.goml
@@ -4,7 +4,7 @@ goto: file://|DOC_PATH|/lib2/long_table/struct.Foo.html
 size: (1100, 800)
 // Logically, the ".docblock" and the "<p>" should have the same scroll width.
 compare-elements-property: (".top-doc .docblock", ".top-doc .docblock > p", ["scrollWidth"])
-assert-property: (".top-doc .docblock", {"scrollWidth": "816"})
+assert-property: (".top-doc .docblock", {"scrollWidth": "801"})
 // However, since there is overflow in the <table>, its scroll width is bigger.
 assert-property: (".top-doc .docblock table", {"scrollWidth": "1573"})
 
@@ -16,6 +16,6 @@ compare-elements-property: (
     "#implementations + details .docblock > p",
     ["scrollWidth"],
 )
-assert-property: ("#implementations + details .docblock", {"scrollWidth": "816"})
+assert-property: ("#implementations + details .docblock", {"scrollWidth": "801"})
 // However, since there is overflow in the <table>, its scroll width is bigger.
 assert-property: ("#implementations + details .docblock table", {"scrollWidth": "1573"})
diff --git a/src/test/rustdoc-gui/headings.goml b/src/test/rustdoc-gui/headings.goml
index 34fadd84ae834..34ff2de3a9b2b 100644
--- a/src/test/rustdoc-gui/headings.goml
+++ b/src/test/rustdoc-gui/headings.goml
@@ -110,7 +110,7 @@ assert-css: ("h6#sub-sub-heading-for-enum-impl-item-doc", {"font-size": "15.2px"
 assert-css: ("h6#sub-sub-heading-for-enum-impl-item-doc", {"border-bottom-width": "0px"})
 
 assert-text: (".sidebar .others h3", "Modules")
-assert-css: (".sidebar .others h3", {"border-bottom-width": "1px"}, ALL)
+assert-css: (".sidebar .others h3", {"border-bottom-width": "0px"}, ALL)
 
 goto: file://|DOC_PATH|/test_docs/union.HeavilyDocumentedUnion.html
 
diff --git a/src/test/rustdoc-gui/item-info-width.goml b/src/test/rustdoc-gui/item-info-width.goml
index cdc00d3411403..acb30141ce577 100644
--- a/src/test/rustdoc-gui/item-info-width.goml
+++ b/src/test/rustdoc-gui/item-info-width.goml
@@ -3,5 +3,5 @@ goto: file://|DOC_PATH|/lib2/struct.Foo.html
 // We set a fixed size so there is no chance of "random" resize.
 size: (1100, 800)
 // We check that ".item-info" is bigger than its content.
-assert-css: (".item-info", {"width": "807px"})
+assert-css: (".item-info", {"width": "757px"})
 assert-css: (".item-info .stab", {"width": "341px"})
diff --git a/src/test/rustdoc-gui/search-result-display.goml b/src/test/rustdoc-gui/search-result-display.goml
index ea94e5640fbd1..3162a067d2107 100644
--- a/src/test/rustdoc-gui/search-result-display.goml
+++ b/src/test/rustdoc-gui/search-result-display.goml
@@ -5,7 +5,7 @@ write: (".search-input", "test")
 wait-for: "#titles"
 // The width is returned by "getComputedStyle" which returns the exact number instead of the
 // CSS rule which is "50%"...
-assert-css: (".search-results div.desc", {"width": "320px"})
+assert-css: (".search-results div.desc", {"width": "295px"})
 size: (600, 100)
 // As counter-intuitive as it may seem, in this width, the width is "100%", which is why
 // when computed it's larger.
diff --git a/src/test/rustdoc-gui/sidebar-mobile.goml b/src/test/rustdoc-gui/sidebar-mobile.goml
index eecd584bca9ec..547eb3fd1b3d1 100644
--- a/src/test/rustdoc-gui/sidebar-mobile.goml
+++ b/src/test/rustdoc-gui/sidebar-mobile.goml
@@ -4,25 +4,28 @@
 goto: file://|DOC_PATH|/test_docs/struct.Foo.html
 // Switching to "mobile view" by reducing the width to 600px.
 size: (600, 600)
-assert-css: (".sidebar-elems", {"display": "block", "left": "-246px"})
+assert-css: (".sidebar", {"display": "block", "left": "-1000px"})
 // Opening the sidebar menu.
-click: ".sidebar-menu"
-assert-css: (".sidebar-elems", {"display": "block", "left": "0px"})
+click: ".sidebar-menu-toggle"
+assert-css: (".sidebar", {"display": "block", "left": "0px"})
 // Closing the sidebar menu.
-click: ".sidebar-menu"
-assert-css: (".sidebar-elems", {"display": "block", "left": "-246px"})
+click: ".sidebar-menu-toggle"
+assert-css: (".sidebar", {"display": "block", "left": "-1000px"})
 // Force the sidebar open by focusing a link inside it.
 // This makes it easier for keyboard users to get to it.
 focus: ".sidebar-title a"
-assert-css: (".sidebar-elems", {"display": "block", "left": "0px"})
+assert-css: (".sidebar", {"display": "block", "left": "0px"})
 // When we tab out of the sidebar, close it.
 focus: ".search-input"
-assert-css: (".sidebar-elems", {"display": "block", "left": "-246px"})
+assert-css: (".sidebar", {"display": "block", "left": "-1000px"})
 
 // Open the sidebar menu.
-click: ".sidebar-menu"
-assert-css: (".sidebar-elems", {"left": "0px"})
+click: ".sidebar-menu-toggle"
+assert-css: (".sidebar", {"left": "0px"})
 
 // Click elsewhere.
 click: "body"
-assert-css: (".sidebar-elems", {"left": "-246px"})
+assert-css: (".sidebar", {"display": "block", "left": "-1000px"})
+
+// Check that the topbar is visible
+assert-property: (".mobile-topbar", {"clientHeight": "45"})
diff --git a/src/test/rustdoc-gui/sidebar-source-code.goml b/src/test/rustdoc-gui/sidebar-source-code.goml
index 98f4fdf4233c2..1c5eb9239ba8b 100644
--- a/src/test/rustdoc-gui/sidebar-source-code.goml
+++ b/src/test/rustdoc-gui/sidebar-source-code.goml
@@ -10,6 +10,7 @@ click: (10, 10)
 // We wait for the sidebar to be expanded (there is a 0.5s animation).
 wait-for: 600
 assert-css: ("nav.sidebar.expanded", {"width": "300px"})
+assert-css: ("nav.sidebar.expanded a", {"font-size": "14.4px"})
 // We collapse the sidebar.
 click: (10, 10)
 // We wait for the sidebar to be collapsed (there is a 0.5s animation).
@@ -30,3 +31,6 @@ click: (10, 10)
 // We ensure that the class has been removed.
 assert-false: "nav.sidebar.expanded"
 assert: "nav.sidebar"
+
+// Check that the topbar is not visible
+assert-property: (".mobile-topbar", {"offsetParent": "null"})
diff --git a/src/test/rustdoc-gui/sidebar.goml b/src/test/rustdoc-gui/sidebar.goml
index 9289244f6f8bb..a117552585820 100644
--- a/src/test/rustdoc-gui/sidebar.goml
+++ b/src/test/rustdoc-gui/sidebar.goml
@@ -1,8 +1,14 @@
 goto: file://|DOC_PATH|/test_docs/index.html
+show-text: true
+local-storage: {"rustdoc-theme": "light"}
+// We reload the page so the local storage settings are being used.
+reload:
+
 assert-text: (".sidebar > .location", "Crate test_docs")
 // In modules, we only have one "location" element.
 assert-count: (".sidebar .location", 1)
-assert-text: (".sidebar-elems > #all-types", "See all test_docs's items")
+assert-text: ("#all-types", "All Items")
+assert-css: ("#all-types", {"color": "rgb(56, 115, 173)"})
 // We check that we have the crates list and that the "current" on is "test_docs".
 assert-text: (".sidebar-elems .crate > ul > li > a.current", "test_docs")
 // And we're also supposed to have the list of items in the current module.
@@ -24,13 +30,14 @@ assert-count: (".sidebar .location", 2)
 assert-false: ".sidebar-elems > .crate"
 
 click: ".sidebar-links a"
-assert-property: ("html", {"scrollTop": "389"})
+assert-property-false: ("html", {"scrollTop": "0"})
 
-click: ".sidebar h2.location"
+click: ".sidebar h2.location a"
 assert-property: ("html", {"scrollTop": "0"})
 
 // We now go back to the crate page to click on the "lib2" crate link.
 goto: file://|DOC_PATH|/test_docs/index.html
+assert-css: (".sidebar-elems .crate > ul > li:first-child > a", {"color": "rgb(56, 115, 173)"})
 click: ".sidebar-elems .crate > ul > li:first-child > a"
 
 // PAGE: lib2/index.html
@@ -51,8 +58,7 @@ click: "#functions + .item-table .item-left > a"
 // In items containing no items (like functions or constants) and in modules, we have one
 // "location" elements.
 assert-count: (".sidebar .location", 1)
-// There is a "<br>" tag between "in" and "lib2", but it doesn't count as a space.
-assert-text: (".sidebar .sidebar-elems .location", "Other items inlib2")
+assert-text: (".sidebar .sidebar-elems .location", "In lib2")
 // We check that we don't have the crate list.
 assert-false: ".sidebar-elems > .crate"
 
diff --git a/src/test/rustdoc-gui/type-declation-overflow.goml b/src/test/rustdoc-gui/type-declation-overflow.goml
index bb24d0ce79254..21874f786f1ad 100644
--- a/src/test/rustdoc-gui/type-declation-overflow.goml
+++ b/src/test/rustdoc-gui/type-declation-overflow.goml
@@ -11,7 +11,7 @@ assert-property: (".item-decl pre", {"scrollWidth": "1324"})
 goto: file://|DOC_PATH|/lib2/too_long/type.ReallyLongTypeNameLongLongLong.html
 assert-property: ("body", {"scrollWidth": "1100"})
 // We now check that the section width hasn't grown because of it.
-assert-property: ("#main-content", {"scrollWidth": "840"})
+assert-property: ("#main-content", {"scrollWidth": "825"})
 // And now checking that it has scrollable content.
 assert-property: (".item-decl pre", {"scrollWidth": "1103"})
 
@@ -20,6 +20,13 @@ assert-property: (".item-decl pre", {"scrollWidth": "1103"})
 goto: file://|DOC_PATH|/lib2/too_long/constant.ReallyLongTypeNameLongLongLongConstBecauseWhyNotAConstRightGigaGigaSupraLong.html
 assert-property: ("body", {"scrollWidth": "1100"})
 // We now check that the section width hasn't grown because of it.
-assert-property: ("#main-content", {"scrollWidth": "840"})
+assert-property: ("#main-content", {"scrollWidth": "825"})
 // And now checking that it has scrollable content.
 assert-property: (".item-decl pre", {"scrollWidth": "950"})
+
+// On mobile:
+size: (600, 600)
+goto: file://|DOC_PATH|/lib2/too_long/struct.SuperIncrediblyLongLongLongLongLongLongLongGigaGigaGigaMegaLongLongLongStructName.html
+assert-property: (".mobile-topbar .location", {"scrollWidth": "504"})
+assert-property: (".mobile-topbar .location", {"clientWidth": "504"})
+assert-css: (".mobile-topbar .location", {"overflow-x": "hidden"})
diff --git a/src/test/rustdoc/cap-lints.rs b/src/test/rustdoc/cap-lints.rs
index 15910e1e9006d..08a35339680cd 100644
--- a/src/test/rustdoc/cap-lints.rs
+++ b/src/test/rustdoc/cap-lints.rs
@@ -3,7 +3,7 @@
 // therefore should not concern itself with the lints.
 #[deny(warnings)]
 
-// @has cap_lints/struct.Foo.html //* 'Struct Foo'
+// @has cap_lints/struct.Foo.html //* 'Foo'
 pub struct Foo {
     field: i32,
 }
diff --git a/src/test/rustdoc/crate-version-escape.rs b/src/test/rustdoc/crate-version-escape.rs
index 2f91eea339b39..8413709f15e90 100644
--- a/src/test/rustdoc/crate-version-escape.rs
+++ b/src/test/rustdoc/crate-version-escape.rs
@@ -2,5 +2,4 @@
 
 #![crate_name = "foo"]
 
-// @has 'foo/index.html' '//div[@class="block version"]/p' 'Version <script>alert("hi")</script>'
-// @has 'foo/all.html' '//div[@class="block version"]/p' 'Version <script>alert("hi")</script>'
+// @has 'foo/index.html' '//li[@class="version"]' 'Version <script>alert("hi")</script>'
diff --git a/src/test/rustdoc/crate-version.rs b/src/test/rustdoc/crate-version.rs
index 893af5c61332d..2592c98530fe4 100644
--- a/src/test/rustdoc/crate-version.rs
+++ b/src/test/rustdoc/crate-version.rs
@@ -1,3 +1,3 @@
 // compile-flags: --crate-version=1.3.37
 
-// @has 'crate_version/index.html' '//div[@class="block version"]/p' 'Version 1.3.37'
+// @has 'crate_version/index.html' '//*[@class="version"]' 'Version 1.3.37'
diff --git a/src/test/rustdoc/titles.rs b/src/test/rustdoc/titles.rs
index 016ec7bfaa307..69e8b856b0a26 100644
--- a/src/test/rustdoc/titles.rs
+++ b/src/test/rustdoc/titles.rs
@@ -1,10 +1,11 @@
 #![crate_name = "foo"]
-
 #![feature(rustdoc_internals)]
 
 // @matches 'foo/index.html' '//h1' 'Crate foo'
+// @matches 'foo/index.html' '//h2[@class="location"]' 'Crate foo'
 
 // @matches 'foo/foo_mod/index.html' '//h1' 'Module foo::foo_mod'
+// @matches 'foo/foo_mod/index.html' '//h2[@class="location"]' 'Module foo_mod'
 pub mod foo_mod {
     pub struct __Thing {}
 }
@@ -18,15 +19,19 @@ extern "C" {
 pub fn foo_fn() {}
 
 // @matches 'foo/trait.FooTrait.html' '//h1' 'Trait foo::FooTrait'
+// @matches 'foo/trait.FooTrait.html' '//h2[@class="location"]' 'FooTrait'
 pub trait FooTrait {}
 
 // @matches 'foo/struct.FooStruct.html' '//h1' 'Struct foo::FooStruct'
+// @matches 'foo/struct.FooStruct.html' '//h2[@class="location"]' 'FooStruct'
 pub struct FooStruct;
 
 // @matches 'foo/enum.FooEnum.html' '//h1' 'Enum foo::FooEnum'
+// @matches 'foo/enum.FooEnum.html' '//h2[@class="location"]' 'FooEnum'
 pub enum FooEnum {}
 
 // @matches 'foo/type.FooType.html' '//h1' 'Type Definition foo::FooType'
+// @matches 'foo/type.FooType.html' '//h2[@class="location"]' 'FooType'
 pub type FooType = FooStruct;
 
 // @matches 'foo/macro.foo_macro.html' '//h1' 'Macro foo::foo_macro'
diff --git a/src/test/rustdoc/typedef.rs b/src/test/rustdoc/typedef.rs
index 1fb28ee99702f..4ecd62cded22e 100644
--- a/src/test/rustdoc/typedef.rs
+++ b/src/test/rustdoc/typedef.rs
@@ -12,7 +12,7 @@ impl MyStruct {
 // @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'impl MyAlias'
 // @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'impl MyTrait for MyAlias'
 // @has - 'Alias docstring'
-// @has - '//*[@class="sidebar"]//*[@class="location"]' 'Type Definition MyAlias'
+// @has - '//*[@class="sidebar"]//*[@class="location"]' 'MyAlias'
 // @has - '//*[@class="sidebar"]//a[@href="#implementations"]' 'Methods'
 // @has - '//*[@class="sidebar"]//a[@href="#trait-implementations"]' 'Trait Implementations'
 /// Alias docstring
diff --git a/src/test/ui/const-generics/issues/issue-92186.rs b/src/test/ui/const-generics/issues/issue-92186.rs
new file mode 100644
index 0000000000000..9ced4667d249a
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-92186.rs
@@ -0,0 +1,12 @@
+// check-pass
+
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+pub struct Foo<const N: usize>;
+pub trait Bar<T> {}
+
+impl<T> Bar<T> for Foo<{ 1 }> {}
+impl<T> Bar<T> for Foo<{ 2 }> {}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/types-mismatch-const-args.full.stderr b/src/test/ui/const-generics/types-mismatch-const-args.full.stderr
index 565c9ba1ff1f6..4d6b752867f1b 100644
--- a/src/test/ui/const-generics/types-mismatch-const-args.full.stderr
+++ b/src/test/ui/const-generics/types-mismatch-const-args.full.stderr
@@ -15,9 +15,20 @@ LL |     let _: A<'a, u16, {2u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data
    |            |
    |            expected due to this
    |
-   = note: expected struct `A<'a, u16, {2u32}, {3u32}>`
-              found struct `A<'b, u32, {2u32}, {3u32}>`
+   = note: expected struct `A<'a, u16, _, _>`
+              found struct `A<'b, u32, _, _>`
 
-error: aborting due to 2 previous errors
+error[E0308]: mismatched types
+  --> $DIR/types-mismatch-const-args.rs:18:41
+   |
+LL |     let _: A<'a, u16, {4u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData };
+   |            --------------------------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u16`, found `u32`
+   |            |
+   |            expected due to this
+   |
+   = note: expected struct `A<'a, u16, 4_u32, _>`
+              found struct `A<'b, u32, 2_u32, _>`
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/types-mismatch-const-args.min.stderr b/src/test/ui/const-generics/types-mismatch-const-args.min.stderr
index ec9221d2486ae..8b60238cb0c03 100644
--- a/src/test/ui/const-generics/types-mismatch-const-args.min.stderr
+++ b/src/test/ui/const-generics/types-mismatch-const-args.min.stderr
@@ -20,6 +20,17 @@ LL |     let _: A<'a, u16, {2u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data
    = note: expected struct `A<'a, u16, _, _>`
               found struct `A<'b, u32, _, _>`
 
-error: aborting due to 2 previous errors
+error[E0308]: mismatched types
+  --> $DIR/types-mismatch-const-args.rs:18:41
+   |
+LL |     let _: A<'a, u16, {4u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData };
+   |            --------------------------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u16`, found `u32`
+   |            |
+   |            expected due to this
+   |
+   = note: expected struct `A<'a, u16, 4_u32, _>`
+              found struct `A<'b, u32, 2_u32, _>`
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/types-mismatch-const-args.rs b/src/test/ui/const-generics/types-mismatch-const-args.rs
index c2092c4268e80..43ef28b268f56 100644
--- a/src/test/ui/const-generics/types-mismatch-const-args.rs
+++ b/src/test/ui/const-generics/types-mismatch-const-args.rs
@@ -15,6 +15,8 @@ fn a<'a, 'b>() {
     //~^ ERROR mismatched types
     let _: A<'a, u16, {2u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData };
     //~^ ERROR mismatched types
+    let _: A<'a, u16, {4u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData };
+    //~^ ERROR mismatched types
 }
 
 pub fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-raw-dylib-windows-gnu.rs b/src/test/ui/feature-gates/feature-gate-raw-dylib-windows-gnu.rs
deleted file mode 100644
index 33f9c5393135f..0000000000000
--- a/src/test/ui/feature-gates/feature-gate-raw-dylib-windows-gnu.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-// gate-test-raw_dylib
-// only-windows-gnu
-#[link(name = "foo", kind = "raw-dylib")]
-//~^ ERROR: kind="raw-dylib" is unstable
-//~| WARNING: `#[link(...)]` with `kind = "raw-dylib"` not supported on windows-gnu
-extern "C" {}
-
-fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-raw-dylib-windows-gnu.stderr b/src/test/ui/feature-gates/feature-gate-raw-dylib-windows-gnu.stderr
deleted file mode 100644
index 14dfadf4126f3..0000000000000
--- a/src/test/ui/feature-gates/feature-gate-raw-dylib-windows-gnu.stderr
+++ /dev/null
@@ -1,18 +0,0 @@
-warning: `#[link(...)]` with `kind = "raw-dylib"` not supported on windows-gnu
-  --> $DIR/feature-gate-raw-dylib-windows-gnu.rs:3:1
-   |
-LL | #[link(name = "foo", kind = "raw-dylib")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0658]: kind="raw-dylib" is unstable
-  --> $DIR/feature-gate-raw-dylib-windows-gnu.rs:3:1
-   |
-LL | #[link(name = "foo", kind = "raw-dylib")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #58713 <https://github.com/rust-lang/rust/issues/58713> for more information
-   = help: add `#![feature(raw_dylib)]` to the crate attributes to enable
-
-error: aborting due to previous error; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-raw-dylib-windows-msvc.rs b/src/test/ui/feature-gates/feature-gate-raw-dylib.rs
similarity index 71%
rename from src/test/ui/feature-gates/feature-gate-raw-dylib-windows-msvc.rs
rename to src/test/ui/feature-gates/feature-gate-raw-dylib.rs
index 49de24ea9ab42..995d9ced4801a 100644
--- a/src/test/ui/feature-gates/feature-gate-raw-dylib-windows-msvc.rs
+++ b/src/test/ui/feature-gates/feature-gate-raw-dylib.rs
@@ -1,5 +1,4 @@
-// gate-test-raw_dylib
-// only-windows-msvc
+// only-windows
 #[link(name = "foo", kind = "raw-dylib")]
 //~^ ERROR: kind="raw-dylib" is unstable
 extern "C" {}
diff --git a/src/test/ui/feature-gates/feature-gate-raw-dylib-windows-msvc.stderr b/src/test/ui/feature-gates/feature-gate-raw-dylib.stderr
similarity index 88%
rename from src/test/ui/feature-gates/feature-gate-raw-dylib-windows-msvc.stderr
rename to src/test/ui/feature-gates/feature-gate-raw-dylib.stderr
index 1198808081213..bb64af38b2cb9 100644
--- a/src/test/ui/feature-gates/feature-gate-raw-dylib-windows-msvc.stderr
+++ b/src/test/ui/feature-gates/feature-gate-raw-dylib.stderr
@@ -1,5 +1,5 @@
 error[E0658]: kind="raw-dylib" is unstable
-  --> $DIR/feature-gate-raw-dylib-windows-msvc.rs:3:1
+  --> $DIR/feature-gate-raw-dylib.rs:2:1
    |
 LL | #[link(name = "foo", kind = "raw-dylib")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/macros/macro-interpolation.rs b/src/test/ui/macros/macro-interpolation.rs
index abe1f2aaf153b..35003a79ad703 100644
--- a/src/test/ui/macros/macro-interpolation.rs
+++ b/src/test/ui/macros/macro-interpolation.rs
@@ -14,8 +14,20 @@ macro_rules! overly_complicated {
 
 }
 
+macro_rules! qpath {
+    (path, <$type:ty as $trait:path>::$name:ident) => {
+        <$type as $trait>::$name
+    };
+
+    (ty, <$type:ty as $trait:ty>::$name:ident) => {
+        <$type as $trait>::$name
+    };
+}
+
 pub fn main() {
+    let _: qpath!(path, <str as ToOwned>::Owned);
+    let _: qpath!(ty, <str as ToOwned>::Owned);
+
     assert!(overly_complicated!(f, x, Option<usize>, { return Some(x); },
                                Some(8), Some(y), y) == 8)
-
 }
diff --git a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-multiple.rs b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-multiple.rs
index 0ab994ecd45be..2a15b1d799f84 100644
--- a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-multiple.rs
+++ b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-multiple.rs
@@ -1,4 +1,4 @@
-// only-windows-msvc
+// only-windows
 #![feature(raw_dylib)]
 //~^ WARN the feature `raw_dylib` is incomplete
 
diff --git a/src/test/ui/rfc-2627-raw-dylib/multiple-declarations.rs b/src/test/ui/rfc-2627-raw-dylib/multiple-declarations.rs
index d02bebc9d61d2..13c9aa01e34ae 100644
--- a/src/test/ui/rfc-2627-raw-dylib/multiple-declarations.rs
+++ b/src/test/ui/rfc-2627-raw-dylib/multiple-declarations.rs
@@ -1,4 +1,5 @@
-// only-i686-pc-windows-msvc
+// only-x86
+// only-windows
 // compile-flags: --crate-type lib --emit link
 #![allow(clashing_extern_declarations)]
 #![feature(raw_dylib)]
diff --git a/src/test/ui/rfc-2627-raw-dylib/multiple-declarations.stderr b/src/test/ui/rfc-2627-raw-dylib/multiple-declarations.stderr
index a9cfd6b23f9f8..93ca8f4d8d448 100644
--- a/src/test/ui/rfc-2627-raw-dylib/multiple-declarations.stderr
+++ b/src/test/ui/rfc-2627-raw-dylib/multiple-declarations.stderr
@@ -1,5 +1,5 @@
 warning: the feature `raw_dylib` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/multiple-declarations.rs:4:12
+  --> $DIR/multiple-declarations.rs:5:12
    |
 LL | #![feature(raw_dylib)]
    |            ^^^^^^^^^
@@ -8,7 +8,7 @@ LL | #![feature(raw_dylib)]
    = note: see issue #58713 <https://github.com/rust-lang/rust/issues/58713> for more information
 
 error: multiple declarations of external function `f` from library `foo.dll` have different calling conventions
-  --> $DIR/multiple-declarations.rs:14:9
+  --> $DIR/multiple-declarations.rs:15:9
    |
 LL |         fn f(x: i32);
    |         ^^^^^^^^^^^^^
diff --git a/src/test/ui/rfc-2627-raw-dylib/raw-dylib-msvc-only.rs b/src/test/ui/rfc-2627-raw-dylib/raw-dylib-msvc-only.rs
deleted file mode 100644
index e9690f03f45c9..0000000000000
--- a/src/test/ui/rfc-2627-raw-dylib/raw-dylib-msvc-only.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-// only-windows-gnu
-// check-pass
-// compile-flags: --crate-type lib
-#![feature(raw_dylib)]
-//~^ WARNING: the feature `raw_dylib` is incomplete
-#[link(name = "foo", kind = "raw-dylib")]
-//~^ WARNING: `#[link(...)]` with `kind = "raw-dylib"` not supported on windows-gnu
-extern "C" {}
diff --git a/src/test/ui/rfc-2627-raw-dylib/raw-dylib-msvc-only.stderr b/src/test/ui/rfc-2627-raw-dylib/raw-dylib-msvc-only.stderr
deleted file mode 100644
index 6e24112b3c3e5..0000000000000
--- a/src/test/ui/rfc-2627-raw-dylib/raw-dylib-msvc-only.stderr
+++ /dev/null
@@ -1,17 +0,0 @@
-warning: the feature `raw_dylib` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/raw-dylib-msvc-only.rs:4:12
-   |
-LL | #![feature(raw_dylib)]
-   |            ^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #58713 <https://github.com/rust-lang/rust/issues/58713> for more information
-
-warning: `#[link(...)]` with `kind = "raw-dylib"` not supported on windows-gnu
-  --> $DIR/raw-dylib-msvc-only.rs:6:1
-   |
-LL | #[link(name = "foo", kind = "raw-dylib")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: 2 warnings emitted
-
diff --git a/src/test/ui/rfc-2627-raw-dylib/unsupported-abi.rs b/src/test/ui/rfc-2627-raw-dylib/unsupported-abi.rs
index e5a5ac2eb2bf1..dc647fd63f527 100644
--- a/src/test/ui/rfc-2627-raw-dylib/unsupported-abi.rs
+++ b/src/test/ui/rfc-2627-raw-dylib/unsupported-abi.rs
@@ -1,4 +1,5 @@
-// only-x86_64-pc-windows-msvc
+// only-x86_64
+// only-windows
 // compile-flags: --crate-type lib --emit link
 #![allow(incomplete_features)]
 #![feature(raw_dylib)]
diff --git a/src/test/ui/rfc-2627-raw-dylib/unsupported-abi.stderr b/src/test/ui/rfc-2627-raw-dylib/unsupported-abi.stderr
index fc9008128ae43..d8a2a6af9c19e 100644
--- a/src/test/ui/rfc-2627-raw-dylib/unsupported-abi.stderr
+++ b/src/test/ui/rfc-2627-raw-dylib/unsupported-abi.stderr
@@ -1,5 +1,5 @@
 error: ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture
-  --> $DIR/unsupported-abi.rs:7:5
+  --> $DIR/unsupported-abi.rs:8:5
    |
 LL |     fn f(x: i32);
    |     ^^^^^^^^^^^^^
diff --git a/src/test/ui/simd/intrinsic/generic-as.rs b/src/test/ui/simd/intrinsic/generic-as.rs
new file mode 100644
index 0000000000000..a975190a2fafd
--- /dev/null
+++ b/src/test/ui/simd/intrinsic/generic-as.rs
@@ -0,0 +1,48 @@
+// run-pass
+
+#![feature(repr_simd, platform_intrinsics)]
+
+extern "platform-intrinsic" {
+    fn simd_as<T, U>(x: T) -> U;
+}
+
+#[derive(Copy, Clone)]
+#[repr(simd)]
+struct V<T>([T; 2]);
+
+fn main() {
+    unsafe {
+        let u = V::<u32>([u32::MIN, u32::MAX]);
+        let i: V<i16> = simd_as(u);
+        assert_eq!(i.0[0], u.0[0] as i16);
+        assert_eq!(i.0[1], u.0[1] as i16);
+    }
+
+    unsafe {
+        let f = V::<f32>([f32::MIN, f32::MAX]);
+        let i: V<i16> = simd_as(f);
+        assert_eq!(i.0[0], f.0[0] as i16);
+        assert_eq!(i.0[1], f.0[1] as i16);
+    }
+
+    unsafe {
+        let f = V::<f32>([f32::MIN, f32::MAX]);
+        let u: V<u8> = simd_as(f);
+        assert_eq!(u.0[0], f.0[0] as u8);
+        assert_eq!(u.0[1], f.0[1] as u8);
+    }
+
+    unsafe {
+        let f = V::<f64>([f64::MIN, f64::MAX]);
+        let i: V<isize> = simd_as(f);
+        assert_eq!(i.0[0], f.0[0] as isize);
+        assert_eq!(i.0[1], f.0[1] as isize);
+    }
+
+    unsafe {
+        let f = V::<f64>([f64::MIN, f64::MAX]);
+        let u: V<usize> = simd_as(f);
+        assert_eq!(u.0[0], f.0[0] as usize);
+        assert_eq!(u.0[1], f.0[1] as usize);
+    }
+}
diff --git a/src/test/ui/simd/intrinsic/generic-cast-pointer-width.rs b/src/test/ui/simd/intrinsic/generic-cast-pointer-width.rs
new file mode 100644
index 0000000000000..b9382310deb2c
--- /dev/null
+++ b/src/test/ui/simd/intrinsic/generic-cast-pointer-width.rs
@@ -0,0 +1,21 @@
+// run-pass
+#![feature(repr_simd, platform_intrinsics)]
+
+extern "platform-intrinsic" {
+    fn simd_cast<T, U>(x: T) -> U;
+}
+
+#[derive(Copy, Clone)]
+#[repr(simd)]
+struct V<T>([T; 4]);
+
+fn main() {
+    let u = V::<usize>([0, 1, 2, 3]);
+    let uu32: V<u32> = unsafe { simd_cast(u) };
+    let ui64: V<i64> = unsafe { simd_cast(u) };
+
+    for (u, (uu32, ui64)) in u.0.iter().zip(uu32.0.iter().zip(ui64.0.iter())) {
+        assert_eq!(*u as u32, *uu32);
+        assert_eq!(*u as i64, *ui64);
+    }
+}