about summary refs log tree commit diff
path: root/tests/assembly-llvm
diff options
context:
space:
mode:
Diffstat (limited to 'tests/assembly-llvm')
-rw-r--r--tests/assembly-llvm/aarch64-pointer-auth.rs30
-rw-r--r--tests/assembly-llvm/aarch64-xray.rs25
-rw-r--r--tests/assembly-llvm/align_offset.rs47
-rw-r--r--tests/assembly-llvm/asm/aarch64-el2vmsa.rs33
-rw-r--r--tests/assembly-llvm/asm/aarch64-modifiers.rs128
-rw-r--r--tests/assembly-llvm/asm/aarch64-outline-atomics.rs17
-rw-r--r--tests/assembly-llvm/asm/aarch64-types.rs633
-rw-r--r--tests/assembly-llvm/asm/arm-modifiers.rs122
-rw-r--r--tests/assembly-llvm/asm/arm-types.rs639
-rw-r--r--tests/assembly-llvm/asm/avr-modifiers.rs43
-rw-r--r--tests/assembly-llvm/asm/avr-types.rs205
-rw-r--r--tests/assembly-llvm/asm/bpf-types.rs133
-rw-r--r--tests/assembly-llvm/asm/comments.rs12
-rw-r--r--tests/assembly-llvm/asm/global_asm.rs32
-rw-r--r--tests/assembly-llvm/asm/hexagon-types.rs139
-rw-r--r--tests/assembly-llvm/asm/inline-asm-avx.rs25
-rw-r--r--tests/assembly-llvm/asm/loongarch-type.rs190
-rw-r--r--tests/assembly-llvm/asm/m68k-types.rs67
-rw-r--r--tests/assembly-llvm/asm/mips-types.rs211
-rw-r--r--tests/assembly-llvm/asm/msp430-types.rs141
-rw-r--r--tests/assembly-llvm/asm/nvptx-types.rs115
-rw-r--r--tests/assembly-llvm/asm/powerpc-types.rs474
-rw-r--r--tests/assembly-llvm/asm/riscv-types.rs227
-rw-r--r--tests/assembly-llvm/asm/s390x-types.rs350
-rw-r--r--tests/assembly-llvm/asm/sparc-types.rs145
-rw-r--r--tests/assembly-llvm/asm/wasm-types.rs131
-rw-r--r--tests/assembly-llvm/asm/x86-modifiers.rs184
-rw-r--r--tests/assembly-llvm/asm/x86-types.rs1095
-rw-r--r--tests/assembly-llvm/auxiliary/breakpoint-panic-handler.rs8
-rw-r--r--tests/assembly-llvm/auxiliary/dwarf-mixed-versions-lto-aux.rs5
-rw-r--r--tests/assembly-llvm/auxiliary/non-inline-dependency.rs14
-rw-r--r--tests/assembly-llvm/breakpoint.rs14
-rw-r--r--tests/assembly-llvm/closure-inherit-target-feature.rs59
-rw-r--r--tests/assembly-llvm/cmse.rs100
-rw-r--r--tests/assembly-llvm/compiletest-self-test/use-minicore-no-run.rs5
-rw-r--r--tests/assembly-llvm/cstring-merging.rs30
-rw-r--r--tests/assembly-llvm/dwarf-mixed-versions-lto.rs20
-rw-r--r--tests/assembly-llvm/dwarf4.rs23
-rw-r--r--tests/assembly-llvm/dwarf5.rs20
-rw-r--r--tests/assembly-llvm/emit-intel-att-syntax.rs75
-rw-r--r--tests/assembly-llvm/is_aligned.rs55
-rw-r--r--tests/assembly-llvm/issue-83585-small-pod-struct-equality.rs27
-rw-r--r--tests/assembly-llvm/libs/issue-115339-zip-arrays.rs25
-rw-r--r--tests/assembly-llvm/libs/issue-140207-slice-min-simd.rs13
-rw-r--r--tests/assembly-llvm/manual-eq-efficient.rs22
-rw-r--r--tests/assembly-llvm/naked-functions/aarch64-naked-fn-no-bti-prolog.rs21
-rw-r--r--tests/assembly-llvm/naked-functions/aix.rs35
-rw-r--r--tests/assembly-llvm/naked-functions/wasm32.rs200
-rw-r--r--tests/assembly-llvm/naked-functions/x86_64-naked-fn-no-cet-prolog.rs24
-rw-r--r--tests/assembly-llvm/niche-prefer-zero.rs25
-rw-r--r--tests/assembly-llvm/nvptx-arch-default.rs12
-rw-r--r--tests/assembly-llvm/nvptx-arch-emit-asm.rs9
-rw-r--r--tests/assembly-llvm/nvptx-arch-link-arg.rs13
-rw-r--r--tests/assembly-llvm/nvptx-arch-target-cpu.rs12
-rw-r--r--tests/assembly-llvm/nvptx-atomics.rs86
-rw-r--r--tests/assembly-llvm/nvptx-c-abi-arg-v7.rs220
-rw-r--r--tests/assembly-llvm/nvptx-c-abi-ret-v7.rs244
-rw-r--r--tests/assembly-llvm/nvptx-internalizing.rs27
-rw-r--r--tests/assembly-llvm/nvptx-kernel-abi/nvptx-kernel-args-abi-v7.rs251
-rw-r--r--tests/assembly-llvm/nvptx-linking-binary.rs40
-rw-r--r--tests/assembly-llvm/nvptx-linking-cdylib.rs39
-rw-r--r--tests/assembly-llvm/nvptx-safe-naming.rs37
-rw-r--r--tests/assembly-llvm/panic-no-unwind-no-uwtable.rs8
-rw-r--r--tests/assembly-llvm/panic-unwind-no-uwtable.rs12
-rw-r--r--tests/assembly-llvm/pic-relocation-model.rs31
-rw-r--r--tests/assembly-llvm/pie-relocation-model.rs34
-rw-r--r--tests/assembly-llvm/powerpc64-struct-abi.rs156
-rw-r--r--tests/assembly-llvm/riscv-float-struct-abi.rs177
-rw-r--r--tests/assembly-llvm/riscv-soft-abi-with-float-features.rs45
-rw-r--r--tests/assembly-llvm/rust-abi-arg-attr.rs110
-rw-r--r--tests/assembly-llvm/s390x-backchain-toggle.rs50
-rw-r--r--tests/assembly-llvm/s390x-vector-abi.rs327
-rw-r--r--tests/assembly-llvm/sanitizer/kcfi/emit-arity-indicator.rs69
-rw-r--r--tests/assembly-llvm/simd-bitmask.rs147
-rw-r--r--tests/assembly-llvm/simd-intrinsic-gather.rs39
-rw-r--r--tests/assembly-llvm/simd-intrinsic-mask-load.rs83
-rw-r--r--tests/assembly-llvm/simd-intrinsic-mask-reduce.rs59
-rw-r--r--tests/assembly-llvm/simd-intrinsic-mask-store.rs82
-rw-r--r--tests/assembly-llvm/simd-intrinsic-scatter.rs35
-rw-r--r--tests/assembly-llvm/simd-intrinsic-select.rs128
-rw-r--r--tests/assembly-llvm/simd/reduce-fadd-unordered.rs31
-rw-r--r--tests/assembly-llvm/slice-is_ascii.rs33
-rw-r--r--tests/assembly-llvm/small_data_threshold.rs98
-rw-r--r--tests/assembly-llvm/sparc-struct-abi.rs68
-rw-r--r--tests/assembly-llvm/stack-probes.rs41
-rw-r--r--tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs359
-rw-r--r--tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs366
-rw-r--r--tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect.rs345
-rw-r--r--tests/assembly-llvm/stack-protector/stack-protector-target-support.rs281
-rw-r--r--tests/assembly-llvm/static-relocation-model.rs69
-rw-r--r--tests/assembly-llvm/strict_provenance.rs37
-rw-r--r--tests/assembly-llvm/target-feature-multiple.rs40
-rw-r--r--tests/assembly-llvm/targets/targets-amdgpu.rs22
-rw-r--r--tests/assembly-llvm/targets/targets-elf.rs734
-rw-r--r--tests/assembly-llvm/targets/targets-macho.rs93
-rw-r--r--tests/assembly-llvm/targets/targets-nvptx.rs22
-rw-r--r--tests/assembly-llvm/targets/targets-pe.rs103
-rw-r--r--tests/assembly-llvm/wasm_exceptions.rs67
-rw-r--r--tests/assembly-llvm/x86-return-float.rs343
-rw-r--r--tests/assembly-llvm/x86_64-array-pair-load-store-merge.rs20
-rw-r--r--tests/assembly-llvm/x86_64-bigint-helpers.rs61
-rw-r--r--tests/assembly-llvm/x86_64-cmp.rs79
-rw-r--r--tests/assembly-llvm/x86_64-floating-point-clamp.rs27
-rw-r--r--tests/assembly-llvm/x86_64-fortanix-unknown-sgx-lvi-generic-load.rs17
-rw-r--r--tests/assembly-llvm/x86_64-fortanix-unknown-sgx-lvi-generic-ret.rs12
-rw-r--r--tests/assembly-llvm/x86_64-fortanix-unknown-sgx-lvi-inline-assembly.rs34
-rw-r--r--tests/assembly-llvm/x86_64-function-return.rs30
-rw-r--r--tests/assembly-llvm/x86_64-no-jump-tables.rs35
-rw-r--r--tests/assembly-llvm/x86_64-sse_crc.rs12
-rw-r--r--tests/assembly-llvm/x86_64-typed-swap.rs81
-rw-r--r--tests/assembly-llvm/x86_64-windows-float-abi.rs46
-rw-r--r--tests/assembly-llvm/x86_64-windows-i128-abi.rs26
-rw-r--r--tests/assembly-llvm/x86_64-xray.rs25
113 files changed, 12652 insertions, 0 deletions
diff --git a/tests/assembly-llvm/aarch64-pointer-auth.rs b/tests/assembly-llvm/aarch64-pointer-auth.rs
new file mode 100644
index 00000000000..56a26df469f
--- /dev/null
+++ b/tests/assembly-llvm/aarch64-pointer-auth.rs
@@ -0,0 +1,30 @@
+// Test that PAC instructions are emitted when branch-protection is specified.
+
+//@ add-core-stubs
+//@ revisions: PACRET PAUTHLR_NOP PAUTHLR
+//@ assembly-output: emit-asm
+//@ needs-llvm-components: aarch64
+//@ compile-flags: --target aarch64-unknown-linux-gnu
+//@ [PACRET] compile-flags: -Z branch-protection=pac-ret,leaf
+//@ [PAUTHLR_NOP] compile-flags: -Z branch-protection=pac-ret,pc,leaf
+//@ [PAUTHLR] compile-flags: -C target-feature=+pauth-lr -Z branch-protection=pac-ret,pc,leaf
+
+#![feature(no_core, lang_items)]
+#![no_std]
+#![no_core]
+#![crate_type = "lib"]
+
+extern crate minicore;
+use minicore::*;
+
+// PACRET: hint #25
+// PACRET: hint #29
+// PAUTHLR_NOP: hint #25
+// PAUTHLR_NOP: hint #39
+// PAUTHLR_NOP: hint #29
+// PAUTHLR: paciasppc
+// PAUTHLR: autiasppc
+#[no_mangle]
+pub fn test() -> u8 {
+    42
+}
diff --git a/tests/assembly-llvm/aarch64-xray.rs b/tests/assembly-llvm/aarch64-xray.rs
new file mode 100644
index 00000000000..d5ee0111843
--- /dev/null
+++ b/tests/assembly-llvm/aarch64-xray.rs
@@ -0,0 +1,25 @@
+//@ assembly-output: emit-asm
+//@ compile-flags: -Zinstrument-xray=always
+
+//@ revisions: aarch64-linux
+//@[aarch64-linux] compile-flags: --target=aarch64-unknown-linux-gnu
+//@[aarch64-linux] needs-llvm-components: aarch64
+//@[aarch64-linux] only-aarch64-unknown-linux-gnu
+
+//@ revisions: aarch64-darwin
+//@[aarch64-darwin] compile-flags: --target=aarch64-apple-darwin
+//@[aarch64-darwin] needs-llvm-components: aarch64
+//@[aarch64-darwin] only-aarch64-apple-darwin
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: xray_func:
+#[no_mangle]
+pub fn xray_func() {
+    // CHECK: nop
+
+    std::hint::black_box(());
+
+    // CHECK: b #32
+    // CHECK-NEXT: nop
+}
diff --git a/tests/assembly-llvm/align_offset.rs b/tests/assembly-llvm/align_offset.rs
new file mode 100644
index 00000000000..d9902ce336b
--- /dev/null
+++ b/tests/assembly-llvm/align_offset.rs
@@ -0,0 +1,47 @@
+//@ assembly-output: emit-asm
+//@ compile-flags: -Copt-level=1
+//@ only-x86_64
+#![crate_type = "rlib"]
+
+// CHECK-LABEL: align_offset_byte_ptr
+// CHECK: leaq 31
+// CHECK: andq $-32
+// CHECK: subq
+#[no_mangle]
+pub fn align_offset_byte_ptr(ptr: *const u8) -> usize {
+    ptr.align_offset(32)
+}
+
+// CHECK-LABEL: align_offset_byte_slice
+// CHECK: leaq 31
+// CHECK: andq $-32
+// CHECK: subq
+#[no_mangle]
+pub fn align_offset_byte_slice(slice: &[u8]) -> usize {
+    slice.as_ptr().align_offset(32)
+}
+
+// CHECK-LABEL: align_offset_word_ptr
+// CHECK: leaq 31
+// CHECK: andq $-32
+// CHECK: subq
+// CHECK: shrq
+// This `ptr` is not known to be aligned, so it is required to check if it is at all possible to
+// align. LLVM applies a simple mask.
+// CHECK: orq
+#[no_mangle]
+pub fn align_offset_word_ptr(ptr: *const u32) -> usize {
+    ptr.align_offset(32)
+}
+
+// CHECK-LABEL: align_offset_word_slice
+// CHECK: leaq 31
+// CHECK: andq $-32
+// CHECK: subq
+// CHECK: shrq
+// `slice` is known to be aligned, so `!0` is not possible as a return
+// CHECK-NOT: orq
+#[no_mangle]
+pub fn align_offset_word_slice(slice: &[u32]) -> usize {
+    slice.as_ptr().align_offset(32)
+}
diff --git a/tests/assembly-llvm/asm/aarch64-el2vmsa.rs b/tests/assembly-llvm/asm/aarch64-el2vmsa.rs
new file mode 100644
index 00000000000..3652d58d85a
--- /dev/null
+++ b/tests/assembly-llvm/asm/aarch64-el2vmsa.rs
@@ -0,0 +1,33 @@
+//@ add-core-stubs
+//@ assembly-output: emit-asm
+//@ compile-flags: --target aarch64-unknown-linux-gnu
+//@ needs-llvm-components: aarch64
+
+#![feature(no_core)]
+#![crate_type = "rlib"]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
+
+// CHECK-LABEL: ttbr0_el2:
+#[no_mangle]
+pub fn ttbr0_el2() {
+    // CHECK: //APP
+    // CHECK-NEXT: msr TTBR0_EL2, x0
+    // CHECK-NEXT: //NO_APP
+    unsafe {
+        asm!("msr ttbr0_el2, x0");
+    }
+}
+
+// CHECK-LABEL: vttbr_el2:
+#[no_mangle]
+pub fn vttbr_el2() {
+    // CHECK: //APP
+    // CHECK-NEXT: msr VTTBR_EL2, x0
+    // CHECK-NEXT: //NO_APP
+    unsafe {
+        asm!("msr vttbr_el2, x0");
+    }
+}
diff --git a/tests/assembly-llvm/asm/aarch64-modifiers.rs b/tests/assembly-llvm/asm/aarch64-modifiers.rs
new file mode 100644
index 00000000000..58f7c114d3a
--- /dev/null
+++ b/tests/assembly-llvm/asm/aarch64-modifiers.rs
@@ -0,0 +1,128 @@
+//@ add-core-stubs
+//@ assembly-output: emit-asm
+//@ compile-flags: -Copt-level=3 -C panic=abort
+//@ compile-flags: --target aarch64-unknown-linux-gnu
+//@ compile-flags: -Zmerge-functions=disabled
+//@ needs-llvm-components: aarch64
+
+#![feature(no_core)]
+#![crate_type = "rlib"]
+#![no_core]
+#![allow(asm_sub_register)]
+
+extern crate minicore;
+use minicore::*;
+
+macro_rules! check {
+    ($func:ident $reg:ident $code:literal) => {
+        // -Copt-level=3 and extern "C" guarantee that the selected register is always r0/s0/d0/q0
+        #[no_mangle]
+        pub unsafe extern "C" fn $func() -> i32 {
+            let y;
+            asm!($code, out($reg) y);
+            y
+        }
+    };
+}
+
+// CHECK-LABEL: reg:
+// CHECK: //APP
+// CHECK: mov x0, x0
+// CHECK: //NO_APP
+check!(reg reg "mov {0}, {0}");
+
+// CHECK-LABEL: reg_w:
+// CHECK: //APP
+// CHECK: mov w0, w0
+// CHECK: //NO_APP
+check!(reg_w reg "mov {0:w}, {0:w}");
+
+// CHECK-LABEL: reg_x:
+// CHECK: //APP
+// CHECK: mov x0, x0
+// CHECK: //NO_APP
+check!(reg_x reg "mov {0:x}, {0:x}");
+
+// CHECK-LABEL: vreg:
+// CHECK: //APP
+// CHECK: add v0.4s, v0.4s, v0.4s
+// CHECK: //NO_APP
+check!(vreg vreg "add {0}.4s, {0}.4s, {0}.4s");
+
+// CHECK-LABEL: vreg_b:
+// CHECK: //APP
+// CHECK: ldr b0, [x0]
+// CHECK: //NO_APP
+check!(vreg_b vreg "ldr {:b}, [x0]");
+
+// CHECK-LABEL: vreg_h:
+// CHECK: //APP
+// CHECK: ldr h0, [x0]
+// CHECK: //NO_APP
+check!(vreg_h vreg "ldr {:h}, [x0]");
+
+// CHECK-LABEL: vreg_s:
+// CHECK: //APP
+// CHECK: ldr s0, [x0]
+// CHECK: //NO_APP
+check!(vreg_s vreg "ldr {:s}, [x0]");
+
+// CHECK-LABEL: vreg_d:
+// CHECK: //APP
+// CHECK: ldr d0, [x0]
+// CHECK: //NO_APP
+check!(vreg_d vreg "ldr {:d}, [x0]");
+
+// CHECK-LABEL: vreg_q:
+// CHECK: //APP
+// CHECK: ldr q0, [x0]
+// CHECK: //NO_APP
+check!(vreg_q vreg "ldr {:q}, [x0]");
+
+// CHECK-LABEL: vreg_v:
+// CHECK: //APP
+// CHECK: add v0.4s, v0.4s, v0.4s
+// CHECK: //NO_APP
+check!(vreg_v vreg "add {0:v}.4s, {0:v}.4s, {0:v}.4s");
+
+// CHECK-LABEL: vreg_low16:
+// CHECK: //APP
+// CHECK: add v0.4s, v0.4s, v0.4s
+// CHECK: //NO_APP
+check!(vreg_low16 vreg_low16 "add {0}.4s, {0}.4s, {0}.4s");
+
+// CHECK-LABEL: vreg_low16_b:
+// CHECK: //APP
+// CHECK: ldr b0, [x0]
+// CHECK: //NO_APP
+check!(vreg_low16_b vreg_low16 "ldr {:b}, [x0]");
+
+// CHECK-LABEL: vreg_low16_h:
+// CHECK: //APP
+// CHECK: ldr h0, [x0]
+// CHECK: //NO_APP
+check!(vreg_low16_h vreg_low16 "ldr {:h}, [x0]");
+
+// CHECK-LABEL: vreg_low16_s:
+// CHECK: //APP
+// CHECK: ldr s0, [x0]
+// CHECK: //NO_APP
+check!(vreg_low16_s vreg_low16 "ldr {:s}, [x0]");
+
+// CHECK-LABEL: vreg_low16_d:
+// CHECK: //APP
+// CHECK: ldr d0, [x0]
+// CHECK: //NO_APP
+check!(vreg_low16_d vreg_low16 "ldr {:d}, [x0]");
+
+// CHECK-LABEL: vreg_low16_q:
+// CHECK: //APP
+// CHECK: ldr q0, [x0]
+// CHECK: //NO_APP
+check!(vreg_low16_q vreg_low16 "ldr {:q}, [x0]");
+
+// CHECK-LABEL: vreg_low16_v:
+// CHECK: //APP
+// CHECK: add v0.4s, v0.4s, v0.4s
+// CHECK: //NO_APP
+check!(vreg_low16_v vreg_low16 "add {0:v}.4s, {0:v}.4s, {0:v}.4s");
diff --git a/tests/assembly-llvm/asm/aarch64-outline-atomics.rs b/tests/assembly-llvm/asm/aarch64-outline-atomics.rs
new file mode 100644
index 00000000000..5990fb84942
--- /dev/null
+++ b/tests/assembly-llvm/asm/aarch64-outline-atomics.rs
@@ -0,0 +1,17 @@
+//@ assembly-output: emit-asm
+//@ compile-flags: -Copt-level=3
+//@ compile-flags: --target aarch64-unknown-linux-gnu
+//@ needs-llvm-components: aarch64
+//@ only-aarch64
+//@ only-linux
+
+#![crate_type = "rlib"]
+
+use std::sync::atomic::AtomicI32;
+use std::sync::atomic::Ordering::*;
+
+pub fn compare_exchange(a: &AtomicI32) {
+    // On AArch64 LLVM should outline atomic operations.
+    // CHECK: __aarch64_cas4_relax
+    let _ = a.compare_exchange(0, 10, Relaxed, Relaxed);
+}
diff --git a/tests/assembly-llvm/asm/aarch64-types.rs b/tests/assembly-llvm/asm/aarch64-types.rs
new file mode 100644
index 00000000000..b7abeb02298
--- /dev/null
+++ b/tests/assembly-llvm/asm/aarch64-types.rs
@@ -0,0 +1,633 @@
+//@ add-core-stubs
+//@ revisions: aarch64 arm64ec
+//@ assembly-output: emit-asm
+//@ [aarch64] compile-flags: --target aarch64-unknown-linux-gnu
+//@ [aarch64] needs-llvm-components: aarch64
+//@ [arm64ec] compile-flags: --target arm64ec-pc-windows-msvc
+//@ [arm64ec] needs-llvm-components: aarch64
+//@ compile-flags: -Zmerge-functions=disabled
+
+#![feature(no_core, repr_simd, f16, f128)]
+#![crate_type = "rlib"]
+#![no_core]
+#![allow(asm_sub_register, non_camel_case_types)]
+
+extern crate minicore;
+use minicore::*;
+
+type ptr = *mut u8;
+
+#[repr(simd)]
+pub struct i8x8([i8; 8]);
+#[repr(simd)]
+pub struct i16x4([i16; 4]);
+#[repr(simd)]
+pub struct i32x2([i32; 2]);
+#[repr(simd)]
+pub struct i64x1([i64; 1]);
+#[repr(simd)]
+pub struct f16x4([f16; 4]);
+#[repr(simd)]
+pub struct f32x2([f32; 2]);
+#[repr(simd)]
+pub struct f64x1([f64; 1]);
+#[repr(simd)]
+pub struct i8x16([i8; 16]);
+#[repr(simd)]
+pub struct i16x8([i16; 8]);
+#[repr(simd)]
+pub struct i32x4([i32; 4]);
+#[repr(simd)]
+pub struct i64x2([i64; 2]);
+#[repr(simd)]
+pub struct f16x8([f16; 8]);
+#[repr(simd)]
+pub struct f32x4([f32; 4]);
+#[repr(simd)]
+pub struct f64x2([f64; 2]);
+
+impl Copy for i8x8 {}
+impl Copy for i16x4 {}
+impl Copy for i32x2 {}
+impl Copy for i64x1 {}
+impl Copy for f16x4 {}
+impl Copy for f32x2 {}
+impl Copy for f64x1 {}
+impl Copy for i8x16 {}
+impl Copy for i16x8 {}
+impl Copy for i32x4 {}
+impl Copy for i64x2 {}
+impl Copy for f16x8 {}
+impl Copy for f32x4 {}
+impl Copy for f64x2 {}
+
+extern "C" {
+    fn extern_func();
+    static extern_static: u8;
+}
+
+// CHECK-LABEL: {{("#)?}}sym_fn{{"?}}
+// CHECK: //APP
+// CHECK: bl extern_func
+// CHECK: //NO_APP
+#[no_mangle]
+pub unsafe fn sym_fn() {
+    asm!("bl {}", sym extern_func);
+}
+
+// CHECK-LABEL: {{("#)?}}sym_static{{"?}}
+// CHECK: //APP
+// CHECK: adr x0, extern_static
+// CHECK: //NO_APP
+#[no_mangle]
+pub unsafe fn sym_static() {
+    asm!("adr x0, {}", sym extern_static);
+}
+
+// Regression test for #75761
+// CHECK-LABEL: {{("#)?}}issue_75761{{"?}}
+// x29 holds the frame pointer, right next to x30, so ldp/stp happens sometimes
+// CHECK: st[[MAY_PAIR:(r|p).*]]x30
+// CHECK: //APP
+// CHECK: //NO_APP
+// CHECK: ld[[MAY_PAIR]]x30
+#[no_mangle]
+pub unsafe fn issue_75761() {
+    asm!("", out("v0") _, out("x30") _);
+}
+
+macro_rules! check {
+    ($func:ident $ty:ident $class:ident $mov:literal $modifier:literal) => {
+        // FIXME(f16_f128): Change back to `$func(x: $ty) -> $ty` once arm64ec can pass and return
+        // `f16` and `f128` without LLVM erroring.
+        // LLVM issue: <https://github.com/llvm/llvm-project/issues/94434>
+        #[no_mangle]
+        pub unsafe fn $func(inp: &$ty, out: &mut $ty) {
+            let x = *inp;
+            let y;
+            asm!(
+                concat!($mov, " {:", $modifier, "}, {:", $modifier, "}"),
+                out($class) y,
+                in($class) x
+            );
+            *out = y;
+        }
+    };
+}
+
+macro_rules! check_reg {
+    ($func:ident $ty:ident $reg:tt $mov:literal) => {
+        // FIXME(f16_f128): See FIXME in `check!`
+        #[no_mangle]
+        pub unsafe fn $func(inp: &$ty, out: &mut $ty) {
+            let x = *inp;
+            let y;
+            asm!(concat!($mov, " ", $reg, ", ", $reg), lateout($reg) y, in($reg) x);
+            *out = y;
+        }
+    };
+}
+
+// CHECK-LABEL: {{("#)?}}reg_i8{{"?}}
+// CHECK: //APP
+// CHECK: mov x{{[0-9]+}}, x{{[0-9]+}}
+// CHECK: //NO_APP
+check!(reg_i8 i8 reg "mov" "");
+
+// CHECK-LABEL: {{("#)?}}reg_i16{{"?}}
+// CHECK: //APP
+// CHECK: mov x{{[0-9]+}}, x{{[0-9]+}}
+// CHECK: //NO_APP
+check!(reg_i16 i16 reg "mov" "");
+
+// CHECK-LABEL: {{("#)?}}reg_f16{{"?}}
+// CHECK: //APP
+// CHECK: mov x{{[0-9]+}}, x{{[0-9]+}}
+// CHECK: //NO_APP
+check!(reg_f16 f16 reg "mov" "");
+
+// CHECK-LABEL: {{("#)?}}reg_i32{{"?}}
+// CHECK: //APP
+// CHECK: mov x{{[0-9]+}}, x{{[0-9]+}}
+// CHECK: //NO_APP
+check!(reg_i32 i32 reg "mov" "");
+
+// CHECK-LABEL: {{("#)?}}reg_f32{{"?}}
+// CHECK: //APP
+// CHECK: mov x{{[0-9]+}}, x{{[0-9]+}}
+// CHECK: //NO_APP
+check!(reg_f32 f32 reg "mov" "");
+
+// CHECK-LABEL: {{("#)?}}reg_i64{{"?}}
+// CHECK: //APP
+// CHECK: mov x{{[0-9]+}}, x{{[0-9]+}}
+// CHECK: //NO_APP
+check!(reg_i64 i64 reg "mov" "");
+
+// CHECK-LABEL: {{("#)?}}reg_f64{{"?}}
+// CHECK: //APP
+// CHECK: mov x{{[0-9]+}}, x{{[0-9]+}}
+// CHECK: //NO_APP
+check!(reg_f64 f64 reg "mov" "");
+
+// CHECK-LABEL: {{("#)?}}reg_ptr{{"?}}
+// CHECK: //APP
+// CHECK: mov x{{[0-9]+}}, x{{[0-9]+}}
+// CHECK: //NO_APP
+check!(reg_ptr ptr reg "mov" "");
+
+// CHECK-LABEL: {{("#)?}}vreg_i8{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_i8 i8 vreg "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_i16{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_i16 i16 vreg "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_f16{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_f16 f16 vreg "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_i32{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_i32 i32 vreg "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_f32{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_f32 f32 vreg "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_i64{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_i64 i64 vreg "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_f64{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_f64 f64 vreg "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_f128{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_f128 f128 vreg "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_ptr{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_ptr ptr vreg "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_i8x8{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_i8x8 i8x8 vreg "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_i16x4{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_i16x4 i16x4 vreg "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_i32x2{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_i32x2 i32x2 vreg "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_i64x1{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_i64x1 i64x1 vreg "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_f16x4{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_f16x4 f16x4 vreg "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_f32x2{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_f32x2 f32x2 vreg "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_f64x1{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_f64x1 f64x1 vreg "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_i8x16{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_i8x16 i8x16 vreg "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_i16x8{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_i16x8 i16x8 vreg "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_i32x4{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_i32x4 i32x4 vreg "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_i64x2{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_i64x2 i64x2 vreg "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_f16x8{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_f16x8 f16x8 vreg "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_f32x4{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_f32x4 f32x4 vreg "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_f64x2{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_f64x2 f64x2 vreg "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_low16_i8{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_low16_i8 i8 vreg_low16 "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_low16_i16{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_low16_i16 i16 vreg_low16 "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_low16_f16{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_low16_f16 f16 vreg_low16 "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_low16_f32{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_low16_f32 f32 vreg_low16 "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_low16_i64{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_low16_i64 i64 vreg_low16 "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_low16_f64{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_low16_f64 f64 vreg_low16 "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_low16_f128{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_low16_f128 f128 vreg_low16 "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_low16_ptr{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_low16_ptr ptr vreg_low16 "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_low16_i8x8{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_low16_i8x8 i8x8 vreg_low16 "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_low16_i16x4{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_low16_i16x4 i16x4 vreg_low16 "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_low16_i32x2{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_low16_i32x2 i32x2 vreg_low16 "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_low16_i64x1{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_low16_i64x1 i64x1 vreg_low16 "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_low16_f16x4{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_low16_f16x4 f16x4 vreg_low16 "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_low16_f32x2{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_low16_f32x2 f32x2 vreg_low16 "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_low16_f64x1{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_low16_f64x1 f64x1 vreg_low16 "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_low16_i8x16{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_low16_i8x16 i8x16 vreg_low16 "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_low16_i16x8{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_low16_i16x8 i16x8 vreg_low16 "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_low16_i32x4{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_low16_i32x4 i32x4 vreg_low16 "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_low16_i64x2{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_low16_i64x2 i64x2 vreg_low16 "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_low16_f16x8{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_low16_f16x8 f16x8 vreg_low16 "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_low16_f32x4{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_low16_f32x4 f32x4 vreg_low16 "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}vreg_low16_f64x2{{"?}}
+// CHECK: //APP
+// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: //NO_APP
+check!(vreg_low16_f64x2 f64x2 vreg_low16 "fmov" "s");
+
+// CHECK-LABEL: {{("#)?}}x0_i8{{"?}}
+// CHECK: //APP
+// CHECK: mov x{{[0-9]+}}, x{{[0-9]+}}
+// CHECK: //NO_APP
+check_reg!(x0_i8 i8 "x0" "mov");
+
+// CHECK-LABEL: {{("#)?}}x0_i16{{"?}}
+// CHECK: //APP
+// CHECK: mov x{{[0-9]+}}, x{{[0-9]+}}
+// CHECK: //NO_APP
+check_reg!(x0_i16 i16 "x0" "mov");
+
+// CHECK-LABEL: {{("#)?}}x0_f16{{"?}}
+// CHECK: //APP
+// CHECK: mov x{{[0-9]+}}, x{{[0-9]+}}
+// CHECK: //NO_APP
+check_reg!(x0_f16 f16 "x0" "mov");
+
+// CHECK-LABEL: {{("#)?}}x0_i32{{"?}}
+// CHECK: //APP
+// CHECK: mov x{{[0-9]+}}, x{{[0-9]+}}
+// CHECK: //NO_APP
+check_reg!(x0_i32 i32 "x0" "mov");
+
+// CHECK-LABEL: {{("#)?}}x0_f32{{"?}}
+// CHECK: //APP
+// CHECK: mov x{{[0-9]+}}, x{{[0-9]+}}
+// CHECK: //NO_APP
+check_reg!(x0_f32 f32 "x0" "mov");
+
+// CHECK-LABEL: {{("#)?}}x0_i64{{"?}}
+// CHECK: //APP
+// CHECK: mov x{{[0-9]+}}, x{{[0-9]+}}
+// CHECK: //NO_APP
+check_reg!(x0_i64 i64 "x0" "mov");
+
+// CHECK-LABEL: {{("#)?}}x0_f64{{"?}}
+// CHECK: //APP
+// CHECK: mov x{{[0-9]+}}, x{{[0-9]+}}
+// CHECK: //NO_APP
+check_reg!(x0_f64 f64 "x0" "mov");
+
+// CHECK-LABEL: {{("#)?}}x0_ptr{{"?}}
+// CHECK: //APP
+// CHECK: mov x{{[0-9]+}}, x{{[0-9]+}}
+// CHECK: //NO_APP
+check_reg!(x0_ptr ptr "x0" "mov");
+
+// CHECK-LABEL: {{("#)?}}v0_i8{{"?}}
+// CHECK: //APP
+// CHECK: fmov s0, s0
+// CHECK: //NO_APP
+check_reg!(v0_i8 i8 "s0" "fmov");
+
+// CHECK-LABEL: {{("#)?}}v0_i16{{"?}}
+// CHECK: //APP
+// CHECK: fmov s0, s0
+// CHECK: //NO_APP
+check_reg!(v0_i16 i16 "s0" "fmov");
+
+// CHECK-LABEL: {{("#)?}}v0_f16{{"?}}
+// CHECK: //APP
+// CHECK: fmov s0, s0
+// CHECK: //NO_APP
+check_reg!(v0_f16 f16 "s0" "fmov");
+
+// CHECK-LABEL: {{("#)?}}v0_i32{{"?}}
+// CHECK: //APP
+// CHECK: fmov s0, s0
+// CHECK: //NO_APP
+check_reg!(v0_i32 i32 "s0" "fmov");
+
+// CHECK-LABEL: {{("#)?}}v0_f32{{"?}}
+// CHECK: //APP
+// CHECK: fmov s0, s0
+// CHECK: //NO_APP
+check_reg!(v0_f32 f32 "s0" "fmov");
+
+// CHECK-LABEL: {{("#)?}}v0_i64{{"?}}
+// CHECK: //APP
+// CHECK: fmov s0, s0
+// CHECK: //NO_APP
+check_reg!(v0_i64 i64 "s0" "fmov");
+
+// CHECK-LABEL: {{("#)?}}v0_f64{{"?}}
+// CHECK: //APP
+// CHECK: fmov s0, s0
+// CHECK: //NO_APP
+check_reg!(v0_f64 f64 "s0" "fmov");
+
+// CHECK-LABEL: {{("#)?}}v0_f128{{"?}}
+// CHECK: //APP
+// CHECK: fmov s0, s0
+// CHECK: //NO_APP
+check_reg!(v0_f128 f128 "s0" "fmov");
+
+// CHECK-LABEL: {{("#)?}}v0_ptr{{"?}}
+// CHECK: //APP
+// CHECK: fmov s0, s0
+// CHECK: //NO_APP
+check_reg!(v0_ptr ptr "s0" "fmov");
+
+// CHECK-LABEL: {{("#)?}}v0_i8x8{{"?}}
+// CHECK: //APP
+// CHECK: fmov s0, s0
+// CHECK: //NO_APP
+check_reg!(v0_i8x8 i8x8 "s0" "fmov");
+
+// CHECK-LABEL: {{("#)?}}v0_i16x4{{"?}}
+// CHECK: //APP
+// CHECK: fmov s0, s0
+// CHECK: //NO_APP
+check_reg!(v0_i16x4 i16x4 "s0" "fmov");
+
+// CHECK-LABEL: {{("#)?}}v0_i32x2{{"?}}
+// CHECK: //APP
+// CHECK: fmov s0, s0
+// CHECK: //NO_APP
+check_reg!(v0_i32x2 i32x2 "s0" "fmov");
+
+// CHECK-LABEL: {{("#)?}}v0_i64x1{{"?}}
+// CHECK: //APP
+// CHECK: fmov s0, s0
+// CHECK: //NO_APP
+check_reg!(v0_i64x1 i64x1 "s0" "fmov");
+
+// CHECK-LABEL: {{("#)?}}v0_f16x4{{"?}}
+// CHECK: //APP
+// CHECK: fmov s0, s0
+// CHECK: //NO_APP
+check_reg!(v0_f16x4 f16x4 "s0" "fmov");
+
+// CHECK-LABEL: {{("#)?}}v0_f32x2{{"?}}
+// CHECK: //APP
+// CHECK: fmov s0, s0
+// CHECK: //NO_APP
+check_reg!(v0_f32x2 f32x2 "s0" "fmov");
+
+// CHECK-LABEL: {{("#)?}}v0_f64x1{{"?}}
+// CHECK: //APP
+// CHECK: fmov s0, s0
+// CHECK: //NO_APP
+check_reg!(v0_f64x1 f64x1 "s0" "fmov");
+
+// CHECK-LABEL: {{("#)?}}v0_i8x16{{"?}}
+// CHECK: //APP
+// CHECK: fmov s0, s0
+// CHECK: //NO_APP
+check_reg!(v0_i8x16 i8x16 "s0" "fmov");
+
+// CHECK-LABEL: {{("#)?}}v0_i16x8{{"?}}
+// CHECK: //APP
+// CHECK: fmov s0, s0
+// CHECK: //NO_APP
+check_reg!(v0_i16x8 i16x8 "s0" "fmov");
+
+// CHECK-LABEL: {{("#)?}}v0_i32x4{{"?}}
+// CHECK: //APP
+// CHECK: fmov s0, s0
+// CHECK: //NO_APP
+check_reg!(v0_i32x4 i32x4 "s0" "fmov");
+
+// CHECK-LABEL: {{("#)?}}v0_i64x2{{"?}}
+// CHECK: //APP
+// CHECK: fmov s0, s0
+// CHECK: //NO_APP
+check_reg!(v0_i64x2 i64x2 "s0" "fmov");
+
+// CHECK-LABEL: {{("#)?}}v0_f16x8{{"?}}
+// CHECK: //APP
+// CHECK: fmov s0, s0
+// CHECK: //NO_APP
+check_reg!(v0_f16x8 f16x8 "s0" "fmov");
+
+// CHECK-LABEL: {{("#)?}}v0_f32x4{{"?}}
+// CHECK: //APP
+// CHECK: fmov s0, s0
+// CHECK: //NO_APP
+check_reg!(v0_f32x4 f32x4 "s0" "fmov");
+
+// CHECK-LABEL: {{("#)?}}v0_f64x2{{"?}}
+// CHECK: //APP
+// CHECK: fmov s0, s0
+// CHECK: //NO_APP
+check_reg!(v0_f64x2 f64x2 "s0" "fmov");
diff --git a/tests/assembly-llvm/asm/arm-modifiers.rs b/tests/assembly-llvm/asm/arm-modifiers.rs
new file mode 100644
index 00000000000..32a36840492
--- /dev/null
+++ b/tests/assembly-llvm/asm/arm-modifiers.rs
@@ -0,0 +1,122 @@
+//@ add-core-stubs
+//@ assembly-output: emit-asm
+//@ compile-flags: -Copt-level=3 -C panic=abort
+//@ compile-flags: --target armv7-unknown-linux-gnueabihf
+//@ compile-flags: -C target-feature=+neon
+//@ compile-flags: -Zmerge-functions=disabled
+//@ needs-llvm-components: arm
+
+#![feature(no_core, repr_simd)]
+#![crate_type = "rlib"]
+#![no_core]
+#![allow(asm_sub_register, non_camel_case_types)]
+
+extern crate minicore;
+use minicore::*;
+
+#[repr(simd)]
+pub struct f32x4([f32; 4]);
+
+impl Copy for f32x4 {}
+
+macro_rules! check {
+    ($func:ident $modifier:literal $reg:ident $ty:ident $mov:literal) => {
+        // -Copt-level=3 and extern "C" guarantee that the selected register is always r0/s0/d0/q0
+        #[no_mangle]
+        pub unsafe extern "C" fn $func() -> $ty {
+            let y;
+            asm!(concat!($mov, " {0:", $modifier, "}, {0:", $modifier, "}"), out($reg) y);
+            y
+        }
+    };
+}
+
+// CHECK-LABEL: reg:
+// CHECK: @APP
+// CHECK: mov r0, r0
+// CHECK: @NO_APP
+check!(reg "" reg i32 "mov");
+
+// CHECK-LABEL: sreg:
+// CHECK: @APP
+// CHECK: vmov.f32 s0, s0
+// CHECK: @NO_APP
+check!(sreg "" sreg f32 "vmov.f32");
+
+// CHECK-LABEL: sreg_low16:
+// CHECK: @APP
+// CHECK: vmov.f32 s0, s0
+// CHECK: @NO_APP
+check!(sreg_low16 "" sreg_low16 f32 "vmov.f32");
+
+// CHECK-LABEL: dreg:
+// CHECK: @APP
+// CHECK: vmov.f64 d0, d0
+// CHECK: @NO_APP
+check!(dreg "" dreg f64 "vmov.f64");
+
+// CHECK-LABEL: dreg_low16:
+// CHECK: @APP
+// CHECK: vmov.f64 d0, d0
+// CHECK: @NO_APP
+check!(dreg_low16 "" dreg_low16 f64 "vmov.f64");
+
+// CHECK-LABEL: dreg_low8:
+// CHECK: @APP
+// CHECK: vmov.f64 d0, d0
+// CHECK: @NO_APP
+check!(dreg_low8 "" dreg_low8 f64 "vmov.f64");
+
+// CHECK-LABEL: qreg:
+// CHECK: @APP
+// CHECK: vorr q0, q0, q0
+// CHECK: @NO_APP
+check!(qreg "" qreg f32x4 "vmov");
+
+// CHECK-LABEL: qreg_e:
+// CHECK: @APP
+// CHECK: vmov.f64 d0, d0
+// CHECK: @NO_APP
+check!(qreg_e "e" qreg f32x4 "vmov.f64");
+
+// CHECK-LABEL: qreg_f:
+// CHECK: @APP
+// CHECK: vmov.f64 d1, d1
+// CHECK: @NO_APP
+check!(qreg_f "f" qreg f32x4 "vmov.f64");
+
+// CHECK-LABEL: qreg_low8:
+// CHECK: @APP
+// CHECK: vorr q0, q0, q0
+// CHECK: @NO_APP
+check!(qreg_low8 "" qreg_low8 f32x4 "vmov");
+
+// CHECK-LABEL: qreg_low8_e:
+// CHECK: @APP
+// CHECK: vmov.f64 d0, d0
+// CHECK: @NO_APP
+check!(qreg_low8_e "e" qreg_low8 f32x4 "vmov.f64");
+
+// CHECK-LABEL: qreg_low8_f:
+// CHECK: @APP
+// CHECK: vmov.f64 d1, d1
+// CHECK: @NO_APP
+check!(qreg_low8_f "f" qreg_low8 f32x4 "vmov.f64");
+
+// CHECK-LABEL: qreg_low4:
+// CHECK: @APP
+// CHECK: vorr q0, q0, q0
+// CHECK: @NO_APP
+check!(qreg_low4 "" qreg_low4 f32x4 "vmov");
+
+// CHECK-LABEL: qreg_low4_e:
+// CHECK: @APP
+// CHECK: vmov.f64 d0, d0
+// CHECK: @NO_APP
+check!(qreg_low4_e "e" qreg_low4 f32x4 "vmov.f64");
+
+// CHECK-LABEL: qreg_low4_f:
+// CHECK: @APP
+// CHECK: vmov.f64 d1, d1
+// CHECK: @NO_APP
+check!(qreg_low4_f "f" qreg_low4 f32x4 "vmov.f64");
diff --git a/tests/assembly-llvm/asm/arm-types.rs b/tests/assembly-llvm/asm/arm-types.rs
new file mode 100644
index 00000000000..fb93f474c20
--- /dev/null
+++ b/tests/assembly-llvm/asm/arm-types.rs
@@ -0,0 +1,639 @@
+//@ add-core-stubs
+//@ revisions: base d32 neon
+//@ assembly-output: emit-asm
+//@ compile-flags: --target armv7-unknown-linux-gnueabihf
+//@ compile-flags: -C opt-level=0
+//@ compile-flags: -Zmerge-functions=disabled
+//@[d32] compile-flags: -C target-feature=+d32
+//@[neon] compile-flags: -C target-feature=+neon --cfg d32
+//@[neon] filecheck-flags: --check-prefix d32
+//@ needs-llvm-components: arm
+
+#![feature(no_core, repr_simd, f16)]
+#![crate_type = "rlib"]
+#![no_core]
+#![allow(asm_sub_register, non_camel_case_types)]
+
+extern crate minicore;
+use minicore::*;
+
+type ptr = *mut u8;
+
+#[repr(simd)]
+pub struct i8x8([i8; 8]);
+#[repr(simd)]
+pub struct i16x4([i16; 4]);
+#[repr(simd)]
+pub struct i32x2([i32; 2]);
+#[repr(simd)]
+pub struct i64x1([i64; 1]);
+#[repr(simd)]
+pub struct f16x4([f16; 4]);
+#[repr(simd)]
+pub struct f32x2([f32; 2]);
+#[repr(simd)]
+pub struct i8x16([i8; 16]);
+#[repr(simd)]
+pub struct i16x8([i16; 8]);
+#[repr(simd)]
+pub struct i32x4([i32; 4]);
+#[repr(simd)]
+pub struct i64x2([i64; 2]);
+#[repr(simd)]
+pub struct f16x8([f16; 8]);
+#[repr(simd)]
+pub struct f32x4([f32; 4]);
+
+impl Copy for i8x8 {}
+impl Copy for i16x4 {}
+impl Copy for i32x2 {}
+impl Copy for i64x1 {}
+impl Copy for f16x4 {}
+impl Copy for f32x2 {}
+impl Copy for i8x16 {}
+impl Copy for i16x8 {}
+impl Copy for i32x4 {}
+impl Copy for i64x2 {}
+impl Copy for f16x8 {}
+impl Copy for f32x4 {}
+
+extern "C" {
+    fn extern_func();
+    static extern_static: u8;
+}
+
+// CHECK-LABEL: sym_fn:
+// CHECK: @APP
+// CHECK: bl extern_func
+// CHECK: @NO_APP
+#[no_mangle]
+pub unsafe fn sym_fn() {
+    asm!("bl {}", sym extern_func);
+}
+
+// CHECK-LABEL: sym_static:
+// CHECK: @APP
+// CHECK: adr r0, extern_static
+// CHECK: @NO_APP
+#[no_mangle]
+pub unsafe fn sym_static() {
+    asm!("adr r0, {}", sym extern_static);
+}
+
+// Regression test for #82052.
+// CHECK-LABEL: issue_82052
+// CHECK: push {{.*}}lr
+// CHECK: @APP
+// CHECK: @NO_APP
+pub unsafe fn issue_82052() {
+    asm!("", out("r14") _);
+}
+
+macro_rules! check {
+    ($func:ident $ty:ident $class:ident $mov:literal) => {
+        #[no_mangle]
+        pub unsafe fn $func(x: $ty) -> $ty {
+            let y;
+            asm!(concat!($mov, " {}, {}"), out($class) y, in($class) x);
+            y
+        }
+    };
+}
+
+macro_rules! check_reg {
+    ($func:ident $ty:ident $reg:tt $mov:literal) => {
+        #[no_mangle]
+        pub unsafe fn $func(x: $ty) -> $ty {
+            let y;
+            asm!(concat!($mov, " ", $reg, ", ", $reg), lateout($reg) y, in($reg) x);
+            y
+        }
+    };
+}
+
+// CHECK-LABEL: reg_i8:
+// CHECK: @APP
+// CHECK: mov {{[a-z0-9]+}}, {{[a-z0-9]+}}
+// CHECK: @NO_APP
+check!(reg_i8 i8 reg "mov");
+
+// CHECK-LABEL: reg_i16:
+// CHECK: @APP
+// CHECK: mov {{[a-z0-9]+}}, {{[a-z0-9]+}}
+// CHECK: @NO_APP
+check!(reg_i16 i16 reg "mov");
+
+// CHECK-LABEL: reg_i32:
+// CHECK: @APP
+// CHECK: mov {{[a-z0-9]+}}, {{[a-z0-9]+}}
+// CHECK: @NO_APP
+check!(reg_i32 i32 reg "mov");
+
+// CHECK-LABEL: reg_f16:
+// CHECK: @APP
+// CHECK: mov {{[a-z0-9]+}}, {{[a-z0-9]+}}
+// CHECK: @NO_APP
+check!(reg_f16 f16 reg "mov");
+
+// CHECK-LABEL: reg_f32:
+// CHECK: @APP
+// CHECK: mov {{[a-z0-9]+}}, {{[a-z0-9]+}}
+// CHECK: @NO_APP
+check!(reg_f32 f32 reg "mov");
+
+// CHECK-LABEL: reg_ptr:
+// CHECK: @APP
+// CHECK: mov {{[a-z0-9]+}}, {{[a-z0-9]+}}
+// CHECK: @NO_APP
+check!(reg_ptr ptr reg "mov");
+
+// CHECK-LABEL: sreg_i32:
+// CHECK: @APP
+// CHECK: vmov.f32 s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: @NO_APP
+check!(sreg_i32 i32 sreg "vmov.f32");
+
+// CHECK-LABEL: sreg_f16:
+// CHECK: @APP
+// CHECK: vmov.f32 s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: @NO_APP
+check!(sreg_f16 f16 sreg "vmov.f32");
+
+// CHECK-LABEL: sreg_f32:
+// CHECK: @APP
+// CHECK: vmov.f32 s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: @NO_APP
+check!(sreg_f32 f32 sreg "vmov.f32");
+
+// CHECK-LABEL: sreg_ptr:
+// CHECK: @APP
+// CHECK: vmov.f32 s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: @NO_APP
+check!(sreg_ptr ptr sreg "vmov.f32");
+
+// CHECK-LABEL: sreg_low16_i32:
+// CHECK: @APP
+// CHECK: vmov.f32 s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: @NO_APP
+check!(sreg_low16_i32 i32 sreg_low16 "vmov.f32");
+
+// CHECK-LABEL: sreg_low16_f16:
+// CHECK: @APP
+// CHECK: vmov.f32 s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: @NO_APP
+check!(sreg_low16_f16 f16 sreg_low16 "vmov.f32");
+
+// CHECK-LABEL: sreg_low16_f32:
+// CHECK: @APP
+// CHECK: vmov.f32 s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: @NO_APP
+check!(sreg_low16_f32 f32 sreg_low16 "vmov.f32");
+
+// d32-LABEL: dreg_i64:
+// d32: @APP
+// d32: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// d32: @NO_APP
+#[cfg(d32)]
+check!(dreg_i64 i64 dreg "vmov.f64");
+
+// d32-LABEL: dreg_f64:
+// d32: @APP
+// d32: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// d32: @NO_APP
+#[cfg(d32)]
+check!(dreg_f64 f64 dreg "vmov.f64");
+
+// neon-LABEL: dreg_i8x8:
+// neon: @APP
+// neon: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// neon: @NO_APP
+#[cfg(neon)]
+check!(dreg_i8x8 i8x8 dreg "vmov.f64");
+
+// neon-LABEL: dreg_i16x4:
+// neon: @APP
+// neon: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// neon: @NO_APP
+#[cfg(neon)]
+check!(dreg_i16x4 i16x4 dreg "vmov.f64");
+
+// neon-LABEL: dreg_i32x2:
+// neon: @APP
+// neon: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// neon: @NO_APP
+#[cfg(neon)]
+check!(dreg_i32x2 i32x2 dreg "vmov.f64");
+
+// neon-LABEL: dreg_i64x1:
+// neon: @APP
+// neon: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// neon: @NO_APP
+#[cfg(neon)]
+check!(dreg_i64x1 i64x1 dreg "vmov.f64");
+
+// neon-LABEL: dreg_f16x4:
+// neon: @APP
+// neon: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// neon: @NO_APP
+#[cfg(neon)]
+check!(dreg_f16x4 f16x4 dreg "vmov.f64");
+
+// neon-LABEL: dreg_f32x2:
+// neon: @APP
+// neon: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// neon: @NO_APP
+#[cfg(neon)]
+check!(dreg_f32x2 f32x2 dreg "vmov.f64");
+
+// CHECK-LABEL: dreg_low16_i64:
+// CHECK: @APP
+// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// CHECK: @NO_APP
+check!(dreg_low16_i64 i64 dreg_low16 "vmov.f64");
+
+// CHECK-LABEL: dreg_low16_f64:
+// CHECK: @APP
+// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// CHECK: @NO_APP
+check!(dreg_low16_f64 f64 dreg_low16 "vmov.f64");
+
+// neon-LABEL: dreg_low16_i8x8:
+// neon: @APP
+// neon: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// neon: @NO_APP
+#[cfg(neon)]
+check!(dreg_low16_i8x8 i8x8 dreg_low16 "vmov.f64");
+
+// neon-LABEL: dreg_low16_i16x4:
+// neon: @APP
+// neon: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// neon: @NO_APP
+#[cfg(neon)]
+check!(dreg_low16_i16x4 i16x4 dreg_low16 "vmov.f64");
+
+// neon-LABEL: dreg_low16_i32x2:
+// neon: @APP
+// neon: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// neon: @NO_APP
+#[cfg(neon)]
+check!(dreg_low16_i32x2 i32x2 dreg_low16 "vmov.f64");
+
+// neon-LABEL: dreg_low16_i64x1:
+// neon: @APP
+// neon: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// neon: @NO_APP
+#[cfg(neon)]
+check!(dreg_low16_i64x1 i64x1 dreg_low16 "vmov.f64");
+
+// neon-LABEL: dreg_low16_f16x4:
+// neon: @APP
+// neon: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// neon: @NO_APP
+#[cfg(neon)]
+check!(dreg_low16_f16x4 f16x4 dreg_low16 "vmov.f64");
+
+// neon-LABEL: dreg_low16_f32x2:
+// neon: @APP
+// neon: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// neon: @NO_APP
+#[cfg(neon)]
+check!(dreg_low16_f32x2 f32x2 dreg_low16 "vmov.f64");
+
+// CHECK-LABEL: dreg_low8_i64:
+// CHECK: @APP
+// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// CHECK: @NO_APP
+check!(dreg_low8_i64 i64 dreg_low8 "vmov.f64");
+
+// CHECK-LABEL: dreg_low8_f64:
+// CHECK: @APP
+// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// CHECK: @NO_APP
+check!(dreg_low8_f64 f64 dreg_low8 "vmov.f64");
+
+// neon-LABEL: dreg_low8_i8x8:
+// neon: @APP
+// neon: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// neon: @NO_APP
+#[cfg(neon)]
+check!(dreg_low8_i8x8 i8x8 dreg_low8 "vmov.f64");
+
+// neon-LABEL: dreg_low8_i16x4:
+// neon: @APP
+// neon: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// neon: @NO_APP
+#[cfg(neon)]
+check!(dreg_low8_i16x4 i16x4 dreg_low8 "vmov.f64");
+
+// neon-LABEL: dreg_low8_i32x2:
+// neon: @APP
+// neon: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// neon: @NO_APP
+#[cfg(neon)]
+check!(dreg_low8_i32x2 i32x2 dreg_low8 "vmov.f64");
+
+// neon-LABEL: dreg_low8_i64x1:
+// neon: @APP
+// neon: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// neon: @NO_APP
+#[cfg(neon)]
+check!(dreg_low8_i64x1 i64x1 dreg_low8 "vmov.f64");
+
+// neon-LABEL: dreg_low8_f16x4:
+// neon: @APP
+// neon: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// neon: @NO_APP
+#[cfg(neon)]
+check!(dreg_low8_f16x4 f16x4 dreg_low8 "vmov.f64");
+
+// neon-LABEL: dreg_low8_f32x2:
+// neon: @APP
+// neon: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// neon: @NO_APP
+#[cfg(neon)]
+check!(dreg_low8_f32x2 f32x2 dreg_low8 "vmov.f64");
+
+// neon-LABEL: qreg_i8x16:
+// neon: @APP
+// neon: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}}
+// neon: @NO_APP
+#[cfg(neon)]
+check!(qreg_i8x16 i8x16 qreg "vmov");
+
+// neon-LABEL: qreg_i16x8:
+// neon: @APP
+// neon: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}}
+// neon: @NO_APP
+#[cfg(neon)]
+check!(qreg_i16x8 i16x8 qreg "vmov");
+
+// neon-LABEL: qreg_i32x4:
+// neon: @APP
+// neon: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}}
+// neon: @NO_APP
+#[cfg(neon)]
+check!(qreg_i32x4 i32x4 qreg "vmov");
+
+// neon-LABEL: qreg_i64x2:
+// neon: @APP
+// neon: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}}
+// neon: @NO_APP
+#[cfg(neon)]
+check!(qreg_i64x2 i64x2 qreg "vmov");
+
+// neon-LABEL: qreg_f16x8:
+// neon: @APP
+// neon: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}}
+// neon: @NO_APP
+#[cfg(neon)]
+check!(qreg_f16x8 f16x8 qreg "vmov");
+
+// neon-LABEL: qreg_f32x4:
+// neon: @APP
+// neon: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}}
+// neon: @NO_APP
+#[cfg(neon)]
+check!(qreg_f32x4 f32x4 qreg "vmov");
+
+// neon-LABEL: qreg_low8_i8x16:
+// neon: @APP
+// neon: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}}
+// neon: @NO_APP
+#[cfg(neon)]
+check!(qreg_low8_i8x16 i8x16 qreg_low8 "vmov");
+
+// neon-LABEL: qreg_low8_i16x8:
+// neon: @APP
+// neon: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}}
+// neon: @NO_APP
+#[cfg(neon)]
+check!(qreg_low8_i16x8 i16x8 qreg_low8 "vmov");
+
+// neon-LABEL: qreg_low8_i32x4:
+// neon: @APP
+// neon: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}}
+// neon: @NO_APP
+#[cfg(neon)]
+check!(qreg_low8_i32x4 i32x4 qreg_low8 "vmov");
+
+// neon-LABEL: qreg_low8_i64x2:
+// neon: @APP
+// neon: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}}
+// neon: @NO_APP
+#[cfg(neon)]
+check!(qreg_low8_i64x2 i64x2 qreg_low8 "vmov");
+
+// neon-LABEL: qreg_low8_f16x8:
+// neon: @APP
+// neon: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}}
+// neon: @NO_APP
+#[cfg(neon)]
+check!(qreg_low8_f16x8 f16x8 qreg_low8 "vmov");
+
+// neon-LABEL: qreg_low8_f32x4:
+// neon: @APP
+// neon: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}}
+// neon: @NO_APP
+#[cfg(neon)]
+check!(qreg_low8_f32x4 f32x4 qreg_low8 "vmov");
+
+// neon-LABEL: qreg_low4_i8x16:
+// neon: @APP
+// neon: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}}
+// neon: @NO_APP
+#[cfg(neon)]
+check!(qreg_low4_i8x16 i8x16 qreg_low4 "vmov");
+
+// neon-LABEL: qreg_low4_i16x8:
+// neon: @APP
+// neon: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}}
+// neon: @NO_APP
+#[cfg(neon)]
+check!(qreg_low4_i16x8 i16x8 qreg_low4 "vmov");
+
+// neon-LABEL: qreg_low4_i32x4:
+// neon: @APP
+// neon: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}}
+// neon: @NO_APP
+#[cfg(neon)]
+check!(qreg_low4_i32x4 i32x4 qreg_low4 "vmov");
+
+// neon-LABEL: qreg_low4_i64x2:
+// neon: @APP
+// neon: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}}
+// neon: @NO_APP
+#[cfg(neon)]
+check!(qreg_low4_i64x2 i64x2 qreg_low4 "vmov");
+
+// neon-LABEL: qreg_low4_f16x8:
+// neon: @APP
+// neon: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}}
+// neon: @NO_APP
+#[cfg(neon)]
+check!(qreg_low4_f16x8 f16x8 qreg_low4 "vmov");
+
+// neon-LABEL: qreg_low4_f32x4:
+// neon: @APP
+// neon: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}}
+// neon: @NO_APP
+#[cfg(neon)]
+check!(qreg_low4_f32x4 f32x4 qreg_low4 "vmov");
+
+// CHECK-LABEL: r0_i8:
+// CHECK: @APP
+// CHECK: mov r0, r0
+// CHECK: @NO_APP
+check_reg!(r0_i8 i8 "r0" "mov");
+
+// CHECK-LABEL: r0_i16:
+// CHECK: @APP
+// CHECK: mov r0, r0
+// CHECK: @NO_APP
+check_reg!(r0_i16 i16 "r0" "mov");
+
+// CHECK-LABEL: r0_i32:
+// CHECK: @APP
+// CHECK: mov r0, r0
+// CHECK: @NO_APP
+check_reg!(r0_i32 i32 "r0" "mov");
+
+// CHECK-LABEL: r0_f16:
+// CHECK: @APP
+// CHECK: mov r0, r0
+// CHECK: @NO_APP
+check_reg!(r0_f16 f16 "r0" "mov");
+
+// CHECK-LABEL: r0_f32:
+// CHECK: @APP
+// CHECK: mov r0, r0
+// CHECK: @NO_APP
+check_reg!(r0_f32 f32 "r0" "mov");
+
+// CHECK-LABEL: r0_ptr:
+// CHECK: @APP
+// CHECK: mov r0, r0
+// CHECK: @NO_APP
+check_reg!(r0_ptr ptr "r0" "mov");
+
+// CHECK-LABEL: s0_i32:
+// CHECK: @APP
+// CHECK: vmov.f32 s0, s0
+// CHECK: @NO_APP
+check_reg!(s0_i32 i32 "s0" "vmov.f32");
+
+// CHECK-LABEL: s0_f16:
+// CHECK: @APP
+// CHECK: vmov.f32 s0, s0
+// CHECK: @NO_APP
+check_reg!(s0_f16 f16 "s0" "vmov.f32");
+
+// CHECK-LABEL: s0_f32:
+// CHECK: @APP
+// CHECK: vmov.f32 s0, s0
+// CHECK: @NO_APP
+check_reg!(s0_f32 f32 "s0" "vmov.f32");
+
+// CHECK-LABEL: s0_ptr:
+// CHECK: @APP
+// CHECK: vmov.f32 s0, s0
+// CHECK: @NO_APP
+check_reg!(s0_ptr ptr "s0" "vmov.f32");
+
+// FIXME(#126797): "d0" should work with `i64` and `f64` even when `d32` is disabled.
+// d32-LABEL: d0_i64:
+// d32: @APP
+// d32: vmov.f64 d0, d0
+// d32: @NO_APP
+#[cfg(d32)]
+check_reg!(d0_i64 i64 "d0" "vmov.f64");
+
+// d32-LABEL: d0_f64:
+// d32: @APP
+// d32: vmov.f64 d0, d0
+// d32: @NO_APP
+#[cfg(d32)]
+check_reg!(d0_f64 f64 "d0" "vmov.f64");
+
+// neon-LABEL: d0_i8x8:
+// neon: @APP
+// neon: vmov.f64 d0, d0
+// neon: @NO_APP
+#[cfg(neon)]
+check_reg!(d0_i8x8 i8x8 "d0" "vmov.f64");
+
+// neon-LABEL: d0_i16x4:
+// neon: @APP
+// neon: vmov.f64 d0, d0
+// neon: @NO_APP
+#[cfg(neon)]
+check_reg!(d0_i16x4 i16x4 "d0" "vmov.f64");
+
+// neon-LABEL: d0_i32x2:
+// neon: @APP
+// neon: vmov.f64 d0, d0
+// neon: @NO_APP
+#[cfg(neon)]
+check_reg!(d0_i32x2 i32x2 "d0" "vmov.f64");
+
+// neon-LABEL: d0_i64x1:
+// neon: @APP
+// neon: vmov.f64 d0, d0
+// neon: @NO_APP
+#[cfg(neon)]
+check_reg!(d0_i64x1 i64x1 "d0" "vmov.f64");
+
+// neon-LABEL: d0_f16x4:
+// neon: @APP
+// neon: vmov.f64 d0, d0
+// neon: @NO_APP
+#[cfg(neon)]
+check_reg!(d0_f16x4 f16x4 "d0" "vmov.f64");
+
+// neon-LABEL: d0_f32x2:
+// neon: @APP
+// neon: vmov.f64 d0, d0
+// neon: @NO_APP
+#[cfg(neon)]
+check_reg!(d0_f32x2 f32x2 "d0" "vmov.f64");
+
+// neon-LABEL: q0_i8x16:
+// neon: @APP
+// neon: vorr q0, q0, q0
+// neon: @NO_APP
+#[cfg(neon)]
+check_reg!(q0_i8x16 i8x16 "q0" "vmov");
+
+// neon-LABEL: q0_i16x8:
+// neon: @APP
+// neon: vorr q0, q0, q0
+// neon: @NO_APP
+#[cfg(neon)]
+check_reg!(q0_i16x8 i16x8 "q0" "vmov");
+
+// neon-LABEL: q0_i32x4:
+// neon: @APP
+// neon: vorr q0, q0, q0
+// neon: @NO_APP
+#[cfg(neon)]
+check_reg!(q0_i32x4 i32x4 "q0" "vmov");
+
+// neon-LABEL: q0_i64x2:
+// neon: @APP
+// neon: vorr q0, q0, q0
+// neon: @NO_APP
+#[cfg(neon)]
+check_reg!(q0_i64x2 i64x2 "q0" "vmov");
+
+// neon-LABEL: q0_f16x8:
+// neon: @APP
+// neon: vorr q0, q0, q0
+// neon: @NO_APP
+#[cfg(neon)]
+check_reg!(q0_f16x8 f16x8 "q0" "vmov");
+
+// neon-LABEL: q0_f32x4:
+// neon: @APP
+// neon: vorr q0, q0, q0
+// neon: @NO_APP
+#[cfg(neon)]
+check_reg!(q0_f32x4 f32x4 "q0" "vmov");
diff --git a/tests/assembly-llvm/asm/avr-modifiers.rs b/tests/assembly-llvm/asm/avr-modifiers.rs
new file mode 100644
index 00000000000..124cad9bef6
--- /dev/null
+++ b/tests/assembly-llvm/asm/avr-modifiers.rs
@@ -0,0 +1,43 @@
+//@ add-core-stubs
+//@ assembly-output: emit-asm
+//@ compile-flags: --target avr-none -C target-cpu=atmega328p
+//@ needs-llvm-components: avr
+
+#![feature(no_core, asm_experimental_arch)]
+#![crate_type = "rlib"]
+#![no_core]
+#![allow(non_camel_case_types)]
+
+extern crate minicore;
+use minicore::*;
+
+type ptr = *const u64;
+
+macro_rules! check {
+    ($func:ident $hi:literal $lo:literal $reg:tt) => {
+        #[no_mangle]
+        unsafe fn $func() -> i16 {
+            let y;
+            asm!(concat!("mov {0:", $hi, "}, {0:", $lo, "}"), out($reg) y);
+            y
+        }
+    };
+}
+
+// CHECK-LABEL: reg_pair_modifiers:
+// CHECK: ;APP
+// CHECK: mov r{{[1-9]?[13579]}}, r{{[1-9]?[24680]}}
+// CHECK: ;NO_APP
+check!(reg_pair_modifiers "h" "l" reg_pair);
+
+// CHECK-LABEL: reg_iw_modifiers:
+// CHECK: ;APP
+// CHECK: mov r{{[1-9]?[13579]}}, r{{[1-9]?[24680]}}
+// CHECK: ;NO_APP
+check!(reg_iw_modifiers "h" "l" reg_iw);
+
+// CHECK-LABEL: reg_ptr_modifiers:
+// CHECK: ;APP
+// CHECK: mov r{{[1-9]?[13579]}}, r{{[1-9]?[24680]}}
+// CHECK: ;NO_APP
+check!(reg_ptr_modifiers "h" "l" reg_ptr);
diff --git a/tests/assembly-llvm/asm/avr-types.rs b/tests/assembly-llvm/asm/avr-types.rs
new file mode 100644
index 00000000000..309405f4d51
--- /dev/null
+++ b/tests/assembly-llvm/asm/avr-types.rs
@@ -0,0 +1,205 @@
+//@ add-core-stubs
+//@ assembly-output: emit-asm
+//@ compile-flags: --target avr-none -C target-cpu=atmega328p
+//@ needs-llvm-components: avr
+
+#![feature(no_core, asm_experimental_arch)]
+#![crate_type = "rlib"]
+#![no_core]
+#![allow(non_camel_case_types)]
+
+extern crate minicore;
+use minicore::*;
+
+type ptr = *const u64;
+
+macro_rules! check {
+    ($func:ident $ty:ident $class:ident) => {
+        #[no_mangle]
+        pub unsafe fn $func(x: $ty) -> $ty {
+            let y;
+            asm!("mov {}, {}", lateout($class) y, in($class) x);
+            y
+        }
+    };
+}
+
+macro_rules! checkw {
+    ($func:ident $ty:ident $class:ident) => {
+        #[no_mangle]
+        pub unsafe fn $func(x: $ty) -> $ty {
+            let y;
+            asm!("movw {}, {}", lateout($class) y, in($class) x);
+            y
+        }
+    };
+}
+
+macro_rules! check_reg {
+    ($func:ident $ty:ident $reg:tt) => {
+        #[no_mangle]
+        pub unsafe fn $func(x: $ty) -> $ty {
+            let y;
+            asm!(concat!("mov ", $reg, ", ", $reg), lateout($reg) y, in($reg) x);
+            y
+        }
+    };
+}
+
+macro_rules! check_regw {
+    ($func:ident $ty:ident $reg:tt $reg_lit:tt) => {
+        #[no_mangle]
+        pub unsafe fn $func(x: $ty) -> $ty {
+            let y;
+            asm!(concat!("movw ", $reg_lit, ", ", $reg_lit), lateout($reg) y, in($reg) x);
+            y
+        }
+    };
+}
+
+extern "C" {
+    fn extern_func();
+    static extern_static: i8;
+}
+
+// CHECK-LABEL: sym_fn
+// CHECK: ;APP
+// CHECK: call extern_func
+// CHECK: ;NO_APP
+#[no_mangle]
+pub unsafe fn sym_fn() {
+    asm!("call {}", sym extern_func);
+}
+
+// CHECK-LABEL: sym_static
+// CHECK: ;APP
+// CHECK: lds r{{[0-9]+}}, extern_static
+// CHECK: ;NO_APP
+#[no_mangle]
+pub unsafe fn sym_static() -> i8 {
+    let y;
+    asm!("lds {}, {}", lateout(reg) y, sym extern_static);
+    y
+}
+
+// CHECK-LABEL: ld_z:
+// CHECK: ;APP
+// CHECK: ld r{{[0-9]+}}, Z
+// CHECK: ;NO_APP
+#[no_mangle]
+pub unsafe fn ld_z(x: i16) -> i8 {
+    let y;
+    asm!("ld {}, Z", out(reg) y, in("Z") x);
+    y
+}
+
+// CHECK-LABEL: ldd_z:
+// CHECK: ;APP
+// CHECK: ldd r{{[0-9]+}}, Z+4
+// CHECK: ;NO_APP
+#[no_mangle]
+pub unsafe fn ldd_z(x: i16) -> i8 {
+    let y;
+    asm!("ldd {}, Z+4", out(reg) y, in("Z") x);
+    y
+}
+
+// CHECK-LABEL: ld_predecrement:
+// CHECK: ;APP
+// CHECK: ld r{{[0-9]+}}, -Z
+// CHECK: ;NO_APP
+#[no_mangle]
+pub unsafe fn ld_predecrement(x: i16) -> i8 {
+    let y;
+    asm!("ld {}, -Z", out(reg) y, in("Z") x);
+    y
+}
+
+// CHECK-LABEL: ld_postincrement:
+// CHECK: ;APP
+// CHECK: ld r{{[0-9]+}}, Z+
+// CHECK: ;NO_APP
+#[no_mangle]
+pub unsafe fn ld_postincrement(x: i16) -> i8 {
+    let y;
+    asm!("ld {}, Z+", out(reg) y, in("Z") x);
+    y
+}
+
+// CHECK-LABEL: muls_clobber:
+// CHECK: ;APP
+// CHECK: muls r{{[0-9]+}}, r{{[0-9]+}}
+// CHECK: movw r{{[0-9]+}}, r0
+// CHECK: ;NO_APP
+#[no_mangle]
+pub unsafe fn muls_clobber(x: i8, y: i8) -> i16 {
+    let z;
+    asm!(
+        "muls {}, {}",
+        "movw {}, r1:r0",
+        out(reg_iw) z,
+        in(reg) x,
+        in(reg) y,
+    );
+    z
+}
+
+// CHECK-LABEL: reg_i8:
+// CHECK: ;APP
+// CHECK: mov r{{[0-9]+}}, r{{[0-9]+}}
+// CHECK: ;NO_APP
+check!(reg_i8 i8 reg);
+
+// CHECK-LABEL: reg_upper_i8:
+// CHECK: ;APP
+// CHECK: mov r{{[1-3][0-9]}}, r{{[1-3][0-9]}}
+// CHECK: ;NO_APP
+check!(reg_upper_i8 i8 reg_upper);
+
+// CHECK-LABEL: reg_pair_i16:
+// CHECK: ;APP
+// CHECK: movw r{{[0-9]+}}, r{{[0-9]+}}
+// CHECK: ;NO_APP
+checkw!(reg_pair_i16 i16 reg_pair);
+
+// CHECK-LABEL: reg_iw_i16:
+// CHECK: ;APP
+// CHECK: movw r{{[0-9]+}}, r{{[0-9]+}}
+// CHECK: ;NO_APP
+checkw!(reg_iw_i16 i16 reg_iw);
+
+// CHECK-LABEL: reg_ptr_i16:
+// CHECK: ;APP
+// CHECK: movw r{{[0-9]+}}, r{{[0-9]+}}
+// CHECK: ;NO_APP
+checkw!(reg_ptr_i16 i16 reg_ptr);
+
+// CHECK-LABEL: r2_i8:
+// CHECK: ;APP
+// CHECK: mov r2, r2
+// CHECK: ;NO_APP
+check_reg!(r2_i8 i8 "r2");
+
+// CHECK-LABEL: xl_i8:
+// CHECK: ;APP
+// CHECK: mov r26, r26
+// CHECK: ;NO_APP
+check_reg!(xl_i8 i8 "XL");
+
+// CHECK-LABEL: xh_i8:
+// CHECK: ;APP
+// CHECK: mov r27, r27
+// CHECK: ;NO_APP
+check_reg!(xh_i8 i8 "XH");
+
+// CHECK-LABEL: x_i16:
+// CHECK: ;APP
+// CHECK: movw r26, r26
+// CHECK: ;NO_APP
+check_regw!(x_i16 i16 "X" "X");
+
+// CHECK-LABEL: r25r24_i16:
+// CHECK: ;APP
+// CHECK: movw r24, r24
+// CHECK: ;NO_APP
+check_regw!(r25r24_i16 i16 "r25r24" "r24");
diff --git a/tests/assembly-llvm/asm/bpf-types.rs b/tests/assembly-llvm/asm/bpf-types.rs
new file mode 100644
index 00000000000..07ea7bd5ce0
--- /dev/null
+++ b/tests/assembly-llvm/asm/bpf-types.rs
@@ -0,0 +1,133 @@
+//@ add-core-stubs
+//@ assembly-output: emit-asm
+//@ compile-flags: --target bpfel-unknown-none -C target_feature=+alu32
+//@ needs-llvm-components: bpf
+
+#![feature(no_core, asm_experimental_arch)]
+#![crate_type = "rlib"]
+#![no_core]
+#![allow(asm_sub_register, non_camel_case_types)]
+
+extern crate minicore;
+use minicore::*;
+
+type ptr = *const u64;
+
+macro_rules! check {
+    ($func:ident $ty:ident $class:ident) => {
+        #[no_mangle]
+        pub unsafe fn $func(x: $ty) -> $ty {
+            let y;
+            asm!("{} = {}", out($class) y, in($class) x);
+            y
+        }
+    };
+}
+
+macro_rules! check_reg {
+    ($func:ident $ty:ident $reg:tt) => {
+        #[no_mangle]
+        pub unsafe fn $func(x: $ty) -> $ty {
+            let y;
+            asm!(concat!($reg, " = ", $reg), lateout($reg) y, in($reg) x);
+            y
+        }
+    };
+}
+
+extern "C" {
+    fn extern_func();
+}
+
+// CHECK-LABEL: sym_fn
+// CHECK: #APP
+// CHECK: call extern_func
+// CHECK: #NO_APP
+#[no_mangle]
+pub unsafe fn sym_fn() {
+    asm!("call {}", sym extern_func);
+}
+
+// CHECK-LABEL: reg_i8:
+// CHECK: #APP
+// CHECK: r{{[0-9]+}} = r{{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i8 i8 reg);
+
+// CHECK-LABEL: reg_i16:
+// CHECK: #APP
+// CHECK: r{{[0-9]+}} = r{{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i16 i16 reg);
+
+// CHECK-LABEL: reg_i32:
+// CHECK: #APP
+// CHECK: r{{[0-9]+}} = r{{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i32 i32 reg);
+
+// CHECK-LABEL: reg_i64:
+// CHECK: #APP
+// CHECK: r{{[0-9]+}} = r{{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i64 i64 reg);
+
+// CHECK-LABEL: wreg_i8:
+// CHECK: #APP
+// CHECK: w{{[0-9]+}} = w{{[0-9]+}}
+// CHECK: #NO_APP
+check!(wreg_i8 i8 wreg);
+
+// CHECK-LABEL: wreg_i16:
+// CHECK: #APP
+// CHECK: w{{[0-9]+}} = w{{[0-9]+}}
+// CHECK: #NO_APP
+check!(wreg_i16 i16 wreg);
+
+// CHECK-LABEL: wreg_i32:
+// CHECK: #APP
+// CHECK: w{{[0-9]+}} = w{{[0-9]+}}
+// CHECK: #NO_APP
+check!(wreg_i32 i32 wreg);
+
+// CHECK-LABEL: r0_i8:
+// CHECK: #APP
+// CHECK: r0 = r0
+// CHECK: #NO_APP
+check_reg!(r0_i8 i8 "r0");
+
+// CHECK-LABEL: r0_i16:
+// CHECK: #APP
+// CHECK: r0 = r0
+// CHECK: #NO_APP
+check_reg!(r0_i16 i16 "r0");
+
+// CHECK-LABEL: r0_i32:
+// CHECK: #APP
+// CHECK: r0 = r0
+// CHECK: #NO_APP
+check_reg!(r0_i32 i32 "r0");
+
+// CHECK-LABEL: r0_i64:
+// CHECK: #APP
+// CHECK: r0 = r0
+// CHECK: #NO_APP
+check_reg!(r0_i64 i64 "r0");
+
+// CHECK-LABEL: w0_i8:
+// CHECK: #APP
+// CHECK: w0 = w0
+// CHECK: #NO_APP
+check_reg!(w0_i8 i8 "w0");
+
+// CHECK-LABEL: w0_i16:
+// CHECK: #APP
+// CHECK: w0 = w0
+// CHECK: #NO_APP
+check_reg!(w0_i16 i16 "w0");
+
+// CHECK-LABEL: w0_i32:
+// CHECK: #APP
+// CHECK: w0 = w0
+// CHECK: #NO_APP
+check_reg!(w0_i32 i32 "w0");
diff --git a/tests/assembly-llvm/asm/comments.rs b/tests/assembly-llvm/asm/comments.rs
new file mode 100644
index 00000000000..557009975dd
--- /dev/null
+++ b/tests/assembly-llvm/asm/comments.rs
@@ -0,0 +1,12 @@
+//@ assembly-output: emit-asm
+//@ only-x86_64
+// Check that comments in assembly get passed
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: test_comments:
+#[no_mangle]
+pub fn test_comments() {
+    // CHECK: example comment
+    unsafe { core::arch::asm!("nop // example comment") };
+}
diff --git a/tests/assembly-llvm/asm/global_asm.rs b/tests/assembly-llvm/asm/global_asm.rs
new file mode 100644
index 00000000000..8a4bf98c745
--- /dev/null
+++ b/tests/assembly-llvm/asm/global_asm.rs
@@ -0,0 +1,32 @@
+//@ only-x86_64
+//@ only-linux
+//@ assembly-output: emit-asm
+//@ compile-flags: -C llvm-args=--x86-asm-syntax=intel
+//@ compile-flags: -C symbol-mangling-version=v0
+
+#![crate_type = "rlib"]
+
+use std::arch::global_asm;
+
+#[no_mangle]
+fn my_func() {}
+
+#[no_mangle]
+static MY_STATIC: i32 = 0;
+
+// CHECK: mov eax, eax
+global_asm!("mov eax, eax");
+// CHECK: mov ebx, 5
+global_asm!("mov ebx, {}", const 5);
+// CHECK: mov ecx, 5
+global_asm!("movl ${}, %ecx", const 5, options(att_syntax));
+// CHECK: call my_func
+global_asm!("call {}", sym my_func);
+// CHECK: lea rax, [rip + MY_STATIC]
+global_asm!("lea rax, [rip + {}]", sym MY_STATIC);
+// CHECK: call _RNvC[[CRATE_IDENT:[a-zA-Z0-9]{12}]]_10global_asm6foobar
+global_asm!("call {}", sym foobar);
+// CHECK: _RNvC[[CRATE_IDENT]]_10global_asm6foobar:
+fn foobar() {
+    loop {}
+}
diff --git a/tests/assembly-llvm/asm/hexagon-types.rs b/tests/assembly-llvm/asm/hexagon-types.rs
new file mode 100644
index 00000000000..ce80fa75b35
--- /dev/null
+++ b/tests/assembly-llvm/asm/hexagon-types.rs
@@ -0,0 +1,139 @@
+//@ add-core-stubs
+//@ assembly-output: emit-asm
+//@ compile-flags: --target hexagon-unknown-linux-musl
+//@ compile-flags: -Zmerge-functions=disabled
+//@ needs-llvm-components: hexagon
+
+#![feature(no_core, asm_experimental_arch)]
+#![crate_type = "rlib"]
+#![no_core]
+#![allow(asm_sub_register, non_camel_case_types)]
+
+extern crate minicore;
+use minicore::*;
+
+type ptr = *const i32;
+
+extern "C" {
+    fn extern_func();
+    static extern_static: u8;
+}
+
+macro_rules! check {
+    ($func:ident $ty:ident $class:ident) => {
+        #[no_mangle]
+        pub unsafe fn $func(x: $ty) -> $ty {
+            let y;
+            asm!("{} = {}", out($class) y, in($class) x);
+            y
+        }
+    };
+}
+
+macro_rules! check_reg {
+    ($func:ident $ty:ident $reg:tt) => {
+        #[no_mangle]
+        pub unsafe fn $func(x: $ty) -> $ty {
+            let y;
+            asm!(concat!($reg, " = ", $reg), lateout($reg) y, in($reg) x);
+            y
+        }
+    };
+}
+
+// CHECK-LABEL: sym_static:
+// CHECK: InlineAsm Start
+// CHECK: r0 = {{#+}}extern_static
+// CHECK: InlineAsm End
+#[no_mangle]
+pub unsafe fn sym_static() {
+    asm!("r0 = #{}", sym extern_static);
+}
+
+// CHECK-LABEL: sym_fn:
+// CHECK: InlineAsm Start
+// CHECK: r0 = {{#+}}extern_func
+// CHECK: InlineAsm End
+#[no_mangle]
+pub unsafe fn sym_fn() {
+    asm!("r0 = #{}", sym extern_func);
+}
+
+// This is a test for multi-instruction packets,
+// which require the escaped braces.
+//
+// CHECK-LABEL: packet:
+// CHECK: InlineAsm Start
+// CHECK: {
+// CHECK:   r{{[0-9]+}} = r0
+// CHECK:   memw(r1{{(\+#0)?}}) = r{{[0-9]+}}
+// CHECK: }
+// CHECK: InlineAsm End
+#[no_mangle]
+pub unsafe fn packet() {
+    let val = 1024;
+    asm!("{{
+        {} = r0
+        memw(r1) = {}
+    }}", out(reg) _, in(reg) &val);
+}
+
+// CHECK-LABEL: reg_ptr:
+// CHECK: InlineAsm Start
+// CHECK: r{{[0-9]+}} = r{{[0-9]+}}
+// CHECK: InlineAsm End
+check!(reg_ptr ptr reg);
+
+// CHECK-LABEL: reg_f32:
+// CHECK: InlineAsm Start
+// CHECK: r{{[0-9]+}} = r{{[0-9]+}}
+// CHECK: InlineAsm End
+check!(reg_f32 f32 reg);
+
+// CHECK-LABEL: reg_i32:
+// CHECK: InlineAsm Start
+// CHECK: r{{[0-9]+}} = r{{[0-9]+}}
+// CHECK: InlineAsm End
+check!(reg_i32 i32 reg);
+
+// CHECK-LABEL: reg_i8:
+// CHECK: InlineAsm Start
+// CHECK: r{{[0-9]+}} = r{{[0-9]+}}
+// CHECK: InlineAsm End
+check!(reg_i8 i8 reg);
+
+// CHECK-LABEL: reg_i16:
+// CHECK: InlineAsm Start
+// CHECK: r{{[0-9]+}} = r{{[0-9]+}}
+// CHECK: InlineAsm End
+check!(reg_i16 i16 reg);
+
+// CHECK-LABEL: r0_ptr:
+// CHECK: InlineAsm Start
+// CHECK: r0 = r0
+// CHECK: InlineAsm End
+check_reg!(r0_ptr ptr "r0");
+
+// CHECK-LABEL: r0_f32:
+// CHECK: InlineAsm Start
+// CHECK: r0 = r0
+// CHECK: InlineAsm End
+check_reg!(r0_f32 f32 "r0");
+
+// CHECK-LABEL: r0_i32:
+// CHECK: InlineAsm Start
+// CHECK: r0 = r0
+// CHECK: InlineAsm End
+check_reg!(r0_i32 i32 "r0");
+
+// CHECK-LABEL: r0_i8:
+// CHECK: InlineAsm Start
+// CHECK: r0 = r0
+// CHECK: InlineAsm End
+check_reg!(r0_i8 i8 "r0");
+
+// CHECK-LABEL: r0_i16:
+// CHECK: InlineAsm Start
+// CHECK: r0 = r0
+// CHECK: InlineAsm End
+check_reg!(r0_i16 i16 "r0");
diff --git a/tests/assembly-llvm/asm/inline-asm-avx.rs b/tests/assembly-llvm/asm/inline-asm-avx.rs
new file mode 100644
index 00000000000..630acbb971a
--- /dev/null
+++ b/tests/assembly-llvm/asm/inline-asm-avx.rs
@@ -0,0 +1,25 @@
+//@ assembly-output: emit-asm
+//@ compile-flags: --crate-type=lib
+//@ only-x86_64
+//@ ignore-sgx
+
+#![feature(portable_simd)]
+
+use std::arch::asm;
+use std::simd::Simd;
+
+#[target_feature(enable = "avx")]
+#[no_mangle]
+// CHECK-LABEL: convert:
+pub unsafe fn convert(a: *const f32) -> Simd<f32, 8> {
+    // CHECK: vbroadcastss (%{{[er][a-ds0-9][xpi0-9]?}}), {{%ymm[0-7]}}
+    let b: Simd<f32, 8>;
+    unsafe {
+        asm!(
+            "vbroadcastss {b}, [{a}]",
+            a = in(reg) a,
+            b = out(ymm_reg) b,
+        );
+    }
+    b
+}
diff --git a/tests/assembly-llvm/asm/loongarch-type.rs b/tests/assembly-llvm/asm/loongarch-type.rs
new file mode 100644
index 00000000000..c782be19f1d
--- /dev/null
+++ b/tests/assembly-llvm/asm/loongarch-type.rs
@@ -0,0 +1,190 @@
+//@ add-core-stubs
+//@ assembly-output: emit-asm
+//@ compile-flags: --target loongarch64-unknown-linux-gnu
+//@ compile-flags: -Zmerge-functions=disabled
+//@ needs-llvm-components: loongarch
+
+#![feature(no_core, f16)]
+#![crate_type = "rlib"]
+#![no_core]
+#![allow(asm_sub_register, non_camel_case_types)]
+
+extern crate minicore;
+use minicore::*;
+
+type ptr = *const i32;
+
+extern "C" {
+    fn extern_func();
+    static extern_static: u8;
+}
+
+// CHECK-LABEL: sym_fn:
+// CHECK: #APP
+// CHECK: pcalau12i $t0, %got_pc_hi20(extern_func)
+// CHECK: ld.d $t0, $t0, %got_pc_lo12(extern_func)
+// CHECK: #NO_APP
+#[no_mangle]
+pub unsafe fn sym_fn() {
+    asm!("la.got $r12, {}", sym extern_func);
+}
+
+// CHECK-LABEL: sym_static:
+// CHECK: #APP
+// CHECK: pcalau12i $t0, %got_pc_hi20(extern_static)
+// CHECK: ld.d $t0, $t0, %got_pc_lo12(extern_static)
+// CHECK: #NO_APP
+#[no_mangle]
+pub unsafe fn sym_static() {
+    asm!("la.got $r12, {}", sym extern_static);
+}
+
+macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => {
+    #[no_mangle]
+    pub unsafe fn $func(x: $ty) -> $ty {
+        let y;
+        asm!(concat!($mov," {}, {}"), out($class) y, in($class) x);
+        y
+    }
+};}
+
+macro_rules! check_reg { ($func:ident, $ty:ty, $reg:tt, $mov:literal) => {
+    #[no_mangle]
+    pub unsafe fn $func(x: $ty) -> $ty {
+        let y;
+        asm!(concat!($mov, " ", $reg, ", ", $reg), lateout($reg) y, in($reg) x);
+        y
+    }
+};}
+
+// CHECK-LABEL: reg_i8:
+// CHECK: #APP
+// CHECK: move ${{[a-z0-9]+}}, ${{[a-z0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i8, i8, reg, "move");
+
+// CHECK-LABEL: reg_i16:
+// CHECK: #APP
+// CHECK: move ${{[a-z0-9]+}}, ${{[a-z0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i16, i16, reg, "move");
+
+// CHECK-LABEL: reg_f16:
+// CHECK: #APP
+// CHECK: move ${{[a-z0-9]+}}, ${{[a-z0-9]+}}
+// CHECK: #NO_APP
+check!(reg_f16, f16, reg, "move");
+
+// CHECK-LABEL: reg_i32:
+// CHECK: #APP
+// CHECK: move ${{[a-z0-9]+}}, ${{[a-z0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i32, i32, reg, "move");
+
+// CHECK-LABEL: reg_f32:
+// CHECK: #APP
+// CHECK: move ${{[a-z0-9]+}}, ${{[a-z0-9]+}}
+// CHECK: #NO_APP
+check!(reg_f32, f32, reg, "move");
+
+// CHECK-LABEL: reg_i64:
+// CHECK: #APP
+// CHECK: move ${{[a-z0-9]+}}, ${{[a-z0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i64, i64, reg, "move");
+
+// CHECK-LABEL: reg_f64:
+// CHECK: #APP
+// CHECK: move ${{[a-z0-9]+}}, ${{[a-z0-9]+}}
+// CHECK: #NO_APP
+check!(reg_f64, f64, reg, "move");
+
+// CHECK-LABEL: reg_ptr:
+// CHECK: #APP
+// CHECK: move ${{[a-z0-9]+}}, ${{[a-z0-9]+}}
+// CHECK: #NO_APP
+check!(reg_ptr, ptr, reg, "move");
+
+// CHECK-LABEL: freg_f16:
+// CHECK: #APP
+// CHECK: fmov.s $f{{[a-z0-9]+}}, $f{{[a-z0-9]+}}
+// CHECK: #NO_APP
+check!(freg_f16, f16, freg, "fmov.s");
+
+// CHECK-LABEL: freg_f32:
+// CHECK: #APP
+// CHECK: fmov.s $f{{[a-z0-9]+}}, $f{{[a-z0-9]+}}
+// CHECK: #NO_APP
+check!(freg_f32, f32, freg, "fmov.s");
+
+// CHECK-LABEL: freg_f64:
+// CHECK: #APP
+// CHECK: fmov.d $f{{[a-z0-9]+}}, $f{{[a-z0-9]+}}
+// CHECK: #NO_APP
+check!(freg_f64, f64, freg, "fmov.d");
+
+// CHECK-LABEL: r4_i8:
+// CHECK: #APP
+// CHECK: move $a0, $a0
+// CHECK: #NO_APP
+check_reg!(r4_i8, i8, "$r4", "move");
+
+// CHECK-LABEL: r4_i16:
+// CHECK: #APP
+// CHECK: move $a0, $a0
+// CHECK: #NO_APP
+check_reg!(r4_i16, i16, "$r4", "move");
+
+// CHECK-LABEL: r4_f16:
+// CHECK: #APP
+// CHECK: move $a0, $a0
+// CHECK: #NO_APP
+check_reg!(r4_f16, f16, "$r4", "move");
+
+// CHECK-LABEL: r4_i32:
+// CHECK: #APP
+// CHECK: move $a0, $a0
+// CHECK: #NO_APP
+check_reg!(r4_i32, i32, "$r4", "move");
+
+// CHECK-LABEL: r4_f32:
+// CHECK: #APP
+// CHECK: move $a0, $a0
+// CHECK: #NO_APP
+check_reg!(r4_f32, f32, "$r4", "move");
+
+// CHECK-LABEL: r4_i64:
+// CHECK: #APP
+// CHECK: move $a0, $a0
+// CHECK: #NO_APP
+check_reg!(r4_i64, i64, "$r4", "move");
+
+// CHECK-LABEL: r4_f64:
+// CHECK: #APP
+// CHECK: move $a0, $a0
+// CHECK: #NO_APP
+check_reg!(r4_f64, f64, "$r4", "move");
+
+// CHECK-LABEL: r4_ptr:
+// CHECK: #APP
+// CHECK: move $a0, $a0
+// CHECK: #NO_APP
+check_reg!(r4_ptr, ptr, "$r4", "move");
+
+// CHECK-LABEL: f0_f16:
+// CHECK: #APP
+// CHECK: fmov.s $f{{[a-z0-9]+}}, $f{{[a-z0-9]+}}
+// CHECK: #NO_APP
+check_reg!(f0_f16, f16, "$f0", "fmov.s");
+
+// CHECK-LABEL: f0_f32:
+// CHECK: #APP
+// CHECK: fmov.s $f{{[a-z0-9]+}}, $f{{[a-z0-9]+}}
+// CHECK: #NO_APP
+check_reg!(f0_f32, f32, "$f0", "fmov.s");
+
+// CHECK-LABEL: f0_f64:
+// CHECK: #APP
+// CHECK: fmov.d $f{{[a-z0-9]+}}, $f{{[a-z0-9]+}}
+// CHECK: #NO_APP
+check_reg!(f0_f64, f64, "$f0", "fmov.d");
diff --git a/tests/assembly-llvm/asm/m68k-types.rs b/tests/assembly-llvm/asm/m68k-types.rs
new file mode 100644
index 00000000000..9e4f6d9a1a9
--- /dev/null
+++ b/tests/assembly-llvm/asm/m68k-types.rs
@@ -0,0 +1,67 @@
+//@ add-core-stubs
+//@ assembly-output: emit-asm
+//@ compile-flags: --target m68k-unknown-linux-gnu
+//@ needs-llvm-components: m68k
+
+#![feature(no_core, asm_experimental_arch)]
+#![crate_type = "rlib"]
+#![no_core]
+#![allow(non_camel_case_types)]
+
+extern crate minicore;
+use minicore::*;
+
+type ptr = *const u64;
+
+macro_rules! check {
+    ($func:ident $ty:ident $class:ident $mov:literal) => {
+        #[no_mangle]
+        pub unsafe fn $func(x: $ty) -> $ty {
+            let y;
+            asm!(concat!($mov, " {}, {};"), out($class) y, in($class) x);
+            y
+        }
+    };
+}
+
+// CHECK-LABEL: reg_data_i8:
+// CHECK: ;APP
+// CHECK: move.b %d{{[0-9]}}, %d{{[0-9]}}
+// CHECK: ;NO_APP
+check!(reg_data_i8 i8 reg_data "move.b");
+
+// CHECK-LABEL: reg_data_i16:
+// CHECK: ;APP
+// CHECK: move.w %d{{[0-9]}}, %d{{[0-9]}}
+// CHECK: ;NO_APP
+check!(reg_data_i16 i16 reg_data "move.w");
+
+// CHECK-LABEL: reg_data_i32:
+// CHECK: ;APP
+// CHECK: move.l %d{{[0-9]}}, %d{{[0-9]}}
+// CHECK: ;NO_APP
+check!(reg_data_i32 i32 reg_data "move.l");
+
+// CHECK-LABEL: reg_addr_i16:
+// CHECK: ;APP
+// CHECK: move.w %a{{[0-9]}}, %a{{[0-9]}}
+// CHECK: ;NO_APP
+check!(reg_addr_i16 i16 reg_addr "move.w");
+
+// CHECK-LABEL: reg_addr_i32:
+// CHECK: ;APP
+// CHECK: move.l %a{{[0-9]}}, %a{{[0-9]}}
+// CHECK: ;NO_APP
+check!(reg_addr_i32 i32 reg_addr "move.l");
+
+// CHECK-LABEL: reg_i16:
+// CHECK: ;APP
+// CHECK: move.w %{{[da][0-9]}}, %{{[da][0-9]}}
+// CHECK: ;NO_APP
+check!(reg_i16 i16 reg "move.w");
+
+// CHECK-LABEL: reg_i32:
+// CHECK: ;APP
+// CHECK: move.l %{{[da][0-9]}}, %{{[da][0-9]}}
+// CHECK: ;NO_APP
+check!(reg_i32 i32 reg "move.l");
diff --git a/tests/assembly-llvm/asm/mips-types.rs b/tests/assembly-llvm/asm/mips-types.rs
new file mode 100644
index 00000000000..00e8ce0b874
--- /dev/null
+++ b/tests/assembly-llvm/asm/mips-types.rs
@@ -0,0 +1,211 @@
+//@ add-core-stubs
+//@ revisions: mips32 mips64
+//@ assembly-output: emit-asm
+//@[mips32] compile-flags: --target mips-unknown-linux-gnu
+//@[mips32] needs-llvm-components: mips
+//@[mips64] compile-flags: --target mips64-unknown-linux-gnuabi64
+//@[mips64] needs-llvm-components: mips
+//@ compile-flags: -Zmerge-functions=disabled
+
+#![feature(no_core, asm_experimental_arch)]
+#![crate_type = "rlib"]
+#![no_core]
+#![allow(asm_sub_register, non_camel_case_types)]
+
+extern crate minicore;
+use minicore::*;
+
+type ptr = *const i32;
+
+extern "C" {
+    fn extern_func();
+    static extern_static: u8;
+}
+
+macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => {
+    #[no_mangle]
+    pub unsafe fn $func(x: $ty) -> $ty {
+        let y;
+        asm!(concat!($mov," {}, {}"), out($class) y, in($class) x);
+        y
+    }
+};}
+
+macro_rules! check_reg { ($func:ident, $ty:ty, $reg:tt, $mov:literal) => {
+    #[no_mangle]
+    pub unsafe fn $func(x: $ty) -> $ty {
+        let y;
+        asm!(concat!($mov, " ", $reg, ", ", $reg), lateout($reg) y, in($reg) x);
+        y
+    }
+};}
+
+// mips32-LABEL: sym_static_32:
+// mips32: #APP
+// mips32: lw $3, %got(extern_static)($gp)
+// mips32: #NO_APP
+#[cfg(mips32)]
+#[no_mangle]
+pub unsafe fn sym_static_32() {
+    asm!("lw $v1, {}", sym extern_static);
+}
+
+// mips32-LABEL: sym_fn_32:
+// mips32: #APP
+// mips32: lw $3, %got(extern_func)($gp)
+// mips32: #NO_APP
+#[cfg(mips32)]
+#[no_mangle]
+pub unsafe fn sym_fn_32() {
+    asm!("lw $v1, {}", sym extern_func);
+}
+
+// mips64-LABEL: sym_static_64:
+// mips64: #APP
+// mips64: lui    $3, %got_hi(extern_static)
+// mips64: daddu  $3, $3, $gp
+// mips64: ld     $3, %got_lo(extern_static)($3)
+// mips64: #NO_APP
+#[cfg(mips64)]
+#[no_mangle]
+pub unsafe fn sym_static_64() {
+    asm!("ld $v1, {}", sym extern_static);
+}
+
+// mips64-LABEL: sym_fn_64:
+// mips64: #APP
+// mips64: lui    $3, %got_hi(extern_func)
+// mips64: daddu  $3, $3, $gp
+// mips64: ld     $3, %got_lo(extern_func)($3)
+// mips64: #NO_APP
+#[cfg(mips64)]
+#[no_mangle]
+pub unsafe fn sym_fn_64() {
+    asm!("ld $v1, {}", sym extern_func);
+}
+
+// CHECK-LABEL: reg_f32:
+// CHECK: #APP
+// CHECK: mov.s $f{{[0-9]+}}, $f{{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_f32, f32, freg, "mov.s");
+
+// CHECK-LABEL: f0_f32:
+// CHECK: #APP
+// CHECK: mov.s $f0, $f0
+// CHECK: #NO_APP
+#[no_mangle]
+check_reg!(f0_f32, f32, "$f0", "mov.s");
+
+// CHECK-LABEL: reg_f32_64:
+// CHECK: #APP
+// CHECK: mov.d $f{{[0-9]+}}, $f{{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_f32_64, f32, freg, "mov.d");
+
+// CHECK-LABEL: f0_f32_64:
+// CHECK: #APP
+// CHECK: mov.d $f0, $f0
+// CHECK: #NO_APP
+#[no_mangle]
+check_reg!(f0_f32_64, f32, "$f0", "mov.d");
+
+// CHECK-LABEL: reg_f64:
+// CHECK: #APP
+// CHECK: mov.d $f{{[0-9]+}}, $f{{[0-9]+}}
+// CHECK: #NO_APP
+#[no_mangle]
+check!(reg_f64, f64, freg, "mov.d");
+
+// CHECK-LABEL: f0_f64:
+// CHECK: #APP
+// CHECK: mov.d $f0, $f0
+// CHECK: #NO_APP
+#[no_mangle]
+check_reg!(f0_f64, f64, "$f0", "mov.d");
+
+// CHECK-LABEL: reg_ptr:
+// CHECK: #APP
+// CHECK: move ${{[0-9]+}}, ${{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_ptr, ptr, reg, "move");
+
+// CHECK-LABEL: reg_i32:
+// CHECK: #APP
+// CHECK: move ${{[0-9]+}}, ${{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i32, i32, reg, "move");
+
+// CHECK-LABEL: reg_f32_soft:
+// CHECK: #APP
+// CHECK: move ${{[0-9]+}}, ${{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_f32_soft, f32, reg, "move");
+
+// mips64-LABEL: reg_f64_soft:
+// mips64: #APP
+// mips64: move ${{[0-9]+}}, ${{[0-9]+}}
+// mips64: #NO_APP
+#[cfg(mips64)]
+check!(reg_f64_soft, f64, reg, "move");
+
+// CHECK-LABEL: reg_i8:
+// CHECK: #APP
+// CHECK: move ${{[0-9]+}}, ${{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i8, i8, reg, "move");
+
+// CHECK-LABEL: reg_u8:
+// CHECK: #APP
+// CHECK: move ${{[0-9]+}}, ${{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_u8, u8, reg, "move");
+
+// CHECK-LABEL: reg_i16:
+// CHECK: #APP
+// CHECK: move ${{[0-9]+}}, ${{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i16, i16, reg, "move");
+
+// mips64-LABEL: reg_i64:
+// mips64: #APP
+// mips64: move ${{[0-9]+}}, ${{[0-9]+}}
+// mips64: #NO_APP
+#[cfg(mips64)]
+check!(reg_i64, i64, reg, "move");
+
+// CHECK-LABEL: r8_ptr:
+// CHECK: #APP
+// CHECK: move $8, $8
+// CHECK: #NO_APP
+check_reg!(r8_ptr, ptr, "$8", "move");
+
+// CHECK-LABEL: r8_i32:
+// CHECK: #APP
+// CHECK: move $8, $8
+// CHECK: #NO_APP
+check_reg!(r8_i32, i32, "$8", "move");
+
+// CHECK-LABEL: r8_f32:
+// CHECK: #APP
+// CHECK: move $8, $8
+// CHECK: #NO_APP
+check_reg!(r8_f32, f32, "$8", "move");
+
+// CHECK-LABEL: r8_i8:
+// CHECK: #APP
+// CHECK: move $8, $8
+// CHECK: #NO_APP
+check_reg!(r8_i8, i8, "$8", "move");
+
+// CHECK-LABEL: r8_u8:
+// CHECK: #APP
+// CHECK: move $8, $8
+// CHECK: #NO_APP
+check_reg!(r8_u8, u8, "$8", "move");
+
+// CHECK-LABEL: r8_i16:
+// CHECK: #APP
+// CHECK: move $8, $8
+// CHECK: #NO_APP
+check_reg!(r8_i16, i16, "$8", "move");
diff --git a/tests/assembly-llvm/asm/msp430-types.rs b/tests/assembly-llvm/asm/msp430-types.rs
new file mode 100644
index 00000000000..442dc77999f
--- /dev/null
+++ b/tests/assembly-llvm/asm/msp430-types.rs
@@ -0,0 +1,141 @@
+//@ add-core-stubs
+//@ assembly-output: emit-asm
+//@ compile-flags: --target msp430-none-elf
+//@ needs-llvm-components: msp430
+
+#![feature(no_core, asm_experimental_arch)]
+#![crate_type = "rlib"]
+#![no_core]
+#![allow(non_camel_case_types)]
+
+extern crate minicore;
+use minicore::*;
+
+type ptr = *const i16;
+
+macro_rules! check {
+    ($func:ident $ty:ident $class:ident) => {
+        #[no_mangle]
+        pub unsafe fn $func(x: $ty) -> $ty {
+            let y;
+            asm!("mov {}, {}", lateout($class) y, in($class) x);
+            y
+        }
+    };
+}
+
+macro_rules! checkb {
+    ($func:ident $ty:ident $class:ident) => {
+        #[no_mangle]
+        pub unsafe fn $func(x: $ty) -> $ty {
+            let y;
+            asm!("mov.b {}, {}", lateout($class) y, in($class) x);
+            y
+        }
+    };
+}
+
+macro_rules! check_reg {
+    ($func:ident $ty:ident $reg:tt) => {
+        #[no_mangle]
+        pub unsafe fn $func(x: $ty) -> $ty {
+            let y;
+            asm!(concat!("mov ", $reg, ", ", $reg), lateout($reg) y, in($reg) x);
+            y
+        }
+    };
+}
+
+macro_rules! check_regb {
+    ($func:ident $ty:ident $reg:tt) => {
+        #[no_mangle]
+        pub unsafe fn $func(x: $ty) -> $ty {
+            let y;
+            asm!(concat!("mov.b ", $reg, ", ", $reg), lateout($reg) y, in($reg) x);
+            y
+        }
+    };
+}
+
+extern "C" {
+    fn extern_func();
+    static extern_static: i8;
+}
+
+// CHECK-LABEL: sym_fn
+// CHECK: ;APP
+// CHECK: call extern_func
+// CHECK: ;NO_APP
+#[no_mangle]
+pub unsafe fn sym_fn() {
+    asm!("call {}", sym extern_func);
+}
+
+// CHECK-LABEL: sym_static
+// CHECK: ;APP
+// CHECK: mov.b extern_static, r{{[0-9]+}}
+// CHECK: ;NO_APP
+#[no_mangle]
+pub unsafe fn sym_static() -> i8 {
+    let y;
+    asm!("mov.b {1}, {0}", lateout(reg) y, sym extern_static);
+    y
+}
+
+// CHECK-LABEL: add_const:
+// CHECK: ;APP
+// CHECK: add.b #5, r{{[0-9]+}}
+// CHECK: ;NO_APP
+#[no_mangle]
+pub unsafe fn add_const() -> i8 {
+    let y;
+    asm!("add.b #{number}, {}", out(reg) y, number = const 5);
+    y
+}
+
+// CHECK-LABEL: mov_postincrement:
+// CHECK: ;APP
+// CHECK: mov @r5+, r{{[0-9]+}}
+// CHECK: ;NO_APP
+#[no_mangle]
+pub unsafe fn mov_postincrement(mut x: *const i16) -> (i16, *const i16) {
+    let y;
+    asm!("mov @r5+, {0}", out(reg) y, inlateout("r5") x);
+    (y, x)
+}
+
+// CHECK-LABEL: reg_i8:
+// CHECK: ;APP
+// CHECK: mov r{{[0-9]+}}, r{{[0-9]+}}
+// CHECK: ;NO_APP
+check!(reg_i8 i8 reg);
+
+// CHECK-LABEL: reg_i16:
+// CHECK: ;APP
+// CHECK: mov r{{[0-9]+}}, r{{[0-9]+}}
+// CHECK: ;NO_APP
+check!(reg_i16 i16 reg);
+
+// CHECK-LABEL: reg_i8b:
+// CHECK: ;APP
+// CHECK: mov.b r{{[0-9]+}}, r{{[0-9]+}}
+// CHECK: ;NO_APP
+checkb!(reg_i8b i8 reg);
+
+// CHECK-LABEL: r5_i8:
+// CHECK: ;APP
+// CHECK: mov r5, r5
+// CHECK: ;NO_APP
+check_reg!(r5_i8 i8 "r5");
+
+// CHECK-LABEL: r5_i16:
+// CHECK: ;APP
+// CHECK: mov r5, r5
+// CHECK: ;NO_APP
+check_reg!(r5_i16 i16 "r5");
+
+// CHECK-LABEL: r5_i8b:
+// CHECK: ;APP
+// CHECK: mov.b r5, r5
+// CHECK: ;NO_APP
+check_regb!(r5_i8b i8 "r5");
diff --git a/tests/assembly-llvm/asm/nvptx-types.rs b/tests/assembly-llvm/asm/nvptx-types.rs
new file mode 100644
index 00000000000..7e8ebd03024
--- /dev/null
+++ b/tests/assembly-llvm/asm/nvptx-types.rs
@@ -0,0 +1,115 @@
+//@ add-core-stubs
+//@ assembly-output: emit-asm
+//@ compile-flags: --target nvptx64-nvidia-cuda
+//@ needs-llvm-components: nvptx
+
+#![feature(no_core, asm_experimental_arch)]
+#![crate_type = "rlib"]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
+
+type ptr = *mut u8;
+
+// NVPTX does not support static variables
+#[no_mangle]
+fn extern_func() {}
+
+// CHECK-LABEL: .visible .func sym_fn()
+// CHECK: // begin inline asm
+// CHECK: call extern_func;
+// CHECK: // end inline asm
+#[no_mangle]
+pub unsafe fn sym_fn() {
+    asm!("call {};", sym extern_func);
+}
+
+macro_rules! check {
+    ($func:ident $ty:ident $class:ident $mov:literal) => {
+        #[no_mangle]
+        pub unsafe fn $func(x: $ty) -> $ty {
+            let y;
+            asm!(concat!($mov, " {}, {};"), out($class) y, in($class) x);
+            y
+        }
+    };
+}
+
+// CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg16_i8
+// CHECK: // begin inline asm
+// CHECK: mov.i16 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: // end inline asm
+check!(reg16_i8 i8 reg16 "mov.i16");
+
+// CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg16_i16
+// CHECK: // begin inline asm
+// CHECK: mov.i16 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: // end inline asm
+check!(reg16_i16 i16 reg16 "mov.i16");
+
+// CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg32_i8
+// CHECK: // begin inline asm
+// CHECK: mov.i32 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: // end inline asm
+check!(reg32_i8 i8 reg32 "mov.i32");
+
+// CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg32_i16
+// CHECK: // begin inline asm
+// CHECK: mov.i32 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: // end inline asm
+check!(reg32_i16 i16 reg32 "mov.i32");
+
+// CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg32_i32
+// CHECK: // begin inline asm
+// CHECK: mov.i32 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: // end inline asm
+check!(reg32_i32 i32 reg32 "mov.i32");
+
+// CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg32_f32
+// CHECK: // begin inline asm
+// CHECK: mov.i32 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: // end inline asm
+check!(reg32_f32 f32 reg32 "mov.i32");
+
+// CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg64_i8
+// CHECK: // begin inline asm
+// CHECK: mov.i64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: // end inline asm
+check!(reg64_i8 i8 reg64 "mov.i64");
+
+// CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg64_i16
+// CHECK: // begin inline asm
+// CHECK: mov.i64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: // end inline asm
+check!(reg64_i16 i16 reg64 "mov.i64");
+
+// CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg64_i32
+// CHECK: // begin inline asm
+// CHECK: mov.i64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: // end inline asm
+check!(reg64_i32 i32 reg64 "mov.i64");
+
+// CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg64_f32
+// CHECK: // begin inline asm
+// CHECK: mov.i64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: // end inline asm
+check!(reg64_f32 f32 reg64 "mov.i64");
+
+// CHECK-LABEL: .visible .func (.param .b64 func_retval0) reg64_i64
+// CHECK: // begin inline asm
+// CHECK: mov.i64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: // end inline asm
+check!(reg64_i64 i64 reg64 "mov.i64");
+
+// CHECK-LABEL: .visible .func (.param .b64 func_retval0) reg64_f64
+// CHECK: // begin inline asm
+// CHECK: mov.i64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: // end inline asm
+check!(reg64_f64 f64 reg64 "mov.i64");
+
+// CHECK-LABEL: .visible .func (.param .b64 func_retval0) reg64_ptr
+// CHECK: // begin inline asm
+// CHECK: mov.i64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: // end inline asm
+check!(reg64_ptr ptr reg64 "mov.i64");
diff --git a/tests/assembly-llvm/asm/powerpc-types.rs b/tests/assembly-llvm/asm/powerpc-types.rs
new file mode 100644
index 00000000000..4291e4c02f3
--- /dev/null
+++ b/tests/assembly-llvm/asm/powerpc-types.rs
@@ -0,0 +1,474 @@
+//@ add-core-stubs
+//@ revisions: powerpc powerpc_altivec powerpc_vsx powerpc64 powerpc64_vsx
+//@ assembly-output: emit-asm
+//@[powerpc] compile-flags: --target powerpc-unknown-linux-gnu
+//@[powerpc] needs-llvm-components: powerpc
+//@[powerpc_altivec] compile-flags: --target powerpc-unknown-linux-gnu -C target-feature=+altivec --cfg altivec
+//@[powerpc_altivec] needs-llvm-components: powerpc
+//@[powerpc_vsx] compile-flags: --target powerpc-unknown-linux-gnu -C target-feature=+altivec,+vsx --cfg altivec --cfg vsx
+//@[powerpc_vsx] needs-llvm-components: powerpc
+//@[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu --cfg altivec
+//@[powerpc64] needs-llvm-components: powerpc
+//@[powerpc64_vsx] compile-flags: --target powerpc64-unknown-linux-gnu -C target-feature=+vsx --cfg altivec --cfg vsx
+//@[powerpc64_vsx] needs-llvm-components: powerpc
+//@ compile-flags: -Zmerge-functions=disabled
+
+#![feature(no_core, repr_simd, asm_experimental_arch)]
+#![crate_type = "rlib"]
+#![no_core]
+#![allow(asm_sub_register, non_camel_case_types)]
+
+extern crate minicore;
+use minicore::*;
+
+#[cfg_attr(altivec, cfg(not(target_feature = "altivec")))]
+#[cfg_attr(not(altivec), cfg(target_feature = "altivec"))]
+compile_error!("altivec cfg and target feature mismatch");
+#[cfg_attr(vsx, cfg(not(target_feature = "vsx")))]
+#[cfg_attr(not(vsx), cfg(target_feature = "vsx"))]
+compile_error!("vsx cfg and target feature mismatch");
+
+type ptr = *const i32;
+
+#[repr(simd)]
+pub struct i8x16([i8; 16]);
+#[repr(simd)]
+pub struct i16x8([i16; 8]);
+#[repr(simd)]
+pub struct i32x4([i32; 4]);
+#[repr(simd)]
+pub struct i64x2([i64; 2]);
+#[repr(simd)]
+pub struct f32x4([f32; 4]);
+#[repr(simd)]
+pub struct f64x2([f64; 2]);
+
+impl Copy for i8x16 {}
+impl Copy for i16x8 {}
+impl Copy for i32x4 {}
+impl Copy for i64x2 {}
+impl Copy for f32x4 {}
+impl Copy for f64x2 {}
+
+extern "C" {
+    fn extern_func();
+    static extern_static: u8;
+}
+
+macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => {
+    #[no_mangle]
+    pub unsafe fn $func(x: $ty) -> $ty {
+        let y;
+        asm!(concat!($mov," {}, {}"), out($class) y, in($class) x);
+        y
+    }
+};}
+
+macro_rules! check_reg { ($func:ident, $ty:ty, $rego:tt, $regc:tt, $mov:literal) => {
+    #[no_mangle]
+    pub unsafe fn $func(x: $ty) -> $ty {
+        let y;
+        asm!(concat!($mov, " ", $rego, ", ", $rego), lateout($regc) y, in($regc) x);
+        y
+    }
+};}
+
+// CHECK-LABEL: reg_i8:
+// CHECK: #APP
+// CHECK: mr {{[0-9]+}}, {{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i8, i8, reg, "mr");
+
+// CHECK-LABEL: reg_i16:
+// CHECK: #APP
+// CHECK: mr {{[0-9]+}}, {{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i16, i16, reg, "mr");
+
+// CHECK-LABEL: reg_i32:
+// CHECK: #APP
+// CHECK: mr {{[0-9]+}}, {{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i32, i32, reg, "mr");
+
+// powerpc64-LABEL: reg_i64:
+// powerpc64: #APP
+// powerpc64: mr {{[0-9]+}}, {{[0-9]+}}
+// powerpc64: #NO_APP
+#[cfg(powerpc64)]
+check!(reg_i64, i64, reg, "mr");
+
+// CHECK-LABEL: reg_i8_nz:
+// CHECK: #APP
+// CHECK: mr {{[0-9]+}}, {{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i8_nz, i8, reg_nonzero, "mr");
+
+// CHECK-LABEL: reg_i16_nz:
+// CHECK: #APP
+// CHECK: mr {{[0-9]+}}, {{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i16_nz, i16, reg_nonzero, "mr");
+
+// CHECK-LABEL: reg_i32_nz:
+// CHECK: #APP
+// CHECK: mr {{[0-9]+}}, {{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i32_nz, i32, reg_nonzero, "mr");
+
+// powerpc64-LABEL: reg_i64_nz:
+// powerpc64: #APP
+// powerpc64: mr {{[0-9]+}}, {{[0-9]+}}
+// powerpc64: #NO_APP
+#[cfg(powerpc64)]
+check!(reg_i64_nz, i64, reg_nonzero, "mr");
+
+// CHECK-LABEL: reg_f32:
+// CHECK: #APP
+// CHECK: fmr {{[0-9]+}}, {{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_f32, f32, freg, "fmr");
+
+// CHECK-LABEL: reg_f64:
+// CHECK: #APP
+// CHECK: fmr {{[0-9]+}}, {{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_f64, f64, freg, "fmr");
+
+// powerpc_altivec-LABEL: vreg_i8x16:
+// powerpc_altivec: #APP
+// powerpc_altivec: vmr {{[0-9]+}}, {{[0-9]+}}
+// powerpc_altivec: #NO_APP
+// powerpc64-LABEL: vreg_i8x16:
+// powerpc64: #APP
+// powerpc64: vmr {{[0-9]+}}, {{[0-9]+}}
+// powerpc64: #NO_APP
+#[cfg(altivec)]
+check!(vreg_i8x16, i8x16, vreg, "vmr");
+
+// powerpc_altivec-LABEL: vreg_i16x8:
+// powerpc_altivec: #APP
+// powerpc_altivec: vmr {{[0-9]+}}, {{[0-9]+}}
+// powerpc_altivec: #NO_APP
+// powerpc64-LABEL: vreg_i16x8:
+// powerpc64: #APP
+// powerpc64: vmr {{[0-9]+}}, {{[0-9]+}}
+// powerpc64: #NO_APP
+#[cfg(altivec)]
+check!(vreg_i16x8, i16x8, vreg, "vmr");
+
+// powerpc_altivec-LABEL: vreg_i32x4:
+// powerpc_altivec: #APP
+// powerpc_altivec: vmr {{[0-9]+}}, {{[0-9]+}}
+// powerpc_altivec: #NO_APP
+// powerpc64-LABEL: vreg_i32x4:
+// powerpc64: #APP
+// powerpc64: vmr {{[0-9]+}}, {{[0-9]+}}
+// powerpc64: #NO_APP
+#[cfg(altivec)]
+check!(vreg_i32x4, i32x4, vreg, "vmr");
+
+// powerpc_vsx-LABEL: vreg_i64x2:
+// powerpc_vsx: #APP
+// powerpc_vsx: vmr {{[0-9]+}}, {{[0-9]+}}
+// powerpc_vsx: #NO_APP
+// powerpc64_vsx-LABEL: vreg_i64x2:
+// powerpc64_vsx: #APP
+// powerpc64_vsx: vmr {{[0-9]+}}, {{[0-9]+}}
+// powerpc64_vsx: #NO_APP
+#[cfg(vsx)]
+check!(vreg_i64x2, i64x2, vreg, "vmr");
+
+// powerpc_altivec-LABEL: vreg_f32x4:
+// powerpc_altivec: #APP
+// powerpc_altivec: vmr {{[0-9]+}}, {{[0-9]+}}
+// powerpc_altivec: #NO_APP
+// powerpc64-LABEL: vreg_f32x4:
+// powerpc64: #APP
+// powerpc64: vmr {{[0-9]+}}, {{[0-9]+}}
+// powerpc64: #NO_APP
+#[cfg(altivec)]
+check!(vreg_f32x4, f32x4, vreg, "vmr");
+
+// powerpc_vsx-LABEL: vreg_f64x2:
+// powerpc_vsx: #APP
+// powerpc_vsx: vmr {{[0-9]+}}, {{[0-9]+}}
+// powerpc_vsx: #NO_APP
+// powerpc64_vsx-LABEL: vreg_f64x2:
+// powerpc64_vsx: #APP
+// powerpc64_vsx: vmr {{[0-9]+}}, {{[0-9]+}}
+// powerpc64_vsx: #NO_APP
+#[cfg(vsx)]
+check!(vreg_f64x2, f64x2, vreg, "vmr");
+
+// powerpc_vsx-LABEL: vreg_f32:
+// powerpc_vsx: #APP
+// powerpc_vsx: vmr {{[0-9]+}}, {{[0-9]+}}
+// powerpc_vsx: #NO_APP
+// powerpc64_vsx-LABEL: vreg_f32:
+// powerpc64_vsx: #APP
+// powerpc64_vsx: vmr {{[0-9]+}}, {{[0-9]+}}
+// powerpc64_vsx: #NO_APP
+#[cfg(vsx)]
+check!(vreg_f32, f32, vreg, "vmr");
+
+// powerpc_vsx-LABEL: vreg_f64:
+// powerpc_vsx: #APP
+// powerpc_vsx: vmr {{[0-9]+}}, {{[0-9]+}}
+// powerpc_vsx: #NO_APP
+// powerpc64_vsx-LABEL: vreg_f64:
+// powerpc64_vsx: #APP
+// powerpc64_vsx: vmr {{[0-9]+}}, {{[0-9]+}}
+// powerpc64_vsx: #NO_APP
+#[cfg(vsx)]
+check!(vreg_f64, f64, vreg, "vmr");
+
+// CHECK-LABEL: reg_i8_r0:
+// CHECK: #APP
+// CHECK: mr 0, 0
+// CHECK: #NO_APP
+check_reg!(reg_i8_r0, i8, "0", "0", "mr");
+
+// CHECK-LABEL: reg_i16_r0:
+// CHECK: #APP
+// CHECK: mr 0, 0
+// CHECK: #NO_APP
+check_reg!(reg_i16_r0, i16, "0", "0", "mr");
+
+// CHECK-LABEL: reg_i32_r0:
+// CHECK: #APP
+// CHECK: mr 0, 0
+// CHECK: #NO_APP
+check_reg!(reg_i32_r0, i32, "0", "0", "mr");
+
+// powerpc64-LABEL: reg_i64_r0:
+// powerpc64: #APP
+// powerpc64: mr 0, 0
+// powerpc64: #NO_APP
+#[cfg(powerpc64)]
+check_reg!(reg_i64_r0, i64, "0", "0", "mr");
+
+// CHECK-LABEL: reg_i8_r18:
+// CHECK: #APP
+// CHECK: mr 18, 18
+// CHECK: #NO_APP
+check_reg!(reg_i8_r18, i8, "18", "18", "mr");
+
+// CHECK-LABEL: reg_i16_r18:
+// CHECK: #APP
+// CHECK: mr 18, 18
+// CHECK: #NO_APP
+check_reg!(reg_i16_r18, i16, "18", "18", "mr");
+
+// CHECK-LABEL: reg_i32_r18:
+// CHECK: #APP
+// CHECK: mr 18, 18
+// CHECK: #NO_APP
+check_reg!(reg_i32_r18, i32, "18", "18", "mr");
+
+// powerpc64-LABEL: reg_i64_r18:
+// powerpc64: #APP
+// powerpc64: mr 18, 18
+// powerpc64: #NO_APP
+#[cfg(powerpc64)]
+check_reg!(reg_i64_r18, i64, "18", "18", "mr");
+
+// CHECK-LABEL: reg_f32_f0:
+// CHECK: #APP
+// CHECK: fmr 0, 0
+// CHECK: #NO_APP
+check_reg!(reg_f32_f0, f32, "0", "f0", "fmr");
+
+// CHECK-LABEL: reg_f64_f0:
+// CHECK: #APP
+// CHECK: fmr 0, 0
+// CHECK: #NO_APP
+check_reg!(reg_f64_f0, f64, "0", "f0", "fmr");
+
+// CHECK-LABEL: reg_f32_f18:
+// CHECK: #APP
+// CHECK: fmr 18, 18
+// CHECK: #NO_APP
+check_reg!(reg_f32_f18, f32, "18", "f18", "fmr");
+
+// CHECK-LABEL: reg_f64_f18:
+// CHECK: #APP
+// CHECK: fmr 18, 18
+// CHECK: #NO_APP
+check_reg!(reg_f64_f18, f64, "18", "f18", "fmr");
+
+// powerpc_altivec-LABEL: vreg_i8x16_v0:
+// powerpc_altivec: #APP
+// powerpc_altivec: vmr 0, 0
+// powerpc_altivec: #NO_APP
+// powerpc64-LABEL: vreg_i8x16_v0:
+// powerpc64: #APP
+// powerpc64: vmr 0, 0
+// powerpc64: #NO_APP
+#[cfg(altivec)]
+check_reg!(vreg_i8x16_v0, i8x16, "0", "v0", "vmr");
+
+// powerpc_altivec-LABEL: vreg_i16x8_v0:
+// powerpc_altivec: #APP
+// powerpc_altivec: vmr 0, 0
+// powerpc_altivec: #NO_APP
+// powerpc64-LABEL: vreg_i16x8_v0:
+// powerpc64: #APP
+// powerpc64: vmr 0, 0
+// powerpc64: #NO_APP
+#[cfg(altivec)]
+check_reg!(vreg_i16x8_v0, i16x8, "0", "v0", "vmr");
+
+// powerpc_altivec-LABEL: vreg_i32x4_v0:
+// powerpc_altivec: #APP
+// powerpc_altivec: vmr 0, 0
+// powerpc_altivec: #NO_APP
+// powerpc64-LABEL: vreg_i32x4_v0:
+// powerpc64: #APP
+// powerpc64: vmr 0, 0
+// powerpc64: #NO_APP
+#[cfg(altivec)]
+check_reg!(vreg_i32x4_v0, i32x4, "0", "v0", "vmr");
+
+// powerpc_vsx-LABEL: vreg_i64x2_v0:
+// powerpc_vsx: #APP
+// powerpc_vsx: vmr 0, 0
+// powerpc_vsx: #NO_APP
+// powerpc64_vsx-LABEL: vreg_i64x2_v0:
+// powerpc64_vsx: #APP
+// powerpc64_vsx: vmr 0, 0
+// powerpc64_vsx: #NO_APP
+#[cfg(vsx)]
+check_reg!(vreg_i64x2_v0, i64x2, "0", "v0", "vmr");
+
+// powerpc_altivec-LABEL: vreg_f32x4_v0:
+// powerpc_altivec: #APP
+// powerpc_altivec: vmr 0, 0
+// powerpc_altivec: #NO_APP
+// powerpc64-LABEL: vreg_f32x4_v0:
+// powerpc64: #APP
+// powerpc64: vmr 0, 0
+// powerpc64: #NO_APP
+#[cfg(altivec)]
+check_reg!(vreg_f32x4_v0, f32x4, "0", "v0", "vmr");
+
+// powerpc_vsx-LABEL: vreg_f64x2_v0:
+// powerpc_vsx: #APP
+// powerpc_vsx: vmr 0, 0
+// powerpc_vsx: #NO_APP
+// powerpc64_vsx-LABEL: vreg_f64x2_v0:
+// powerpc64_vsx: #APP
+// powerpc64_vsx: vmr 0, 0
+// powerpc64_vsx: #NO_APP
+#[cfg(vsx)]
+check_reg!(vreg_f64x2_v0, f64x2, "0", "v0", "vmr");
+
+// powerpc_vsx-LABEL: vreg_f32_v0:
+// powerpc_vsx: #APP
+// powerpc_vsx: vmr 0, 0
+// powerpc_vsx: #NO_APP
+// powerpc64_vsx-LABEL: vreg_f32_v0:
+// powerpc64_vsx: #APP
+// powerpc64_vsx: vmr 0, 0
+// powerpc64_vsx: #NO_APP
+#[cfg(vsx)]
+check_reg!(vreg_f32_v0, f32, "0", "v0", "vmr");
+
+// powerpc_vsx-LABEL: vreg_f64_v0:
+// powerpc_vsx: #APP
+// powerpc_vsx: vmr 0, 0
+// powerpc_vsx: #NO_APP
+// powerpc64_vsx-LABEL: vreg_f64_v0:
+// powerpc64_vsx: #APP
+// powerpc64_vsx: vmr 0, 0
+// powerpc64_vsx: #NO_APP
+#[cfg(vsx)]
+check_reg!(vreg_f64_v0, f64, "0", "v0", "vmr");
+
+// powerpc_altivec-LABEL: vreg_i8x16_v18:
+// powerpc_altivec: #APP
+// powerpc_altivec: vmr 18, 18
+// powerpc_altivec: #NO_APP
+// powerpc64-LABEL: vreg_i8x16_v18:
+// powerpc64: #APP
+// powerpc64: vmr 18, 18
+// powerpc64: #NO_APP
+#[cfg(altivec)]
+check_reg!(vreg_i8x16_v18, i8x16, "18", "v18", "vmr");
+
+// powerpc_altivec-LABEL: vreg_i16x8_v18:
+// powerpc_altivec: #APP
+// powerpc_altivec: vmr 18, 18
+// powerpc_altivec: #NO_APP
+// powerpc64-LABEL: vreg_i16x8_v18:
+// powerpc64: #APP
+// powerpc64: vmr 18, 18
+// powerpc64: #NO_APP
+#[cfg(altivec)]
+check_reg!(vreg_i16x8_v18, i16x8, "18", "v18", "vmr");
+
+// powerpc_altivec-LABEL: vreg_i32x4_v18:
+// powerpc_altivec: #APP
+// powerpc_altivec: vmr 18, 18
+// powerpc_altivec: #NO_APP
+// powerpc64-LABEL: vreg_i32x4_v18:
+// powerpc64: #APP
+// powerpc64: vmr 18, 18
+// powerpc64: #NO_APP
+#[cfg(altivec)]
+check_reg!(vreg_i32x4_v18, i32x4, "18", "v18", "vmr");
+
+// powerpc_vsx-LABEL: vreg_i64x2_v18:
+// powerpc_vsx: #APP
+// powerpc_vsx: vmr 18, 18
+// powerpc_vsx: #NO_APP
+// powerpc64_vsx-LABEL: vreg_i64x2_v18:
+// powerpc64_vsx: #APP
+// powerpc64_vsx: vmr 18, 18
+// powerpc64_vsx: #NO_APP
+#[cfg(vsx)]
+check_reg!(vreg_i64x2_v18, i64x2, "18", "v18", "vmr");
+
+// powerpc_altivec-LABEL: vreg_f32x4_v18:
+// powerpc_altivec: #APP
+// powerpc_altivec: vmr 18, 18
+// powerpc_altivec: #NO_APP
+// powerpc64-LABEL: vreg_f32x4_v18:
+// powerpc64: #APP
+// powerpc64: vmr 18, 18
+// powerpc64: #NO_APP
+#[cfg(altivec)]
+check_reg!(vreg_f32x4_v18, f32x4, "18", "v18", "vmr");
+
+// powerpc_vsx-LABEL: vreg_f64x2_v18:
+// powerpc_vsx: #APP
+// powerpc_vsx: vmr 18, 18
+// powerpc_vsx: #NO_APP
+// powerpc64_vsx-LABEL: vreg_f64x2_v18:
+// powerpc64_vsx: #APP
+// powerpc64_vsx: vmr 18, 18
+// powerpc64_vsx: #NO_APP
+#[cfg(vsx)]
+check_reg!(vreg_f64x2_v18, f64x2, "18", "v18", "vmr");
+
+// powerpc_vsx-LABEL: vreg_f32_v18:
+// powerpc_vsx: #APP
+// powerpc_vsx: vmr 18, 18
+// powerpc_vsx: #NO_APP
+// powerpc64_vsx-LABEL: vreg_f32_v18:
+// powerpc64_vsx: #APP
+// powerpc64_vsx: vmr 18, 18
+// powerpc64_vsx: #NO_APP
+#[cfg(vsx)]
+check_reg!(vreg_f32_v18, f32, "18", "v18", "vmr");
+
+// powerpc_vsx-LABEL: vreg_f64_v18:
+// powerpc_vsx: #APP
+// powerpc_vsx: vmr 18, 18
+// powerpc_vsx: #NO_APP
+// powerpc64_vsx-LABEL: vreg_f64_v18:
+// powerpc64_vsx: #APP
+// powerpc64_vsx: vmr 18, 18
+// powerpc64_vsx: #NO_APP
+#[cfg(vsx)]
+check_reg!(vreg_f64_v18, f64, "18", "v18", "vmr");
diff --git a/tests/assembly-llvm/asm/riscv-types.rs b/tests/assembly-llvm/asm/riscv-types.rs
new file mode 100644
index 00000000000..724aa154da8
--- /dev/null
+++ b/tests/assembly-llvm/asm/riscv-types.rs
@@ -0,0 +1,227 @@
+//@ add-core-stubs
+//@ revisions: riscv64 riscv32 riscv64-zfhmin riscv32-zfhmin riscv64-zfh riscv32-zfh
+//@ assembly-output: emit-asm
+
+//@[riscv64] compile-flags: --target riscv64imac-unknown-none-elf
+//@[riscv64] needs-llvm-components: riscv
+
+//@[riscv32] compile-flags: --target riscv32imac-unknown-none-elf
+//@[riscv32] needs-llvm-components: riscv
+
+//@[riscv64-zfhmin] compile-flags: --target riscv64imac-unknown-none-elf --cfg riscv64
+//@[riscv64-zfhmin] needs-llvm-components: riscv
+//@[riscv64-zfhmin] compile-flags: -C target-feature=+zfhmin
+//@[riscv64-zfhmin] filecheck-flags: --check-prefix riscv64
+
+//@[riscv32-zfhmin] compile-flags: --target riscv32imac-unknown-none-elf
+//@[riscv32-zfhmin] needs-llvm-components: riscv
+//@[riscv32-zfhmin] compile-flags: -C target-feature=+zfhmin
+
+//@[riscv64-zfh] compile-flags: --target riscv64imac-unknown-none-elf --cfg riscv64
+//@[riscv64-zfh] needs-llvm-components: riscv
+//@[riscv64-zfh] compile-flags: -C target-feature=+zfh
+//@[riscv64-zfh] filecheck-flags: --check-prefix riscv64 --check-prefix zfhmin
+
+//@[riscv32-zfh] compile-flags: --target riscv32imac-unknown-none-elf
+//@[riscv32-zfh] needs-llvm-components: riscv
+//@[riscv32-zfh] compile-flags: -C target-feature=+zfh
+//@[riscv32-zfh] filecheck-flags: --check-prefix zfhmin
+
+//@ compile-flags: -C target-feature=+d
+//@ compile-flags: -Zmerge-functions=disabled
+
+#![feature(no_core, f16)]
+#![crate_type = "rlib"]
+#![no_core]
+#![allow(asm_sub_register)]
+
+extern crate minicore;
+use minicore::*;
+
+type ptr = *mut u8;
+
+extern "C" {
+    fn extern_func();
+    static extern_static: u8;
+}
+
+// CHECK-LABEL: sym_fn:
+// CHECK: #APP
+// CHECK: call extern_func
+// CHECK: #NO_APP
+#[no_mangle]
+pub unsafe fn sym_fn() {
+    asm!("call {}", sym extern_func);
+}
+
+// CHECK-LABEL: sym_static:
+// CHECK: #APP
+// CHECK: auipc t0, %pcrel_hi(extern_static)
+// CHECK: lb t0, %pcrel_lo(.Lpcrel_hi{{[0-9]+}})(t0)
+// CHECK: #NO_APP
+#[no_mangle]
+pub unsafe fn sym_static() {
+    asm!("lb t0, {}", sym extern_static);
+}
+
+macro_rules! check {
+    ($func:ident $ty:ident $class:ident $mov:literal) => {
+        #[no_mangle]
+        pub unsafe fn $func(x: $ty) -> $ty {
+            let y;
+            asm!(concat!($mov, " {}, {}"), out($class) y, in($class) x);
+            y
+        }
+    };
+}
+
+macro_rules! check_reg {
+    ($func:ident $ty:ident $reg:tt $mov:literal) => {
+        #[no_mangle]
+        pub unsafe fn $func(x: $ty) -> $ty {
+            let y;
+            asm!(concat!($mov, " ", $reg, ", ", $reg), lateout($reg) y, in($reg) x);
+            y
+        }
+    };
+}
+
+// CHECK-LABEL: reg_i8:
+// CHECK: #APP
+// CHECK: mv {{[a-z0-9]+}}, {{[a-z0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i8 i8 reg "mv");
+
+// CHECK-LABEL: reg_f16:
+// CHECK: #APP
+// CHECK: mv {{[a-z0-9]+}}, {{[a-z0-9]+}}
+// CHECK: #NO_APP
+check!(reg_f16 f16 reg "mv");
+
+// CHECK-LABEL: reg_i16:
+// CHECK: #APP
+// CHECK: mv {{[a-z0-9]+}}, {{[a-z0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i16 i16 reg "mv");
+
+// CHECK-LABEL: reg_i32:
+// CHECK: #APP
+// CHECK: mv {{[a-z0-9]+}}, {{[a-z0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i32 i32 reg "mv");
+
+// CHECK-LABEL: reg_f32:
+// CHECK: #APP
+// CHECK: mv {{[a-z0-9]+}}, {{[a-z0-9]+}}
+// CHECK: #NO_APP
+check!(reg_f32 f32 reg "mv");
+
+// riscv64-LABEL: reg_i64:
+// riscv64: #APP
+// riscv64: mv {{[a-z0-9]+}}, {{[a-z0-9]+}}
+// riscv64: #NO_APP
+#[cfg(riscv64)]
+check!(reg_i64 i64 reg "mv");
+
+// riscv64-LABEL: reg_f64:
+// riscv64: #APP
+// riscv64: mv {{[a-z0-9]+}}, {{[a-z0-9]+}}
+// riscv64: #NO_APP
+#[cfg(riscv64)]
+check!(reg_f64 f64 reg "mv");
+
+// CHECK-LABEL: reg_ptr:
+// CHECK: #APP
+// CHECK: mv {{[a-z0-9]+}}, {{[a-z0-9]+}}
+// CHECK: #NO_APP
+check!(reg_ptr ptr reg "mv");
+
+// CHECK-LABEL: freg_f16:
+// zfhmin-NOT: or
+// CHECK: #APP
+// CHECK: fmv.s f{{[a-z0-9]+}}, f{{[a-z0-9]+}}
+// CHECK: #NO_APP
+// zfhmin-NOT: or
+check!(freg_f16 f16 freg "fmv.s");
+
+// CHECK-LABEL: freg_f32:
+// CHECK: #APP
+// CHECK: fmv.s f{{[a-z0-9]+}}, f{{[a-z0-9]+}}
+// CHECK: #NO_APP
+check!(freg_f32 f32 freg "fmv.s");
+
+// CHECK-LABEL: freg_f64:
+// CHECK: #APP
+// CHECK: fmv.d f{{[a-z0-9]+}}, f{{[a-z0-9]+}}
+// CHECK: #NO_APP
+check!(freg_f64 f64 freg "fmv.d");
+
+// CHECK-LABEL: a0_i8:
+// CHECK: #APP
+// CHECK: mv a0, a0
+// CHECK: #NO_APP
+check_reg!(a0_i8 i8 "a0" "mv");
+
+// CHECK-LABEL: a0_i16:
+// CHECK: #APP
+// CHECK: mv a0, a0
+// CHECK: #NO_APP
+check_reg!(a0_i16 i16 "a0" "mv");
+
+// CHECK-LABEL: a0_f16:
+// CHECK: #APP
+// CHECK: mv a0, a0
+// CHECK: #NO_APP
+check_reg!(a0_f16 f16 "a0" "mv");
+
+// CHECK-LABEL: a0_i32:
+// CHECK: #APP
+// CHECK: mv a0, a0
+// CHECK: #NO_APP
+check_reg!(a0_i32 i32 "a0" "mv");
+
+// CHECK-LABEL: a0_f32:
+// CHECK: #APP
+// CHECK: mv a0, a0
+// CHECK: #NO_APP
+check_reg!(a0_f32 f32 "a0" "mv");
+
+// riscv64-LABEL: a0_i64:
+// riscv64: #APP
+// riscv64: mv a0, a0
+// riscv64: #NO_APP
+#[cfg(riscv64)]
+check_reg!(a0_i64 i64 "a0" "mv");
+
+// riscv64-LABEL: a0_f64:
+// riscv64: #APP
+// riscv64: mv a0, a0
+// riscv64: #NO_APP
+#[cfg(riscv64)]
+check_reg!(a0_f64 f64 "a0" "mv");
+
+// CHECK-LABEL: a0_ptr:
+// CHECK: #APP
+// CHECK: mv a0, a0
+// CHECK: #NO_APP
+check_reg!(a0_ptr ptr "a0" "mv");
+
+// CHECK-LABEL: fa0_f16:
+// zfhmin-NOT: or
+// CHECK: #APP
+// CHECK: fmv.s fa0, fa0
+// CHECK: #NO_APP
+// zfhmin-NOT: or
+check_reg!(fa0_f16 f16 "fa0" "fmv.s");
+
+// CHECK-LABEL: fa0_f32:
+// CHECK: #APP
+// CHECK: fmv.s fa0, fa0
+// CHECK: #NO_APP
+check_reg!(fa0_f32 f32 "fa0" "fmv.s");
+
+// CHECK-LABEL: fa0_f64:
+// CHECK: #APP
+// CHECK: fmv.d fa0, fa0
+// CHECK: #NO_APP
+check_reg!(fa0_f64 f64 "fa0" "fmv.d");
diff --git a/tests/assembly-llvm/asm/s390x-types.rs b/tests/assembly-llvm/asm/s390x-types.rs
new file mode 100644
index 00000000000..e6fe38ecb0d
--- /dev/null
+++ b/tests/assembly-llvm/asm/s390x-types.rs
@@ -0,0 +1,350 @@
+//@ add-core-stubs
+//@ revisions: s390x s390x_vector
+//@ assembly-output: emit-asm
+//@[s390x] compile-flags: --target s390x-unknown-linux-gnu
+//@[s390x] needs-llvm-components: systemz
+//@[s390x_vector] compile-flags: --target s390x-unknown-linux-gnu -C target-feature=+vector
+//@[s390x_vector] needs-llvm-components: systemz
+//@ compile-flags: -Zmerge-functions=disabled
+
+#![feature(no_core, repr_simd, f128)]
+#![cfg_attr(s390x_vector, feature(asm_experimental_reg))]
+#![crate_type = "rlib"]
+#![no_core]
+#![allow(asm_sub_register, non_camel_case_types)]
+
+extern crate minicore;
+use minicore::*;
+
+type ptr = *const i32;
+
+#[repr(simd)]
+pub struct i8x16([i8; 16]);
+#[repr(simd)]
+pub struct i16x8([i16; 8]);
+#[repr(simd)]
+pub struct i32x4([i32; 4]);
+#[repr(simd)]
+pub struct i64x2([i64; 2]);
+#[repr(simd)]
+pub struct f32x4([f32; 4]);
+#[repr(simd)]
+pub struct f64x2([f64; 2]);
+
+impl Copy for i8x16 {}
+impl Copy for i16x8 {}
+impl Copy for i32x4 {}
+impl Copy for i64x2 {}
+impl Copy for f32x4 {}
+impl Copy for f64x2 {}
+
+extern "C" {
+    fn extern_func();
+    static extern_static: u8;
+}
+
+macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => {
+    #[no_mangle]
+    pub unsafe fn $func(x: $ty) -> $ty {
+        let y;
+        asm!(concat!($mov," {}, {}"), out($class) y, in($class) x);
+        y
+    }
+};}
+
+macro_rules! check_reg { ($func:ident, $ty:ty, $reg:tt, $mov:literal) => {
+    #[no_mangle]
+    pub unsafe fn $func(x: $ty) -> $ty {
+        let y;
+        asm!(concat!($mov, " %", $reg, ", %", $reg), lateout($reg) y, in($reg) x);
+        y
+    }
+};}
+
+// CHECK-LABEL: sym_fn_32:
+// CHECK: #APP
+// CHECK: brasl %r14, extern_func
+// CHECK: #NO_APP
+#[no_mangle]
+pub unsafe fn sym_fn_32() {
+    asm!("brasl %r14, {}", sym extern_func);
+}
+
+// CHECK-LABEL: sym_static:
+// CHECK: #APP
+// CHECK: brasl %r14, extern_static
+// CHECK: #NO_APP
+#[no_mangle]
+pub unsafe fn sym_static() {
+    asm!("brasl %r14, {}", sym extern_static);
+}
+
+// CHECK-LABEL: reg_i8:
+// CHECK: #APP
+// CHECK: lgr %r{{[0-9]+}}, %r{{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i8, i8, reg, "lgr");
+
+// CHECK-LABEL: reg_i16:
+// CHECK: #APP
+// CHECK: lgr %r{{[0-9]+}}, %r{{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i16, i16, reg, "lgr");
+
+// CHECK-LABEL: reg_i32:
+// CHECK: #APP
+// CHECK: lgr %r{{[0-9]+}}, %r{{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i32, i32, reg, "lgr");
+
+// CHECK-LABEL: reg_i64:
+// CHECK: #APP
+// CHECK: lgr %r{{[0-9]+}}, %r{{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i64, i64, reg, "lgr");
+
+// CHECK-LABEL: reg_i8_addr:
+// CHECK: #APP
+// CHECK: lgr %r{{[0-9]+}}, %r{{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i8_addr, i8, reg_addr, "lgr");
+
+// CHECK-LABEL: reg_i16_addr:
+// CHECK: #APP
+// CHECK: lgr %r{{[0-9]+}}, %r{{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i16_addr, i16, reg_addr, "lgr");
+
+// CHECK-LABEL: reg_i32_addr:
+// CHECK: #APP
+// CHECK: lgr %r{{[0-9]+}}, %r{{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i32_addr, i32, reg_addr, "lgr");
+
+// CHECK-LABEL: reg_i64_addr:
+// CHECK: #APP
+// CHECK: lgr %r{{[0-9]+}}, %r{{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i64_addr, i64, reg_addr, "lgr");
+
+// CHECK-LABEL: reg_f32:
+// CHECK: #APP
+// CHECK: ler %f{{[0-9]+}}, %f{{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_f32, f32, freg, "ler");
+
+// CHECK-LABEL: reg_f64:
+// CHECK: #APP
+// CHECK: ldr %f{{[0-9]+}}, %f{{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_f64, f64, freg, "ldr");
+
+// CHECK-LABEL: reg_ptr:
+// CHECK: #APP
+// CHECK: lgr %r{{[0-9]+}}, %r{{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_ptr, ptr, reg, "lgr");
+
+// s390x_vector-LABEL: vreg_i8x16:
+// s390x_vector: #APP
+// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}}
+// s390x_vector: #NO_APP
+#[cfg(s390x_vector)]
+check!(vreg_i8x16, i8x16, vreg, "vlr");
+
+// s390x_vector-LABEL: vreg_i16x8:
+// s390x_vector: #APP
+// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}}
+// s390x_vector: #NO_APP
+#[cfg(s390x_vector)]
+check!(vreg_i16x8, i16x8, vreg, "vlr");
+
+// s390x_vector-LABEL: vreg_i32x4:
+// s390x_vector: #APP
+// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}}
+// s390x_vector: #NO_APP
+#[cfg(s390x_vector)]
+check!(vreg_i32x4, i32x4, vreg, "vlr");
+
+// s390x_vector-LABEL: vreg_i64x2:
+// s390x_vector: #APP
+// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}}
+// s390x_vector: #NO_APP
+#[cfg(s390x_vector)]
+check!(vreg_i64x2, i64x2, vreg, "vlr");
+
+// s390x_vector-LABEL: vreg_f32x4:
+// s390x_vector: #APP
+// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}}
+// s390x_vector: #NO_APP
+#[cfg(s390x_vector)]
+check!(vreg_f32x4, f32x4, vreg, "vlr");
+
+// s390x_vector-LABEL: vreg_f64x2:
+// s390x_vector: #APP
+// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}}
+// s390x_vector: #NO_APP
+#[cfg(s390x_vector)]
+check!(vreg_f64x2, f64x2, vreg, "vlr");
+
+// s390x_vector-LABEL: vreg_i32:
+// s390x_vector: #APP
+// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}}
+// s390x_vector: #NO_APP
+#[cfg(s390x_vector)]
+check!(vreg_i32, i32, vreg, "vlr");
+
+// s390x_vector-LABEL: vreg_i64:
+// s390x_vector: #APP
+// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}}
+// s390x_vector: #NO_APP
+#[cfg(s390x_vector)]
+check!(vreg_i64, i64, vreg, "vlr");
+
+// s390x_vector-LABEL: vreg_i128:
+// s390x_vector: #APP
+// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}}
+// s390x_vector: #NO_APP
+#[cfg(s390x_vector)]
+check!(vreg_i128, i128, vreg, "vlr");
+
+// s390x_vector-LABEL: vreg_f32:
+// s390x_vector: #APP
+// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}}
+// s390x_vector: #NO_APP
+#[cfg(s390x_vector)]
+check!(vreg_f32, f32, vreg, "vlr");
+
+// s390x_vector-LABEL: vreg_f64:
+// s390x_vector: #APP
+// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}}
+// s390x_vector: #NO_APP
+#[cfg(s390x_vector)]
+check!(vreg_f64, f64, vreg, "vlr");
+
+// s390x_vector-LABEL: vreg_f128:
+// s390x_vector: #APP
+// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}}
+// s390x_vector: #NO_APP
+#[cfg(s390x_vector)]
+check!(vreg_f128, f128, vreg, "vlr");
+
+// CHECK-LABEL: r0_i8:
+// CHECK: #APP
+// CHECK: lr %r0, %r0
+// CHECK: #NO_APP
+check_reg!(r0_i8, i8, "r0", "lr");
+
+// CHECK-LABEL: r0_i16:
+// CHECK: #APP
+// CHECK: lr %r0, %r0
+// CHECK: #NO_APP
+check_reg!(r0_i16, i16, "r0", "lr");
+
+// CHECK-LABEL: r0_i32:
+// CHECK: #APP
+// CHECK: lr %r0, %r0
+// CHECK: #NO_APP
+check_reg!(r0_i32, i32, "r0", "lr");
+
+// CHECK-LABEL: r0_i64:
+// CHECK: #APP
+// CHECK: lr %r0, %r0
+// CHECK: #NO_APP
+check_reg!(r0_i64, i64, "r0", "lr");
+
+// CHECK-LABEL: f0_f32:
+// CHECK: #APP
+// CHECK: ler %f0, %f0
+// CHECK: #NO_APP
+check_reg!(f0_f32, f32, "f0", "ler");
+
+// CHECK-LABEL: f0_f64:
+// CHECK: #APP
+// CHECK: ldr %f0, %f0
+// CHECK: #NO_APP
+check_reg!(f0_f64, f64, "f0", "ldr");
+
+// s390x_vector-LABEL: v0_i8x16:
+// s390x_vector: #APP
+// s390x_vector: vlr %v0, %v0
+// s390x_vector: #NO_APP
+#[cfg(s390x_vector)]
+check_reg!(v0_i8x16, i8x16, "v0", "vlr");
+
+// s390x_vector-LABEL: v0_i16x8:
+// s390x_vector: #APP
+// s390x_vector: vlr %v0, %v0
+// s390x_vector: #NO_APP
+#[cfg(s390x_vector)]
+check_reg!(v0_i16x8, i16x8, "v0", "vlr");
+
+// s390x_vector-LABEL: v0_i32x4:
+// s390x_vector: #APP
+// s390x_vector: vlr %v0, %v0
+// s390x_vector: #NO_APP
+#[cfg(s390x_vector)]
+check_reg!(v0_i32x4, i32x4, "v0", "vlr");
+
+// s390x_vector-LABEL: v0_i64x2:
+// s390x_vector: #APP
+// s390x_vector: vlr %v0, %v0
+// s390x_vector: #NO_APP
+#[cfg(s390x_vector)]
+check_reg!(v0_i64x2, i64x2, "v0", "vlr");
+
+// s390x_vector-LABEL: v0_f32x4:
+// s390x_vector: #APP
+// s390x_vector: vlr %v0, %v0
+// s390x_vector: #NO_APP
+#[cfg(s390x_vector)]
+check_reg!(v0_f32x4, f32x4, "v0", "vlr");
+
+// s390x_vector-LABEL: v0_f64x2:
+// s390x_vector: #APP
+// s390x_vector: vlr %v0, %v0
+// s390x_vector: #NO_APP
+#[cfg(s390x_vector)]
+check_reg!(v0_f64x2, f64x2, "v0", "vlr");
+
+// s390x_vector-LABEL: v0_i32:
+// s390x_vector: #APP
+// s390x_vector: vlr %v0, %v0
+// s390x_vector: #NO_APP
+#[cfg(s390x_vector)]
+check_reg!(v0_i32, i32, "v0", "vlr");
+
+// s390x_vector-LABEL: v0_i64:
+// s390x_vector: #APP
+// s390x_vector: vlr %v0, %v0
+// s390x_vector: #NO_APP
+#[cfg(s390x_vector)]
+check_reg!(v0_i64, i64, "v0", "vlr");
+
+// s390x_vector-LABEL: v0_i128:
+// s390x_vector: #APP
+// s390x_vector: vlr %v0, %v0
+// s390x_vector: #NO_APP
+#[cfg(s390x_vector)]
+check_reg!(v0_i128, i128, "v0", "vlr");
+
+// s390x_vector-LABEL: v0_f32:
+// s390x_vector: #APP
+// s390x_vector: vlr %v0, %v0
+// s390x_vector: #NO_APP
+#[cfg(s390x_vector)]
+check_reg!(v0_f32, f32, "v0", "vlr");
+
+// s390x_vector-LABEL: v0_f64:
+// s390x_vector: #APP
+// s390x_vector: vlr %v0, %v0
+// s390x_vector: #NO_APP
+#[cfg(s390x_vector)]
+check_reg!(v0_f64, f64, "v0", "vlr");
+
+// s390x_vector-LABEL: v0_f128:
+// s390x_vector: #APP
+// s390x_vector: vlr %v0, %v0
+// s390x_vector: #NO_APP
+#[cfg(s390x_vector)]
+check_reg!(v0_f128, f128, "v0", "vlr");
diff --git a/tests/assembly-llvm/asm/sparc-types.rs b/tests/assembly-llvm/asm/sparc-types.rs
new file mode 100644
index 00000000000..49cc377cd95
--- /dev/null
+++ b/tests/assembly-llvm/asm/sparc-types.rs
@@ -0,0 +1,145 @@
+//@ add-core-stubs
+//@ revisions: sparc sparcv8plus sparc64
+//@ assembly-output: emit-asm
+//@[sparc] compile-flags: --target sparc-unknown-none-elf
+//@[sparc] needs-llvm-components: sparc
+//@[sparcv8plus] compile-flags: --target sparc-unknown-linux-gnu
+//@[sparcv8plus] needs-llvm-components: sparc
+//@[sparc64] compile-flags: --target sparc64-unknown-linux-gnu
+//@[sparc64] needs-llvm-components: sparc
+//@ compile-flags: -Zmerge-functions=disabled
+
+#![feature(no_core, asm_experimental_arch)]
+#![crate_type = "rlib"]
+#![no_core]
+#![allow(asm_sub_register, non_camel_case_types)]
+
+extern crate minicore;
+use minicore::*;
+
+type ptr = *const i32;
+
+extern "C" {
+    fn extern_func();
+    static extern_static: u8;
+}
+
+macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => {
+    #[no_mangle]
+    pub unsafe fn $func(x: $ty) -> $ty {
+        let y;
+        asm!(concat!($mov," {}, {}"), in($class) x, out($class) y);
+        y
+    }
+};}
+
+macro_rules! check_reg { ($func:ident, $ty:ty, $reg:tt, $mov:literal) => {
+    #[no_mangle]
+    pub unsafe fn $func(x: $ty) -> $ty {
+        let y;
+        asm!(concat!($mov, " %", $reg, ", %", $reg), in($reg) x, lateout($reg) y);
+        y
+    }
+};}
+
+// CHECK-LABEL: sym_fn_32:
+// CHECK: !APP
+// CHECK-NEXT: call extern_func
+// CHECK-NEXT: !NO_APP
+#[no_mangle]
+pub unsafe fn sym_fn_32() {
+    asm!("call {}", sym extern_func);
+}
+
+// CHECK-LABEL: sym_static:
+// CHECK: !APP
+// CHECK-NEXT: call extern_static
+// CHECK-NEXT: !NO_APP
+#[no_mangle]
+pub unsafe fn sym_static() {
+    asm!("call {}", sym extern_static);
+}
+
+// CHECK-LABEL: reg_i8:
+// CHECK: !APP
+// CHECK-NEXT: mov %{{[goli]}}{{[0-9]+}}, %{{[goli]}}{{[0-9]+}}
+// CHECK-NEXT: !NO_APP
+check!(reg_i8, i8, reg, "mov");
+
+// CHECK-LABEL: reg_i16:
+// CHECK: !APP
+// CHECK-NEXT: mov %{{[goli]}}{{[0-9]+}}, %{{[goli]}}{{[0-9]+}}
+// CHECK-NEXT: !NO_APP
+check!(reg_i16, i16, reg, "mov");
+
+// CHECK-LABEL: reg_i32:
+// CHECK: !APP
+// CHECK-NEXT: mov %{{[goli]}}{{[0-9]+}}, %{{[goli]}}{{[0-9]+}}
+// CHECK-NEXT: !NO_APP
+check!(reg_i32, i32, reg, "mov");
+
+// FIXME: should be allowed for sparcv8plus but not yet supported in LLVM
+// sparc64-LABEL: reg_i64:
+// sparc64: !APP
+// sparc64-NEXT: mov %{{[goli]}}{{[0-9]+}}, %{{[goli]}}{{[0-9]+}}
+// sparc64-NEXT: !NO_APP
+#[cfg(sparc64)]
+check!(reg_i64, i64, reg, "mov");
+
+// CHECK-LABEL: reg_ptr:
+// CHECK: !APP
+// CHECK-NEXT: mov %{{[goli]}}{{[0-9]+}}, %{{[goli]}}{{[0-9]+}}
+// CHECK-NEXT: !NO_APP
+check!(reg_ptr, ptr, reg, "mov");
+
+// CHECK-LABEL: o0_i8:
+// CHECK: !APP
+// CHECK-NEXT: mov %o0, %o0
+// CHECK-NEXT: !NO_APP
+check_reg!(o0_i8, i8, "o0", "mov");
+
+// CHECK-LABEL: o0_i16:
+// CHECK: !APP
+// CHECK-NEXT: mov %o0, %o0
+// CHECK-NEXT: !NO_APP
+check_reg!(o0_i16, i16, "o0", "mov");
+
+// CHECK-LABEL: o0_i32:
+// CHECK: !APP
+// CHECK-NEXT: mov %o0, %o0
+// CHECK-NEXT: !NO_APP
+check_reg!(o0_i32, i32, "o0", "mov");
+
+// FIXME: should be allowed for sparcv8plus but not yet supported in LLVM
+// sparc64-LABEL: o0_i64:
+// sparc64: !APP
+// sparc64-NEXT: mov %o0, %o0
+// sparc64-NEXT: !NO_APP
+#[cfg(sparc64)]
+check_reg!(o0_i64, i64, "o0", "mov");
+
+// CHECK-LABEL: r9_i8:
+// CHECK: !APP
+// CHECK-NEXT: mov %o1, %o1
+// CHECK-NEXT: !NO_APP
+check_reg!(r9_i8, i8, "r9", "mov");
+
+// CHECK-LABEL: r9_i16:
+// CHECK: !APP
+// CHECK-NEXT: mov %o1, %o1
+// CHECK-NEXT: !NO_APP
+check_reg!(r9_i16, i16, "r9", "mov");
+
+// CHECK-LABEL: r9_i32:
+// CHECK: !APP
+// CHECK-NEXT: mov %o1, %o1
+// CHECK-NEXT: !NO_APP
+check_reg!(r9_i32, i32, "r9", "mov");
+
+// FIXME: should be allowed for sparcv8plus but not yet supported in LLVM
+// sparc64-LABEL: r9_i64:
+// sparc64: !APP
+// sparc64-NEXT: mov %o1, %o1
+// sparc64-NEXT: !NO_APP
+#[cfg(sparc64)]
+check_reg!(r9_i64, i64, "r9", "mov");
diff --git a/tests/assembly-llvm/asm/wasm-types.rs b/tests/assembly-llvm/asm/wasm-types.rs
new file mode 100644
index 00000000000..78e555c5317
--- /dev/null
+++ b/tests/assembly-llvm/asm/wasm-types.rs
@@ -0,0 +1,131 @@
+//@ add-core-stubs
+//@ assembly-output: emit-asm
+//@ compile-flags: --target wasm32-unknown-unknown
+//@ needs-llvm-components: webassembly
+
+#![feature(no_core, asm_experimental_arch)]
+#![crate_type = "rlib"]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
+
+type ptr = *mut u8;
+
+extern "C" {
+    fn extern_func();
+    static extern_static: u8;
+}
+
+// CHECK-LABEL: sym_fn:
+// CHECK: #APP
+// CHECK: call extern_func
+// CHECK: #NO_APP
+#[no_mangle]
+pub unsafe fn sym_fn() {
+    asm!("call {}", sym extern_func);
+}
+
+// CHECK-LABEL: sym_static
+// CHECK: #APP
+// CHECK: i32.const 42
+// CHECK: i32.store extern_static
+// CHECK: #NO_APP
+#[no_mangle]
+pub unsafe fn sym_static() {
+    asm!("
+        i32.const 42
+        i32.store {}
+    ", sym extern_static);
+}
+
+macro_rules! check {
+    ($func:ident $ty:ident $instr:literal) => {
+        #[no_mangle]
+        pub unsafe fn $func(x: $ty) -> $ty {
+            let y;
+            asm!(concat!("local.get {}\n", $instr, "\nlocal.set {}"), in(local) x, out(local) y);
+            y
+        }
+    };
+}
+
+// CHECK-LABEL: i8_i32:
+// CHECK: #APP
+// CHECK: local.get {{[0-9]}}
+// CHECK: i32.clz
+// CHECK: local.set {{[0-9]}}
+// CHECK: #NO_APP
+check!(i8_i32 i8 "i32.clz");
+
+// CHECK-LABEL: i16_i32:
+// CHECK: #APP
+// CHECK: local.get {{[0-9]}}
+// CHECK: i32.clz
+// CHECK: local.set {{[0-9]}}
+// CHECK: #NO_APP
+check!(i16_i32 i16 "i32.clz");
+
+// CHECK-LABEL: i32_i32:
+// CHECK: #APP
+// CHECK: local.get {{[0-9]}}
+// CHECK: i32.clz
+// CHECK: local.set {{[0-9]}}
+// CHECK: #NO_APP
+check!(i32_i32 i32 "i32.clz");
+
+// CHECK-LABEL: i8_i64
+// CHECK: #APP
+// CHECK: local.get {{[0-9]}}
+// CHECK: i64.clz
+// CHECK: local.set {{[0-9]}}
+// CHECK: #NO_APP
+check!(i8_i64 i8 "i64.clz");
+
+// CHECK-LABEL: i16_i64
+// CHECK: #APP
+// CHECK: local.get {{[0-9]}}
+// CHECK: i64.clz
+// CHECK: local.set {{[0-9]}}
+// CHECK: #NO_APP
+check!(i16_i64 i16 "i64.clz");
+
+// CHECK-LABEL: i32_i64
+// CHECK: #APP
+// CHECK: local.get {{[0-9]}}
+// CHECK: i64.clz
+// CHECK: local.set {{[0-9]}}
+// CHECK: #NO_APP
+check!(i32_i64 i32 "i64.clz");
+
+// CHECK-LABEL: i64_i64
+// CHECK: #APP
+// CHECK: local.get {{[0-9]}}
+// CHECK: i64.clz
+// CHECK: local.set {{[0-9]}}
+// CHECK: #NO_APP
+check!(i64_i64 i64 "i64.clz");
+
+// CHECK-LABEL: f32_f32
+// CHECK: #APP
+// CHECK: local.get {{[0-9]}}
+// CHECK: f32.abs
+// CHECK: local.set {{[0-9]}}
+// CHECK: #NO_APP
+check!(f32_f32 f32 "f32.abs");
+
+// CHECK-LABEL: f64_f64
+// CHECK: #APP
+// CHECK: local.get {{[0-9]}}
+// CHECK: f64.abs
+// CHECK: local.set {{[0-9]}}
+// CHECK: #NO_APP
+check!(f64_f64 f64 "f64.abs");
+
+// CHECK-LABEL: i32_ptr
+// CHECK: #APP
+// CHECK: local.get {{[0-9]}}
+// CHECK: i32.eqz
+// CHECK: local.set {{[0-9]}}
+// CHECK: #NO_APP
+check!(i32_ptr ptr "i32.eqz");
diff --git a/tests/assembly-llvm/asm/x86-modifiers.rs b/tests/assembly-llvm/asm/x86-modifiers.rs
new file mode 100644
index 00000000000..5f68e5c7317
--- /dev/null
+++ b/tests/assembly-llvm/asm/x86-modifiers.rs
@@ -0,0 +1,184 @@
+//@ add-core-stubs
+//@ revisions: x86_64 i686
+//@ assembly-output: emit-asm
+//@ compile-flags: -Copt-level=3 -C panic=abort
+//@[x86_64] compile-flags: --target x86_64-unknown-linux-gnu
+//@[x86_64] needs-llvm-components: x86
+//@[i686] compile-flags: --target i686-unknown-linux-gnu
+//@[i686] needs-llvm-components: x86
+//@ compile-flags: -C llvm-args=--x86-asm-syntax=intel
+//@ compile-flags: -C target-feature=+avx512bw
+//@ compile-flags: -Zmerge-functions=disabled
+
+#![feature(no_core)]
+#![crate_type = "rlib"]
+#![no_core]
+#![allow(asm_sub_register)]
+
+extern crate minicore;
+use minicore::*;
+
+macro_rules! check {
+    ($func:ident $modifier:literal $reg:ident $mov:literal) => {
+        // -Copt-level=3 and extern "C" guarantee that the selected register is always ax/xmm0
+        #[no_mangle]
+        pub unsafe extern "C" fn $func() -> i32 {
+            let y;
+            asm!(concat!($mov, " {0:", $modifier, "}, {0:", $modifier, "}"), out($reg) y);
+            y
+        }
+    };
+}
+
+// CHECK-LABEL: reg:
+// CHECK: #APP
+// x86_64: mov rax, rax
+// i686: mov eax, eax
+// CHECK: #NO_APP
+check!(reg "" reg "mov");
+
+// x86_64-LABEL: reg_l:
+// x86_64: #APP
+// x86_64: mov al, al
+// x86_64: #NO_APP
+#[cfg(x86_64)]
+check!(reg_l "l" reg "mov");
+
+// CHECK-LABEL: reg_x:
+// CHECK: #APP
+// CHECK: mov ax, ax
+// CHECK: #NO_APP
+check!(reg_x "x" reg "mov");
+
+// CHECK-LABEL: reg_e:
+// CHECK: #APP
+// CHECK: mov eax, eax
+// CHECK: #NO_APP
+check!(reg_e "e" reg "mov");
+
+// x86_64-LABEL: reg_r:
+// x86_64: #APP
+// x86_64: mov rax, rax
+// x86_64: #NO_APP
+#[cfg(x86_64)]
+check!(reg_r "r" reg "mov");
+
+// CHECK-LABEL: reg_abcd:
+// CHECK: #APP
+// x86_64: mov rax, rax
+// i686: mov eax, eax
+// CHECK: #NO_APP
+check!(reg_abcd "" reg_abcd "mov");
+
+// CHECK-LABEL: reg_abcd_l:
+// CHECK: #APP
+// CHECK: mov al, al
+// CHECK: #NO_APP
+check!(reg_abcd_l "l" reg_abcd "mov");
+
+// CHECK-LABEL: reg_abcd_h:
+// CHECK: #APP
+// CHECK: mov ah, ah
+// CHECK: #NO_APP
+check!(reg_abcd_h "h" reg_abcd "mov");
+
+// CHECK-LABEL: reg_abcd_x:
+// CHECK: #APP
+// CHECK: mov ax, ax
+// CHECK: #NO_APP
+check!(reg_abcd_x "x" reg_abcd "mov");
+
+// CHECK-LABEL: reg_abcd_e:
+// CHECK: #APP
+// CHECK: mov eax, eax
+// CHECK: #NO_APP
+check!(reg_abcd_e "e" reg_abcd "mov");
+
+// x86_64-LABEL: reg_abcd_r:
+// x86_64: #APP
+// x86_64: mov rax, rax
+// x86_64: #NO_APP
+#[cfg(x86_64)]
+check!(reg_abcd_r "r" reg_abcd "mov");
+
+// CHECK-LABEL: xmm_reg
+// CHECK: #APP
+// CHECK: movaps xmm0, xmm0
+// CHECK: #NO_APP
+check!(xmm_reg "" xmm_reg "movaps");
+
+// CHECK-LABEL: xmm_reg_x
+// CHECK: #APP
+// CHECK: movaps xmm0, xmm0
+// CHECK: #NO_APP
+check!(xmm_reg_x "x" xmm_reg "movaps");
+
+// CHECK-LABEL: xmm_reg_y
+// CHECK: #APP
+// CHECK: vmovaps ymm0, ymm0
+// CHECK: #NO_APP
+check!(xmm_reg_y "y" xmm_reg "vmovaps");
+
+// CHECK-LABEL: xmm_reg_z
+// CHECK: #APP
+// CHECK: vmovaps zmm0, zmm0
+// CHECK: #NO_APP
+check!(xmm_reg_z "z" xmm_reg "vmovaps");
+
+// CHECK-LABEL: ymm_reg
+// CHECK: #APP
+// CHECK: movaps ymm0, ymm0
+// CHECK: #NO_APP
+check!(ymm_reg "" ymm_reg "vmovaps");
+
+// CHECK-LABEL: ymm_reg_x
+// CHECK: #APP
+// CHECK: movaps xmm0, xmm0
+// CHECK: #NO_APP
+check!(ymm_reg_x "x" ymm_reg "movaps");
+
+// CHECK-LABEL: ymm_reg_y
+// CHECK: #APP
+// CHECK: vmovaps ymm0, ymm0
+// CHECK: #NO_APP
+check!(ymm_reg_y "y" ymm_reg "vmovaps");
+
+// CHECK-LABEL: ymm_reg_z
+// CHECK: #APP
+// CHECK: vmovaps zmm0, zmm0
+// CHECK: #NO_APP
+check!(ymm_reg_z "z" ymm_reg "vmovaps");
+
+// CHECK-LABEL: zmm_reg
+// CHECK: #APP
+// CHECK: movaps zmm0, zmm0
+// CHECK: #NO_APP
+check!(zmm_reg "" zmm_reg "vmovaps");
+
+// CHECK-LABEL: zmm_reg_x
+// CHECK: #APP
+// CHECK: movaps xmm0, xmm0
+// CHECK: #NO_APP
+check!(zmm_reg_x "x" zmm_reg "movaps");
+
+// CHECK-LABEL: zmm_reg_y
+// CHECK: #APP
+// CHECK: vmovaps ymm0, ymm0
+// CHECK: #NO_APP
+check!(zmm_reg_y "y" zmm_reg "vmovaps");
+
+// CHECK-LABEL: zmm_reg_z
+// CHECK: #APP
+// CHECK: vmovaps zmm0, zmm0
+// CHECK: #NO_APP
+check!(zmm_reg_z "z" zmm_reg "vmovaps");
+
+// Note: we don't have any way of ensuring that k1 is actually the register
+// chosen by the register allocator, so this check may fail if a different
+// register is chosen.
+
+// CHECK-LABEL: kreg:
+// CHECK: #APP
+// CHECK: kmovb k1, k1
+// CHECK: #NO_APP
+check!(kreg "" kreg "kmovb");
diff --git a/tests/assembly-llvm/asm/x86-types.rs b/tests/assembly-llvm/asm/x86-types.rs
new file mode 100644
index 00000000000..6120ed0d532
--- /dev/null
+++ b/tests/assembly-llvm/asm/x86-types.rs
@@ -0,0 +1,1095 @@
+//@ add-core-stubs
+//@ revisions: x86_64 i686
+//@ assembly-output: emit-asm
+//@[x86_64] compile-flags: --target x86_64-unknown-linux-gnu
+//@[x86_64] needs-llvm-components: x86
+//@[i686] compile-flags: --target i686-unknown-linux-gnu
+//@[i686] needs-llvm-components: x86
+//@ compile-flags: -C llvm-args=--x86-asm-syntax=intel
+//@ compile-flags: -C target-feature=+avx512bw
+//@ compile-flags: -Zmerge-functions=disabled
+
+#![feature(no_core, repr_simd, f16, f128)]
+#![crate_type = "rlib"]
+#![no_core]
+#![allow(asm_sub_register, non_camel_case_types)]
+
+extern crate minicore;
+use minicore::*;
+
+type ptr = *mut u8;
+
+#[repr(simd)]
+pub struct i8x16([i8; 16]);
+#[repr(simd)]
+pub struct i16x8([i16; 8]);
+#[repr(simd)]
+pub struct i32x4([i32; 4]);
+#[repr(simd)]
+pub struct i64x2([i64; 2]);
+#[repr(simd)]
+pub struct f16x8([f16; 8]);
+#[repr(simd)]
+pub struct f32x4([f32; 4]);
+#[repr(simd)]
+pub struct f64x2([f64; 2]);
+
+#[repr(simd)]
+pub struct i8x32([i8; 32]);
+#[repr(simd)]
+pub struct i16x16([i16; 16]);
+#[repr(simd)]
+pub struct i32x8([i32; 8]);
+#[repr(simd)]
+pub struct i64x4([i64; 4]);
+#[repr(simd)]
+pub struct f16x16([f16; 16]);
+#[repr(simd)]
+pub struct f32x8([f32; 8]);
+#[repr(simd)]
+pub struct f64x4([f64; 4]);
+
+#[repr(simd)]
+pub struct i8x64([i8; 64]);
+#[repr(simd)]
+pub struct i16x32([i16; 32]);
+#[repr(simd)]
+pub struct i32x16([i32; 16]);
+#[repr(simd)]
+pub struct i64x8([i64; 8]);
+#[repr(simd)]
+pub struct f16x32([f16; 32]);
+#[repr(simd)]
+pub struct f32x16([f32; 16]);
+#[repr(simd)]
+pub struct f64x8([f64; 8]);
+
+macro_rules! impl_copy {
+    ($($ty:ident)*) => {
+        $(
+            impl Copy for $ty {}
+        )*
+    };
+}
+
+impl_copy!(
+    i8x16 i16x8 i32x4 i64x2 f16x8 f32x4 f64x2
+    i8x32 i16x16 i32x8 i64x4 f16x16 f32x8 f64x4
+    i8x64 i16x32 i32x16 i64x8 f16x32 f32x16 f64x8
+);
+
+extern "C" {
+    fn extern_func();
+    static extern_static: u8;
+}
+
+// CHECK-LABEL: sym_fn:
+// CHECK: #APP
+// CHECK: call extern_func
+// CHECK: #NO_APP
+#[no_mangle]
+pub unsafe fn sym_fn() {
+    asm!("call {}", sym extern_func);
+}
+
+// CHECK-LABEL: sym_static:
+// CHECK: #APP
+// CHECK: mov al, byte ptr [extern_static]
+// CHECK: #NO_APP
+#[no_mangle]
+pub unsafe fn sym_static() {
+    asm!("mov al, byte ptr [{}]", sym extern_static);
+}
+
+macro_rules! check {
+    ($func:ident $ty:ident $class:ident $mov:literal) => {
+        #[no_mangle]
+        pub unsafe fn $func(x: $ty) -> $ty {
+            let y;
+            asm!(concat!($mov, " {}, {}"), lateout($class) y, in($class) x);
+            y
+        }
+    };
+}
+
+macro_rules! check_reg {
+    ($func:ident $ty:ident $reg:tt $mov:literal) => {
+        #[no_mangle]
+        pub unsafe fn $func(x: $ty) -> $ty {
+            let y;
+            asm!(concat!($mov, " ", $reg, ", ", $reg), lateout($reg) y, in($reg) x);
+            y
+        }
+    };
+}
+
+// CHECK-LABEL: reg_i16:
+// CHECK: #APP
+// x86_64: mov r{{[a-z0-9]+}}, r{{[a-z0-9]+}}
+// i686: mov e{{[a-z0-9]+}}, e{{[a-z0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i16 i16 reg "mov");
+
+// CHECK-LABEL: reg_f16:
+// CHECK: #APP
+// x86_64: mov r{{[a-z0-9]+}}, r{{[a-z0-9]+}}
+// i686: mov e{{[a-z0-9]+}}, e{{[a-z0-9]+}}
+// CHECK: #NO_APP
+check!(reg_f16 f16 reg "mov");
+
+// CHECK-LABEL: reg_i32:
+// CHECK: #APP
+// x86_64: mov r{{[a-z0-9]+}}, r{{[a-z0-9]+}}
+// i686: mov e{{[a-z0-9]+}}, e{{[a-z0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i32 i32 reg "mov");
+
+// CHECK-LABEL: reg_f32:
+// CHECK: #APP
+// x86_64: mov r{{[a-z0-9]+}}, r{{[a-z0-9]+}}
+// i686: mov e{{[a-z0-9]+}}, e{{[a-z0-9]+}}
+// CHECK: #NO_APP
+check!(reg_f32 f32 reg "mov");
+
+// x86_64-LABEL: reg_i64:
+// x86_64: #APP
+// x86_64: mov r{{[a-z0-9]+}}, r{{[a-z0-9]+}}
+// x86_64: #NO_APP
+#[cfg(x86_64)]
+check!(reg_i64 i64 reg "mov");
+
+// x86_64-LABEL: reg_f64:
+// x86_64: #APP
+// x86_64: mov r{{[a-z0-9]+}}, r{{[a-z0-9]+}}
+// x86_64: #NO_APP
+#[cfg(x86_64)]
+check!(reg_f64 f64 reg "mov");
+
+// CHECK-LABEL: reg_ptr:
+// CHECK: #APP
+// x86_64: mov r{{[a-z0-9]+}}, r{{[a-z0-9]+}}
+// i686: mov e{{[a-z0-9]+}}, e{{[a-z0-9]+}}
+// CHECK: #NO_APP
+check!(reg_ptr ptr reg "mov");
+
+// CHECK-LABEL: reg_abcd_i16:
+// CHECK: #APP
+// x86_64: mov r{{[a-z0-9]+}}, r{{[a-z0-9]+}}
+// i686: mov e{{[a-z0-9]+}}, e{{[a-z0-9]+}}
+// CHECK: #NO_APP
+check!(reg_abcd_i16 i16 reg_abcd "mov");
+
+// CHECK-LABEL: reg_abcd_f16:
+// CHECK: #APP
+// x86_64: mov r{{[a-z0-9]+}}, r{{[a-z0-9]+}}
+// i686: mov e{{[a-z0-9]+}}, e{{[a-z0-9]+}}
+// CHECK: #NO_APP
+check!(reg_abcd_f16 f16 reg_abcd "mov");
+
+// CHECK-LABEL: reg_abcd_i32:
+// CHECK: #APP
+// x86_64: mov r{{[a-z0-9]+}}, r{{[a-z0-9]+}}
+// i686: mov e{{[a-z0-9]+}}, e{{[a-z0-9]+}}
+// CHECK: #NO_APP
+check!(reg_abcd_i32 i32 reg_abcd "mov");
+
+// CHECK-LABEL: reg_abcd_f32:
+// CHECK: #APP
+// x86_64: mov r{{[a-z0-9]+}}, r{{[a-z0-9]+}}
+// i686: mov e{{[a-z0-9]+}}, e{{[a-z0-9]+}}
+// CHECK: #NO_APP
+check!(reg_abcd_f32 f32 reg_abcd "mov");
+
+// x86_64-LABEL: reg_abcd_i64:
+// x86_64: #APP
+// x86_64: mov r{{[a-z0-9]+}}, r{{[a-z0-9]+}}
+// x86_64: #NO_APP
+#[cfg(x86_64)]
+check!(reg_abcd_i64 i64 reg_abcd "mov");
+
+// x86_64-LABEL: reg_abcd_f64:
+// x86_64: #APP
+// x86_64: mov r{{[a-z0-9]+}}, r{{[a-z0-9]+}}
+// x86_64: #NO_APP
+#[cfg(x86_64)]
+check!(reg_abcd_f64 f64 reg_abcd "mov");
+
+// CHECK-LABEL: reg_abcd_ptr:
+// CHECK: #APP
+// x86_64: mov r{{[a-z0-9]+}}, r{{[a-z0-9]+}}
+// i686: mov e{{[a-z0-9]+}}, e{{[a-z0-9]+}}
+// CHECK: #NO_APP
+check!(reg_abcd_ptr ptr reg_abcd "mov");
+
+// CHECK-LABEL: reg_byte:
+// CHECK: #APP
+// CHECK: mov {{[a-z0-9]+}}, {{[a-z0-9]+}}
+// CHECK: #NO_APP
+check!(reg_byte i8 reg_byte "mov");
+
+// CHECK-LABEL: xmm_reg_f16:
+// CHECK: #APP
+// CHECK: movaps xmm{{[0-9]+}}, xmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(xmm_reg_f16 f16 xmm_reg "movaps");
+
+// CHECK-LABEL: xmm_reg_i32:
+// CHECK: #APP
+// CHECK: movaps xmm{{[0-9]+}}, xmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(xmm_reg_i32 i32 xmm_reg "movaps");
+
+// CHECK-LABEL: xmm_reg_f32:
+// CHECK: #APP
+// CHECK: movaps xmm{{[0-9]+}}, xmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(xmm_reg_f32 f32 xmm_reg "movaps");
+
+// CHECK-LABEL: xmm_reg_i64:
+// CHECK: #APP
+// CHECK: movaps xmm{{[0-9]+}}, xmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(xmm_reg_i64 i64 xmm_reg "movaps");
+
+// CHECK-LABEL: xmm_reg_f64:
+// CHECK: #APP
+// CHECK: movaps xmm{{[0-9]+}}, xmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(xmm_reg_f64 f64 xmm_reg "movaps");
+
+// CHECK-LABEL: xmm_reg_f128:
+// CHECK: #APP
+// CHECK: movaps xmm{{[0-9]+}}, xmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(xmm_reg_f128 f128 xmm_reg "movaps");
+
+// CHECK-LABEL: xmm_reg_ptr:
+// CHECK: #APP
+// CHECK: movaps xmm{{[0-9]+}}, xmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(xmm_reg_ptr ptr xmm_reg "movaps");
+
+// CHECK-LABEL: xmm_reg_i8x16:
+// CHECK: #APP
+// CHECK: movaps xmm{{[0-9]+}}, xmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(xmm_reg_i8x16 i8x16 xmm_reg "movaps");
+
+// CHECK-LABEL: xmm_reg_i16x8:
+// CHECK: #APP
+// CHECK: movaps xmm{{[0-9]+}}, xmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(xmm_reg_i16x8 i16x8 xmm_reg "movaps");
+
+// CHECK-LABEL: xmm_reg_i32x4:
+// CHECK: #APP
+// CHECK: movaps xmm{{[0-9]+}}, xmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(xmm_reg_i32x4 i32x4 xmm_reg "movaps");
+
+// CHECK-LABEL: xmm_reg_i64x2:
+// CHECK: #APP
+// CHECK: movaps xmm{{[0-9]+}}, xmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(xmm_reg_i64x2 i64x2 xmm_reg "movaps");
+
+// CHECK-LABEL: xmm_reg_f16x8:
+// CHECK: #APP
+// CHECK: movaps xmm{{[0-9]+}}, xmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(xmm_reg_f16x8 f16x8 xmm_reg "movaps");
+
+// CHECK-LABEL: xmm_reg_f32x4:
+// CHECK: #APP
+// CHECK: movaps xmm{{[0-9]+}}, xmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(xmm_reg_f32x4 f32x4 xmm_reg "movaps");
+
+// CHECK-LABEL: xmm_reg_f64x2:
+// CHECK: #APP
+// CHECK: movaps xmm{{[0-9]+}}, xmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(xmm_reg_f64x2 f64x2 xmm_reg "movaps");
+
+// CHECK-LABEL: ymm_reg_f16:
+// CHECK: #APP
+// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(ymm_reg_f16 f16 ymm_reg "vmovaps");
+
+// CHECK-LABEL: ymm_reg_i32:
+// CHECK: #APP
+// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(ymm_reg_i32 i32 ymm_reg "vmovaps");
+
+// CHECK-LABEL: ymm_reg_f32:
+// CHECK: #APP
+// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(ymm_reg_f32 f32 ymm_reg "vmovaps");
+
+// CHECK-LABEL: ymm_reg_i64:
+// CHECK: #APP
+// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(ymm_reg_i64 i64 ymm_reg "vmovaps");
+
+// CHECK-LABEL: ymm_reg_f64:
+// CHECK: #APP
+// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(ymm_reg_f64 f64 ymm_reg "vmovaps");
+
+// CHECK-LABEL: ymm_reg_f128:
+// CHECK: #APP
+// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(ymm_reg_f128 f128 ymm_reg "vmovaps");
+
+// CHECK-LABEL: ymm_reg_ptr:
+// CHECK: #APP
+// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(ymm_reg_ptr ptr ymm_reg "vmovaps");
+
+// CHECK-LABEL: ymm_reg_i8x16:
+// CHECK: #APP
+// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(ymm_reg_i8x16 i8x16 ymm_reg "vmovaps");
+
+// CHECK-LABEL: ymm_reg_i16x8:
+// CHECK: #APP
+// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(ymm_reg_i16x8 i16x8 ymm_reg "vmovaps");
+
+// CHECK-LABEL: ymm_reg_i32x4:
+// CHECK: #APP
+// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(ymm_reg_i32x4 i32x4 ymm_reg "vmovaps");
+
+// CHECK-LABEL: ymm_reg_i64x2:
+// CHECK: #APP
+// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(ymm_reg_i64x2 i64x2 ymm_reg "vmovaps");
+
+// CHECK-LABEL: ymm_reg_f16x8:
+// CHECK: #APP
+// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(ymm_reg_f16x8 f16x8 ymm_reg "vmovaps");
+
+// CHECK-LABEL: ymm_reg_f32x4:
+// CHECK: #APP
+// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(ymm_reg_f32x4 f32x4 ymm_reg "vmovaps");
+
+// CHECK-LABEL: ymm_reg_f64x2:
+// CHECK: #APP
+// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(ymm_reg_f64x2 f64x2 ymm_reg "vmovaps");
+
+// CHECK-LABEL: ymm_reg_i8x32:
+// CHECK: #APP
+// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(ymm_reg_i8x32 i8x32 ymm_reg "vmovaps");
+
+// CHECK-LABEL: ymm_reg_i16x16:
+// CHECK: #APP
+// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(ymm_reg_i16x16 i16x16 ymm_reg "vmovaps");
+
+// CHECK-LABEL: ymm_reg_i32x8:
+// CHECK: #APP
+// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(ymm_reg_i32x8 i32x8 ymm_reg "vmovaps");
+
+// CHECK-LABEL: ymm_reg_i64x4:
+// CHECK: #APP
+// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(ymm_reg_i64x4 i64x4 ymm_reg "vmovaps");
+
+// CHECK-LABEL: ymm_reg_f16x16:
+// CHECK: #APP
+// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(ymm_reg_f16x16 f16x16 ymm_reg "vmovaps");
+
+// CHECK-LABEL: ymm_reg_f32x8:
+// CHECK: #APP
+// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(ymm_reg_f32x8 f32x8 ymm_reg "vmovaps");
+
+// CHECK-LABEL: ymm_reg_f64x4:
+// CHECK: #APP
+// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(ymm_reg_f64x4 f64x4 ymm_reg "vmovaps");
+
+// CHECK-LABEL: zmm_reg_f16:
+// CHECK: #APP
+// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(zmm_reg_f16 f16 zmm_reg "vmovaps");
+
+// CHECK-LABEL: zmm_reg_i32:
+// CHECK: #APP
+// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(zmm_reg_i32 i32 zmm_reg "vmovaps");
+
+// CHECK-LABEL: zmm_reg_f32:
+// CHECK: #APP
+// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(zmm_reg_f32 f32 zmm_reg "vmovaps");
+
+// CHECK-LABEL: zmm_reg_i64:
+// CHECK: #APP
+// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(zmm_reg_i64 i64 zmm_reg "vmovaps");
+
+// CHECK-LABEL: zmm_reg_f64:
+// CHECK: #APP
+// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(zmm_reg_f64 f64 zmm_reg "vmovaps");
+
+// CHECK-LABEL: zmm_reg_f128:
+// CHECK: #APP
+// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(zmm_reg_f128 f128 zmm_reg "vmovaps");
+
+// CHECK-LABEL: zmm_reg_ptr:
+// CHECK: #APP
+// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(zmm_reg_ptr ptr zmm_reg "vmovaps");
+
+// CHECK-LABEL: zmm_reg_i8x16:
+// CHECK: #APP
+// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(zmm_reg_i8x16 i8x16 zmm_reg "vmovaps");
+
+// CHECK-LABEL: zmm_reg_i16x8:
+// CHECK: #APP
+// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(zmm_reg_i16x8 i16x8 zmm_reg "vmovaps");
+
+// CHECK-LABEL: zmm_reg_i32x4:
+// CHECK: #APP
+// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(zmm_reg_i32x4 i32x4 zmm_reg "vmovaps");
+
+// CHECK-LABEL: zmm_reg_i64x2:
+// CHECK: #APP
+// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(zmm_reg_i64x2 i64x2 zmm_reg "vmovaps");
+
+// CHECK-LABEL: zmm_reg_f16x8:
+// CHECK: #APP
+// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(zmm_reg_f16x8 f16x8 zmm_reg "vmovaps");
+
+// CHECK-LABEL: zmm_reg_f32x4:
+// CHECK: #APP
+// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(zmm_reg_f32x4 f32x4 zmm_reg "vmovaps");
+
+// CHECK-LABEL: zmm_reg_f64x2:
+// CHECK: #APP
+// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(zmm_reg_f64x2 f64x2 zmm_reg "vmovaps");
+
+// CHECK-LABEL: zmm_reg_i8x32:
+// CHECK: #APP
+// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(zmm_reg_i8x32 i8x32 zmm_reg "vmovaps");
+
+// CHECK-LABEL: zmm_reg_i16x16:
+// CHECK: #APP
+// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(zmm_reg_i16x16 i16x16 zmm_reg "vmovaps");
+
+// CHECK-LABEL: zmm_reg_i32x8:
+// CHECK: #APP
+// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(zmm_reg_i32x8 i32x8 zmm_reg "vmovaps");
+
+// CHECK-LABEL: zmm_reg_i64x4:
+// CHECK: #APP
+// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(zmm_reg_i64x4 i64x4 zmm_reg "vmovaps");
+
+// CHECK-LABEL: zmm_reg_f16x16:
+// CHECK: #APP
+// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(zmm_reg_f16x16 f16x16 zmm_reg "vmovaps");
+
+// CHECK-LABEL: zmm_reg_f32x8:
+// CHECK: #APP
+// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(zmm_reg_f32x8 f32x8 zmm_reg "vmovaps");
+
+// CHECK-LABEL: zmm_reg_f64x4:
+// CHECK: #APP
+// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(zmm_reg_f64x4 f64x4 zmm_reg "vmovaps");
+
+// CHECK-LABEL: zmm_reg_i8x64:
+// CHECK: #APP
+// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(zmm_reg_i8x64 i8x64 zmm_reg "vmovaps");
+
+// CHECK-LABEL: zmm_reg_i16x32:
+// CHECK: #APP
+// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(zmm_reg_i16x32 i16x32 zmm_reg "vmovaps");
+
+// CHECK-LABEL: zmm_reg_i32x16:
+// CHECK: #APP
+// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(zmm_reg_i32x16 i32x16 zmm_reg "vmovaps");
+
+// CHECK-LABEL: zmm_reg_i64x8:
+// CHECK: #APP
+// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(zmm_reg_i64x8 i64x8 zmm_reg "vmovaps");
+
+// CHECK-LABEL: zmm_reg_f16x32:
+// CHECK: #APP
+// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(zmm_reg_f16x32 f16x32 zmm_reg "vmovaps");
+
+// CHECK-LABEL: zmm_reg_f32x16:
+// CHECK: #APP
+// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(zmm_reg_f32x16 f32x16 zmm_reg "vmovaps");
+
+// CHECK-LABEL: zmm_reg_f64x8:
+// CHECK: #APP
+// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(zmm_reg_f64x8 f64x8 zmm_reg "vmovaps");
+
+// CHECK-LABEL: kreg_i8:
+// CHECK: #APP
+// CHECK: kmovb k{{[0-9]+}}, k{{[0-9]+}}
+// CHECK: #NO_APP
+check!(kreg_i8 i8 kreg "kmovb");
+
+// CHECK-LABEL: kreg_i16:
+// CHECK: #APP
+// CHECK: kmovw k{{[0-9]+}}, k{{[0-9]+}}
+// CHECK: #NO_APP
+check!(kreg_i16 i16 kreg "kmovw");
+
+// CHECK-LABEL: kreg_i32:
+// CHECK: #APP
+// CHECK: kmovd k{{[0-9]+}}, k{{[0-9]+}}
+// CHECK: #NO_APP
+check!(kreg_i32 i32 kreg "kmovd");
+
+// CHECK-LABEL: kreg_i64:
+// CHECK: #APP
+// CHECK: kmovq k{{[0-9]+}}, k{{[0-9]+}}
+// CHECK: #NO_APP
+check!(kreg_i64 i64 kreg "kmovq");
+
+// CHECK-LABEL: kreg_ptr:
+// CHECK: #APP
+// CHECK: kmovq k{{[0-9]+}}, k{{[0-9]+}}
+// CHECK: #NO_APP
+check!(kreg_ptr ptr kreg "kmovq");
+
+// CHECK-LABEL: eax_i16:
+// CHECK: #APP
+// CHECK: mov eax, eax
+// CHECK: #NO_APP
+check_reg!(eax_i16 i16 "eax" "mov");
+
+// CHECK-LABEL: eax_f16:
+// CHECK: #APP
+// CHECK: mov eax, eax
+// CHECK: #NO_APP
+check_reg!(eax_f16 f16 "eax" "mov");
+
+// CHECK-LABEL: eax_i32:
+// CHECK: #APP
+// CHECK: mov eax, eax
+// CHECK: #NO_APP
+check_reg!(eax_i32 i32 "eax" "mov");
+
+// CHECK-LABEL: eax_f32:
+// CHECK: #APP
+// CHECK: mov eax, eax
+// CHECK: #NO_APP
+check_reg!(eax_f32 f32 "eax" "mov");
+
+// x86_64-LABEL: eax_i64:
+// x86_64: #APP
+// x86_64: mov eax, eax
+// x86_64: #NO_APP
+#[cfg(x86_64)]
+check_reg!(eax_i64 i64 "eax" "mov");
+
+// x86_64-LABEL: eax_f64:
+// x86_64: #APP
+// x86_64: mov eax, eax
+// x86_64: #NO_APP
+#[cfg(x86_64)]
+check_reg!(eax_f64 f64 "eax" "mov");
+
+// CHECK-LABEL: eax_ptr:
+// CHECK: #APP
+// CHECK: mov eax, eax
+// CHECK: #NO_APP
+check_reg!(eax_ptr ptr "eax" "mov");
+
+// i686-LABEL: ah_byte:
+// i686: #APP
+// i686: mov ah, ah
+// i686: #NO_APP
+#[cfg(i686)]
+check_reg!(ah_byte i8 "ah" "mov");
+
+// CHECK-LABEL: xmm0_f16:
+// CHECK: #APP
+// CHECK: movaps xmm0, xmm0
+// CHECK: #NO_APP
+check_reg!(xmm0_f16 f16 "xmm0" "movaps");
+
+// CHECK-LABEL: xmm0_i32:
+// CHECK: #APP
+// CHECK: movaps xmm0, xmm0
+// CHECK: #NO_APP
+check_reg!(xmm0_i32 i32 "xmm0" "movaps");
+
+// CHECK-LABEL: xmm0_f32:
+// CHECK: #APP
+// CHECK: movaps xmm0, xmm0
+// CHECK: #NO_APP
+check_reg!(xmm0_f32 f32 "xmm0" "movaps");
+
+// CHECK-LABEL: xmm0_i64:
+// CHECK: #APP
+// CHECK: movaps xmm0, xmm0
+// CHECK: #NO_APP
+check_reg!(xmm0_i64 i64 "xmm0" "movaps");
+
+// CHECK-LABEL: xmm0_f64:
+// CHECK: #APP
+// CHECK: movaps xmm0, xmm0
+// CHECK: #NO_APP
+check_reg!(xmm0_f64 f64 "xmm0" "movaps");
+
+// CHECK-LABEL: xmm0_f128:
+// CHECK: #APP
+// CHECK: movaps xmm0, xmm0
+// CHECK: #NO_APP
+check_reg!(xmm0_f128 f128 "xmm0" "movaps");
+
+// CHECK-LABEL: xmm0_ptr:
+// CHECK: #APP
+// CHECK: movaps xmm0, xmm0
+// CHECK: #NO_APP
+check_reg!(xmm0_ptr ptr "xmm0" "movaps");
+
+// CHECK-LABEL: xmm0_i8x16:
+// CHECK: #APP
+// CHECK: movaps xmm0, xmm0
+// CHECK: #NO_APP
+check_reg!(xmm0_i8x16 i8x16 "xmm0" "movaps");
+
+// CHECK-LABEL: xmm0_i16x8:
+// CHECK: #APP
+// CHECK: movaps xmm0, xmm0
+// CHECK: #NO_APP
+check_reg!(xmm0_i16x8 i16x8 "xmm0" "movaps");
+
+// CHECK-LABEL: xmm0_i32x4:
+// CHECK: #APP
+// CHECK: movaps xmm0, xmm0
+// CHECK: #NO_APP
+check_reg!(xmm0_i32x4 i32x4 "xmm0" "movaps");
+
+// CHECK-LABEL: xmm0_i64x2:
+// CHECK: #APP
+// CHECK: movaps xmm0, xmm0
+// CHECK: #NO_APP
+check_reg!(xmm0_i64x2 i64x2 "xmm0" "movaps");
+
+// CHECK-LABEL: xmm0_f16x8:
+// CHECK: #APP
+// CHECK: movaps xmm0, xmm0
+// CHECK: #NO_APP
+check_reg!(xmm0_f16x8 f16x8 "xmm0" "movaps");
+
+// CHECK-LABEL: xmm0_f32x4:
+// CHECK: #APP
+// CHECK: movaps xmm0, xmm0
+// CHECK: #NO_APP
+check_reg!(xmm0_f32x4 f32x4 "xmm0" "movaps");
+
+// CHECK-LABEL: xmm0_f64x2:
+// CHECK: #APP
+// CHECK: movaps xmm0, xmm0
+// CHECK: #NO_APP
+check_reg!(xmm0_f64x2 f64x2 "xmm0" "movaps");
+
+// CHECK-LABEL: ymm0_f16:
+// CHECK: #APP
+// CHECK: vmovaps ymm0, ymm0
+// CHECK: #NO_APP
+check_reg!(ymm0_f16 f16 "ymm0" "vmovaps");
+
+// CHECK-LABEL: ymm0_i32:
+// CHECK: #APP
+// CHECK: vmovaps ymm0, ymm0
+// CHECK: #NO_APP
+check_reg!(ymm0_i32 i32 "ymm0" "vmovaps");
+
+// CHECK-LABEL: ymm0_f32:
+// CHECK: #APP
+// CHECK: vmovaps ymm0, ymm0
+// CHECK: #NO_APP
+check_reg!(ymm0_f32 f32 "ymm0" "vmovaps");
+
+// CHECK-LABEL: ymm0_i64:
+// CHECK: #APP
+// CHECK: vmovaps ymm0, ymm0
+// CHECK: #NO_APP
+check_reg!(ymm0_i64 i64 "ymm0" "vmovaps");
+
+// CHECK-LABEL: ymm0_f64:
+// CHECK: #APP
+// CHECK: vmovaps ymm0, ymm0
+// CHECK: #NO_APP
+check_reg!(ymm0_f64 f64 "ymm0" "vmovaps");
+
+// CHECK-LABEL: ymm0_f128:
+// CHECK: #APP
+// CHECK: vmovaps ymm0, ymm0
+// CHECK: #NO_APP
+check_reg!(ymm0_f128 f128 "ymm0" "vmovaps");
+
+// CHECK-LABEL: ymm0_ptr:
+// CHECK: #APP
+// CHECK: vmovaps ymm0, ymm0
+// CHECK: #NO_APP
+check_reg!(ymm0_ptr ptr "ymm0" "vmovaps");
+
+// CHECK-LABEL: ymm0_i8x16:
+// CHECK: #APP
+// CHECK: vmovaps ymm0, ymm0
+// CHECK: #NO_APP
+check_reg!(ymm0_i8x16 i8x16 "ymm0" "vmovaps");
+
+// CHECK-LABEL: ymm0_i16x8:
+// CHECK: #APP
+// CHECK: vmovaps ymm0, ymm0
+// CHECK: #NO_APP
+check_reg!(ymm0_i16x8 i16x8 "ymm0" "vmovaps");
+
+// CHECK-LABEL: ymm0_i32x4:
+// CHECK: #APP
+// CHECK: vmovaps ymm0, ymm0
+// CHECK: #NO_APP
+check_reg!(ymm0_i32x4 i32x4 "ymm0" "vmovaps");
+
+// CHECK-LABEL: ymm0_i64x2:
+// CHECK: #APP
+// CHECK: vmovaps ymm0, ymm0
+// CHECK: #NO_APP
+check_reg!(ymm0_i64x2 i64x2 "ymm0" "vmovaps");
+
+// CHECK-LABEL: ymm0_f16x8:
+// CHECK: #APP
+// CHECK: vmovaps ymm0, ymm0
+// CHECK: #NO_APP
+check_reg!(ymm0_f16x8 f16x8 "ymm0" "vmovaps");
+
+// CHECK-LABEL: ymm0_f32x4:
+// CHECK: #APP
+// CHECK: vmovaps ymm0, ymm0
+// CHECK: #NO_APP
+check_reg!(ymm0_f32x4 f32x4 "ymm0" "vmovaps");
+
+// CHECK-LABEL: ymm0_f64x2:
+// CHECK: #APP
+// CHECK: vmovaps ymm0, ymm0
+// CHECK: #NO_APP
+check_reg!(ymm0_f64x2 f64x2 "ymm0" "vmovaps");
+
+// CHECK-LABEL: ymm0_i8x32:
+// CHECK: #APP
+// CHECK: vmovaps ymm0, ymm0
+// CHECK: #NO_APP
+check_reg!(ymm0_i8x32 i8x32 "ymm0" "vmovaps");
+
+// CHECK-LABEL: ymm0_i16x16:
+// CHECK: #APP
+// CHECK: vmovaps ymm0, ymm0
+// CHECK: #NO_APP
+check_reg!(ymm0_i16x16 i16x16 "ymm0" "vmovaps");
+
+// CHECK-LABEL: ymm0_i32x8:
+// CHECK: #APP
+// CHECK: vmovaps ymm0, ymm0
+// CHECK: #NO_APP
+check_reg!(ymm0_i32x8 i32x8 "ymm0" "vmovaps");
+
+// CHECK-LABEL: ymm0_i64x4:
+// CHECK: #APP
+// CHECK: vmovaps ymm0, ymm0
+// CHECK: #NO_APP
+check_reg!(ymm0_i64x4 i64x4 "ymm0" "vmovaps");
+
+// CHECK-LABEL: ymm0_f16x16:
+// CHECK: #APP
+// CHECK: vmovaps ymm0, ymm0
+// CHECK: #NO_APP
+check_reg!(ymm0_f16x16 f16x16 "ymm0" "vmovaps");
+
+// CHECK-LABEL: ymm0_f32x8:
+// CHECK: #APP
+// CHECK: vmovaps ymm0, ymm0
+// CHECK: #NO_APP
+check_reg!(ymm0_f32x8 f32x8 "ymm0" "vmovaps");
+
+// CHECK-LABEL: ymm0_f64x4:
+// CHECK: #APP
+// CHECK: vmovaps ymm0, ymm0
+// CHECK: #NO_APP
+check_reg!(ymm0_f64x4 f64x4 "ymm0" "vmovaps");
+
+// CHECK-LABEL: zmm0_f16:
+// CHECK: #APP
+// CHECK: vmovaps zmm0, zmm0
+// CHECK: #NO_APP
+check_reg!(zmm0_f16 f16 "zmm0" "vmovaps");
+
+// CHECK-LABEL: zmm0_i32:
+// CHECK: #APP
+// CHECK: vmovaps zmm0, zmm0
+// CHECK: #NO_APP
+check_reg!(zmm0_i32 i32 "zmm0" "vmovaps");
+
+// CHECK-LABEL: zmm0_f32:
+// CHECK: #APP
+// CHECK: vmovaps zmm0, zmm0
+// CHECK: #NO_APP
+check_reg!(zmm0_f32 f32 "zmm0" "vmovaps");
+
+// CHECK-LABEL: zmm0_i64:
+// CHECK: #APP
+// CHECK: vmovaps zmm0, zmm0
+// CHECK: #NO_APP
+check_reg!(zmm0_i64 i64 "zmm0" "vmovaps");
+
+// CHECK-LABEL: zmm0_f64:
+// CHECK: #APP
+// CHECK: vmovaps zmm0, zmm0
+// CHECK: #NO_APP
+check_reg!(zmm0_f64 f64 "zmm0" "vmovaps");
+
+// CHECK-LABEL: zmm0_f128:
+// CHECK: #APP
+// CHECK: vmovaps zmm0, zmm0
+// CHECK: #NO_APP
+check_reg!(zmm0_f128 f128 "zmm0" "vmovaps");
+
+// CHECK-LABEL: zmm0_ptr:
+// CHECK: #APP
+// CHECK: vmovaps zmm0, zmm0
+// CHECK: #NO_APP
+check_reg!(zmm0_ptr ptr "zmm0" "vmovaps");
+
+// CHECK-LABEL: zmm0_i8x16:
+// CHECK: #APP
+// CHECK: vmovaps zmm0, zmm0
+// CHECK: #NO_APP
+check_reg!(zmm0_i8x16 i8x16 "zmm0" "vmovaps");
+
+// CHECK-LABEL: zmm0_i16x8:
+// CHECK: #APP
+// CHECK: vmovaps zmm0, zmm0
+// CHECK: #NO_APP
+check_reg!(zmm0_i16x8 i16x8 "zmm0" "vmovaps");
+
+// CHECK-LABEL: zmm0_i32x4:
+// CHECK: #APP
+// CHECK: vmovaps zmm0, zmm0
+// CHECK: #NO_APP
+check_reg!(zmm0_i32x4 i32x4 "zmm0" "vmovaps");
+
+// CHECK-LABEL: zmm0_i64x2:
+// CHECK: #APP
+// CHECK: vmovaps zmm0, zmm0
+// CHECK: #NO_APP
+check_reg!(zmm0_i64x2 i64x2 "zmm0" "vmovaps");
+
+// CHECK-LABEL: zmm0_f16x8:
+// CHECK: #APP
+// CHECK: vmovaps zmm0, zmm0
+// CHECK: #NO_APP
+check_reg!(zmm0_f16x8 f16x8 "zmm0" "vmovaps");
+
+// CHECK-LABEL: zmm0_f32x4:
+// CHECK: #APP
+// CHECK: vmovaps zmm0, zmm0
+// CHECK: #NO_APP
+check_reg!(zmm0_f32x4 f32x4 "zmm0" "vmovaps");
+
+// CHECK-LABEL: zmm0_f64x2:
+// CHECK: #APP
+// CHECK: vmovaps zmm0, zmm0
+// CHECK: #NO_APP
+check_reg!(zmm0_f64x2 f64x2 "zmm0" "vmovaps");
+
+// CHECK-LABEL: zmm0_i8x32:
+// CHECK: #APP
+// CHECK: vmovaps zmm0, zmm0
+// CHECK: #NO_APP
+check_reg!(zmm0_i8x32 i8x32 "zmm0" "vmovaps");
+
+// CHECK-LABEL: zmm0_i16x16:
+// CHECK: #APP
+// CHECK: vmovaps zmm0, zmm0
+// CHECK: #NO_APP
+check_reg!(zmm0_i16x16 i16x16 "zmm0" "vmovaps");
+
+// CHECK-LABEL: zmm0_i32x8:
+// CHECK: #APP
+// CHECK: vmovaps zmm0, zmm0
+// CHECK: #NO_APP
+check_reg!(zmm0_i32x8 i32x8 "zmm0" "vmovaps");
+
+// CHECK-LABEL: zmm0_i64x4:
+// CHECK: #APP
+// CHECK: vmovaps zmm0, zmm0
+// CHECK: #NO_APP
+check_reg!(zmm0_i64x4 i64x4 "zmm0" "vmovaps");
+
+// CHECK-LABEL: zmm0_f16x16:
+// CHECK: #APP
+// CHECK: vmovaps zmm0, zmm0
+// CHECK: #NO_APP
+check_reg!(zmm0_f16x16 f16x16 "zmm0" "vmovaps");
+
+// CHECK-LABEL: zmm0_f32x8:
+// CHECK: #APP
+// CHECK: vmovaps zmm0, zmm0
+// CHECK: #NO_APP
+check_reg!(zmm0_f32x8 f32x8 "zmm0" "vmovaps");
+
+// CHECK-LABEL: zmm0_f64x4:
+// CHECK: #APP
+// CHECK: vmovaps zmm0, zmm0
+// CHECK: #NO_APP
+check_reg!(zmm0_f64x4 f64x4 "zmm0" "vmovaps");
+
+// CHECK-LABEL: zmm0_i8x64:
+// CHECK: #APP
+// CHECK: vmovaps zmm0, zmm0
+// CHECK: #NO_APP
+check_reg!(zmm0_i8x64 i8x64 "zmm0" "vmovaps");
+
+// CHECK-LABEL: zmm0_i16x32:
+// CHECK: #APP
+// CHECK: vmovaps zmm0, zmm0
+// CHECK: #NO_APP
+check_reg!(zmm0_i16x32 i16x32 "zmm0" "vmovaps");
+
+// CHECK-LABEL: zmm0_i32x16:
+// CHECK: #APP
+// CHECK: vmovaps zmm0, zmm0
+// CHECK: #NO_APP
+check_reg!(zmm0_i32x16 i32x16 "zmm0" "vmovaps");
+
+// CHECK-LABEL: zmm0_i64x8:
+// CHECK: #APP
+// CHECK: vmovaps zmm0, zmm0
+// CHECK: #NO_APP
+check_reg!(zmm0_i64x8 i64x8 "zmm0" "vmovaps");
+
+// CHECK-LABEL: zmm0_f16x32:
+// CHECK: #APP
+// CHECK: vmovaps zmm0, zmm0
+// CHECK: #NO_APP
+check_reg!(zmm0_f16x32 f16x32 "zmm0" "vmovaps");
+
+// CHECK-LABEL: zmm0_f32x16:
+// CHECK: #APP
+// CHECK: vmovaps zmm0, zmm0
+// CHECK: #NO_APP
+check_reg!(zmm0_f32x16 f32x16 "zmm0" "vmovaps");
+
+// CHECK-LABEL: zmm0_f64x8:
+// CHECK: #APP
+// CHECK: vmovaps zmm0, zmm0
+// CHECK: #NO_APP
+check_reg!(zmm0_f64x8 f64x8 "zmm0" "vmovaps");
+
+// CHECK-LABEL: k1_i8:
+// CHECK: #APP
+// CHECK: kmovb k1, k1
+// CHECK: #NO_APP
+check_reg!(k1_i8 i8 "k1" "kmovb");
+
+// CHECK-LABEL: k1_i16:
+// CHECK: #APP
+// CHECK: kmovw k1, k1
+// CHECK: #NO_APP
+check_reg!(k1_i16 i16 "k1" "kmovw");
+
+// CHECK-LABEL: k1_i32:
+// CHECK: #APP
+// CHECK: kmovd k1, k1
+// CHECK: #NO_APP
+check_reg!(k1_i32 i32 "k1" "kmovd");
+
+// CHECK-LABEL: k1_i64:
+// CHECK: #APP
+// CHECK: kmovq k1, k1
+// CHECK: #NO_APP
+check_reg!(k1_i64 i64 "k1" "kmovq");
+
+// CHECK-LABEL: k1_ptr:
+// CHECK: #APP
+// CHECK: kmovq k1, k1
+// CHECK: #NO_APP
+check_reg!(k1_ptr ptr "k1" "kmovq");
diff --git a/tests/assembly-llvm/auxiliary/breakpoint-panic-handler.rs b/tests/assembly-llvm/auxiliary/breakpoint-panic-handler.rs
new file mode 100644
index 00000000000..d54c1181e1a
--- /dev/null
+++ b/tests/assembly-llvm/auxiliary/breakpoint-panic-handler.rs
@@ -0,0 +1,8 @@
+#![feature(core_intrinsics)]
+#![no_std]
+
+#[panic_handler]
+unsafe fn breakpoint_panic_handler(_: &::core::panic::PanicInfo) -> ! {
+    core::intrinsics::breakpoint();
+    core::hint::unreachable_unchecked();
+}
diff --git a/tests/assembly-llvm/auxiliary/dwarf-mixed-versions-lto-aux.rs b/tests/assembly-llvm/auxiliary/dwarf-mixed-versions-lto-aux.rs
new file mode 100644
index 00000000000..257608f881f
--- /dev/null
+++ b/tests/assembly-llvm/auxiliary/dwarf-mixed-versions-lto-aux.rs
@@ -0,0 +1,5 @@
+//@ compile-flags: -g --crate-type=rlib -Cdwarf-version=4
+
+pub fn check_is_even(number: &u64) -> bool {
+    number % 2 == 0
+}
diff --git a/tests/assembly-llvm/auxiliary/non-inline-dependency.rs b/tests/assembly-llvm/auxiliary/non-inline-dependency.rs
new file mode 100644
index 00000000000..57f3ee87cdb
--- /dev/null
+++ b/tests/assembly-llvm/auxiliary/non-inline-dependency.rs
@@ -0,0 +1,14 @@
+#![no_std]
+#![deny(warnings)]
+
+#[inline(never)]
+#[no_mangle]
+pub fn wrapping_external_fn(a: u32) -> u32 {
+    a.wrapping_mul(a)
+}
+
+#[inline(never)]
+#[no_mangle]
+pub fn panicking_external_fn(a: u32) -> u32 {
+    a * a
+}
diff --git a/tests/assembly-llvm/breakpoint.rs b/tests/assembly-llvm/breakpoint.rs
new file mode 100644
index 00000000000..e0cc2d1eebb
--- /dev/null
+++ b/tests/assembly-llvm/breakpoint.rs
@@ -0,0 +1,14 @@
+//@ revisions: aarch64 x86_64
+//@ assembly-output: emit-asm
+//@[aarch64] only-aarch64
+//@[x86_64] only-x86_64
+
+#![feature(breakpoint)]
+#![crate_type = "lib"]
+
+// CHECK-LABEL: use_bp
+// aarch64: brk #0xf000
+// x86_64: int3
+pub fn use_bp() {
+    core::arch::breakpoint();
+}
diff --git a/tests/assembly-llvm/closure-inherit-target-feature.rs b/tests/assembly-llvm/closure-inherit-target-feature.rs
new file mode 100644
index 00000000000..069204bbd34
--- /dev/null
+++ b/tests/assembly-llvm/closure-inherit-target-feature.rs
@@ -0,0 +1,59 @@
+//@ only-x86_64
+//@ ignore-sgx Tests incompatible with LVI mitigations
+//@ assembly-output: emit-asm
+// make sure the feature is not enabled at compile-time
+//@ compile-flags: -C opt-level=3 -C target-feature=-sse4.1 -C llvm-args=-x86-asm-syntax=intel
+
+#![crate_type = "rlib"]
+
+use std::arch::x86_64::{__m128, _mm_blend_ps};
+
+// Use an explicit return pointer to prevent tail call optimization.
+#[no_mangle]
+pub unsafe fn sse41_blend_nofeature(x: __m128, y: __m128, ret: *mut __m128) {
+    let f = {
+        // check that _mm_blend_ps is not being inlined into the closure
+        // CHECK-LABEL: {{sse41_blend_nofeature.*closure.*:}}
+        // CHECK-NOT: blendps
+        // CHECK: {{call .*_mm_blend_ps.*}}
+        // CHECK-NOT: blendps
+        // CHECK: ret
+        #[inline(never)]
+        |x, y, ret: *mut __m128| unsafe { *ret = _mm_blend_ps(x, y, 0b0101) }
+    };
+    f(x, y, ret);
+}
+
+#[no_mangle]
+#[target_feature(enable = "sse4.1")]
+pub fn sse41_blend_noinline(x: __m128, y: __m128) -> __m128 {
+    let f = {
+        // check that _mm_blend_ps is being inlined into the closure
+        // CHECK-LABEL: {{sse41_blend_noinline.*closure.*:}}
+        // CHECK-NOT: _mm_blend_ps
+        // CHECK: blendps
+        // CHECK-NOT: _mm_blend_ps
+        // CHECK: ret
+        #[inline(never)]
+        |x, y| unsafe { _mm_blend_ps(x, y, 0b0101) }
+    };
+    f(x, y)
+}
+
+#[no_mangle]
+#[target_feature(enable = "sse4.1")]
+pub fn sse41_blend_doinline(x: __m128, y: __m128) -> __m128 {
+    // check that the closure and _mm_blend_ps are being inlined into the function
+    // CHECK-LABEL: sse41_blend_doinline:
+    // CHECK-NOT: {{sse41_blend_doinline.*closure.*}}
+    // CHECK-NOT: _mm_blend_ps
+    // CHECK: blendps
+    // CHECK-NOT: {{sse41_blend_doinline.*closure.*}}
+    // CHECK-NOT: _mm_blend_ps
+    // CHECK: ret
+    let f = {
+        #[inline]
+        |x, y| unsafe { _mm_blend_ps(x, y, 0b0101) }
+    };
+    f(x, y)
+}
diff --git a/tests/assembly-llvm/cmse.rs b/tests/assembly-llvm/cmse.rs
new file mode 100644
index 00000000000..a68ee99eac6
--- /dev/null
+++ b/tests/assembly-llvm/cmse.rs
@@ -0,0 +1,100 @@
+//@ add-core-stubs
+//@ revisions: hard soft
+//@ assembly-output: emit-asm
+//@ [hard] compile-flags: --target thumbv8m.main-none-eabihf --crate-type lib -Copt-level=1
+//@ [soft] compile-flags: --target thumbv8m.main-none-eabi --crate-type lib -Copt-level=1
+//@ [hard] needs-llvm-components: arm
+//@ [soft] needs-llvm-components: arm
+#![crate_type = "lib"]
+#![feature(abi_cmse_nonsecure_call, cmse_nonsecure_entry, no_core, lang_items)]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
+
+// CHECK-LABEL: __acle_se_entry_point:
+// CHECK-NEXT: entry_point:
+//
+// Write return argument (two registers since 64bit integer)
+// CHECK: movs r0, #0
+// CHECK: movs r1, #0
+//
+// If we are using hard-float:
+// * Check if the float registers were touched (bit 3 in CONTROL)
+// hard: mrs     [[REG:r[0-9]+]], control
+// hard: tst.w   [[REG]], #8
+// hard: beq     [[LABEL:[\.a-zA-Z0-9_]+]]
+//
+// * If touched clear all float registers (d0..=d7)
+// hard: vmov    d0,
+// hard: vmov    d1,
+// hard: vmov    d2,
+// hard: vmov    d3,
+// hard: vmov    d4,
+// hard: vmov    d5,
+// hard: vmov    d6,
+// hard: vmov    d7,
+//
+// * If touched clear FPU status register
+// hard: vmrs    [[REG:r[0-9]+]], fpscr
+// hard: bic     [[REG]], [[REG]], #159
+// hard: bic     [[REG]], [[REG]], #4026531840
+// hard: vmsr    fpscr, [[REG]]
+// hard: [[LABEL]]:
+//
+// Clear all other registers that might have been used
+// CHECK: mov r2,
+// CHECK: mov r3,
+// CHECK: mov r12,
+//
+// Clear the flags
+// CHECK: msr apsr_nzcvq,
+//
+// Branch back to non-secure side
+// CHECK: bxns lr
+#[no_mangle]
+pub extern "cmse-nonsecure-entry" fn entry_point() -> i64 {
+    0
+}
+
+// NOTE for future codegen changes:
+// The specific register assignment is not important, however:
+// * all registers must be cleared before `blxns` is executed
+//     (either by writing arguments or any other value)
+// * the lowest bit on the address of the callee must be cleared
+// * the flags need to be overwritten
+// * `blxns` needs to be called with the callee address
+//     (with the lowest bit cleared)
+//
+// CHECK-LABEL: call_nonsecure
+// Save callee pointer
+// CHECK: mov r12, r0
+//
+// All arguments are written to (writes r0..=r3)
+// CHECK: movs r0, #0
+// CHECK: movs r1, #1
+// CHECK: movs r2, #2
+// CHECK: movs r3, #3
+//
+// Lowest bit gets cleared on callee address
+// CHECK: bic r12, r12, #1
+//
+// Ununsed registers get cleared (r4..=r11)
+// CHECK: mov r4,
+// CHECK: mov r5,
+// CHECK: mov r6,
+// CHECK: mov r7,
+// CHECK: mov r8,
+// CHECK: mov r9,
+// CHECK: mov r10,
+// CHECK: mov r11,
+//
+// Flags get cleared
+// CHECK: msr apsr_nzcvq,
+//
+// Call to non-secure
+// CHECK: blxns r12
+#[no_mangle]
+pub fn call_nonsecure(f: unsafe extern "cmse-nonsecure-call" fn(u32, u32, u32, u32) -> u64) -> u64 {
+    unsafe { f(0, 1, 2, 3) }
+}
diff --git a/tests/assembly-llvm/compiletest-self-test/use-minicore-no-run.rs b/tests/assembly-llvm/compiletest-self-test/use-minicore-no-run.rs
new file mode 100644
index 00000000000..0e4f05c4b37
--- /dev/null
+++ b/tests/assembly-llvm/compiletest-self-test/use-minicore-no-run.rs
@@ -0,0 +1,5 @@
+//! `compiletest` self-test to check that `add-core-stubs` is incompatible with run pass modes.
+
+//@ add-core-stubs
+//@ run-pass
+//@ should-fail
diff --git a/tests/assembly-llvm/cstring-merging.rs b/tests/assembly-llvm/cstring-merging.rs
new file mode 100644
index 00000000000..03688e0068b
--- /dev/null
+++ b/tests/assembly-llvm/cstring-merging.rs
@@ -0,0 +1,30 @@
+// MIPS assembler uses the label prefix `$anon.` for local anonymous variables
+// other architectures (including ARM and x86-64) use the prefix `.Lanon.`
+//@ only-linux
+//@ assembly-output: emit-asm
+//@ compile-flags: --crate-type=lib -Copt-level=3 -Cllvm-args=-enable-global-merge=0
+//@ edition: 2024
+
+use std::ffi::CStr;
+
+// CHECK: .section .rodata.str1.{{[12]}},"aMS"
+// CHECK: {{(\.L|\$)}}anon.{{.+}}:
+// CHECK-NEXT: .asciz "foo"
+#[unsafe(no_mangle)]
+static CSTR: &[u8; 4] = b"foo\0";
+
+// CHECK-NOT: .section
+// CHECK: {{(\.L|\$)}}anon.{{.+}}:
+// CHECK-NEXT: .asciz "bar"
+#[unsafe(no_mangle)]
+pub fn cstr() -> &'static CStr {
+    c"bar"
+}
+
+// CHECK-NOT: .section
+// CHECK: {{(\.L|\$)}}anon.{{.+}}:
+// CHECK-NEXT: .asciz "baz"
+#[unsafe(no_mangle)]
+pub fn manual_cstr() -> &'static str {
+    "baz\0"
+}
diff --git a/tests/assembly-llvm/dwarf-mixed-versions-lto.rs b/tests/assembly-llvm/dwarf-mixed-versions-lto.rs
new file mode 100644
index 00000000000..9910a6e2f5f
--- /dev/null
+++ b/tests/assembly-llvm/dwarf-mixed-versions-lto.rs
@@ -0,0 +1,20 @@
+// This test ensures that if LTO occurs between crates with different DWARF versions, we
+// will choose the highest DWARF version for the final binary. This matches Clang's behavior.
+// Note: `.2byte` directive is used on MIPS.
+
+//@ only-linux
+//@ aux-build:dwarf-mixed-versions-lto-aux.rs
+//@ compile-flags: -C lto -g -Cdwarf-version=5
+//@ assembly-output: emit-asm
+//@ no-prefer-dynamic
+
+extern crate dwarf_mixed_versions_lto_aux;
+
+fn main() {
+    dwarf_mixed_versions_lto_aux::check_is_even(&0);
+}
+
+// CHECK: .section .debug_info
+// CHECK-NOT: {{\.(short|hword|2byte)}} 2
+// CHECK-NOT: {{\.(short|hword|2byte)}} 4
+// CHECK: {{\.(short|hword|2byte)}} 5
diff --git a/tests/assembly-llvm/dwarf4.rs b/tests/assembly-llvm/dwarf4.rs
new file mode 100644
index 00000000000..03a388603b4
--- /dev/null
+++ b/tests/assembly-llvm/dwarf4.rs
@@ -0,0 +1,23 @@
+// Makes sure that `-C dwarf-version=4` causes `rustc` to emit DWARF version 4.
+//@ assembly-output: emit-asm
+//@ add-core-stubs
+//@ compile-flags: -g --target x86_64-unknown-linux-gnu -C dwarf-version=4 -Copt-level=0
+//@ needs-llvm-components: x86
+
+#![feature(no_core, lang_items)]
+#![crate_type = "rlib"]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
+
+pub fn wibble() {}
+
+pub struct X;
+
+// CHECK: .section .debug_info
+// CHECK-NOT: .short 2
+// CHECK-NOT: .short 5
+// CHECK: .short 4
+// CHECK-NOT: .section .debug_pubnames
+// CHECK-NOT: .section .debug_pubtypes
diff --git a/tests/assembly-llvm/dwarf5.rs b/tests/assembly-llvm/dwarf5.rs
new file mode 100644
index 00000000000..9bd92cc0d09
--- /dev/null
+++ b/tests/assembly-llvm/dwarf5.rs
@@ -0,0 +1,20 @@
+// Makes sure that `-C dwarf-version=5` causes `rustc` to emit DWARF version 5.
+//@ add-core-stubs
+//@ assembly-output: emit-asm
+//@ compile-flags: -g --target x86_64-unknown-linux-gnu -C dwarf-version=5 -Copt-level=0
+//@ needs-llvm-components: x86
+
+#![feature(no_core, lang_items)]
+#![crate_type = "rlib"]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
+
+pub fn wibble() {}
+
+// CHECK: .section .debug_info
+// CHECK-NOT: .short 2
+// CHECK-NOT: .short 4
+// CHECK: .short 5
+// CHECK: .section .debug_names
diff --git a/tests/assembly-llvm/emit-intel-att-syntax.rs b/tests/assembly-llvm/emit-intel-att-syntax.rs
new file mode 100644
index 00000000000..7b479a0f79e
--- /dev/null
+++ b/tests/assembly-llvm/emit-intel-att-syntax.rs
@@ -0,0 +1,75 @@
+//@ assembly-output: emit-asm
+//@ revisions: att intel
+//@ [att] compile-flags: -Cllvm-args=-x86-asm-syntax=att
+//@ [intel] compile-flags: -Cllvm-args=-x86-asm-syntax=intel
+//@ only-x86_64
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: naked_att:
+// intel-CHECK: mov rax, qword ptr [rdi]
+// intel-CHECK: ret
+// att-CHECK: movq (%rdi), %rax
+// att-CHECK: retq
+
+#[unsafe(naked)]
+#[unsafe(no_mangle)]
+extern "sysv64" fn naked_att() {
+    std::arch::naked_asm!(
+        "
+        movq (%rdi), %rax
+        retq
+        ",
+        options(att_syntax),
+    );
+}
+
+// CHECK-LABEL: naked_intel:
+// intel-CHECK: mov rax, rdi
+// intel-CHECK: ret
+// att-CHECK: movq (%rdi), %rax
+// att-CHECK: retq
+
+#[unsafe(naked)]
+#[unsafe(no_mangle)]
+extern "sysv64" fn naked_intel() {
+    std::arch::naked_asm!(
+        "
+        mov rax, rdi
+        ret
+        ",
+        options(),
+    );
+}
+
+// CHECK-LABEL: global_att:
+// intel-CHECK: mov rax, rdi
+// intel-CHECK: ret
+// att-CHECK: movq (%rdi), %rax
+// att-CHECK: retq
+
+core::arch::global_asm!(
+    "
+    .globl global_att
+    global_att:
+        movq (%rdi), %rax
+        retq
+    ",
+    options(att_syntax),
+);
+
+// CHECK-LABEL: global_intel:
+// intel-CHECK: mov rax, rdi
+// intel-CHECK: ret
+// att-CHECK: movq (%rdi), %rax
+// att-CHECK: retq
+
+core::arch::global_asm!(
+    "
+    .globl global_intel
+    global_intel:
+        mov rax, rdi
+        ret
+    ",
+    options(),
+);
diff --git a/tests/assembly-llvm/is_aligned.rs b/tests/assembly-llvm/is_aligned.rs
new file mode 100644
index 00000000000..ab8f7dea808
--- /dev/null
+++ b/tests/assembly-llvm/is_aligned.rs
@@ -0,0 +1,55 @@
+//@ assembly-output: emit-asm
+//@ only-x86_64
+//@ ignore-sgx
+//@ revisions: opt-speed opt-size
+//@ [opt-speed] compile-flags: -Copt-level=2 -Cdebug-assertions=no
+//@ [opt-size] compile-flags: -Copt-level=s -Cdebug-assertions=no
+#![crate_type = "rlib"]
+#![feature(core_intrinsics)]
+#![feature(pointer_is_aligned_to)]
+
+// CHECK-LABEL: is_aligned_to_unchecked
+// CHECK: decq
+// CHECK-NEXT: testq
+// CHECK-NEXT: sete
+// CHECK: retq
+#[no_mangle]
+pub unsafe fn is_aligned_to_unchecked(ptr: *const u8, align: usize) -> bool {
+    unsafe { std::intrinsics::assume(align.is_power_of_two()) }
+    ptr.is_aligned_to(align)
+}
+
+// CHECK-LABEL: is_aligned_1
+// CHECK: movb $1
+// CHECK: retq
+#[no_mangle]
+pub fn is_aligned_1(ptr: *const u8) -> bool {
+    ptr.is_aligned()
+}
+
+// CHECK-LABEL: is_aligned_2
+// CHECK: testb $1
+// CHECK-NEXT: sete
+// CHECK: retq
+#[no_mangle]
+pub fn is_aligned_2(ptr: *const u16) -> bool {
+    ptr.is_aligned()
+}
+
+// CHECK-LABEL: is_aligned_4
+// CHECK: testb $3
+// CHECK-NEXT: sete
+// CHECK: retq
+#[no_mangle]
+pub fn is_aligned_4(ptr: *const u32) -> bool {
+    ptr.is_aligned()
+}
+
+// CHECK-LABEL: is_aligned_8
+// CHECK: testb $7
+// CHECK-NEXT: sete
+// CHECK: retq
+#[no_mangle]
+pub fn is_aligned_8(ptr: *const u64) -> bool {
+    ptr.is_aligned()
+}
diff --git a/tests/assembly-llvm/issue-83585-small-pod-struct-equality.rs b/tests/assembly-llvm/issue-83585-small-pod-struct-equality.rs
new file mode 100644
index 00000000000..14bec1337f0
--- /dev/null
+++ b/tests/assembly-llvm/issue-83585-small-pod-struct-equality.rs
@@ -0,0 +1,27 @@
+//@ assembly-output: emit-asm
+//@ compile-flags: -Copt-level=3
+//@ only-x86_64
+
+#![crate_type = "lib"]
+
+type T = u8;
+type T1 = (T, T, T, T, T, T, T, T);
+
+// CHECK-LABEL: foo1a
+// CHECK: cmpq
+// CHECK-NEXT: sete
+// CHECK-NEXT: {{retq|popq}}
+#[no_mangle]
+pub fn foo1a(a: T1, b: T1) -> bool {
+    a == b
+}
+
+// CHECK-LABEL: foo1b
+// CHECK: movq
+// CHECK: cmpq
+// CHECK-NEXT: sete
+// CHECK-NEXT: {{retq|popq}}
+#[no_mangle]
+pub fn foo1b(a: &T1, b: &T1) -> bool {
+    a == b
+}
diff --git a/tests/assembly-llvm/libs/issue-115339-zip-arrays.rs b/tests/assembly-llvm/libs/issue-115339-zip-arrays.rs
new file mode 100644
index 00000000000..098382502e8
--- /dev/null
+++ b/tests/assembly-llvm/libs/issue-115339-zip-arrays.rs
@@ -0,0 +1,25 @@
+//@ assembly-output: emit-asm
+// # zen3 previously exhibited odd vectorization
+//@ compile-flags: --crate-type=lib -Ctarget-cpu=znver3 -Copt-level=3
+//@ only-x86_64
+//@ ignore-sgx
+
+use std::iter;
+
+// previously this produced a long chain of
+// 56:  vpextrb $6, %xmm0, %ecx
+// 57:  orb %cl, 22(%rsi)
+// 58:  vpextrb $7, %xmm0, %ecx
+// 59:  orb %cl, 23(%rsi)
+// [...]
+
+// CHECK-LABEL: zip_arrays:
+#[no_mangle]
+pub fn zip_arrays(mut a: [u8; 32], b: [u8; 32]) -> [u8; 32] {
+    // CHECK-NOT: vpextrb
+    // CHECK-NOT: orb %cl
+    // CHECK: vorps
+    iter::zip(&mut a, b).for_each(|(a, b)| *a |= b);
+    // CHECK: retq
+    a
+}
diff --git a/tests/assembly-llvm/libs/issue-140207-slice-min-simd.rs b/tests/assembly-llvm/libs/issue-140207-slice-min-simd.rs
new file mode 100644
index 00000000000..86f067cac08
--- /dev/null
+++ b/tests/assembly-llvm/libs/issue-140207-slice-min-simd.rs
@@ -0,0 +1,13 @@
+//@ assembly-output: emit-asm
+// # avx has a dedicated instruction for this
+//@ compile-flags: --crate-type=lib -Ctarget-cpu=znver2 -Copt-level=3
+//@ only-x86_64
+//@ ignore-sgx
+// https://github.com/rust-lang/rust/issues/140207
+
+#[unsafe(no_mangle)]
+pub fn array_min(a: &[u16; 8]) -> u16 {
+    // CHECK: vphminposuw
+    // CHECK: ret
+    a.iter().copied().min().unwrap()
+}
diff --git a/tests/assembly-llvm/manual-eq-efficient.rs b/tests/assembly-llvm/manual-eq-efficient.rs
new file mode 100644
index 00000000000..8dafed354be
--- /dev/null
+++ b/tests/assembly-llvm/manual-eq-efficient.rs
@@ -0,0 +1,22 @@
+// Regression test for #106269
+//@ assembly-output: emit-asm
+//@ compile-flags: --crate-type=lib -Copt-level=3 -C llvm-args=-x86-asm-syntax=intel
+//@ only-x86_64
+//@ ignore-sgx
+
+pub struct S {
+    a: u8,
+    b: u8,
+    c: u8,
+    d: u8,
+}
+
+// CHECK-LABEL: manual_eq:
+#[no_mangle]
+pub fn manual_eq(s1: &S, s2: &S) -> bool {
+    // CHECK: mov [[REG:[a-z0-9]+]], dword ptr [{{[a-z0-9]+}}]
+    // CHECK-NEXT: cmp [[REG]], dword ptr [{{[a-z0-9]+}}]
+    // CHECK-NEXT: sete al
+    // CHECK: ret
+    s1.a == s2.a && s1.b == s2.b && s1.c == s2.c && s1.d == s2.d
+}
diff --git a/tests/assembly-llvm/naked-functions/aarch64-naked-fn-no-bti-prolog.rs b/tests/assembly-llvm/naked-functions/aarch64-naked-fn-no-bti-prolog.rs
new file mode 100644
index 00000000000..860ecc3cfcd
--- /dev/null
+++ b/tests/assembly-llvm/naked-functions/aarch64-naked-fn-no-bti-prolog.rs
@@ -0,0 +1,21 @@
+//@ compile-flags: -C no-prepopulate-passes -Zbranch-protection=bti
+//@ assembly-output: emit-asm
+//@ needs-asm-support
+//@ only-aarch64
+
+#![crate_type = "lib"]
+
+use std::arch::naked_asm;
+
+// The problem at hand: Rust has adopted a fairly strict meaning for "naked functions",
+// meaning "no prologue whatsoever, no, really, not one instruction."
+// Unfortunately, aarch64's "branch target identification" works via hints at landing sites.
+// LLVM implements this via making sure of that, even for functions with the naked attribute.
+// So, we must emit an appropriate instruction instead!
+#[no_mangle]
+#[unsafe(naked)]
+pub extern "C" fn _hlt() -> ! {
+    // CHECK-NOT: hint #34
+    // CHECK: hlt #0x1
+    naked_asm!("hlt #1")
+}
diff --git a/tests/assembly-llvm/naked-functions/aix.rs b/tests/assembly-llvm/naked-functions/aix.rs
new file mode 100644
index 00000000000..57ff0e183be
--- /dev/null
+++ b/tests/assembly-llvm/naked-functions/aix.rs
@@ -0,0 +1,35 @@
+//@ revisions: elfv1-be aix
+//@ add-core-stubs
+//@ assembly-output: emit-asm
+//
+//@[elfv1-be] compile-flags: --target powerpc64-unknown-linux-gnu
+//@[elfv1-be] needs-llvm-components: powerpc
+//
+//@[aix] compile-flags: --target powerpc64-ibm-aix
+//@[aix] needs-llvm-components: powerpc
+
+#![crate_type = "lib"]
+#![feature(no_core, asm_experimental_arch, f128, linkage, fn_align)]
+#![no_core]
+
+// tests that naked functions work for the `powerpc64-ibm-aix` target.
+//
+// This target is special because it uses the XCOFF binary format
+// It is tested alongside an elf powerpc target to pin down commonalities and differences.
+//
+// https://doc.rust-lang.org/rustc/platform-support/aix.html
+// https://www.ibm.com/docs/en/aix/7.2?topic=formats-xcoff-object-file-format
+
+extern crate minicore;
+use minicore::*;
+
+// elfv1-be: .p2align 2
+// aix: .align 2
+// CHECK: .globl blr
+// CHECK-LABEL: blr:
+// CHECK: blr
+#[no_mangle]
+#[unsafe(naked)]
+extern "C" fn blr() {
+    naked_asm!("blr")
+}
diff --git a/tests/assembly-llvm/naked-functions/wasm32.rs b/tests/assembly-llvm/naked-functions/wasm32.rs
new file mode 100644
index 00000000000..77547e82041
--- /dev/null
+++ b/tests/assembly-llvm/naked-functions/wasm32.rs
@@ -0,0 +1,200 @@
+//@ revisions: wasm32-unknown wasm64-unknown wasm32-wasip1
+//@ add-core-stubs
+//@ assembly-output: emit-asm
+//@ [wasm32-unknown] compile-flags: --target wasm32-unknown-unknown
+//@ [wasm64-unknown] compile-flags: --target wasm64-unknown-unknown
+//@ [wasm32-wasip1] compile-flags: --target wasm32-wasip1
+//@ [wasm32-unknown] needs-llvm-components: webassembly
+//@ [wasm64-unknown] needs-llvm-components: webassembly
+//@ [wasm32-wasip1] needs-llvm-components: webassembly
+
+#![crate_type = "lib"]
+#![feature(no_core, asm_experimental_arch, f128, linkage, fn_align)]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
+
+// CHECK: .section  .text.nop,"",@
+// CHECK: .globl nop
+// CHECK-LABEL: nop:
+// CHECK: .functype nop () -> ()
+// CHECK-NOT: .size
+// CHECK: end_function
+#[no_mangle]
+#[unsafe(naked)]
+extern "C" fn nop() {
+    naked_asm!("nop")
+}
+
+// CHECK: .section  .text.weak_nop,"",@
+// CHECK: .weak weak_nop
+// CHECK-LABEL: nop:
+// CHECK: .functype weak_nop () -> ()
+// CHECK-NOT: .size
+// CHECK: end_function
+#[no_mangle]
+#[unsafe(naked)]
+#[linkage = "weak"]
+extern "C" fn weak_nop() {
+    naked_asm!("nop")
+}
+
+// CHECK-LABEL: fn_i8_i8:
+// CHECK-NEXT: .functype fn_i8_i8 (i32) -> (i32)
+//
+// CHECK-NEXT: local.get 0
+// CHECK-NEXT: local.get 0
+// CHECK-NEXT: i32.mul
+//
+// CHECK-NEXT: end_function
+#[no_mangle]
+#[unsafe(naked)]
+extern "C" fn fn_i8_i8(num: i8) -> i8 {
+    naked_asm!("local.get 0", "local.get 0", "i32.mul")
+}
+
+// CHECK-LABEL: fn_i8_i8_i8:
+// CHECK: .functype fn_i8_i8_i8 (i32, i32) -> (i32)
+#[no_mangle]
+#[unsafe(naked)]
+extern "C" fn fn_i8_i8_i8(a: i8, b: i8) -> i8 {
+    naked_asm!("local.get 1", "local.get 0", "i32.mul")
+}
+
+// CHECK-LABEL: fn_unit_i8:
+// CHECK: .functype fn_unit_i8 () -> (i32)
+#[no_mangle]
+#[unsafe(naked)]
+extern "C" fn fn_unit_i8() -> i8 {
+    naked_asm!("i32.const 42")
+}
+
+// CHECK-LABEL: fn_i8_unit:
+// CHECK: .functype fn_i8_unit (i32) -> ()
+#[no_mangle]
+#[unsafe(naked)]
+extern "C" fn fn_i8_unit(_: i8) {
+    naked_asm!("nop")
+}
+
+// CHECK-LABEL: fn_i32_i32:
+// CHECK: .functype fn_i32_i32 (i32) -> (i32)
+#[no_mangle]
+#[unsafe(naked)]
+extern "C" fn fn_i32_i32(num: i32) -> i32 {
+    naked_asm!("local.get 0", "local.get 0", "i32.mul")
+}
+
+// CHECK-LABEL: fn_i64_i64:
+// CHECK: .functype fn_i64_i64 (i64) -> (i64)
+#[no_mangle]
+#[unsafe(naked)]
+extern "C" fn fn_i64_i64(num: i64) -> i64 {
+    naked_asm!("local.get 0", "local.get 0", "i64.mul")
+}
+
+// CHECK-LABEL: fn_i128_i128:
+// wasm32-unknown: .functype fn_i128_i128 (i32, i64, i64) -> ()
+// wasm32-wasip1: .functype fn_i128_i128 (i32, i64, i64) -> ()
+// wasm64-unknown: .functype fn_i128_i128 (i64, i64, i64) -> ()
+#[allow(improper_ctypes_definitions)]
+#[no_mangle]
+#[unsafe(naked)]
+extern "C" fn fn_i128_i128(num: i128) -> i128 {
+    naked_asm!(
+        "local.get       0",
+        "local.get       2",
+        "i64.store       8",
+        "local.get       0",
+        "local.get       1",
+        "i64.store       0",
+    )
+}
+
+// CHECK-LABEL: fn_f128_f128:
+// wasm32-unknown: .functype fn_f128_f128 (i32, i64, i64) -> ()
+// wasm32-wasip1: .functype fn_f128_f128 (i32, i64, i64) -> ()
+// wasm64-unknown: .functype fn_f128_f128 (i64, i64, i64) -> ()
+#[no_mangle]
+#[unsafe(naked)]
+extern "C" fn fn_f128_f128(num: f128) -> f128 {
+    naked_asm!(
+        "local.get       0",
+        "local.get       2",
+        "i64.store       8",
+        "local.get       0",
+        "local.get       1",
+        "i64.store       0",
+    )
+}
+
+#[repr(C)]
+struct Compound {
+    a: u16,
+    b: i64,
+}
+
+// CHECK-LABEL: fn_compound_compound:
+// wasm32-unknown: .functype fn_compound_compound (i32, i32) -> ()
+// wasm32-wasip1: .functype fn_compound_compound (i32, i32) -> ()
+// wasm64-unknown: .functype fn_compound_compound (i64, i64) -> ()
+#[no_mangle]
+#[unsafe(naked)]
+extern "C" fn fn_compound_compound(_: Compound) -> Compound {
+    // this is the wasm32-wasip1 assembly
+    naked_asm!(
+        "local.get       0",
+        "local.get       1",
+        "i64.load        8",
+        "i64.store       8",
+        "local.get       0",
+        "local.get       1",
+        "i32.load16_u    0",
+        "i32.store16     0",
+    )
+}
+
+#[repr(C)]
+struct WrapperI32(i32);
+
+// CHECK-LABEL: fn_wrapperi32_wrapperi32:
+// CHECK: .functype fn_wrapperi32_wrapperi32 (i32) -> (i32)
+#[no_mangle]
+#[unsafe(naked)]
+extern "C" fn fn_wrapperi32_wrapperi32(_: WrapperI32) -> WrapperI32 {
+    naked_asm!("local.get       0")
+}
+
+#[repr(C)]
+struct WrapperI64(i64);
+
+// CHECK-LABEL: fn_wrapperi64_wrapperi64:
+// CHECK: .functype fn_wrapperi64_wrapperi64 (i64) -> (i64)
+#[no_mangle]
+#[unsafe(naked)]
+extern "C" fn fn_wrapperi64_wrapperi64(_: WrapperI64) -> WrapperI64 {
+    naked_asm!("local.get       0")
+}
+
+#[repr(C)]
+struct WrapperF32(f32);
+
+// CHECK-LABEL: fn_wrapperf32_wrapperf32:
+// CHECK: .functype fn_wrapperf32_wrapperf32 (f32) -> (f32)
+#[no_mangle]
+#[unsafe(naked)]
+extern "C" fn fn_wrapperf32_wrapperf32(_: WrapperF32) -> WrapperF32 {
+    naked_asm!("local.get       0")
+}
+
+#[repr(C)]
+struct WrapperF64(f64);
+
+// CHECK-LABEL: fn_wrapperf64_wrapperf64:
+// CHECK: .functype fn_wrapperf64_wrapperf64 (f64) -> (f64)
+#[no_mangle]
+#[unsafe(naked)]
+extern "C" fn fn_wrapperf64_wrapperf64(_: WrapperF64) -> WrapperF64 {
+    naked_asm!("local.get       0")
+}
diff --git a/tests/assembly-llvm/naked-functions/x86_64-naked-fn-no-cet-prolog.rs b/tests/assembly-llvm/naked-functions/x86_64-naked-fn-no-cet-prolog.rs
new file mode 100644
index 00000000000..81ee9b13b4e
--- /dev/null
+++ b/tests/assembly-llvm/naked-functions/x86_64-naked-fn-no-cet-prolog.rs
@@ -0,0 +1,24 @@
+//@ compile-flags: -C no-prepopulate-passes -Zcf-protection=full
+//@ assembly-output: emit-asm
+//@ needs-asm-support
+//@ only-x86_64
+
+#![crate_type = "lib"]
+
+use std::arch::naked_asm;
+
+// The problem at hand: Rust has adopted a fairly strict meaning for "naked functions",
+// meaning "no prologue whatsoever, no, really, not one instruction."
+// Unfortunately, x86's control-flow enforcement, specifically indirect branch protection,
+// works by using an instruction for each possible landing site,
+// and LLVM implements this via making sure of that.
+#[no_mangle]
+#[unsafe(naked)]
+pub extern "sysv64" fn will_halt() -> ! {
+    // CHECK-NOT: endbr{{32|64}}
+    // CHECK: hlt
+    naked_asm!("hlt")
+}
+
+// what about aarch64?
+// "branch-protection"=false
diff --git a/tests/assembly-llvm/niche-prefer-zero.rs b/tests/assembly-llvm/niche-prefer-zero.rs
new file mode 100644
index 00000000000..4e260ebc09b
--- /dev/null
+++ b/tests/assembly-llvm/niche-prefer-zero.rs
@@ -0,0 +1,25 @@
+// Check that niche selection prefers zero and that jumps are optimized away.
+// See https://github.com/rust-lang/rust/pull/87794
+//@ assembly-output: emit-asm
+//@ only-x86
+//@ compile-flags: -Copt-level=3
+
+#![crate_type = "lib"]
+
+#[repr(u8)]
+pub enum Size {
+    One = 1,
+    Two = 2,
+    Three = 3,
+}
+
+#[no_mangle]
+pub fn handle(x: Option<Size>) -> u8 {
+    match x {
+        None => 0,
+        Some(size) => size as u8,
+    }
+}
+
+// There should be no jumps in output
+// CHECK-NOT: j
diff --git a/tests/assembly-llvm/nvptx-arch-default.rs b/tests/assembly-llvm/nvptx-arch-default.rs
new file mode 100644
index 00000000000..a621fd6dcb2
--- /dev/null
+++ b/tests/assembly-llvm/nvptx-arch-default.rs
@@ -0,0 +1,12 @@
+//@ assembly-output: ptx-linker
+//@ compile-flags: --crate-type cdylib -Z unstable-options -Clinker-flavor=llbc
+//@ only-nvptx64
+
+#![no_std]
+
+//@ aux-build: breakpoint-panic-handler.rs
+extern crate breakpoint_panic_handler;
+
+// Verify default target arch with ptx-linker.
+// CHECK: .target sm_30
+// CHECK: .address_size 64
diff --git a/tests/assembly-llvm/nvptx-arch-emit-asm.rs b/tests/assembly-llvm/nvptx-arch-emit-asm.rs
new file mode 100644
index 00000000000..e47f8e78e36
--- /dev/null
+++ b/tests/assembly-llvm/nvptx-arch-emit-asm.rs
@@ -0,0 +1,9 @@
+//@ assembly-output: emit-asm
+//@ compile-flags: --crate-type rlib
+//@ only-nvptx64
+
+#![no_std]
+
+// Verify default arch without ptx-linker involved.
+// CHECK: .target sm_30
+// CHECK: .address_size 64
diff --git a/tests/assembly-llvm/nvptx-arch-link-arg.rs b/tests/assembly-llvm/nvptx-arch-link-arg.rs
new file mode 100644
index 00000000000..3432e6161bf
--- /dev/null
+++ b/tests/assembly-llvm/nvptx-arch-link-arg.rs
@@ -0,0 +1,13 @@
+//@ assembly-output: ptx-linker
+//@ compile-flags: --crate-type cdylib -C link-arg=--arch=sm_60
+//@ only-nvptx64
+//@ ignore-nvptx64
+
+#![no_std]
+
+//@ aux-build: breakpoint-panic-handler.rs
+extern crate breakpoint_panic_handler;
+
+// Verify target arch override via `link-arg`.
+// CHECK: .target sm_60
+// CHECK: .address_size 64
diff --git a/tests/assembly-llvm/nvptx-arch-target-cpu.rs b/tests/assembly-llvm/nvptx-arch-target-cpu.rs
new file mode 100644
index 00000000000..609ab297e63
--- /dev/null
+++ b/tests/assembly-llvm/nvptx-arch-target-cpu.rs
@@ -0,0 +1,12 @@
+//@ assembly-output: ptx-linker
+//@ compile-flags: --crate-type cdylib -C target-cpu=sm_50 -Z unstable-options -Clinker-flavor=llbc
+//@ only-nvptx64
+
+#![no_std]
+
+//@ aux-build: breakpoint-panic-handler.rs
+extern crate breakpoint_panic_handler;
+
+// Verify target arch override via `target-cpu`.
+// CHECK: .target sm_50
+// CHECK: .address_size 64
diff --git a/tests/assembly-llvm/nvptx-atomics.rs b/tests/assembly-llvm/nvptx-atomics.rs
new file mode 100644
index 00000000000..52b8c86d8a9
--- /dev/null
+++ b/tests/assembly-llvm/nvptx-atomics.rs
@@ -0,0 +1,86 @@
+//@ assembly-output: ptx-linker
+//@ compile-flags: --crate-type cdylib
+//@ only-nvptx64
+//@ ignore-nvptx64
+
+#![feature(abi_ptx, core_intrinsics)]
+#![no_std]
+
+use core::intrinsics::*;
+
+//@ aux-build: breakpoint-panic-handler.rs
+extern crate breakpoint_panic_handler;
+
+// Currently, LLVM NVPTX backend can only emit atomic instructions with
+// `relaxed` (PTX default) ordering. But it's also useful to make sure
+// the backend won't fail with other orders. Apparently, the backend
+// doesn't support fences as well. As a workaround `llvm.nvvm.membar.*`
+// could work, and perhaps on the long run, all the atomic operations
+// should rather be provided by `core::arch::nvptx`.
+
+// Also, PTX ISA doesn't have atomic `load`, `store` and `nand`.
+
+// FIXME(denzp): add tests for `core::sync::atomic::*`.
+
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn atomics_kernel(a: *mut u32) {
+    // CHECK: atom.global.and.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
+    // CHECK: atom.global.and.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
+    atomic_and(a, 1);
+    atomic_and_relaxed(a, 1);
+
+    // CHECK: atom.global.cas.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1, 2;
+    // CHECK: atom.global.cas.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1, 2;
+    atomic_cxchg(a, 1, 2);
+    atomic_cxchg_relaxed(a, 1, 2);
+
+    // CHECK: atom.global.max.s32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
+    // CHECK: atom.global.max.s32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
+    atomic_max(a, 1);
+    atomic_max_relaxed(a, 1);
+
+    // CHECK: atom.global.min.s32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
+    // CHECK: atom.global.min.s32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
+    atomic_min(a, 1);
+    atomic_min_relaxed(a, 1);
+
+    // CHECK: atom.global.or.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
+    // CHECK: atom.global.or.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
+    atomic_or(a, 1);
+    atomic_or_relaxed(a, 1);
+
+    // CHECK: atom.global.max.u32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
+    // CHECK: atom.global.max.u32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
+    atomic_umax(a, 1);
+    atomic_umax_relaxed(a, 1);
+
+    // CHECK: atom.global.min.u32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
+    // CHECK: atom.global.min.u32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
+    atomic_umin(a, 1);
+    atomic_umin_relaxed(a, 1);
+
+    // CHECK: atom.global.add.u32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
+    // CHECK: atom.global.add.u32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
+    atomic_xadd(a, 1);
+    atomic_xadd_relaxed(a, 1);
+
+    // CHECK: atom.global.exch.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
+    // CHECK: atom.global.exch.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
+    atomic_xchg(a, 1);
+    atomic_xchg_relaxed(a, 1);
+
+    // CHECK: atom.global.xor.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
+    // CHECK: atom.global.xor.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1;
+    atomic_xor(a, 1);
+    atomic_xor_relaxed(a, 1);
+
+    // CHECK: mov.u32 %[[sub_0_arg:r[0-9]+]], 100;
+    // CHECK: neg.s32 temp, %[[sub_0_arg]];
+    // CHECK: atom.global.add.u32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], temp;
+    atomic_xsub(a, 100);
+
+    // CHECK: mov.u32 %[[sub_1_arg:r[0-9]+]], 200;
+    // CHECK: neg.s32 temp, %[[sub_1_arg]];
+    // CHECK: atom.global.add.u32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], temp;
+    atomic_xsub_relaxed(a, 200);
+}
diff --git a/tests/assembly-llvm/nvptx-c-abi-arg-v7.rs b/tests/assembly-llvm/nvptx-c-abi-arg-v7.rs
new file mode 100644
index 00000000000..be98b167470
--- /dev/null
+++ b/tests/assembly-llvm/nvptx-c-abi-arg-v7.rs
@@ -0,0 +1,220 @@
+//@ assembly-output: ptx-linker
+//@ compile-flags: --crate-type cdylib -C target-cpu=sm_86 -Z unstable-options -Clinker-flavor=llbc
+//@ only-nvptx64
+
+// The PTX ABI stability is tied to major versions of the PTX ISA
+// These tests assume major version 7
+
+// CHECK: .version 7
+
+#![feature(abi_ptx, lang_items, no_core)]
+#![no_core]
+
+#[lang = "pointee_sized"]
+trait PointeeSized {}
+#[lang = "meta_sized"]
+trait MetaSized: PointeeSized {}
+#[lang = "sized"]
+trait Sized: MetaSized {}
+#[lang = "copy"]
+trait Copy {}
+
+#[repr(C)]
+pub struct SingleU8 {
+    f: u8,
+}
+
+#[repr(C)]
+pub struct DoubleU8 {
+    f: u8,
+    g: u8,
+}
+
+#[repr(C)]
+pub struct TripleU8 {
+    f: u8,
+    g: u8,
+    h: u8,
+}
+
+#[repr(C)]
+pub struct TripleU16 {
+    f: u16,
+    g: u16,
+    h: u16,
+}
+#[repr(C)]
+pub struct DoubleI32 {
+    f: i32,
+    g: i32,
+}
+#[repr(C)]
+pub struct TripleU32 {
+    f: u32,
+    g: u32,
+    h: u32,
+}
+#[repr(C)]
+pub struct TripleU64 {
+    f: u64,
+    g: u64,
+    h: u64,
+}
+
+#[repr(C)]
+pub struct DoubleFloat {
+    f: f32,
+    g: f32,
+}
+
+#[repr(C)]
+pub struct TripleFloat {
+    f: f32,
+    g: f32,
+    h: f32,
+}
+
+#[repr(C)]
+pub struct TripleDouble {
+    f: f64,
+    g: f64,
+    h: f64,
+}
+
+#[repr(C)]
+pub struct ManyIntegers {
+    f: u8,
+    g: u16,
+    h: u32,
+    i: u64,
+}
+
+#[repr(C)]
+pub struct ManyNumerics {
+    f: u8,
+    g: u16,
+    h: u32,
+    i: u64,
+    j: f32,
+    k: f64,
+}
+
+// CHECK: .visible .func f_u8_arg(
+// CHECK: .param .b32 f_u8_arg_param_0
+#[no_mangle]
+pub unsafe extern "C" fn f_u8_arg(_a: u8) {}
+
+// CHECK: .visible .func f_u16_arg(
+// CHECK: .param .b32 f_u16_arg_param_0
+#[no_mangle]
+pub unsafe extern "C" fn f_u16_arg(_a: u16) {}
+
+// CHECK: .visible .func f_u32_arg(
+// CHECK: .param .b32 f_u32_arg_param_0
+#[no_mangle]
+pub unsafe extern "C" fn f_u32_arg(_a: u32) {}
+
+// CHECK: .visible .func f_u64_arg(
+// CHECK: .param .b64 f_u64_arg_param_0
+#[no_mangle]
+pub unsafe extern "C" fn f_u64_arg(_a: u64) {}
+
+// CHECK: .visible .func f_u128_arg(
+// CHECK: .param .align 16 .b8 f_u128_arg_param_0[16]
+#[no_mangle]
+pub unsafe extern "C" fn f_u128_arg(_a: u128) {}
+
+// CHECK: .visible .func f_i8_arg(
+// CHECK: .param .b32 f_i8_arg_param_0
+#[no_mangle]
+pub unsafe extern "C" fn f_i8_arg(_a: i8) {}
+
+// CHECK: .visible .func f_i16_arg(
+// CHECK: .param .b32 f_i16_arg_param_0
+#[no_mangle]
+pub unsafe extern "C" fn f_i16_arg(_a: i16) {}
+
+// CHECK: .visible .func f_i32_arg(
+// CHECK: .param .b32 f_i32_arg_param_0
+#[no_mangle]
+pub unsafe extern "C" fn f_i32_arg(_a: i32) {}
+
+// CHECK: .visible .func f_i64_arg(
+// CHECK: .param .b64 f_i64_arg_param_0
+#[no_mangle]
+pub unsafe extern "C" fn f_i64_arg(_a: i64) {}
+
+// CHECK: .visible .func f_i128_arg(
+// CHECK: .param .align 16 .b8 f_i128_arg_param_0[16]
+#[no_mangle]
+pub unsafe extern "C" fn f_i128_arg(_a: i128) {}
+
+// CHECK: .visible .func f_f32_arg(
+// CHECK: .param .b32 f_f32_arg_param_0
+#[no_mangle]
+pub unsafe extern "C" fn f_f32_arg(_a: f32) {}
+
+// CHECK: .visible .func f_f64_arg(
+// CHECK: .param .b64 f_f64_arg_param_0
+#[no_mangle]
+pub unsafe extern "C" fn f_f64_arg(_a: f64) {}
+
+// CHECK: .visible .func f_single_u8_arg(
+// CHECK: .param .align 1 .b8 f_single_u8_arg_param_0[1]
+#[no_mangle]
+pub unsafe extern "C" fn f_single_u8_arg(_a: SingleU8) {}
+
+// CHECK: .visible .func f_double_u8_arg(
+// CHECK: .param .align 1 .b8 f_double_u8_arg_param_0[2]
+#[no_mangle]
+pub unsafe extern "C" fn f_double_u8_arg(_a: DoubleU8) {}
+
+// CHECK: .visible .func f_triple_u8_arg(
+// CHECK: .param .align 1 .b8 f_triple_u8_arg_param_0[3]
+#[no_mangle]
+pub unsafe extern "C" fn f_triple_u8_arg(_a: TripleU8) {}
+
+// CHECK: .visible .func f_triple_u16_arg(
+// CHECK: .param .align 2 .b8 f_triple_u16_arg_param_0[6]
+#[no_mangle]
+pub unsafe extern "C" fn f_triple_u16_arg(_a: TripleU16) {}
+
+// CHECK: .visible .func f_triple_u32_arg(
+// CHECK: .param .align 4 .b8 f_triple_u32_arg_param_0[12]
+#[no_mangle]
+pub unsafe extern "C" fn f_triple_u32_arg(_a: TripleU32) {}
+
+// CHECK: .visible .func f_double_i32_arg(
+// CHECK: .param .align 4 .b8 f_double_i32_arg_param_0[8]
+#[no_mangle]
+pub unsafe extern "C" fn f_double_i32_arg(_a: DoubleI32) {}
+
+// CHECK: .visible .func f_triple_u64_arg(
+// CHECK: .param .align 8 .b8 f_triple_u64_arg_param_0[24]
+#[no_mangle]
+pub unsafe extern "C" fn f_triple_u64_arg(_a: TripleU64) {}
+
+// CHECK: .visible .func f_many_integers_arg(
+// CHECK: .param .align 8 .b8 f_many_integers_arg_param_0[16]
+#[no_mangle]
+pub unsafe extern "C" fn f_many_integers_arg(_a: ManyIntegers) {}
+
+// CHECK: .visible .func f_double_float_arg(
+// CHECK: .param .align 4 .b8 f_double_float_arg_param_0[8]
+#[no_mangle]
+pub unsafe extern "C" fn f_double_float_arg(_a: DoubleFloat) {}
+
+// CHECK: .visible .func f_triple_float_arg(
+// CHECK: .param .align 4 .b8 f_triple_float_arg_param_0[12]
+#[no_mangle]
+pub unsafe extern "C" fn f_triple_float_arg(_a: TripleFloat) {}
+
+// CHECK: .visible .func f_triple_double_arg(
+// CHECK: .param .align 8 .b8 f_triple_double_arg_param_0[24]
+#[no_mangle]
+pub unsafe extern "C" fn f_triple_double_arg(_a: TripleDouble) {}
+
+// CHECK: .visible .func f_many_numerics_arg(
+// CHECK: .param .align 8 .b8 f_many_numerics_arg_param_0[32]
+#[no_mangle]
+pub unsafe extern "C" fn f_many_numerics_arg(_a: ManyNumerics) {}
diff --git a/tests/assembly-llvm/nvptx-c-abi-ret-v7.rs b/tests/assembly-llvm/nvptx-c-abi-ret-v7.rs
new file mode 100644
index 00000000000..c68c71c872c
--- /dev/null
+++ b/tests/assembly-llvm/nvptx-c-abi-ret-v7.rs
@@ -0,0 +1,244 @@
+//@ assembly-output: ptx-linker
+//@ compile-flags: --crate-type cdylib -C target-cpu=sm_86 -Z unstable-options -Clinker-flavor=llbc
+//@ only-nvptx64
+
+// The PTX ABI stability is tied to major versions of the PTX ISA
+// These tests assume major version 7
+
+// CHECK: .version 7
+
+#![feature(abi_ptx, lang_items, no_core)]
+#![no_core]
+
+#[lang = "pointee_sized"]
+trait PointeeSized {}
+#[lang = "meta_sized"]
+trait MetaSized: PointeeSized {}
+#[lang = "sized"]
+trait Sized: MetaSized {}
+#[lang = "copy"]
+trait Copy {}
+
+#[repr(C)]
+pub struct SingleU8 {
+    f: u8,
+}
+
+#[repr(C)]
+pub struct DoubleU8 {
+    f: u8,
+    g: u8,
+}
+
+#[repr(C)]
+pub struct TripleU8 {
+    f: u8,
+    g: u8,
+    h: u8,
+}
+
+#[repr(C)]
+pub struct TripleU16 {
+    f: u16,
+    g: u16,
+    h: u16,
+}
+#[repr(C)]
+pub struct DoubleI32 {
+    f: i32,
+    g: i32,
+}
+#[repr(C)]
+pub struct TripleU32 {
+    f: u32,
+    g: u32,
+    h: u32,
+}
+#[repr(C)]
+pub struct TripleU64 {
+    f: u64,
+    g: u64,
+    h: u64,
+}
+
+#[repr(C)]
+pub struct DoubleFloat {
+    f: f32,
+    g: f32,
+}
+
+#[repr(C)]
+pub struct TripleFloat {
+    f: f32,
+    g: f32,
+    h: f32,
+}
+
+#[repr(C)]
+pub struct TripleDouble {
+    f: f64,
+    g: f64,
+    h: f64,
+}
+
+#[repr(C)]
+pub struct ManyIntegers {
+    f: u8,
+    g: u16,
+    h: u32,
+    i: u64,
+}
+
+#[repr(C)]
+pub struct ManyNumerics {
+    f: u8,
+    g: u16,
+    h: u32,
+    i: u64,
+    j: f32,
+    k: f64,
+}
+
+// CHECK: .visible .func (.param .b32 func_retval0) f_u8_ret(
+#[no_mangle]
+pub unsafe extern "C" fn f_u8_ret() -> u8 {
+    0
+}
+
+// CHECK: .visible .func (.param .b32 func_retval0) f_u16_ret(
+#[no_mangle]
+pub unsafe extern "C" fn f_u16_ret() -> u16 {
+    1
+}
+
+// CHECK: .visible .func (.param .b32 func_retval0) f_u32_ret(
+#[no_mangle]
+pub unsafe extern "C" fn f_u32_ret() -> u32 {
+    2
+}
+
+// CHECK: .visible .func (.param .b64 func_retval0) f_u64_ret(
+#[no_mangle]
+pub unsafe extern "C" fn f_u64_ret() -> u64 {
+    3
+}
+
+// CHECK: .visible .func (.param .align 16 .b8 func_retval0[16]) f_u128_ret(
+#[no_mangle]
+pub unsafe extern "C" fn f_u128_ret() -> u128 {
+    4
+}
+
+// CHECK: .visible .func (.param .b32 func_retval0) f_i8_ret(
+#[no_mangle]
+pub unsafe extern "C" fn f_i8_ret() -> i8 {
+    5
+}
+
+// CHECK: .visible .func (.param .b32 func_retval0) f_i16_ret(
+#[no_mangle]
+pub unsafe extern "C" fn f_i16_ret() -> i16 {
+    6
+}
+
+// CHECK: .visible .func (.param .b32 func_retval0) f_i32_ret(
+#[no_mangle]
+pub unsafe extern "C" fn f_i32_ret() -> i32 {
+    7
+}
+
+// CHECK: .visible .func (.param .b64 func_retval0) f_i64_ret(
+#[no_mangle]
+pub unsafe extern "C" fn f_i64_ret() -> i64 {
+    8
+}
+
+// CHECK: .visible .func  (.param .align 16 .b8 func_retval0[16]) f_i128_ret(
+#[no_mangle]
+pub unsafe extern "C" fn f_i128_ret() -> i128 {
+    9
+}
+
+// CHECK: .visible .func (.param .b32 func_retval0) f_f32_ret(
+#[no_mangle]
+pub unsafe extern "C" fn f_f32_ret() -> f32 {
+    10.0
+}
+
+// CHECK: .visible .func (.param .b64 func_retval0) f_f64_ret(
+#[no_mangle]
+pub unsafe extern "C" fn f_f64_ret() -> f64 {
+    11.0
+}
+
+// CHECK: .visible .func (.param .align 1 .b8 func_retval0[1]) f_single_u8_ret(
+#[no_mangle]
+pub unsafe extern "C" fn f_single_u8_ret() -> SingleU8 {
+    SingleU8 { f: 12 }
+}
+
+// CHECK: .visible .func (.param .align 1 .b8 func_retval0[2]) f_double_u8_ret(
+#[no_mangle]
+pub unsafe extern "C" fn f_double_u8_ret() -> DoubleU8 {
+    DoubleU8 { f: 13, g: 14 }
+}
+
+// CHECK: .visible .func (.param .align 1 .b8 func_retval0[3]) f_triple_u8_ret(
+#[no_mangle]
+pub unsafe extern "C" fn f_triple_u8_ret() -> TripleU8 {
+    TripleU8 { f: 15, g: 16, h: 17 }
+}
+
+// CHECK: .visible .func (.param .align 2 .b8 func_retval0[6]) f_triple_u16_ret(
+#[no_mangle]
+pub unsafe extern "C" fn f_triple_u16_ret() -> TripleU16 {
+    TripleU16 { f: 18, g: 19, h: 20 }
+}
+
+// CHECK: .visible .func (.param .align 4 .b8 func_retval0[8]) f_double_i32_ret(
+#[no_mangle]
+pub unsafe extern "C" fn f_double_i32_ret() -> DoubleI32 {
+    DoubleI32 { f: 1, g: 2 }
+}
+
+// CHECK: .visible .func (.param .align 4 .b8 func_retval0[12]) f_triple_u32_ret(
+#[no_mangle]
+pub unsafe extern "C" fn f_triple_u32_ret() -> TripleU32 {
+    TripleU32 { f: 20, g: 21, h: 22 }
+}
+
+// CHECK: .visible .func (.param .align 8 .b8 func_retval0[24]) f_triple_u64_ret(
+#[no_mangle]
+pub unsafe extern "C" fn f_triple_u64_ret() -> TripleU64 {
+    TripleU64 { f: 23, g: 24, h: 25 }
+}
+
+// CHECK: .visible .func (.param .align 8 .b8 func_retval0[16]) f_many_integers_ret(
+#[no_mangle]
+pub unsafe extern "C" fn f_many_integers_ret() -> ManyIntegers {
+    ManyIntegers { f: 26, g: 27, h: 28, i: 29 }
+}
+
+// CHECK: .visible .func (.param .align 4 .b8 func_retval0[8]) f_double_float_ret(
+#[no_mangle]
+pub unsafe extern "C" fn f_double_float_ret() -> DoubleFloat {
+    DoubleFloat { f: 29.0, g: 30.0 }
+}
+
+// CHECK: .visible .func (.param .align 4 .b8 func_retval0[12]) f_triple_float_ret(
+#[no_mangle]
+pub unsafe extern "C" fn f_triple_float_ret() -> TripleFloat {
+    TripleFloat { f: 31.0, g: 32.0, h: 33.0 }
+}
+
+// CHECK: .visible .func (.param .align 8 .b8 func_retval0[24]) f_triple_double_ret(
+#[no_mangle]
+pub unsafe extern "C" fn f_triple_double_ret() -> TripleDouble {
+    TripleDouble { f: 34.0, g: 35.0, h: 36.0 }
+}
+
+// CHECK: .visible .func (.param .align 8 .b8 func_retval0[32]) f_many_numerics_ret(
+#[no_mangle]
+pub unsafe extern "C" fn f_many_numerics_ret() -> ManyNumerics {
+    ManyNumerics { f: 37, g: 38, h: 39, i: 40, j: 41.0, k: 43.0 }
+}
diff --git a/tests/assembly-llvm/nvptx-internalizing.rs b/tests/assembly-llvm/nvptx-internalizing.rs
new file mode 100644
index 00000000000..0acfd5c2443
--- /dev/null
+++ b/tests/assembly-llvm/nvptx-internalizing.rs
@@ -0,0 +1,27 @@
+//@ assembly-output: ptx-linker
+//@ compile-flags: --crate-type cdylib
+//@ only-nvptx64
+//@ ignore-nvptx64
+
+#![feature(abi_ptx)]
+#![no_std]
+
+//@ aux-build: breakpoint-panic-handler.rs
+extern crate breakpoint_panic_handler;
+
+//@ aux-build: non-inline-dependency.rs
+extern crate non_inline_dependency as dep;
+
+// Verify that no extra function declarations are present.
+// CHECK-NOT: .func
+
+// CHECK: .visible .entry top_kernel(
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn top_kernel(a: *const u32, b: *mut u32) {
+    // CHECK: add.s32 %{{r[0-9]+}}, %{{r[0-9]+}}, 5;
+    *b = *a + 5;
+}
+
+// Verify that no extra function definitions are here.
+// CHECK-NOT: .func
+// CHECK-NOT: .entry
diff --git a/tests/assembly-llvm/nvptx-kernel-abi/nvptx-kernel-args-abi-v7.rs b/tests/assembly-llvm/nvptx-kernel-abi/nvptx-kernel-args-abi-v7.rs
new file mode 100644
index 00000000000..f245b4460f2
--- /dev/null
+++ b/tests/assembly-llvm/nvptx-kernel-abi/nvptx-kernel-args-abi-v7.rs
@@ -0,0 +1,251 @@
+//@ assembly-output: ptx-linker
+//@ compile-flags: --crate-type cdylib -C target-cpu=sm_86 -Z unstable-options -Clinker-flavor=llbc
+//@ only-nvptx64
+
+// The following ABI tests are made with nvcc 11.6 does.
+//
+// The PTX ABI stability is tied to major versions of the PTX ISA
+// These tests assume major version 7
+//
+//
+// The following correspondence between types are assumed:
+// u<N> - uint<N>_t
+// i<N> - int<N>_t
+// [T, N] - std::array<T, N>
+// &T - T const*
+// &mut T - T*
+
+// CHECK: .version 7
+
+#![feature(abi_ptx, lang_items, no_core)]
+#![no_core]
+
+#[lang = "pointee_sized"]
+trait PointeeSized {}
+#[lang = "meta_sized"]
+trait MetaSized: PointeeSized {}
+#[lang = "sized"]
+trait Sized: MetaSized {}
+#[lang = "copy"]
+trait Copy {}
+
+#[repr(C)]
+pub struct SingleU8 {
+    f: u8,
+}
+
+#[repr(C)]
+pub struct DoubleU8 {
+    f: u8,
+    g: u8,
+}
+
+#[repr(C)]
+pub struct TripleU8 {
+    f: u8,
+    g: u8,
+    h: u8,
+}
+
+#[repr(C)]
+pub struct TripleU16 {
+    f: u16,
+    g: u16,
+    h: u16,
+}
+#[repr(C)]
+pub struct DoubleI32 {
+    f: i32,
+    g: i32,
+}
+#[repr(C)]
+pub struct TripleU32 {
+    f: u32,
+    g: u32,
+    h: u32,
+}
+#[repr(C)]
+pub struct TripleU64 {
+    f: u64,
+    g: u64,
+    h: u64,
+}
+
+#[repr(C)]
+pub struct DoubleFloat {
+    f: f32,
+    g: f32,
+}
+
+#[repr(C)]
+pub struct TripleFloat {
+    f: f32,
+    g: f32,
+    h: f32,
+}
+
+#[repr(C)]
+pub struct TripleDouble {
+    f: f64,
+    g: f64,
+    h: f64,
+}
+
+#[repr(C)]
+pub struct ManyIntegers {
+    f: u8,
+    g: u16,
+    h: u32,
+    i: u64,
+}
+
+#[repr(C)]
+pub struct ManyNumerics {
+    f: u8,
+    g: u16,
+    h: u32,
+    i: u64,
+    j: f32,
+    k: f64,
+}
+
+// CHECK: .visible .entry f_u8_arg(
+// CHECK: .param .u8 f_u8_arg_param_0
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn f_u8_arg(_a: u8) {}
+
+// CHECK: .visible .entry f_u16_arg(
+// CHECK: .param .u16 f_u16_arg_param_0
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn f_u16_arg(_a: u16) {}
+
+// CHECK: .visible .entry f_u32_arg(
+// CHECK: .param .u32 f_u32_arg_param_0
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn f_u32_arg(_a: u32) {}
+
+// CHECK: .visible .entry f_u64_arg(
+// CHECK: .param .u64 f_u64_arg_param_0
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn f_u64_arg(_a: u64) {}
+
+// CHECK: .visible .entry f_u128_arg(
+// CHECK: .param .align 16 .b8 f_u128_arg_param_0[16]
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn f_u128_arg(_a: u128) {}
+
+// CHECK: .visible .entry f_i8_arg(
+// CHECK: .param .u8 f_i8_arg_param_0
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn f_i8_arg(_a: i8) {}
+
+// CHECK: .visible .entry f_i16_arg(
+// CHECK: .param .u16 f_i16_arg_param_0
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn f_i16_arg(_a: i16) {}
+
+// CHECK: .visible .entry f_i32_arg(
+// CHECK: .param .u32 f_i32_arg_param_0
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn f_i32_arg(_a: i32) {}
+
+// CHECK: .visible .entry f_i64_arg(
+// CHECK: .param .u64 f_i64_arg_param_0
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn f_i64_arg(_a: i64) {}
+
+// CHECK: .visible .entry f_i128_arg(
+// CHECK: .param .align 16 .b8 f_i128_arg_param_0[16]
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn f_i128_arg(_a: i128) {}
+
+// CHECK: .visible .entry f_f32_arg(
+// CHECK: .param .f32 f_f32_arg_param_0
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn f_f32_arg(_a: f32) {}
+
+// CHECK: .visible .entry f_f64_arg(
+// CHECK: .param .f64 f_f64_arg_param_0
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn f_f64_arg(_a: f64) {}
+
+// CHECK: .visible .entry f_single_u8_arg(
+// CHECK: .param .align 1 .b8 f_single_u8_arg_param_0[1]
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn f_single_u8_arg(_a: SingleU8) {}
+
+// CHECK: .visible .entry f_double_u8_arg(
+// CHECK: .param .align 1 .b8 f_double_u8_arg_param_0[2]
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn f_double_u8_arg(_a: DoubleU8) {}
+
+// CHECK: .visible .entry f_triple_u8_arg(
+// CHECK: .param .align 1 .b8 f_triple_u8_arg_param_0[3]
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn f_triple_u8_arg(_a: TripleU8) {}
+
+// CHECK: .visible .entry f_triple_u16_arg(
+// CHECK: .param .align 2 .b8 f_triple_u16_arg_param_0[6]
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn f_triple_u16_arg(_a: TripleU16) {}
+
+// CHECK: .visible .entry f_double_i32_arg(
+// CHECK: .param .align 4 .b8 f_double_i32_arg_param_0[8]
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn f_double_i32_arg(_a: DoubleI32) {}
+
+// CHECK: .visible .entry f_triple_u32_arg(
+// CHECK: .param .align 4 .b8 f_triple_u32_arg_param_0[12]
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn f_triple_u32_arg(_a: TripleU32) {}
+
+// CHECK: .visible .entry f_triple_u64_arg(
+// CHECK: .param .align 8 .b8 f_triple_u64_arg_param_0[24]
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn f_triple_u64_arg(_a: TripleU64) {}
+
+// CHECK: .visible .entry f_many_integers_arg(
+// CHECK: .param .align 8 .b8 f_many_integers_arg_param_0[16]
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn f_many_integers_arg(_a: ManyIntegers) {}
+
+// CHECK: .visible .entry f_double_float_arg(
+// CHECK: .param .align 4 .b8 f_double_float_arg_param_0[8]
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn f_double_float_arg(_a: DoubleFloat) {}
+
+// CHECK: .visible .entry f_triple_float_arg(
+// CHECK: .param .align 4 .b8 f_triple_float_arg_param_0[12]
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn f_triple_float_arg(_a: TripleFloat) {}
+
+// CHECK: .visible .entry f_triple_double_arg(
+// CHECK: .param .align 8 .b8 f_triple_double_arg_param_0[24]
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn f_triple_double_arg(_a: TripleDouble) {}
+
+// CHECK: .visible .entry f_many_numerics_arg(
+// CHECK: .param .align 8 .b8 f_many_numerics_arg_param_0[32]
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn f_many_numerics_arg(_a: ManyNumerics) {}
+
+// CHECK: .visible .entry f_byte_array_arg(
+// CHECK: .param .align 1 .b8 f_byte_array_arg_param_0[5]
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn f_byte_array_arg(_a: [u8; 5]) {}
+
+// CHECK: .visible .entry f_float_array_arg(
+// CHECK: .param .align 4 .b8 f_float_array_arg_param_0[20]
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn f_float_array_arg(_a: [f32; 5]) {}
+
+// FIXME: u128 started to break compilation with disabled CI
+// NO_CHECK: .visible .entry f_u128_array_arg(
+// NO_CHECK: .param .align 16 .b8 f_u128_array_arg_param_0[80]
+//#[no_mangle]
+//pub unsafe extern "ptx-kernel" fn f_u128_array_arg(_a: [u128; 5]) {}
+
+// CHECK: .visible .entry f_u32_slice_arg(
+// CHECK: .param .align 8 .b8 f_u32_slice_arg_param_0[16]
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn f_u32_slice_arg(_a: &[u32]) {}
diff --git a/tests/assembly-llvm/nvptx-linking-binary.rs b/tests/assembly-llvm/nvptx-linking-binary.rs
new file mode 100644
index 00000000000..3b50b472ab1
--- /dev/null
+++ b/tests/assembly-llvm/nvptx-linking-binary.rs
@@ -0,0 +1,40 @@
+//@ assembly-output: ptx-linker
+//@ compile-flags: --crate-type bin
+//@ only-nvptx64
+//@ ignore-nvptx64
+
+#![feature(abi_ptx)]
+#![no_main]
+#![no_std]
+
+//@ aux-build: breakpoint-panic-handler.rs
+extern crate breakpoint_panic_handler;
+
+//@ aux-build: non-inline-dependency.rs
+extern crate non_inline_dependency as dep;
+
+// Make sure declarations are there.
+// CHECK: .func (.param .b32 func_retval0) wrapping_external_fn
+// CHECK: .func (.param .b32 func_retval0) panicking_external_fn
+
+// CHECK-LABEL: .visible .entry top_kernel(
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn top_kernel(a: *const u32, b: *mut u32) {
+    // CHECK:      call.uni (retval0),
+    // CHECK-NEXT: wrapping_external_fn
+    // CHECK:      ld.param.b32 %[[LHS:r[0-9]+]], [retval0+0];
+    let lhs = dep::wrapping_external_fn(*a);
+
+    // CHECK:      call.uni (retval0),
+    // CHECK-NEXT: panicking_external_fn
+    // CHECK:      ld.param.b32 %[[RHS:r[0-9]+]], [retval0+0];
+    let rhs = dep::panicking_external_fn(*a);
+
+    // CHECK: add.s32 %[[RES:r[0-9]+]], %[[RHS]], %[[LHS]];
+    // CHECK: st.global.u32 [%{{rd[0-9]+}}], %[[RES]];
+    *b = lhs + rhs;
+}
+
+// Verify that external function bodies are available.
+// CHECK: .func (.param .b32 func_retval0) wrapping_external_fn
+// CHECK: .func (.param .b32 func_retval0) panicking_external_fn
diff --git a/tests/assembly-llvm/nvptx-linking-cdylib.rs b/tests/assembly-llvm/nvptx-linking-cdylib.rs
new file mode 100644
index 00000000000..9742e26fb31
--- /dev/null
+++ b/tests/assembly-llvm/nvptx-linking-cdylib.rs
@@ -0,0 +1,39 @@
+//@ assembly-output: ptx-linker
+//@ compile-flags: --crate-type cdylib
+//@ only-nvptx64
+//@ ignore-nvptx64
+
+#![feature(abi_ptx)]
+#![no_std]
+
+//@ aux-build: breakpoint-panic-handler.rs
+extern crate breakpoint_panic_handler;
+
+//@ aux-build: non-inline-dependency.rs
+extern crate non_inline_dependency as dep;
+
+// Make sure declarations are there.
+// CHECK: .func (.param .b32 func_retval0) wrapping_external_fn
+// CHECK: .func (.param .b32 func_retval0) panicking_external_fn
+
+// CHECK-LABEL: .visible .entry top_kernel(
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn top_kernel(a: *const u32, b: *mut u32) {
+    // CHECK:      call.uni (retval0),
+    // CHECK-NEXT: wrapping_external_fn
+    // CHECK:      ld.param.b32 %[[LHS:r[0-9]+]], [retval0+0];
+    let lhs = dep::wrapping_external_fn(*a);
+
+    // CHECK:      call.uni (retval0),
+    // CHECK-NEXT: panicking_external_fn
+    // CHECK:      ld.param.b32 %[[RHS:r[0-9]+]], [retval0+0];
+    let rhs = dep::panicking_external_fn(*a);
+
+    // CHECK: add.s32 %[[RES:r[0-9]+]], %[[RHS]], %[[LHS]];
+    // CHECK: st.global.u32 [%{{rd[0-9]+}}], %[[RES]];
+    *b = lhs + rhs;
+}
+
+// Verify that external function bodies are available.
+// CHECK: .func (.param .b32 func_retval0) wrapping_external_fn
+// CHECK: .func (.param .b32 func_retval0) panicking_external_fn
diff --git a/tests/assembly-llvm/nvptx-safe-naming.rs b/tests/assembly-llvm/nvptx-safe-naming.rs
new file mode 100644
index 00000000000..d7b46aadd9c
--- /dev/null
+++ b/tests/assembly-llvm/nvptx-safe-naming.rs
@@ -0,0 +1,37 @@
+//@ assembly-output: ptx-linker
+//@ compile-flags: --crate-type cdylib -Z unstable-options -Clinker-flavor=llbc
+//@ only-nvptx64
+
+#![feature(abi_ptx)]
+#![no_std]
+
+//@ aux-build: breakpoint-panic-handler.rs
+extern crate breakpoint_panic_handler;
+
+// Verify function name doesn't contain unacceaptable characters.
+// CHECK: .func (.param .b32 func_retval0) [[IMPL_FN:[a-zA-Z0-9$_]+square[a-zA-Z0-9$_]+]]
+
+// CHECK-LABEL: .visible .entry top_kernel(
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn top_kernel(a: *const u32, b: *mut u32) {
+    // CHECK:      call.uni (retval0),
+    // CHECK-NEXT: [[IMPL_FN]]
+    *b = deep::private::MyStruct::new(*a).square();
+}
+
+pub mod deep {
+    pub mod private {
+        pub struct MyStruct<T>(T);
+
+        impl MyStruct<u32> {
+            pub fn new(a: u32) -> Self {
+                MyStruct(a)
+            }
+
+            #[inline(never)]
+            pub fn square(&self) -> u32 {
+                self.0.wrapping_mul(self.0)
+            }
+        }
+    }
+}
diff --git a/tests/assembly-llvm/panic-no-unwind-no-uwtable.rs b/tests/assembly-llvm/panic-no-unwind-no-uwtable.rs
new file mode 100644
index 00000000000..b51b173e961
--- /dev/null
+++ b/tests/assembly-llvm/panic-no-unwind-no-uwtable.rs
@@ -0,0 +1,8 @@
+//@ assembly-output: emit-asm
+//@ only-x86_64-unknown-linux-gnu
+//@ compile-flags: -C panic=unwind -C force-unwind-tables=n -Copt-level=3
+
+#![crate_type = "lib"]
+
+// CHECK-NOT: .cfi_startproc
+pub fn foo() {}
diff --git a/tests/assembly-llvm/panic-unwind-no-uwtable.rs b/tests/assembly-llvm/panic-unwind-no-uwtable.rs
new file mode 100644
index 00000000000..181656a8987
--- /dev/null
+++ b/tests/assembly-llvm/panic-unwind-no-uwtable.rs
@@ -0,0 +1,12 @@
+//@ assembly-output: emit-asm
+//@ only-x86_64-unknown-linux-gnu
+//@ compile-flags: -C panic=unwind -C force-unwind-tables=n
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: foo:
+// CHECK: .cfi_startproc
+#[no_mangle]
+fn foo() {
+    panic!();
+}
diff --git a/tests/assembly-llvm/pic-relocation-model.rs b/tests/assembly-llvm/pic-relocation-model.rs
new file mode 100644
index 00000000000..15a8723f756
--- /dev/null
+++ b/tests/assembly-llvm/pic-relocation-model.rs
@@ -0,0 +1,31 @@
+//@ add-core-stubs
+//@ revisions: x64
+//@ assembly-output: emit-asm
+//@ [x64] compile-flags: --target x86_64-unknown-linux-gnu -Crelocation-model=pic
+//@ [x64] needs-llvm-components: x86
+
+#![feature(no_core, lang_items)]
+#![no_core]
+#![crate_type = "rlib"]
+
+extern crate minicore;
+use minicore::*;
+
+// CHECK-LABEL: call_other_fn:
+// CHECK:       {{(jmpq|callq)}} *other_fn@GOTPCREL(%rip)
+#[no_mangle]
+pub fn call_other_fn() -> u8 {
+    unsafe { other_fn() }
+}
+
+// CHECK-LABEL: other_fn:
+// CHECK:       {{(jmpq|callq)}} *foreign_fn@GOTPCREL(%rip)
+#[no_mangle]
+#[inline(never)]
+pub fn other_fn() -> u8 {
+    unsafe { foreign_fn() }
+}
+
+extern "C" {
+    fn foreign_fn() -> u8;
+}
diff --git a/tests/assembly-llvm/pie-relocation-model.rs b/tests/assembly-llvm/pie-relocation-model.rs
new file mode 100644
index 00000000000..cbe0001041e
--- /dev/null
+++ b/tests/assembly-llvm/pie-relocation-model.rs
@@ -0,0 +1,34 @@
+//@ add-core-stubs
+//@ revisions: x64
+//@ assembly-output: emit-asm
+//@ [x64] compile-flags: --target x86_64-unknown-linux-gnu -Crelocation-model=pie
+//@ [x64] needs-llvm-components: x86
+
+#![feature(no_core, lang_items)]
+#![no_core]
+#![crate_type = "rlib"]
+
+extern crate minicore;
+use minicore::*;
+
+// CHECK-LABEL: call_other_fn:
+// With PIE local functions are called "directly".
+// CHECK:       {{(jmp|callq)}} other_fn
+#[no_mangle]
+pub fn call_other_fn() -> u8 {
+    unsafe { other_fn() }
+}
+
+// CHECK-LABEL: other_fn:
+// External functions are still called through GOT, since we don't know if the symbol
+// is defined in the binary or in the shared library.
+// CHECK:       {{(jmpq|callq)}} *foreign_fn@GOTPCREL(%rip)
+#[no_mangle]
+#[inline(never)]
+pub fn other_fn() -> u8 {
+    unsafe { foreign_fn() }
+}
+
+extern "C" {
+    fn foreign_fn() -> u8;
+}
diff --git a/tests/assembly-llvm/powerpc64-struct-abi.rs b/tests/assembly-llvm/powerpc64-struct-abi.rs
new file mode 100644
index 00000000000..ee4965deb4f
--- /dev/null
+++ b/tests/assembly-llvm/powerpc64-struct-abi.rs
@@ -0,0 +1,156 @@
+//@ add-core-stubs
+//@ revisions: elfv1-be elfv2-be elfv2-le aix
+//@ assembly-output: emit-asm
+//@ compile-flags: -Copt-level=3
+//@[elfv1-be] compile-flags: --target powerpc64-unknown-linux-gnu
+//@[elfv1-be] needs-llvm-components: powerpc
+//@[elfv2-be] compile-flags: --target powerpc64-unknown-linux-musl
+//@[elfv2-be] needs-llvm-components: powerpc
+//@[elfv2-le] compile-flags: --target powerpc64le-unknown-linux-gnu -C target-cpu=pwr8
+//@[elfv2-le] needs-llvm-components: powerpc
+//@[aix] compile-flags: --target powerpc64-ibm-aix
+//@[aix] needs-llvm-components: powerpc
+//@[elfv1-be] filecheck-flags: --check-prefix be
+//@[elfv2-be] filecheck-flags: --check-prefix be
+//@[elfv1-be] filecheck-flags: --check-prefix elf
+//@[elfv2-be] filecheck-flags: --check-prefix elf
+//@[elfv2-le] filecheck-flags: --check-prefix elf
+
+#![feature(no_core, lang_items)]
+#![no_std]
+#![no_core]
+#![crate_type = "lib"]
+
+extern crate minicore;
+use minicore::*;
+
+impl Copy for FiveU32s {}
+impl Copy for FiveU16s {}
+impl Copy for ThreeU8s {}
+
+#[repr(C)]
+struct FiveU32s(u32, u32, u32, u32, u32);
+
+#[repr(C)]
+struct FiveU16s(u16, u16, u16, u16, u16);
+
+#[repr(C)]
+struct ThreeU8s(u8, u8, u8);
+
+// CHECK-LABEL: read_large
+// aix: lwz [[REG1:.*]], 16(4)
+// aix-NEXT: lxv{{d2x|w4x}} 0, 0, 4
+// aix-NEXT: stw [[REG1]], 16(3)
+// aix-NEXT: stxv{{d2x|w4x}} 0, 0, 3
+// be: lwz [[REG1:.*]], 16(4)
+// be-NEXT: stw [[REG1]], 16(3)
+// be-NEXT: ld [[REG2:.*]], 8(4)
+// be-NEXT: ld [[REG3:.*]], 0(4)
+// be-NEXT: std [[REG2]], 8(3)
+// be-NEXT: std [[REG3]], 0(3)
+// elfv2-le: lxvd2x [[REG1:.*]], 0, 4
+// elfv2-le-NEXT: lwz [[REG2:.*]], 16(4)
+// elfv2-le-NEXT: stw [[REG2]], 16(3)
+// elfv2-le-NEXT: stxvd2x [[REG1]], 0, 3
+// CHECK-NEXT: blr
+#[no_mangle]
+extern "C" fn read_large(x: &FiveU32s) -> FiveU32s {
+    *x
+}
+
+// CHECK-LABEL: read_medium
+// aix: lhz [[REG1:.*]], 8(4)
+// aix-NEXT: ld [[REG2:.*]], 0(4)
+// aix-NEXT: sth [[REG1]], 8(3)
+// aix-NEXT: std [[REG2]], 0(3)
+// elfv1-be: lhz [[REG1:.*]], 8(4)
+// elfv1-be-NEXT: ld [[REG2:.*]], 0(4)
+// elfv1-be-NEXT: sth [[REG1]], 8(3)
+// elfv1-be-NEXT: std [[REG2]], 0(3)
+// elfv2-be: lhz [[REG1:.*]], 8(3)
+// elfv2-be-NEXT: ld 3, 0(3)
+// elfv2-be-NEXT: sldi 4, [[REG1]], 48
+// elfv2-le: ld [[REG1:.*]], 0(3)
+// elfv2-le-NEXT: lhz 4, 8(3)
+// elfv2-le-NEXT: mr 3, [[REG1]]
+// CHECK-NEXT: blr
+#[no_mangle]
+extern "C" fn read_medium(x: &FiveU16s) -> FiveU16s {
+    *x
+}
+
+// CHECK-LABEL: read_small
+// aix: lbz [[REG1:.*]], 2(4)
+// aix-NEXT: lhz [[REG2:.*]], 0(4)
+// aix-NEXT: stb [[REG1]], 2(3)
+// aix-NEXT: sth [[REG2]], 0(3)
+// elfv1-be: lbz [[REG1:.*]], 2(4)
+// elfv1-be-NEXT: lhz [[REG2:.*]], 0(4)
+// elfv1-be-NEXT: stb [[REG1]], 2(3)
+// elfv1-be-NEXT: sth [[REG2]], 0(3)
+// elfv2-be: lhz [[REG1:.*]], 0(3)
+// elfv2-be-NEXT: lbz 3, 2(3)
+// elfv2-be-NEXT: rldimi 3, [[REG1]], 8, 0
+// elfv2-le: lbz [[REG1:.*]], 2(3)
+// elfv2-le-NEXT: lhz 3, 0(3)
+// elfv2-le-NEXT: rldimi 3, [[REG1]], 16, 0
+// CHECK-NEXT: blr
+#[no_mangle]
+extern "C" fn read_small(x: &ThreeU8s) -> ThreeU8s {
+    *x
+}
+
+// CHECK-LABEL: write_large
+// aix: std 3, 48(1)
+// aix-NEXT: rldicl [[REG1:.*]], 5, 32, 32
+// aix-NEXT: std 5, 64(1)
+// aix-NEXT: std 4, 56(1)
+// aix-NEXT: stw [[REG1]], 16(6)
+// aix-NEXT: addi [[REG2:.*]], 1, 48
+// aix-NEXT: lxv{{d2x|w4x}} 0, 0, [[REG2]]
+// aix-NEXT: stxv{{d2x|w4x}} 0, 0, 6
+// elf: std 3, 0(6)
+// be-NEXT: rldicl [[REG1:.*]], 5, 32, 32
+// elf-NEXT: std 4, 8(6)
+// be-NEXT: stw [[REG1]], 16(6)
+// elfv2-le-NEXT: stw 5, 16(6)
+// CHECK-NEXT: blr
+#[no_mangle]
+extern "C" fn write_large(x: FiveU32s, dest: &mut FiveU32s) {
+    *dest = x;
+}
+
+// CHECK-LABEL: write_medium
+// aix: std 4, 56(1)
+// aix-NEXT: rldicl [[REG1:.*]], 4, 16, 48
+// aix-NEXT: std 3, 48(1)
+// aix-NEXT: std 3, 0(5)
+// aix-NEXT: sth [[REG1]], 8(5)
+// elf: std 3, 0(5)
+// be-NEXT: rldicl [[REG1:.*]], 4, 16, 48
+// be-NEXT: sth [[REG1]], 8(5)
+// elfv2-le-NEXT: sth 4, 8(5)
+// CHECK-NEXT: blr
+#[no_mangle]
+extern "C" fn write_medium(x: FiveU16s, dest: &mut FiveU16s) {
+    *dest = x;
+}
+
+// CHECK-LABEL: write_small
+// aix: std 3, 48(1)
+// aix-NEXT: rldicl [[REG1:.*]], 3, 16, 48
+// aix-NEXT: sth 3, 0(4)
+// aix-NEXT: lbz 3, 50(1)
+// aix-NEXT: stb [[REG1]], 2(4)
+// be: stb 3, 2(4)
+// be-NEXT: srwi [[REG1:.*]], 3, 8
+// be-NEXT: sth [[REG1]], 0(4)
+// The order these instructions are emitted in changed in LLVM 18.
+// elfv2-le-DAG: sth 3, 0(4)
+// elfv2-le-DAG: srwi [[REG1:.*]], 3, 16
+// elfv2-le-NEXT: stb [[REG1]], 2(4)
+// CHECK-NEXT: blr
+#[no_mangle]
+extern "C" fn write_small(x: ThreeU8s, dest: &mut ThreeU8s) {
+    *dest = x;
+}
diff --git a/tests/assembly-llvm/riscv-float-struct-abi.rs b/tests/assembly-llvm/riscv-float-struct-abi.rs
new file mode 100644
index 00000000000..5d9ac9d70b8
--- /dev/null
+++ b/tests/assembly-llvm/riscv-float-struct-abi.rs
@@ -0,0 +1,177 @@
+//@ add-core-stubs
+//@ assembly-output: emit-asm
+//@ compile-flags: -Copt-level=3 --target riscv64gc-unknown-linux-gnu
+//@ needs-llvm-components: riscv
+
+#![feature(no_core, lang_items)]
+#![no_std]
+#![no_core]
+#![crate_type = "lib"]
+
+extern crate minicore;
+use minicore::*;
+
+#[repr(C, align(64))]
+struct Aligned(f64);
+
+#[repr(C)]
+struct Padded(u8, Aligned);
+
+#[repr(C, packed)]
+struct Packed(u8, f32);
+
+impl Copy for Aligned {}
+impl Copy for Padded {}
+impl Copy for Packed {}
+
+extern "C" {
+    fn take_padded(x: Padded);
+    fn get_padded() -> Padded;
+    fn take_packed(x: Packed);
+    fn get_packed() -> Packed;
+}
+
+// CHECK-LABEL: pass_padded
+#[unsafe(no_mangle)]
+extern "C" fn pass_padded(out: &mut Padded, x: Padded) {
+    // CHECK: sb a1, 0(a0)
+    // CHECK-NEXT: fsd fa0, 64(a0)
+    // CHECK-NEXT: ret
+    *out = x;
+}
+
+// CHECK-LABEL: ret_padded
+#[unsafe(no_mangle)]
+extern "C" fn ret_padded(x: &Padded) -> Padded {
+    // CHECK: fld fa0, 64(a0)
+    // CHECK-NEXT: lbu a0, 0(a0)
+    // CHECK-NEXT: ret
+    *x
+}
+
+#[unsafe(no_mangle)]
+extern "C" fn call_padded(x: &Padded) {
+    // CHECK: fld fa0, 64(a0)
+    // CHECK-NEXT: lbu a0, 0(a0)
+    // CHECK-NEXT: tail take_padded
+    unsafe {
+        take_padded(*x);
+    }
+}
+
+#[unsafe(no_mangle)]
+extern "C" fn receive_padded(out: &mut Padded) {
+    // CHECK: addi sp, sp, -16
+    // CHECK-NEXT: .cfi_def_cfa_offset 16
+    // CHECK-NEXT: sd ra, [[#%d,RA_SPILL:]](sp)
+    // CHECK-NEXT: sd [[TEMP:.*]], [[#%d,TEMP_SPILL:]](sp)
+    // CHECK-NEXT: .cfi_offset ra, [[#%d,RA_SPILL - 16]]
+    // CHECK-NEXT: .cfi_offset [[TEMP]], [[#%d,TEMP_SPILL - 16]]
+    // CHECK-NEXT: mv [[TEMP]], a0
+    // CHECK-NEXT: call get_padded
+    // CHECK-NEXT: sb a0, 0([[TEMP]])
+    // CHECK-NEXT: fsd fa0, 64([[TEMP]])
+    // CHECK-NEXT: ld ra, [[#%d,RA_SPILL]](sp)
+    // CHECK-NEXT: ld [[TEMP]], [[#%d,TEMP_SPILL]](sp)
+    // CHECK: addi sp, sp, 16
+    // CHECK: ret
+    unsafe {
+        *out = get_padded();
+    }
+}
+
+// CHECK-LABEL: pass_packed
+#[unsafe(no_mangle)]
+extern "C" fn pass_packed(out: &mut Packed, x: Packed) {
+    // CHECK: addi sp, sp, -16
+    // CHECK-NEXT: .cfi_def_cfa_offset 16
+    // CHECK-NEXT: sb a1, 0(a0)
+    // CHECK-NEXT: fsw fa0, 8(sp)
+    // CHECK-NEXT: lw [[VALUE:.*]], 8(sp)
+    // CHECK-DAG: srli [[BYTE4:.*]], [[VALUE]], 24
+    // CHECK-DAG: srli [[BYTE3:.*]], [[VALUE]], 16
+    // CHECK-DAG: srli [[BYTE2:.*]], [[VALUE]], 8
+    // CHECK-DAG: sb [[VALUE]], 1(a0)
+    // CHECK-DAG: sb [[BYTE2]], 2(a0)
+    // CHECK-DAG: sb [[BYTE3]], 3(a0)
+    // CHECK-DAG: sb [[BYTE4]], 4(a0)
+    // CHECK-NEXT: addi sp, sp, 16
+    // CHECK: ret
+    *out = x;
+}
+
+// CHECK-LABEL: ret_packed
+#[unsafe(no_mangle)]
+extern "C" fn ret_packed(x: &Packed) -> Packed {
+    // CHECK: addi sp, sp, -16
+    // CHECK-NEXT: .cfi_def_cfa_offset 16
+    // CHECK-NEXT: lbu [[BYTE2:.*]], 2(a0)
+    // CHECK-NEXT: lbu [[BYTE1:.*]], 1(a0)
+    // CHECK-NEXT: lbu [[BYTE3:.*]], 3(a0)
+    // CHECK-NEXT: lbu [[BYTE4:.*]], 4(a0)
+    // CHECK-NEXT: slli [[SHIFTED2:.*]], [[BYTE2]], 8
+    // CHECK-NEXT: or [[BYTE12:.*]], [[SHIFTED2]], [[BYTE1]]
+    // CHECK-NEXT: slli [[SHIFTED3:.*]], [[BYTE3]], 16
+    // CHECK-NEXT: slli [[SHIFTED4:.*]], [[BYTE4]], 24
+    // CHECK-NEXT: or [[BYTE34:.*]], [[SHIFTED3]], [[SHIFTED4]]
+    // CHECK-NEXT: or [[VALUE:.*]], [[BYTE12]], [[BYTE34]]
+    // CHECK-NEXT: sw [[VALUE]], 8(sp)
+    // CHECK-NEXT: flw fa0, 8(sp)
+    // CHECK-NEXT: lbu a0, 0(a0)
+    // CHECK-NEXT: addi sp, sp, 16
+    // CHECK: ret
+    *x
+}
+
+#[unsafe(no_mangle)]
+extern "C" fn call_packed(x: &Packed) {
+    // CHECK: addi sp, sp, -16
+    // CHECK-NEXT: .cfi_def_cfa_offset 16
+    // CHECK-NEXT: lbu [[BYTE2:.*]], 2(a0)
+    // CHECK-NEXT: lbu [[BYTE1:.*]], 1(a0)
+    // CHECK-NEXT: lbu [[BYTE3:.*]], 3(a0)
+    // CHECK-NEXT: lbu [[BYTE4:.*]], 4(a0)
+    // CHECK-NEXT: slli [[SHIFTED2:.*]], [[BYTE2]], 8
+    // CHECK-NEXT: or [[BYTE12:.*]], [[SHIFTED2]], [[BYTE1]]
+    // CHECK-NEXT: slli [[SHIFTED3:.*]], [[BYTE3]], 16
+    // CHECK-NEXT: slli [[SHIFTED4:.*]], [[BYTE4]], 24
+    // CHECK-NEXT: or [[BYTE34:.*]], [[SHIFTED3]], [[SHIFTED4]]
+    // CHECK-NEXT: or [[VALUE:.*]], [[BYTE12]], [[BYTE34]]
+    // CHECK-NEXT: sw [[VALUE]], 8(sp)
+    // CHECK-NEXT: flw fa0, 8(sp)
+    // CHECK-NEXT: lbu a0, 0(a0)
+    // CHECK-NEXT: addi sp, sp, 16
+    // CHECK: tail take_packed
+    unsafe {
+        take_packed(*x);
+    }
+}
+
+#[unsafe(no_mangle)]
+extern "C" fn receive_packed(out: &mut Packed) {
+    // CHECK: addi sp, sp, -32
+    // CHECK-NEXT: .cfi_def_cfa_offset 32
+    // CHECK-NEXT: sd ra, [[#%d,RA_SPILL:]](sp)
+    // CHECK-NEXT: sd [[TEMP:.*]], [[#%d,TEMP_SPILL:]](sp)
+    // CHECK-NEXT: .cfi_offset ra, [[#%d,RA_SPILL - 32]]
+    // CHECK-NEXT: .cfi_offset [[TEMP]], [[#%d,TEMP_SPILL - 32]]
+    // CHECK-NEXT: mv [[TEMP]], a0
+    // CHECK-NEXT: call get_packed
+    // CHECK-NEXT: sb a0, 0([[TEMP]])
+    // CHECK-NEXT: fsw fa0, [[FLOAT_SPILL:.*]](sp)
+    // CHECK-NEXT: lw [[VALUE:.*]], [[FLOAT_SPILL]](sp)
+    // CHECK-DAG: srli [[BYTE4:.*]], [[VALUE]], 24
+    // CHECK-DAG: srli [[BYTE3:.*]], [[VALUE]], 16
+    // CHECK-DAG: srli [[BYTE2:.*]], [[VALUE]], 8
+    // CHECK-DAG: sb [[VALUE]], 1([[TEMP]])
+    // CHECK-DAG: sb [[BYTE2]], 2([[TEMP]])
+    // CHECK-DAG: sb [[BYTE3]], 3([[TEMP]])
+    // CHECK-DAG: sb [[BYTE4]], 4([[TEMP]])
+    // CHECK-NEXT: ld ra, [[#%d,RA_SPILL]](sp)
+    // CHECK-NEXT: ld [[TEMP]], [[#%d,TEMP_SPILL]](sp)
+    // CHECK: addi sp, sp, 32
+    // CHECK: ret
+    unsafe {
+        *out = get_packed();
+    }
+}
diff --git a/tests/assembly-llvm/riscv-soft-abi-with-float-features.rs b/tests/assembly-llvm/riscv-soft-abi-with-float-features.rs
new file mode 100644
index 00000000000..72cbd3841c1
--- /dev/null
+++ b/tests/assembly-llvm/riscv-soft-abi-with-float-features.rs
@@ -0,0 +1,45 @@
+//@ add-core-stubs
+//@ assembly-output: emit-asm
+//@ compile-flags: --target riscv64imac-unknown-none-elf -Ctarget-feature=+f,+d
+//@ needs-llvm-components: riscv
+//@ revisions: LLVM-PRE-20 LLVM-POST-20
+//@ [LLVM-PRE-20] max-llvm-major-version: 19
+//@ [LLVM-POST-20] min-llvm-version: 20
+
+#![feature(no_core, lang_items, f16)]
+#![crate_type = "lib"]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
+
+// This test checks that the floats are all returned in `a0` as required by the `lp64` ABI.
+
+// CHECK-LABEL: read_f16
+#[no_mangle]
+pub extern "C" fn read_f16(x: &f16) -> f16 {
+    // CHECK: lh a0, 0(a0)
+    // CHECK-NEXT: lui a1, 1048560
+    // CHECK-NEXT: or a0, a0, a1
+    // CHECK-NEXT: ret
+    *x
+}
+
+// CHECK-LABEL: read_f32
+#[no_mangle]
+pub extern "C" fn read_f32(x: &f32) -> f32 {
+    // LLVM-PRE-20: flw fa5, 0(a0)
+    // LLVM-PRE-20-NEXT: fmv.x.w a0, fa5
+    // LLVM-PRE-20-NEXT: ret
+    // LLVM-POST-20: lw a0, 0(a0)
+    // LLVM-POST-20-NEXT: ret
+    *x
+}
+
+// CHECK-LABEL: read_f64
+#[no_mangle]
+pub extern "C" fn read_f64(x: &f64) -> f64 {
+    // CHECK: ld a0, 0(a0)
+    // CHECK-NEXT: ret
+    *x
+}
diff --git a/tests/assembly-llvm/rust-abi-arg-attr.rs b/tests/assembly-llvm/rust-abi-arg-attr.rs
new file mode 100644
index 00000000000..4f3673ccfc3
--- /dev/null
+++ b/tests/assembly-llvm/rust-abi-arg-attr.rs
@@ -0,0 +1,110 @@
+//@ assembly-output: emit-asm
+//@ revisions: riscv64 riscv64-zbb loongarch64
+//@ compile-flags: -C opt-level=3
+//@ [riscv64] compile-flags: --target riscv64gc-unknown-linux-gnu
+//@ [riscv64] needs-llvm-components: riscv
+//@ [riscv64-zbb] compile-flags: --target riscv64gc-unknown-linux-gnu
+//@ [riscv64-zbb] compile-flags: -C target-feature=+zbb
+//@ [riscv64-zbb] needs-llvm-components: riscv
+//@ [loongarch64] compile-flags: --target loongarch64-unknown-linux-gnu
+//@ [loongarch64] needs-llvm-components: loongarch
+
+#![feature(no_core, lang_items, intrinsics, rustc_attrs)]
+#![crate_type = "lib"]
+#![no_std]
+#![no_core]
+// FIXME: Migrate these code after PR #130693 is landed.
+
+#[lang = "pointee_sized"]
+pub trait PointeeSized {}
+
+#[lang = "meta_sized"]
+pub trait MetaSized: PointeeSized {}
+
+#[lang = "sized"]
+pub trait Sized: MetaSized {}
+
+#[lang = "copy"]
+trait Copy {}
+
+impl Copy for i8 {}
+impl Copy for u32 {}
+impl Copy for i32 {}
+
+#[lang = "neg"]
+trait Neg {
+    type Output;
+
+    fn neg(self) -> Self::Output;
+}
+
+impl Neg for i8 {
+    type Output = i8;
+
+    fn neg(self) -> Self::Output {
+        -self
+    }
+}
+
+#[lang = "Ordering"]
+#[repr(i8)]
+enum Ordering {
+    Less = -1,
+    Equal = 0,
+    Greater = 1,
+}
+
+#[rustc_intrinsic]
+fn three_way_compare<T: Copy>(lhs: T, rhs: T) -> Ordering;
+
+// ^^^^^ core
+
+// Reimplementation of function `{integer}::max`.
+macro_rules! max {
+    ($a:expr, $b:expr) => {
+        match three_way_compare($a, $b) {
+            Ordering::Less | Ordering::Equal => $b,
+            Ordering::Greater => $a,
+        }
+    };
+}
+
+#[no_mangle]
+// CHECK-LABEL: issue_114508_u32:
+pub fn issue_114508_u32(a: u32, b: u32) -> u32 {
+    // CHECK-NEXT:       .cfi_startproc
+
+    // riscv64-NEXT:     bltu a1, a0, .[[RET:.+]]
+    // riscv64-NEXT:     mv a0, a1
+    // riscv64-NEXT: .[[RET]]:
+
+    // riscv64-zbb-NEXT: maxu a0, a0, a1
+
+    // loongarch64-NEXT: sltu $a2, $a1, $a0
+    // loongarch64-NEXT: masknez $a1, $a1, $a2
+    // loongarch64-NEXT: maskeqz $a0, $a0, $a2
+    // loongarch64-NEXT: or $a0, $a0, $a1
+
+    // CHECK-NEXT:       ret
+    max!(a, b)
+}
+
+#[no_mangle]
+// CHECK-LABEL: issue_114508_i32:
+pub fn issue_114508_i32(a: i32, b: i32) -> i32 {
+    // CHECK-NEXT:       .cfi_startproc
+
+    // riscv64-NEXT:     blt a1, a0, .[[RET:.+]]
+    // riscv64-NEXT:     mv a0, a1
+    // riscv64-NEXT: .[[RET]]:
+
+    // riscv64-zbb-NEXT: max a0, a0, a1
+
+    // loongarch64-NEXT: slt $a2, $a1, $a0
+    // loongarch64-NEXT: masknez $a1, $a1, $a2
+    // loongarch64-NEXT: maskeqz $a0, $a0, $a2
+    // loongarch64-NEXT: or $a0, $a0, $a1
+
+    // CHECK-NEXT:       ret
+    max!(a, b)
+}
diff --git a/tests/assembly-llvm/s390x-backchain-toggle.rs b/tests/assembly-llvm/s390x-backchain-toggle.rs
new file mode 100644
index 00000000000..9bae15b7d11
--- /dev/null
+++ b/tests/assembly-llvm/s390x-backchain-toggle.rs
@@ -0,0 +1,50 @@
+//@ add-core-stubs
+//@ revisions: enable-backchain disable-backchain default-backchain
+//@ assembly-output: emit-asm
+//@ compile-flags: -Copt-level=3 --crate-type=lib --target=s390x-unknown-linux-gnu
+//@ needs-llvm-components: systemz
+//@[enable-backchain] compile-flags: -Ctarget-feature=+backchain
+//@[disable-backchain] compile-flags: -Ctarget-feature=-backchain
+#![feature(no_core, lang_items)]
+#![no_std]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
+
+extern "C" {
+    fn extern_func();
+}
+
+// CHECK-LABEL: test_backchain
+#[no_mangle]
+extern "C" fn test_backchain() -> i32 {
+    // Here we try to match if backchain register is saved to the parameter area (stored in r15/sp)
+    // And also if a new parameter area (160 bytes) is allocated for the upcoming function call
+    // enable-backchain: lgr [[REG1:.*]], %r15
+    // enable-backchain-NEXT: aghi %r15, -160
+    // enable-backchain: stg [[REG1]], 0(%r15)
+    // disable-backchain: aghi %r15, -160
+    // disable-backchain-NOT: stg %r{{.*}}, 0(%r15)
+    // default-backchain: aghi %r15, -160
+    // default-backchain-NOT: stg %r{{.*}}, 0(%r15)
+    unsafe {
+        extern_func();
+    }
+    // enable-backchain-NEXT: brasl %r{{.*}}, extern_func@PLT
+    // disable-backchain: brasl %r{{.*}}, extern_func@PLT
+
+    // Make sure that the expected return value is written into %r2 (return register):
+    // enable-backchain-NEXT: lghi %r2, 1
+    // disable-backchain: lghi %r2, 0
+    // default-backchain: lghi %r2, 0
+    #[cfg(target_feature = "backchain")]
+    {
+        1
+    }
+    #[cfg(not(target_feature = "backchain"))]
+    {
+        0
+    }
+    // CHECK: br %r{{.*}}
+}
diff --git a/tests/assembly-llvm/s390x-vector-abi.rs b/tests/assembly-llvm/s390x-vector-abi.rs
new file mode 100644
index 00000000000..fcf42664034
--- /dev/null
+++ b/tests/assembly-llvm/s390x-vector-abi.rs
@@ -0,0 +1,327 @@
+//@ revisions: z10 z10_vector z13 z13_no_vector
+// ignore-tidy-linelength
+//@ assembly-output: emit-asm
+//@ compile-flags: -Copt-level=3 -Z merge-functions=disabled
+//@[z10] compile-flags: --target s390x-unknown-linux-gnu  -C target-cpu=z10 --cfg no_vector
+//@[z10] needs-llvm-components: systemz
+//@[z10_vector] compile-flags: --target s390x-unknown-linux-gnu -C target-cpu=z10 -C target-feature=+vector
+//@[z10_vector] needs-llvm-components: systemz
+//@[z13] compile-flags: --target s390x-unknown-linux-gnu -C target-cpu=z13
+//@[z13] needs-llvm-components: systemz
+//@[z13_no_vector] compile-flags: --target s390x-unknown-linux-gnu -C target-cpu=z13 -C target-feature=-vector --cfg no_vector
+//@[z13_no_vector] needs-llvm-components: systemz
+
+#![feature(no_core, lang_items, repr_simd, s390x_target_feature)]
+#![no_core]
+#![crate_type = "lib"]
+#![allow(non_camel_case_types)]
+// Cases where vector feature is disabled are rejected.
+// See tests/ui/simd-abi-checks-s390x.rs for test for them.
+
+#[lang = "pointee_sized"]
+pub trait PointeeSized {}
+
+#[lang = "meta_sized"]
+pub trait MetaSized: PointeeSized {}
+
+#[lang = "sized"]
+pub trait Sized: MetaSized {}
+#[lang = "copy"]
+pub trait Copy {}
+#[lang = "freeze"]
+pub trait Freeze {}
+
+impl<T: Copy, const N: usize> Copy for [T; N] {}
+
+#[lang = "phantom_data"]
+pub struct PhantomData<T: ?Sized>;
+impl<T: ?Sized> Copy for PhantomData<T> {}
+
+#[repr(simd)]
+pub struct i8x8([i8; 8]);
+#[repr(simd)]
+pub struct i8x16([i8; 16]);
+#[repr(simd)]
+pub struct i8x32([i8; 32]);
+#[repr(C)]
+pub struct Wrapper<T>(T);
+#[repr(C, align(16))]
+pub struct WrapperAlign16<T>(T);
+#[repr(C)]
+pub struct WrapperWithZst<T>(T, PhantomData<()>);
+#[repr(transparent)]
+pub struct TransparentWrapper<T>(T);
+
+impl Copy for i8 {}
+impl Copy for i64 {}
+impl Copy for i8x8 {}
+impl Copy for i8x16 {}
+impl Copy for i8x32 {}
+impl<T: Copy> Copy for Wrapper<T> {}
+impl<T: Copy> Copy for WrapperAlign16<T> {}
+impl<T: Copy> Copy for WrapperWithZst<T> {}
+impl<T: Copy> Copy for TransparentWrapper<T> {}
+
+// CHECK-LABEL: vector_ret_small:
+// CHECK: vlrepg %v24, 0(%r2)
+// CHECK-NEXT: br %r14
+#[cfg_attr(no_vector, target_feature(enable = "vector"))]
+#[no_mangle]
+unsafe extern "C" fn vector_ret_small(x: &i8x8) -> i8x8 {
+    *x
+}
+// CHECK-LABEL: vector_ret:
+// CHECK: vl %v24, 0(%r2), 3
+// CHECK-NEXT: br %r14
+#[cfg_attr(no_vector, target_feature(enable = "vector"))]
+#[no_mangle]
+unsafe extern "C" fn vector_ret(x: &i8x16) -> i8x16 {
+    *x
+}
+// CHECK-LABEL: vector_ret_large:
+// z10: vl %v0, 16(%r3), 4
+// z10-NEXT: vl %v1, 0(%r3), 4
+// z10-NEXT: vst %v0, 16(%r2), 4
+// z10-NEXT: vst %v1, 0(%r2), 4
+// z10-NEXT: br %r14
+// z13: vl %v0, 0(%r3), 4
+// z13-NEXT: vl %v1, 16(%r3), 4
+// z13-NEXT: vst %v1, 16(%r2), 4
+// z13-NEXT: vst %v0, 0(%r2), 4
+// z13-NEXT: br %r14
+#[cfg_attr(no_vector, target_feature(enable = "vector"))]
+#[no_mangle]
+unsafe extern "C" fn vector_ret_large(x: &i8x32) -> i8x32 {
+    *x
+}
+
+// CHECK-LABEL: vector_wrapper_ret_small:
+// CHECK: mvc 0(8,%r2), 0(%r3)
+// CHECK-NEXT: br %r14
+#[cfg_attr(no_vector, target_feature(enable = "vector"))]
+#[no_mangle]
+unsafe extern "C" fn vector_wrapper_ret_small(x: &Wrapper<i8x8>) -> Wrapper<i8x8> {
+    *x
+}
+// CHECK-LABEL: vector_wrapper_ret:
+// CHECK: mvc 0(16,%r2), 0(%r3)
+// CHECK-NEXT: br %r14
+#[cfg_attr(no_vector, target_feature(enable = "vector"))]
+#[no_mangle]
+unsafe extern "C" fn vector_wrapper_ret(x: &Wrapper<i8x16>) -> Wrapper<i8x16> {
+    *x
+}
+// CHECK-LABEL: vector_wrapper_ret_large:
+// z10: vl %v0, 16(%r3), 4
+// z10-NEXT: vl %v1, 0(%r3), 4
+// z10-NEXT: vst %v0, 16(%r2), 4
+// z10-NEXT: vst %v1, 0(%r2), 4
+// z10-NEXT: br %r14
+// z13: vl %v0, 16(%r3), 4
+// z13-NEXT: vst %v0, 16(%r2), 4
+// z13-NEXT: vl %v0, 0(%r3), 4
+// z13-NEXT: vst %v0, 0(%r2), 4
+// z13-NEXT: br %r14
+#[cfg_attr(no_vector, target_feature(enable = "vector"))]
+#[no_mangle]
+unsafe extern "C" fn vector_wrapper_ret_large(x: &Wrapper<i8x32>) -> Wrapper<i8x32> {
+    *x
+}
+
+// CHECK-LABEL: vector_wrapper_padding_ret:
+// CHECK: mvc 0(16,%r2), 0(%r3)
+// CHECK-NEXT: br %r14
+#[cfg_attr(no_vector, target_feature(enable = "vector"))]
+#[no_mangle]
+unsafe extern "C" fn vector_wrapper_padding_ret(x: &WrapperAlign16<i8x8>) -> WrapperAlign16<i8x8> {
+    *x
+}
+
+// CHECK-LABEL: vector_wrapper_with_zst_ret_small:
+// CHECK: mvc 0(8,%r2), 0(%r3)
+// CHECK-NEXT: br %r14
+#[cfg_attr(no_vector, target_feature(enable = "vector"))]
+#[no_mangle]
+unsafe extern "C" fn vector_wrapper_with_zst_ret_small(
+    x: &WrapperWithZst<i8x8>,
+) -> WrapperWithZst<i8x8> {
+    *x
+}
+// CHECK-LABEL: vector_wrapper_with_zst_ret:
+// CHECK: mvc 0(16,%r2), 0(%r3)
+// CHECK-NEXT: br %r14
+#[cfg_attr(no_vector, target_feature(enable = "vector"))]
+#[no_mangle]
+unsafe extern "C" fn vector_wrapper_with_zst_ret(
+    x: &WrapperWithZst<i8x16>,
+) -> WrapperWithZst<i8x16> {
+    *x
+}
+// CHECK-LABEL: vector_wrapper_with_zst_ret_large:
+// z10: vl %v0, 16(%r3), 4
+// z10-NEXT: vl %v1, 0(%r3), 4
+// z10-NEXT: vst %v0, 16(%r2), 4
+// z10-NEXT: vst %v1, 0(%r2), 4
+// z10-NEXT: br %r14
+// z13: vl %v0, 16(%r3), 4
+// z13-NEXT: vst %v0, 16(%r2), 4
+// z13-NEXT: vl %v0, 0(%r3), 4
+// z13-NEXT: vst %v0, 0(%r2), 4
+// z13-NEXT: br %r14
+#[cfg_attr(no_vector, target_feature(enable = "vector"))]
+#[no_mangle]
+unsafe extern "C" fn vector_wrapper_with_zst_ret_large(
+    x: &WrapperWithZst<i8x32>,
+) -> WrapperWithZst<i8x32> {
+    *x
+}
+
+// CHECK-LABEL: vector_transparent_wrapper_ret_small:
+// CHECK: vlrepg %v24, 0(%r2)
+// CHECK-NEXT: br %r14
+#[cfg_attr(no_vector, target_feature(enable = "vector"))]
+#[no_mangle]
+unsafe extern "C" fn vector_transparent_wrapper_ret_small(
+    x: &TransparentWrapper<i8x8>,
+) -> TransparentWrapper<i8x8> {
+    *x
+}
+// CHECK-LABEL: vector_transparent_wrapper_ret:
+// CHECK: vl %v24, 0(%r2), 3
+// CHECK-NEXT: br %r14
+#[cfg_attr(no_vector, target_feature(enable = "vector"))]
+#[no_mangle]
+unsafe extern "C" fn vector_transparent_wrapper_ret(
+    x: &TransparentWrapper<i8x16>,
+) -> TransparentWrapper<i8x16> {
+    *x
+}
+// CHECK-LABEL: vector_transparent_wrapper_ret_large:
+// z10: vl %v0, 16(%r3), 4
+// z10-NEXT: vl %v1, 0(%r3), 4
+// z10-NEXT: vst %v0, 16(%r2), 4
+// z10-NEXT: vst %v1, 0(%r2), 4
+// z10-NEXT: br %r14
+// z13: vl %v0, 0(%r3), 4
+// z13-NEXT: vl %v1, 16(%r3), 4
+// z13-NEXT: vst %v1, 16(%r2), 4
+// z13-NEXT: vst %v0, 0(%r2), 4
+// z13-NEXT: br %r14
+#[cfg_attr(no_vector, target_feature(enable = "vector"))]
+#[no_mangle]
+unsafe extern "C" fn vector_transparent_wrapper_ret_large(
+    x: &TransparentWrapper<i8x32>,
+) -> TransparentWrapper<i8x32> {
+    *x
+}
+
+// CHECK-LABEL: vector_arg_small:
+// CHECK: vlgvg %r2, %v24, 0
+// CHECK-NEXT: br %r14
+#[cfg_attr(no_vector, target_feature(enable = "vector"))]
+#[no_mangle]
+unsafe extern "C" fn vector_arg_small(x: i8x8) -> i64 {
+    unsafe { *(&x as *const i8x8 as *const i64) }
+}
+// CHECK-LABEL: vector_arg:
+// CHECK: vlgvg %r2, %v24, 0
+// CHECK-NEXT: br %r14
+#[cfg_attr(no_vector, target_feature(enable = "vector"))]
+#[no_mangle]
+unsafe extern "C" fn vector_arg(x: i8x16) -> i64 {
+    unsafe { *(&x as *const i8x16 as *const i64) }
+}
+// CHECK-LABEL: vector_arg_large:
+// CHECK: lg %r2, 0(%r2)
+// CHECK-NEXT: br %r14
+#[cfg_attr(no_vector, target_feature(enable = "vector"))]
+#[no_mangle]
+unsafe extern "C" fn vector_arg_large(x: i8x32) -> i64 {
+    unsafe { *(&x as *const i8x32 as *const i64) }
+}
+
+// CHECK-LABEL: vector_wrapper_arg_small:
+// CHECK: vlgvg %r2, %v24, 0
+// CHECK-NEXT: br %r14
+#[cfg_attr(no_vector, target_feature(enable = "vector"))]
+#[no_mangle]
+unsafe extern "C" fn vector_wrapper_arg_small(x: Wrapper<i8x8>) -> i64 {
+    unsafe { *(&x as *const Wrapper<i8x8> as *const i64) }
+}
+// CHECK-LABEL: vector_wrapper_arg:
+// CHECK: vlgvg %r2, %v24, 0
+// CHECK-NEXT: br %r14
+#[cfg_attr(no_vector, target_feature(enable = "vector"))]
+#[no_mangle]
+unsafe extern "C" fn vector_wrapper_arg(x: Wrapper<i8x16>) -> i64 {
+    unsafe { *(&x as *const Wrapper<i8x16> as *const i64) }
+}
+// CHECK-LABEL: vector_wrapper_arg_large:
+// CHECK: lg %r2, 0(%r2)
+// CHECK-NEXT: br %r14
+#[cfg_attr(no_vector, target_feature(enable = "vector"))]
+#[no_mangle]
+unsafe extern "C" fn vector_wrapper_arg_large(x: Wrapper<i8x32>) -> i64 {
+    unsafe { *(&x as *const Wrapper<i8x32> as *const i64) }
+}
+
+// https://github.com/rust-lang/rust/pull/131586#discussion_r1837071121
+// CHECK-LABEL: vector_wrapper_padding_arg:
+// CHECK: lg %r2, 0(%r2)
+// CHECK-NEXT: br %r14
+#[cfg_attr(no_vector, target_feature(enable = "vector"))]
+#[no_mangle]
+unsafe extern "C" fn vector_wrapper_padding_arg(x: WrapperAlign16<i8x8>) -> i64 {
+    unsafe { *(&x as *const WrapperAlign16<i8x8> as *const i64) }
+}
+
+// CHECK-LABEL: vector_wrapper_with_zst_arg_small:
+// CHECK: .cfi_startproc
+// CHECK-NOT: vlgvg
+// CHECK-NEXT: br %r14
+#[cfg_attr(no_vector, target_feature(enable = "vector"))]
+#[no_mangle]
+unsafe extern "C" fn vector_wrapper_with_zst_arg_small(x: WrapperWithZst<i8x8>) -> i64 {
+    unsafe { *(&x as *const WrapperWithZst<i8x8> as *const i64) }
+}
+// CHECK-LABEL: vector_wrapper_with_zst_arg:
+// CHECK: lg %r2, 0(%r2)
+// CHECK-NEXT: br %r14
+#[cfg_attr(no_vector, target_feature(enable = "vector"))]
+#[no_mangle]
+unsafe extern "C" fn vector_wrapper_with_zst_arg(x: WrapperWithZst<i8x16>) -> i64 {
+    unsafe { *(&x as *const WrapperWithZst<i8x16> as *const i64) }
+}
+// CHECK-LABEL: vector_wrapper_with_zst_arg_large:
+// CHECK: lg %r2, 0(%r2)
+// CHECK-NEXT: br %r14
+#[cfg_attr(no_vector, target_feature(enable = "vector"))]
+#[no_mangle]
+unsafe extern "C" fn vector_wrapper_with_zst_arg_large(x: WrapperWithZst<i8x32>) -> i64 {
+    unsafe { *(&x as *const WrapperWithZst<i8x32> as *const i64) }
+}
+
+// CHECK-LABEL: vector_transparent_wrapper_arg_small:
+// CHECK: vlgvg %r2, %v24, 0
+// CHECK-NEXT: br %r14
+#[cfg_attr(no_vector, target_feature(enable = "vector"))]
+#[no_mangle]
+unsafe extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper<i8x8>) -> i64 {
+    unsafe { *(&x as *const TransparentWrapper<i8x8> as *const i64) }
+}
+// CHECK-LABEL: vector_transparent_wrapper_arg:
+// CHECK: vlgvg %r2, %v24, 0
+// CHECK-NEXT: br %r14
+#[cfg_attr(no_vector, target_feature(enable = "vector"))]
+#[no_mangle]
+unsafe extern "C" fn vector_transparent_wrapper_arg(x: TransparentWrapper<i8x16>) -> i64 {
+    unsafe { *(&x as *const TransparentWrapper<i8x16> as *const i64) }
+}
+// CHECK-LABEL: vector_transparent_wrapper_arg_large:
+// CHECK: lg %r2, 0(%r2)
+// CHECK-NEXT: br %r14
+#[cfg_attr(no_vector, target_feature(enable = "vector"))]
+#[no_mangle]
+unsafe extern "C" fn vector_transparent_wrapper_arg_large(x: TransparentWrapper<i8x32>) -> i64 {
+    unsafe { *(&x as *const TransparentWrapper<i8x32> as *const i64) }
+}
diff --git a/tests/assembly-llvm/sanitizer/kcfi/emit-arity-indicator.rs b/tests/assembly-llvm/sanitizer/kcfi/emit-arity-indicator.rs
new file mode 100644
index 00000000000..f9966a23446
--- /dev/null
+++ b/tests/assembly-llvm/sanitizer/kcfi/emit-arity-indicator.rs
@@ -0,0 +1,69 @@
+// Verifies that KCFI arity indicator is emitted.
+//
+//@ add-core-stubs
+//@ revisions: x86_64
+//@ assembly-output: emit-asm
+//@[x86_64] compile-flags: --target x86_64-unknown-linux-gnu -Cllvm-args=-x86-asm-syntax=intel -Ctarget-feature=-crt-static -Cpanic=abort -Zsanitizer=kcfi -Zsanitizer-kcfi-arity -Copt-level=0
+//@ [x86_64] needs-llvm-components: x86
+//@ min-llvm-version: 21.0.0
+
+#![crate_type = "lib"]
+#![feature(no_core)]
+#![no_core]
+
+extern crate minicore;
+
+unsafe extern "C" {
+    safe fn add(x: i32, y: i32) -> i32;
+}
+
+pub fn add_one(x: i32) -> i32 {
+    // CHECK-LABEL: __cfi__{{.*}}7add_one{{.*}}:
+    // CHECK-NEXT:  nop
+    // CHECK-NEXT:  nop
+    // CHECK-NEXT:  nop
+    // CHECK-NEXT:  nop
+    // CHECK-NEXT:  nop
+    // CHECK-NEXT:  nop
+    // CHECK-NEXT:  nop
+    // CHECK-NEXT:  nop
+    // CHECK-NEXT:  nop
+    // CHECK-NEXT:  nop
+    // CHECK-NEXT:  nop
+    // CHECK-NEXT:  mov ecx, 2628068948
+    add(x, 1)
+}
+
+pub fn add_two(x: i32, _y: i32) -> i32 {
+    // CHECK-LABEL: __cfi__{{.*}}7add_two{{.*}}:
+    // CHECK-NEXT:  nop
+    // CHECK-NEXT:  nop
+    // CHECK-NEXT:  nop
+    // CHECK-NEXT:  nop
+    // CHECK-NEXT:  nop
+    // CHECK-NEXT:  nop
+    // CHECK-NEXT:  nop
+    // CHECK-NEXT:  nop
+    // CHECK-NEXT:  nop
+    // CHECK-NEXT:  nop
+    // CHECK-NEXT:  nop
+    // CHECK-NEXT:  mov edx, 2505940310
+    add(x, 2)
+}
+
+pub fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
+    // CHECK-LABEL: __cfi__{{.*}}8do_twice{{.*}}:
+    // CHECK-NEXT:  nop
+    // CHECK-NEXT:  nop
+    // CHECK-NEXT:  nop
+    // CHECK-NEXT:  nop
+    // CHECK-NEXT:  nop
+    // CHECK-NEXT:  nop
+    // CHECK-NEXT:  nop
+    // CHECK-NEXT:  nop
+    // CHECK-NEXT:  nop
+    // CHECK-NEXT:  nop
+    // CHECK-NEXT:  nop
+    // CHECK-NEXT:  mov edx, 653723426
+    add(f(arg), f(arg))
+}
diff --git a/tests/assembly-llvm/simd-bitmask.rs b/tests/assembly-llvm/simd-bitmask.rs
new file mode 100644
index 00000000000..d3e20f6ae1a
--- /dev/null
+++ b/tests/assembly-llvm/simd-bitmask.rs
@@ -0,0 +1,147 @@
+//@ add-core-stubs
+//@ revisions: x86 x86-avx2 x86-avx512 aarch64
+//@ [x86] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
+//@ [x86] needs-llvm-components: x86
+//@ [x86-avx2] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
+//@ [x86-avx2] compile-flags: -C target-feature=+avx2
+//@ [x86-avx2] needs-llvm-components: x86
+//@ [x86-avx512] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
+//@ [x86-avx512] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq
+//@ [x86-avx512] needs-llvm-components: x86
+//@ [aarch64] compile-flags: --target=aarch64-unknown-linux-gnu
+//@ [aarch64] needs-llvm-components: aarch64
+//@ assembly-output: emit-asm
+//@ compile-flags: --crate-type=lib -Copt-level=3 -C panic=abort
+
+#![feature(no_core, lang_items, repr_simd, intrinsics)]
+#![no_core]
+#![allow(non_camel_case_types)]
+
+extern crate minicore;
+use minicore::*;
+
+#[repr(simd)]
+pub struct m8x16([i8; 16]);
+
+#[repr(simd)]
+pub struct m8x64([i8; 64]);
+
+#[repr(simd)]
+pub struct m32x4([i32; 4]);
+
+#[repr(simd)]
+pub struct m64x2([i64; 2]);
+
+#[repr(simd)]
+pub struct m64x4([i64; 4]);
+
+#[rustc_intrinsic]
+unsafe fn simd_bitmask<V, B>(mask: V) -> B;
+
+// CHECK-LABEL: bitmask_m8x16
+#[no_mangle]
+pub unsafe extern "C" fn bitmask_m8x16(mask: m8x16) -> u16 {
+    // The simd_bitmask intrinsic already uses the most significant bit, so no shift is necessary.
+    // Note that x86 has no byte shift, llvm uses a word shift to move the least significant bit
+    // of each byte into the right position.
+    //
+    // x86-NOT: psllw
+    // x86: movmskb eax, xmm0
+    //
+    // x86-avx2-NOT: vpsllw
+    // x86-avx2: vpmovmskb eax, xmm0
+    //
+    // x86-avx512-NOT: vpsllw xmm0
+    // x86-avx512: vpmovmskb eax, xmm0
+    //
+    // aarch64: adrp
+    // aarch64-NEXT: cmlt
+    // aarch64-NEXT: ldr
+    // aarch64-NEXT: and
+    // aarch64-NEXT: ext
+    // aarch64-NEXT: zip1
+    // aarch64-NEXT: addv
+    // aarch64-NEXT: fmov
+    simd_bitmask(mask)
+}
+
+// x86-avx512-LABEL: bitmask_m8x64
+#[no_mangle]
+#[cfg(x86_avx512)]
+pub unsafe extern "C" fn bitmask_m8x64(mask: m8x64) -> u64 {
+    // The simd_bitmask intrinsic already uses the most significant bit, so no shift is necessary.
+    // Note that x86 has no byte shift, llvm uses a word shift to move the least significant bit
+    // of each byte into the right position.
+    //
+    // The parameter is a 512 bit vector which in the C abi is only valid for avx512 targets.
+    //
+    // x86-avx512-NOT: vpsllw
+    // x86-avx512: vpmovb2m k0, zmm0
+    // x86-avx512: kmovq rax, k0
+    simd_bitmask(mask)
+}
+
+// CHECK-LABEL: bitmask_m32x4
+#[no_mangle]
+pub unsafe extern "C" fn bitmask_m32x4(mask: m32x4) -> u8 {
+    // The simd_bitmask intrinsic already uses the most significant bit, so no shift is necessary.
+    //
+    // x86-NOT: psllq
+    // x86: movmskps eax, xmm0
+    //
+    // x86-avx2-NOT: vpsllq
+    // x86-avx2: vmovmskps eax, xmm0
+    //
+    // x86-avx512-NOT: vpsllq
+    // x86-avx512: vmovmskps eax, xmm0
+    //
+    // aarch64: adrp
+    // aarch64-NEXT: cmlt
+    // aarch64-NEXT: ldr
+    // aarch64-NEXT: and
+    // aarch64-NEXT: addv
+    // aarch64-NEXT: fmov
+    // aarch64-NEXT: and
+    simd_bitmask(mask)
+}
+
+// CHECK-LABEL: bitmask_m64x2
+#[no_mangle]
+pub unsafe extern "C" fn bitmask_m64x2(mask: m64x2) -> u8 {
+    // The simd_bitmask intrinsic already uses the most significant bit, so no shift is necessary.
+    //
+    // x86-NOT: psllq
+    // x86: movmskpd eax, xmm0
+    //
+    // x86-avx2-NOT: vpsllq
+    // x86-avx2: vmovmskpd eax, xmm0
+    //
+    // x86-avx512-NOT: vpsllq
+    // x86-avx512: vmovmskpd eax, xmm0
+    //
+    // aarch64: adrp
+    // aarch64-NEXT: cmlt
+    // aarch64-NEXT: ldr
+    // aarch64-NEXT: and
+    // aarch64-NEXT: addp
+    // aarch64-NEXT: fmov
+    // aarch64-NEXT: and
+    simd_bitmask(mask)
+}
+
+// x86-avx2-LABEL: bitmask_m64x4
+// x86-avx512-LABEL: bitmask_m64x4
+#[no_mangle]
+#[cfg(any(x86_avx2, x86_avx512))]
+pub unsafe extern "C" fn bitmask_m64x4(mask: m64x4) -> u8 {
+    // The simd_bitmask intrinsic already uses the most significant bit, so no shift is necessary.
+    //
+    // The parameter is a 256 bit vector which in the C abi is only valid for avx/avx512 targets.
+    //
+    // x86-avx2-NOT: vpsllq
+    // x86-avx2: vmovmskpd eax, ymm0
+    //
+    // x86-avx512-NOT: vpsllq
+    // x86-avx512: vmovmskpd eax, ymm0
+    simd_bitmask(mask)
+}
diff --git a/tests/assembly-llvm/simd-intrinsic-gather.rs b/tests/assembly-llvm/simd-intrinsic-gather.rs
new file mode 100644
index 00000000000..bcab0ba1cc0
--- /dev/null
+++ b/tests/assembly-llvm/simd-intrinsic-gather.rs
@@ -0,0 +1,39 @@
+//@ add-core-stubs
+//@ revisions: x86-avx512
+//@ [x86-avx512] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
+//@ [x86-avx512] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq
+//@ [x86-avx512] needs-llvm-components: x86
+//@ assembly-output: emit-asm
+//@ compile-flags: --crate-type=lib -Copt-level=3 -C panic=abort
+
+#![feature(no_core, lang_items, repr_simd, intrinsics)]
+#![no_core]
+#![allow(non_camel_case_types)]
+
+extern crate minicore;
+use minicore::*;
+
+#[repr(simd)]
+pub struct f64x4([f64; 4]);
+
+#[repr(simd)]
+pub struct m64x4([i64; 4]);
+
+#[repr(simd)]
+pub struct pf64x4([*const f64; 4]);
+
+#[rustc_intrinsic]
+unsafe fn simd_gather<V, M, P>(values: V, mask: M, pointer: P) -> V;
+
+// CHECK-LABEL: gather_f64x4
+#[no_mangle]
+pub unsafe extern "C" fn gather_f64x4(mask: m64x4, ptrs: pf64x4) -> f64x4 {
+    // FIXME: This should also get checked to generate a gather instruction for avx2.
+    // Currently llvm scalarizes this code, see https://github.com/llvm/llvm-project/issues/59789
+    //
+    // x86-avx512-NOT: vpsllq
+    // x86-avx512: vpmovq2m k1, ymm0
+    // x86-avx512-NEXT: vpxor xmm0, xmm0, xmm0
+    // x86-avx512-NEXT: vgatherqpd ymm0 {k1}, {{(ymmword)|(qword)}} ptr [1*ymm1]
+    simd_gather(f64x4([0_f64, 0_f64, 0_f64, 0_f64]), ptrs, mask)
+}
diff --git a/tests/assembly-llvm/simd-intrinsic-mask-load.rs b/tests/assembly-llvm/simd-intrinsic-mask-load.rs
new file mode 100644
index 00000000000..d3f3453a780
--- /dev/null
+++ b/tests/assembly-llvm/simd-intrinsic-mask-load.rs
@@ -0,0 +1,83 @@
+//@ add-core-stubs
+//@ revisions: x86-avx2 x86-avx512
+//@ [x86-avx2] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
+//@ [x86-avx2] compile-flags: -C target-feature=+avx2
+//@ [x86-avx2] needs-llvm-components: x86
+//@ [x86-avx512] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
+//@ [x86-avx512] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq
+//@ [x86-avx512] needs-llvm-components: x86
+//@ assembly-output: emit-asm
+//@ compile-flags: --crate-type=lib -Copt-level=3 -C panic=abort
+
+#![feature(no_core, lang_items, repr_simd, intrinsics)]
+#![no_core]
+#![allow(non_camel_case_types)]
+
+extern crate minicore;
+use minicore::*;
+
+#[repr(simd)]
+pub struct i8x16([i8; 16]);
+
+#[repr(simd)]
+pub struct m8x16([i8; 16]);
+
+#[repr(simd)]
+pub struct f32x8([f32; 8]);
+
+#[repr(simd)]
+pub struct m32x8([i32; 8]);
+
+#[repr(simd)]
+pub struct f64x4([f64; 4]);
+
+#[repr(simd)]
+pub struct m64x4([i64; 4]);
+
+#[rustc_intrinsic]
+unsafe fn simd_masked_load<M, P, T>(mask: M, pointer: P, values: T) -> T;
+
+// CHECK-LABEL: load_i8x16
+#[no_mangle]
+pub unsafe extern "C" fn load_i8x16(mask: m8x16, pointer: *const i8) -> i8x16 {
+    // Since avx2 supports no masked loads for bytes, the code tests each individual bit
+    // and jumps to code that inserts individual bytes.
+    // x86-avx2-NOT: vpsllw
+    // x86-avx2-DAG: vpmovmskb eax
+    // x86-avx2-DAG: vpxor
+    // x86-avx2-NEXT: test al, 1
+    // x86-avx2-NEXT: jne
+    // x86-avx2-NEXT: test al, 2
+    // x86-avx2-NEXT: jne
+    // x86-avx2-DAG: movzx [[REG:[a-z]+]], byte ptr [rdi]
+    // x86-avx2-NEXT: vmovd xmm0, [[REG]]
+    // x86-avx2-DAG: vpinsrb xmm0, xmm0, byte ptr [rdi + 1], 1
+    //
+    // x86-avx512-NOT: vpsllw
+    // x86-avx512: vpmovb2m k1, xmm0
+    // x86-avx512-NEXT: vmovdqu8 xmm0 {k1} {z}, xmmword ptr [rdi]
+    simd_masked_load(mask, pointer, i8x16([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]))
+}
+
+// CHECK-LABEL: load_f32x8
+#[no_mangle]
+pub unsafe extern "C" fn load_f32x8(mask: m32x8, pointer: *const f32) -> f32x8 {
+    // x86-avx2-NOT: vpslld
+    // x86-avx2: vmaskmovps ymm0, ymm0, ymmword ptr [rdi]
+    //
+    // x86-avx512-NOT: vpslld
+    // x86-avx512: vpmovd2m k1, ymm0
+    // x86-avx512-NEXT: vmovups ymm0 {k1} {z}, ymmword ptr [rdi]
+    simd_masked_load(mask, pointer, f32x8([0_f32, 0_f32, 0_f32, 0_f32, 0_f32, 0_f32, 0_f32, 0_f32]))
+}
+
+// CHECK-LABEL: load_f64x4
+#[no_mangle]
+pub unsafe extern "C" fn load_f64x4(mask: m64x4, pointer: *const f64) -> f64x4 {
+    // x86-avx2-NOT: vpsllq
+    // x86-avx2: vmaskmovpd ymm0, ymm0, ymmword ptr [rdi]
+    //
+    // x86-avx512-NOT: vpsllq
+    // x86-avx512: vpmovq2m k1, ymm0
+    simd_masked_load(mask, pointer, f64x4([0_f64, 0_f64, 0_f64, 0_f64]))
+}
diff --git a/tests/assembly-llvm/simd-intrinsic-mask-reduce.rs b/tests/assembly-llvm/simd-intrinsic-mask-reduce.rs
new file mode 100644
index 00000000000..8b15ed0a254
--- /dev/null
+++ b/tests/assembly-llvm/simd-intrinsic-mask-reduce.rs
@@ -0,0 +1,59 @@
+// verify that simd mask reductions do not introduce additional bit shift operations
+//@ add-core-stubs
+//@ revisions: x86 aarch64
+//@ [x86] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
+// Set the base cpu explicitly, in case the default has been changed.
+//@ [x86] compile-flags: -C target-cpu=x86-64
+//@ [x86] needs-llvm-components: x86
+//@ [aarch64] compile-flags: --target=aarch64-unknown-linux-gnu
+//@ [aarch64] needs-llvm-components: aarch64
+//@ assembly-output: emit-asm
+//@ compile-flags: --crate-type=lib -Copt-level=3 -C panic=abort
+
+#![feature(no_core, lang_items, repr_simd, intrinsics)]
+#![no_core]
+#![allow(non_camel_case_types)]
+
+extern crate minicore;
+use minicore::*;
+
+#[repr(simd)]
+pub struct mask8x16([i8; 16]);
+
+#[rustc_intrinsic]
+unsafe fn simd_reduce_all<T>(x: T) -> bool;
+#[rustc_intrinsic]
+unsafe fn simd_reduce_any<T>(x: T) -> bool;
+
+// CHECK-LABEL: mask_reduce_all:
+#[no_mangle]
+pub unsafe extern "C" fn mask_reduce_all(m: mask8x16) -> bool {
+    // x86-NOT: psllw
+    // x86: pmovmskb eax, xmm0
+    // x86-NEXT: {{cmp ax, -1|cmp eax, 65535|xor eax, 65535}}
+    // x86-NEXT: sete al
+    //
+    // aarch64-NOT: shl
+    // aarch64: cmge v0.16b, v0.16b, #0
+    // aarch64-DAG: mov [[REG1:[a-z0-9]+]], #1
+    // aarch64-DAG: umaxv b0, v0.16b
+    // aarch64-NEXT: fmov [[REG2:[a-z0-9]+]], s0
+    // aarch64-NEXT: bic w0, [[REG1]], [[REG2]]
+    simd_reduce_all(m)
+}
+
+// CHECK-LABEL: mask_reduce_any:
+#[no_mangle]
+pub unsafe extern "C" fn mask_reduce_any(m: mask8x16) -> bool {
+    // x86-NOT: psllw
+    // x86: pmovmskb
+    // x86-NEXT: test eax, eax
+    // x86-NEXT: setne al
+    //
+    // aarch64-NOT: shl
+    // aarch64: cmlt v0.16b, v0.16b, #0
+    // aarch64-NEXT: umaxv b0, v0.16b
+    // aarch64-NEXT: fmov [[REG:[a-z0-9]+]], s0
+    // aarch64-NEXT: and w0, [[REG]], #0x1
+    simd_reduce_any(m)
+}
diff --git a/tests/assembly-llvm/simd-intrinsic-mask-store.rs b/tests/assembly-llvm/simd-intrinsic-mask-store.rs
new file mode 100644
index 00000000000..001762e5060
--- /dev/null
+++ b/tests/assembly-llvm/simd-intrinsic-mask-store.rs
@@ -0,0 +1,82 @@
+//@ add-core-stubs
+//@ revisions: x86-avx2 x86-avx512
+//@ [x86-avx2] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
+//@ [x86-avx2] compile-flags: -C target-feature=+avx2
+//@ [x86-avx2] needs-llvm-components: x86
+//@ [x86-avx512] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
+//@ [x86-avx512] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq
+//@ [x86-avx512] needs-llvm-components: x86
+//@ assembly-output: emit-asm
+//@ compile-flags: --crate-type=lib -Copt-level=3 -C panic=abort
+
+#![feature(no_core, lang_items, repr_simd, intrinsics)]
+#![no_core]
+#![allow(non_camel_case_types)]
+
+extern crate minicore;
+use minicore::*;
+
+#[repr(simd)]
+pub struct i8x16([i8; 16]);
+
+#[repr(simd)]
+pub struct m8x16([i8; 16]);
+
+#[repr(simd)]
+pub struct f32x8([f32; 8]);
+
+#[repr(simd)]
+pub struct m32x8([i32; 8]);
+
+#[repr(simd)]
+pub struct f64x4([f64; 4]);
+
+#[repr(simd)]
+pub struct m64x4([i64; 4]);
+
+#[rustc_intrinsic]
+unsafe fn simd_masked_store<M, P, T>(mask: M, pointer: P, values: T);
+
+// CHECK-LABEL: store_i8x16
+#[no_mangle]
+pub unsafe extern "C" fn store_i8x16(mask: m8x16, pointer: *mut i8, value: i8x16) {
+    // Since avx2 supports no masked stores for bytes, the code tests each individual bit
+    // and jumps to code that extracts individual bytes to memory.
+    // x86-avx2-NOT: vpsllw
+    // x86-avx2: vpmovmskb eax, xmm0
+    // x86-avx2-NEXT: test al, 1
+    // x86-avx2-NEXT: jne
+    // x86-avx2-NEXT: test al, 2
+    // x86-avx2-NEXT: jne
+    // x86-avx2-DAG: vpextrb byte ptr [rdi + 1], xmm1, 1
+    // x86-avx2-DAG: vpextrb byte ptr [rdi], xmm1, 0
+    //
+    // x86-avx512-NOT: vpsllw
+    // x86-avx512: vpmovb2m k1, xmm0
+    // x86-avx512-NEXT: vmovdqu8 xmmword ptr [rdi] {k1}, xmm1
+    simd_masked_store(mask, pointer, value)
+}
+
+// CHECK-LABEL: store_f32x8
+#[no_mangle]
+pub unsafe extern "C" fn store_f32x8(mask: m32x8, pointer: *mut f32, value: f32x8) {
+    // x86-avx2-NOT: vpslld
+    // x86-avx2: vmaskmovps ymmword ptr [rdi], ymm0, ymm1
+    //
+    // x86-avx512-NOT: vpslld
+    // x86-avx512: vpmovd2m k1, ymm0
+    // x86-avx512-NEXT: vmovups ymmword ptr [rdi] {k1}, ymm1
+    simd_masked_store(mask, pointer, value)
+}
+
+// CHECK-LABEL: store_f64x4
+#[no_mangle]
+pub unsafe extern "C" fn store_f64x4(mask: m64x4, pointer: *mut f64, value: f64x4) {
+    // x86-avx2-NOT: vpsllq
+    // x86-avx2: vmaskmovpd ymmword ptr [rdi], ymm0, ymm1
+    //
+    // x86-avx512-NOT: vpsllq
+    // x86-avx512: vpmovq2m k1, ymm0
+    // x86-avx512-NEXT: vmovupd ymmword ptr [rdi] {k1}, ymm1
+    simd_masked_store(mask, pointer, value)
+}
diff --git a/tests/assembly-llvm/simd-intrinsic-scatter.rs b/tests/assembly-llvm/simd-intrinsic-scatter.rs
new file mode 100644
index 00000000000..d77dfad3546
--- /dev/null
+++ b/tests/assembly-llvm/simd-intrinsic-scatter.rs
@@ -0,0 +1,35 @@
+//@ add-core-stubs
+//@ revisions: x86-avx512
+//@ [x86-avx512] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
+//@ [x86-avx512] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq
+//@ [x86-avx512] needs-llvm-components: x86
+//@ assembly-output: emit-asm
+//@ compile-flags: --crate-type=lib -Copt-level=3 -C panic=abort
+
+#![feature(no_core, lang_items, repr_simd, intrinsics)]
+#![no_core]
+#![allow(non_camel_case_types)]
+
+extern crate minicore;
+use minicore::*;
+
+#[repr(simd)]
+pub struct f64x4([f64; 4]);
+
+#[repr(simd)]
+pub struct m64x4([i64; 4]);
+
+#[repr(simd)]
+pub struct pf64x4([*mut f64; 4]);
+
+#[rustc_intrinsic]
+unsafe fn simd_scatter<V, P, M>(values: V, pointer: P, mask: M);
+
+// CHECK-LABEL: scatter_f64x4
+#[no_mangle]
+pub unsafe extern "C" fn scatter_f64x4(values: f64x4, ptrs: pf64x4, mask: m64x4) {
+    // x86-avx512-NOT: vpsllq
+    // x86-avx512: vpmovq2m k1, ymm2
+    // x86-avx512-NEXT: vscatterqpd {{(ymmword)|(qword)}} ptr [1*ymm1] {k1}, ymm0
+    simd_scatter(values, ptrs, mask)
+}
diff --git a/tests/assembly-llvm/simd-intrinsic-select.rs b/tests/assembly-llvm/simd-intrinsic-select.rs
new file mode 100644
index 00000000000..e7c7b0db0d5
--- /dev/null
+++ b/tests/assembly-llvm/simd-intrinsic-select.rs
@@ -0,0 +1,128 @@
+//@ add-core-stubs
+//@ revisions: x86-avx2 x86-avx512 aarch64
+//@ [x86-avx2] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
+//@ [x86-avx2] compile-flags: -C target-feature=+avx2
+//@ [x86-avx2] needs-llvm-components: x86
+//@ [x86-avx512] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
+//@ [x86-avx512] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq
+//@ [x86-avx512] needs-llvm-components: x86
+//@ [aarch64] compile-flags: --target=aarch64-unknown-linux-gnu
+//@ [aarch64] needs-llvm-components: aarch64
+//@ assembly-output: emit-asm
+//@ compile-flags: --crate-type=lib -Copt-level=3 -C panic=abort
+
+#![feature(no_core, lang_items, repr_simd, intrinsics)]
+#![no_core]
+#![allow(non_camel_case_types)]
+
+extern crate minicore;
+use minicore::*;
+
+#[repr(simd)]
+pub struct i8x16([i8; 16]);
+
+#[repr(simd)]
+pub struct m8x16([i8; 16]);
+
+#[repr(simd)]
+pub struct f32x4([f32; 4]);
+
+#[repr(simd)]
+pub struct m32x4([i32; 4]);
+
+#[repr(simd)]
+pub struct f64x2([f64; 2]);
+
+#[repr(simd)]
+pub struct m64x2([i64; 2]);
+
+#[repr(simd)]
+pub struct f64x4([f64; 4]);
+
+#[repr(simd)]
+pub struct m64x4([i64; 4]);
+
+#[repr(simd)]
+pub struct f64x8([f64; 8]);
+
+#[repr(simd)]
+pub struct m64x8([i64; 8]);
+
+#[rustc_intrinsic]
+unsafe fn simd_select<M, V>(mask: M, a: V, b: V) -> V;
+
+// CHECK-LABEL: select_i8x16
+#[no_mangle]
+pub unsafe extern "C" fn select_i8x16(mask: m8x16, a: i8x16, b: i8x16) -> i8x16 {
+    // x86-avx2-NOT: vpsllw
+    // x86-avx2: vpblendvb xmm0, xmm2, xmm1, xmm0
+    //
+    // x86-avx512-NOT: vpsllw
+    // x86-avx512: vpmovb2m k1, xmm0
+    // x86-avx512-NEXT: vpblendmb xmm0 {k1}, xmm2, xmm1
+    //
+    // aarch64-NOT: shl
+    // aarch64: cmlt v0.16b, v0.16b, #0
+    // aarch64-NEXT: bsl v0.16b, v1.16b, v2.16b
+    simd_select(mask, a, b)
+}
+
+// CHECK-LABEL: select_f32x4
+#[no_mangle]
+pub unsafe extern "C" fn select_f32x4(mask: m32x4, a: f32x4, b: f32x4) -> f32x4 {
+    // x86-avx2-NOT: vpslld
+    // x86-avx2: vblendvps xmm0, xmm2, xmm1, xmm0
+    //
+    // x86-avx512-NOT: vpslld
+    // x86-avx512: vpmovd2m k1, xmm0
+    // x86-avx512-NEXT: vblendmps xmm0 {k1}, xmm2, xmm1
+    //
+    // aarch64-NOT: shl
+    // aarch64: cmlt v0.4s, v0.4s, #0
+    // aarch64-NEXT: bsl v0.16b, v1.16b, v2.16b
+    simd_select(mask, a, b)
+}
+
+// CHECK-LABEL: select_f64x2
+#[no_mangle]
+pub unsafe extern "C" fn select_f64x2(mask: m64x2, a: f64x2, b: f64x2) -> f64x2 {
+    // x86-avx2-NOT: vpsllq
+    // x86-avx2: vblendvpd xmm0, xmm2, xmm1, xmm0
+    //
+    // x86-avx512-NOT: vpsllq
+    // x86-avx512: vpmovq2m k1, xmm0
+    // x86-avx512-NEXT: vblendmpd xmm0 {k1}, xmm2, xmm1
+    //
+    // aarch64-NOT: shl
+    // aarch64: cmlt v0.2d, v0.2d, #0
+    // aarch64-NEXT: bsl v0.16b, v1.16b, v2.16b
+    simd_select(mask, a, b)
+}
+
+// x86-avx2-LABEL: select_f64x4
+// x86-avx512-LABEL: select_f64x4
+#[no_mangle]
+#[cfg(any(x86_avx2, x86_avx512))]
+pub unsafe extern "C" fn select_f64x4(mask: m64x4, a: f64x4, b: f64x4) -> f64x4 {
+    // The parameter is a 256 bit vector which in the C abi is only valid for avx targets.
+    //
+    // x86-avx2-NOT: vpsllq
+    // x86-avx2: vblendvpd ymm0, ymm2, ymm1, ymm0
+    //
+    // x86-avx512-NOT: vpsllq
+    // x86-avx512: vpmovq2m k1, ymm0
+    // x86-avx512-NEXT: vblendmpd ymm0 {k1}, ymm2, ymm1
+    simd_select(mask, a, b)
+}
+
+// x86-avx512-LABEL: select_f64x8
+#[no_mangle]
+#[cfg(x86_avx512)]
+pub unsafe extern "C" fn select_f64x8(mask: m64x8, a: f64x8, b: f64x8) -> f64x8 {
+    // The parameter is a 256 bit vector which in the C abi is only valid for avx512 targets.
+    //
+    // x86-avx512-NOT: vpsllq
+    // x86-avx512: vpmovq2m k1, zmm0
+    // x86-avx512-NEXT: vblendmpd zmm0 {k1}, zmm2, zmm1
+    simd_select(mask, a, b)
+}
diff --git a/tests/assembly-llvm/simd/reduce-fadd-unordered.rs b/tests/assembly-llvm/simd/reduce-fadd-unordered.rs
new file mode 100644
index 00000000000..e872826f6ef
--- /dev/null
+++ b/tests/assembly-llvm/simd/reduce-fadd-unordered.rs
@@ -0,0 +1,31 @@
+//@ revisions: x86_64 aarch64
+//@ assembly-output: emit-asm
+//@ compile-flags: --crate-type=lib -Copt-level=3
+
+//@[aarch64] only-aarch64
+//@[x86_64] only-x86_64
+//@[x86_64] compile-flags: -Ctarget-feature=+sse3
+//@ ignore-sgx Test incompatible with LVI mitigations
+#![feature(portable_simd)]
+#![feature(core_intrinsics)]
+use std::intrinsics::simd as intrinsics;
+use std::simd::*;
+// Regression test for https://github.com/rust-lang/rust/issues/130028
+// This intrinsic produces much worse code if you use +0.0 instead of -0.0 because
+// +0.0 isn't as easy to algebraically reassociate, even using LLVM's reassoc attribute!
+// It would emit about an extra fadd, depending on the architecture.
+
+// CHECK-LABEL: reduce_fadd_negative_zero
+pub unsafe fn reduce_fadd_negative_zero(v: f32x4) -> f32 {
+    // x86_64: addps
+    // x86_64-NEXT: movshdup
+    // x86_64-NEXT: addss
+    // x86_64-NOT: xorps
+
+    // aarch64: faddp
+    // aarch64-NEXT: faddp
+
+    // CHECK-NOT: {{f?}}add{{p?s*}}
+    // CHECK: ret
+    intrinsics::simd_reduce_add_unordered(v)
+}
diff --git a/tests/assembly-llvm/slice-is_ascii.rs b/tests/assembly-llvm/slice-is_ascii.rs
new file mode 100644
index 00000000000..e53cd5160cf
--- /dev/null
+++ b/tests/assembly-llvm/slice-is_ascii.rs
@@ -0,0 +1,33 @@
+//@ revisions: WIN LIN
+//@ [WIN] only-windows
+//@ [LIN] only-linux
+//@ assembly-output: emit-asm
+//@ compile-flags: --crate-type=lib -Copt-level=3 -C llvm-args=-x86-asm-syntax=intel
+//@ only-x86_64
+//@ ignore-sgx
+
+#![feature(str_internals)]
+
+// CHECK-LABEL: is_ascii_simple_demo:
+#[no_mangle]
+pub fn is_ascii_simple_demo(bytes: &[u8]) -> bool {
+    // Linux (System V): pointer is rdi; length is rsi
+    // Windows: pointer is rcx; length is rdx.
+
+    // CHECK-NOT: mov
+    // CHECK-NOT: test
+    // CHECK-NOT: cmp
+
+    // CHECK: .[[LOOPHEAD:.+]]:
+    // CHECK-NEXT: mov [[TEMP:.+]], [[LEN:rsi|rdx]]
+    // CHECK-NEXT: sub [[LEN]], 1
+    // CHECK-NEXT: jb .[[LOOPEXIT:.+]]
+    // CHECK-NEXT: cmp byte ptr [{{rdi|rcx}} + [[TEMP]] - 1], 0
+    // CHECK-NEXT: jns .[[LOOPHEAD]]
+
+    // CHECK-NEXT: .[[LOOPEXIT]]:
+    // CHECK-NEXT: test [[TEMP]], [[TEMP]]
+    // CHECK-NEXT: sete al
+    // CHECK-NEXT: ret
+    core::slice::is_ascii_simple(bytes)
+}
diff --git a/tests/assembly-llvm/small_data_threshold.rs b/tests/assembly-llvm/small_data_threshold.rs
new file mode 100644
index 00000000000..2abe8687d8b
--- /dev/null
+++ b/tests/assembly-llvm/small_data_threshold.rs
@@ -0,0 +1,98 @@
+// Test for -Z small_data_threshold=...
+//@ revisions: RISCV MIPS HEXAGON M68K
+//@ assembly-output: emit-asm
+//@ compile-flags: -Z small_data_threshold=4
+//@ [RISCV] compile-flags: --target=riscv32im-unknown-none-elf
+//@ [RISCV] needs-llvm-components: riscv
+//@ [MIPS] compile-flags: --target=mips-unknown-linux-uclibc -C relocation-model=static
+//@ [MIPS] compile-flags: -C llvm-args=-mgpopt -C llvm-args=-mlocal-sdata
+//@ [MIPS] compile-flags: -C target-feature=+noabicalls
+//@ [MIPS] needs-llvm-components: mips
+//@ [HEXAGON] compile-flags: --target=hexagon-unknown-linux-musl -C target-feature=+small-data
+//@ [HEXAGON] compile-flags: -C llvm-args=--hexagon-statics-in-small-data
+//@ [HEXAGON] needs-llvm-components: hexagon
+//@ [M68K] compile-flags: --target=m68k-unknown-linux-gnu
+//@ [M68K] needs-llvm-components: m68k
+
+#![feature(no_core, lang_items)]
+#![no_std]
+#![no_core]
+#![crate_type = "lib"]
+
+#[lang = "pointee_sized"]
+pub trait PointeeSized {}
+
+#[lang = "meta_sized"]
+pub trait MetaSized: PointeeSized {}
+
+#[lang = "sized"]
+pub trait Sized: MetaSized {}
+
+#[lang = "drop_in_place"]
+fn drop_in_place<T>(_: *mut T) {}
+
+#[used]
+#[no_mangle]
+// U is below the threshold, should be in sdata
+static mut U: u16 = 123;
+
+#[used]
+#[no_mangle]
+// V is below the threshold, should be in sbss
+static mut V: u16 = 0;
+
+#[used]
+#[no_mangle]
+// W is at the threshold, should be in sdata
+static mut W: u32 = 123;
+
+#[used]
+#[no_mangle]
+// X is at the threshold, should be in sbss
+static mut X: u32 = 0;
+
+#[used]
+#[no_mangle]
+// Y is over the threshold, should be in its own .data section
+static mut Y: u64 = 123;
+
+#[used]
+#[no_mangle]
+// Z is over the threshold, should be in its own .bss section
+static mut Z: u64 = 0;
+
+// Currently, only MIPS and RISCV successfully put any objects in the small data
+// sections so the U/V/W/X tests are skipped on Hexagon and M68K
+
+// RISCV: .section .sdata
+// RISCV-NOT: .section
+// RISCV: U:
+// RISCV: .section .sbss
+// RISCV-NOT: .section
+// RISCV: V:
+// RISCV: .section .sdata
+// RISCV-NOT: .section
+// RISCV: W:
+// RISCV: .section .sbss
+// RISCV-NOT: .section
+// RISCV: X:
+
+// MIPS: .section .sdata
+// MIPS-NOT: .section
+// MIPS: U:
+// MIPS: .section .sbss
+// MIPS-NOT: .section
+// MIPS: V:
+// MIPS: .section .sdata
+// MIPS-NOT: .section
+// MIPS: W:
+// MIPS: .section .sbss
+// MIPS-NOT: .section
+// MIPS: X:
+
+// CHECK: .section .data.Y,
+// CHECK-NOT: .section
+// CHECK: Y:
+// CHECK: .section .bss.Z,
+// CHECK-NOT: .section
+// CHECK: Z:
diff --git a/tests/assembly-llvm/sparc-struct-abi.rs b/tests/assembly-llvm/sparc-struct-abi.rs
new file mode 100644
index 00000000000..b1594428811
--- /dev/null
+++ b/tests/assembly-llvm/sparc-struct-abi.rs
@@ -0,0 +1,68 @@
+// Test SPARC64 ABI
+// - float structure members are passes in floating point registers
+// (#86163)
+
+//@ add-core-stubs
+//@ assembly-output: emit-asm
+//@ needs-llvm-components: sparc
+//@ compile-flags: --target=sparcv9-sun-solaris -Copt-level=3
+#![crate_type = "lib"]
+#![feature(no_core, lang_items)]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
+
+#[repr(C)]
+pub struct Franta {
+    a: f32,
+    b: f32,
+    c: f32,
+    d: f32,
+}
+
+// NB: due to delay slots the `ld` following the call is actually executed before the call.
+#[no_mangle]
+pub unsafe extern "C" fn callee(arg: Franta) {
+    // CHECK-LABEL: callee:
+    // CHECK: st %f3, [[PLACE_D:.*]]
+    // CHECK: st %f2, [[PLACE_C:.*]]
+    // CHECK: st %f1, [[PLACE_B:.*]]
+    // CHECK: st %f0, [[PLACE_A:.*]]
+    // CHECK: call tst_use
+    // CHECK-NEXT: ld [[PLACE_A]], %f1
+    // CHECK: call tst_use
+    // CHECK-NEXT: ld [[PLACE_B]], %f1
+    // CHECK: call tst_use
+    // CHECK-NEXT: ld [[PLACE_C]], %f1
+    // CHECK: call tst_use
+    // CHECK-NEXT: ld [[PLACE_D]], %f1
+    clobber();
+    tst_use(arg.a);
+    tst_use(arg.b);
+    tst_use(arg.c);
+    tst_use(arg.d);
+    tail_call_avoidance_fn();
+}
+
+extern "C" {
+    fn opaque_callee(arg: Franta, intarg: i32);
+    fn tst_use(arg: f32);
+    fn clobber();
+    // This exists so that post-https://reviews.llvm.org/D138741 LLVM doesn't
+    // tail-call away some of our assertions.
+    fn tail_call_avoidance_fn();
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn caller() {
+    // CHECK-LABEL: caller:
+    // CHECK: ld [{{.*}}], %f0
+    // CHECK: ld [{{.*}}], %f1
+    // CHECK: ld [{{.*}}], %f2
+    // CHECK: ld [{{.*}}], %f3
+    // CHECK: call opaque_callee
+    // CHECK: mov     3, %o2
+    opaque_callee(Franta { a: 1.0, b: 2.0, c: 3.0, d: 4.0 }, 3);
+    tail_call_avoidance_fn();
+}
diff --git a/tests/assembly-llvm/stack-probes.rs b/tests/assembly-llvm/stack-probes.rs
new file mode 100644
index 00000000000..de245431f47
--- /dev/null
+++ b/tests/assembly-llvm/stack-probes.rs
@@ -0,0 +1,41 @@
+//@ add-core-stubs
+//@ revisions: x86_64 i686 aarch64
+//@ assembly-output: emit-asm
+//@[x86_64] compile-flags: --target x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
+//@[x86_64] needs-llvm-components: x86
+//@[i686] compile-flags: --target i686-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
+//@[i686] needs-llvm-components: x86
+//@[aarch64] compile-flags: --target aarch64-unknown-linux-gnu
+//@[aarch64] needs-llvm-components: aarch64
+
+#![feature(no_core, lang_items)]
+#![crate_type = "lib"]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
+
+// Check that inline-asm stack probes are generated correctly.
+// To avoid making this test fragile to slight asm changes,
+// we only check that the stack pointer is decremented by a page at a time,
+// instead of matching the whole probe sequence.
+
+// CHECK-LABEL: small_stack_probe:
+#[no_mangle]
+pub fn small_stack_probe(x: u8, f: fn(&mut [u8; 8192])) {
+    // CHECK-NOT: __rust_probestack
+    // x86_64: sub rsp, 4096
+    // i686: sub esp, 4096
+    // aarch64: sub sp, sp, #1, lsl #12
+    f(&mut [x; 8192]);
+}
+
+// CHECK-LABEL: big_stack_probe:
+#[no_mangle]
+pub fn big_stack_probe(x: u8, f: fn(&[u8; 65536])) {
+    // CHECK-NOT: __rust_probestack
+    // x86_64: sub rsp, 4096
+    // i686: sub esp, 4096
+    // aarch64: sub sp, sp, #1, lsl #12
+    f(&mut [x; 65536]);
+}
diff --git a/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs b/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs
new file mode 100644
index 00000000000..3287e018b40
--- /dev/null
+++ b/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs
@@ -0,0 +1,359 @@
+//@ revisions: all strong basic none missing
+//@ assembly-output: emit-asm
+//@ only-windows
+//@ only-msvc
+//@ ignore-64bit 64-bit table based SEH has slightly different behaviors than classic SEH
+//@ [all] compile-flags: -Z stack-protector=all
+//@ [strong] compile-flags: -Z stack-protector=strong
+//@ [basic] compile-flags: -Z stack-protector=basic
+//@ [none] compile-flags: -Z stack-protector=none
+//@ compile-flags: -C opt-level=2 -Z merge-functions=disabled
+
+#![crate_type = "lib"]
+#![allow(internal_features)]
+#![feature(unsized_fn_params)]
+
+// CHECK-LABEL: emptyfn:
+#[no_mangle]
+pub fn emptyfn() {
+    // all: __security_check_cookie
+    // strong-NOT: __security_check_cookie
+    // basic-NOT: __security_check_cookie
+    // none-NOT: __security_check_cookie
+    // missing-NOT: __security_check_cookie
+}
+
+// CHECK-LABEL: array_char
+#[no_mangle]
+pub fn array_char(f: fn(*const char)) {
+    let a = ['c'; 1];
+    let b = ['d'; 3];
+    let c = ['e'; 15];
+
+    f(&a as *const _);
+    f(&b as *const _);
+    f(&c as *const _);
+
+    // all: __security_check_cookie
+    // strong: __security_check_cookie
+    // basic: __security_check_cookie
+    // none-NOT: __security_check_cookie
+    // missing-NOT: __security_check_cookie
+}
+
+// CHECK-LABEL: array_u8_1
+#[no_mangle]
+pub fn array_u8_1(f: fn(*const u8)) {
+    let a = [0u8; 1];
+    f(&a as *const _);
+
+    // The 'strong' heuristic adds stack protection to functions with local
+    // array variables regardless of their size.
+
+    // all: __security_check_cookie
+    // strong: __security_check_cookie
+    // basic-NOT: __security_check_cookie
+    // none-NOT: __security_check_cookie
+    // missing-NOT: __security_check_cookie
+}
+
+// CHECK-LABEL: array_u8_small:
+#[no_mangle]
+pub fn array_u8_small(f: fn(*const u8)) {
+    let a = [0u8; 2];
+    let b = [0u8; 7];
+    f(&a as *const _);
+    f(&b as *const _);
+
+    // Small arrays do not lead to stack protection by the 'basic' heuristic.
+
+    // all: __security_check_cookie
+    // strong: __security_check_cookie
+    // basic-NOT: __security_check_cookie
+    // none-NOT: __security_check_cookie
+    // missing-NOT: __security_check_cookie
+}
+
+// CHECK-LABEL: array_u8_large:
+#[no_mangle]
+pub fn array_u8_large(f: fn(*const u8)) {
+    let a = [0u8; 9];
+    f(&a as *const _);
+
+    // Since `a` is a byte array with size greater than 8, the basic heuristic
+    // will also protect this function.
+
+    // all: __security_check_cookie
+    // strong: __security_check_cookie
+    // basic: __security_check_cookie
+    // none-NOT: __security_check_cookie
+    // missing-NOT: __security_check_cookie
+}
+
+#[derive(Copy, Clone)]
+pub struct ByteSizedNewtype(u8);
+
+// CHECK-LABEL: array_bytesizednewtype_9:
+#[no_mangle]
+pub fn array_bytesizednewtype_9(f: fn(*const ByteSizedNewtype)) {
+    let a = [ByteSizedNewtype(0); 9];
+    f(&a as *const _);
+
+    // Since `a` is a byte array in the LLVM output, the basic heuristic will
+    // also protect this function.
+
+    // all: __security_check_cookie
+    // strong: __security_check_cookie
+    // basic: __security_check_cookie
+    // none-NOT: __security_check_cookie
+    // missing-NOT: __security_check_cookie
+}
+
+// CHECK-LABEL: local_var_addr_used_indirectly
+#[no_mangle]
+pub fn local_var_addr_used_indirectly(f: fn(bool)) {
+    let a = 5;
+    let a_addr = &a as *const _ as usize;
+    f(a_addr & 0x10 == 0);
+
+    // This function takes the address of a local variable taken. Although this
+    // address is never used as a way to refer to stack memory, the `strong`
+    // heuristic adds stack smash protection. This is also the case in C++:
+    // ```
+    // cat << EOF | clang++ -O2 -fstack-protector-strong -S -x c++ - -o - | grep stack_chk
+    // #include <cstdint>
+    // void f(void (*g)(bool)) {
+    //     int32_t x;
+    //     g((reinterpret_cast<uintptr_t>(&x) & 0x10U) == 0);
+    // }
+    // EOF
+    // ```
+
+    // all: __security_check_cookie
+    // strong: __security_check_cookie
+    // basic-NOT: __security_check_cookie
+    // none-NOT: __security_check_cookie
+    // missing-NOT: __security_check_cookie
+}
+
+// CHECK-LABEL: local_string_addr_taken
+#[no_mangle]
+pub fn local_string_addr_taken(f: fn(&String)) {
+    let x = String::new();
+    f(&x);
+
+    // Taking the address of the local variable `x` leads to stack smash
+    // protection with the `strong` heuristic, but not with the `basic`
+    // heuristic. It does not matter that the reference is not mut.
+    //
+    // An interesting note is that a similar function in C++ *would* be
+    // protected by the `basic` heuristic, because `std::string` has a char
+    // array internally as a small object optimization:
+    // ```
+    // cat <<EOF | clang++ -O2 -fstack-protector -S -x c++ - -o - | grep stack_chk
+    // #include <string>
+    // void f(void (*g)(const std::string&)) {
+    //     std::string x;
+    //     g(x);
+    // }
+    // EOF
+    // ```
+    //
+
+    // all: __security_check_cookie
+    // strong-NOT: __security_check_cookie
+    // basic-NOT: __security_check_cookie
+    // none-NOT: __security_check_cookie
+    // missing-NOT: __security_check_cookie
+}
+
+pub trait SelfByRef {
+    fn f(&self) -> i32;
+}
+
+impl SelfByRef for i32 {
+    fn f(&self) -> i32 {
+        return self + 1;
+    }
+}
+
+// CHECK-LABEL: local_var_addr_taken_used_locally_only
+#[no_mangle]
+pub fn local_var_addr_taken_used_locally_only(factory: fn() -> i32, sink: fn(i32)) {
+    let x = factory();
+    let g = x.f();
+    sink(g);
+
+    // Even though the local variable conceptually has its address taken, as
+    // it's passed by reference to the trait function, the use of the reference
+    // is easily inlined. There is therefore no stack smash protection even with
+    // the `strong` heuristic.
+
+    // all: __security_check_cookie
+    // strong-NOT: __security_check_cookie
+    // basic-NOT: __security_check_cookie
+    // none-NOT: __security_check_cookie
+    // missing-NOT: __security_check_cookie
+}
+
+pub struct Gigastruct {
+    does: u64,
+    not: u64,
+    have: u64,
+    array: u64,
+    members: u64,
+}
+
+// CHECK-LABEL: local_large_var_moved
+#[no_mangle]
+pub fn local_large_var_moved(f: fn(Gigastruct)) {
+    let x = Gigastruct { does: 0, not: 1, have: 2, array: 3, members: 4 };
+    f(x);
+
+    // Even though the local variable conceptually doesn't have its address
+    // taken, it's so large that the "move" is implemented with a reference to a
+    // stack-local variable in the ABI. Consequently, this function *is*
+    // protected. This is also the case for rvalue-references in C++,
+    // regardless of struct size:
+    // ```
+    // cat <<EOF | clang++ -O2 -fstack-protector-strong -S -x c++ - -o - | grep stack_chk
+    // #include <cstdint>
+    // #include <utility>
+    // void f(void (*g)(uint64_t&&)) {
+    //     uint64_t x;
+    //     g(std::move(x));
+    // }
+    // EOF
+    // ```
+
+    // all: __security_check_cookie
+    // strong: __security_check_cookie
+    // basic: __security_check_cookie
+    // none-NOT: __security_check_cookie
+    // missing-NOT: __security_check_cookie
+}
+
+// CHECK-LABEL: local_large_var_cloned
+#[no_mangle]
+pub fn local_large_var_cloned(f: fn(Gigastruct)) {
+    f(Gigastruct { does: 0, not: 1, have: 2, array: 3, members: 4 });
+
+    // A new instance of `Gigastruct` is passed to `f()`, without any apparent
+    // connection to this stack frame. Still, since instances of `Gigastruct`
+    // are sufficiently large, it is allocated in the caller stack frame and
+    // passed as a pointer. As such, this function is *also* protected, just
+    // like `local_large_var_moved`. This is also the case for pass-by-value
+    // of sufficiently large structs in C++:
+    // ```
+    // cat <<EOF | clang++ -O2 -fstack-protector-strong -S -x c++ - -o - | grep stack_chk
+    // #include <cstdint>
+    // #include <utility>
+    // struct Gigastruct { uint64_t a, b, c, d, e; };
+    // void f(void (*g)(Gigastruct)) {
+    //     g(Gigastruct{});
+    // }
+    // EOF
+    // ```
+
+    // all: __security_check_cookie
+    // strong: __security_check_cookie
+    // basic: __security_check_cookie
+    // none-NOT: __security_check_cookie
+    // missing-NOT: __security_check_cookie
+}
+
+extern "C" {
+    // A call to an external `alloca` function is *not* recognized as an
+    // `alloca(3)` operation. This function is a compiler built-in, as the
+    // man page explains. Clang translates it to an LLVM `alloca`
+    // instruction with a count argument, which is also what the LLVM stack
+    // protector heuristics looks for. The man page for `alloca(3)` details
+    // a way to avoid using the compiler built-in: pass a -std=c11
+    // argument, *and* don't include <alloca.h>. Though this leads to an
+    // external alloca() function being called, it doesn't lead to stack
+    // protection being included. It even fails with a linker error
+    // "undefined reference to `alloca'". Example:
+    // ```
+    // cat<<EOF | clang -fstack-protector-strong -x c -std=c11 - -o /dev/null
+    // #include <stdlib.h>
+    // void * alloca(size_t);
+    // void f(void (*g)(void*)) {
+    //     void * p = alloca(10);
+    //     g(p);
+    // }
+    // int main() { return 0; }
+    // EOF
+    // ```
+    // The following tests demonstrate that calls to an external `alloca`
+    // function in Rust also doesn't trigger stack protection.
+
+    fn alloca(size: usize) -> *mut ();
+}
+
+// CHECK-LABEL: alloca_small_compile_time_constant_arg
+#[no_mangle]
+pub fn alloca_small_compile_time_constant_arg(f: fn(*mut ())) {
+    f(unsafe { alloca(8) });
+
+    // all: __security_check_cookie
+    // strong-NOT: __security_check_cookie
+    // basic-NOT: __security_check_cookie
+    // none-NOT: __security_check_cookie
+    // missing-NOT: __security_check_cookie
+}
+
+// CHECK-LABEL: alloca_large_compile_time_constant_arg
+#[no_mangle]
+pub fn alloca_large_compile_time_constant_arg(f: fn(*mut ())) {
+    f(unsafe { alloca(9) });
+
+    // all: __security_check_cookie
+    // strong-NOT: __security_check_cookie
+    // basic-NOT: __security_check_cookie
+    // none-NOT: __security_check_cookie
+    // missing-NOT: __security_check_cookie
+}
+
+// CHECK-LABEL: alloca_dynamic_arg
+#[no_mangle]
+pub fn alloca_dynamic_arg(f: fn(*mut ()), n: usize) {
+    f(unsafe { alloca(n) });
+
+    // all: __security_check_cookie
+    // strong-NOT: __security_check_cookie
+    // basic-NOT: __security_check_cookie
+    // none-NOT: __security_check_cookie
+    // missing-NOT: __security_check_cookie
+}
+
+// The question then is: in what ways can Rust code generate array-`alloca`
+// LLVM instructions? This appears to only be generated by
+// rustc_codegen_ssa::traits::Builder::array_alloca() through
+// rustc_codegen_ssa::mir::operand::OperandValue::store_unsized(). FWICT
+// this is support for the "unsized locals" unstable feature:
+// https://doc.rust-lang.org/unstable-book/language-features/unsized-locals.html.
+
+// CHECK-LABEL: unsized_fn_param
+#[no_mangle]
+pub fn unsized_fn_param(s: [u8], l: bool, f: fn([u8])) {
+    let n = if l { 1 } else { 2 };
+    f(*Box::<[u8]>::from(&s[0..n])); // slice-copy with Box::from
+
+    // Even though slices are conceptually passed by-value both into this
+    // function and into `f()`, this is implemented with pass-by-reference
+    // using a suitably constructed fat-pointer (as if the functions
+    // accepted &[u8]). This function therefore doesn't need dynamic array
+    // alloca, and is therefore not protected by the `strong` or `basic`
+    // heuristics.
+
+    // We should have a __security_check_cookie call in `all` and `strong` modes but
+    // LLVM does not support generating stack protectors in functions with funclet
+    // based EH personalities.
+    // https://github.com/llvm/llvm-project/blob/37fd3c96b917096d8a550038f6e61cdf0fc4174f/llvm/lib/CodeGen/StackProtector.cpp#L103C1-L109C4
+    // all-NOT: __security_check_cookie
+    // strong-NOT: __security_check_cookie
+
+    // basic-NOT: __security_check_cookie
+    // none-NOT: __security_check_cookie
+    // missing-NOT: __security_check_cookie
+}
diff --git a/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs b/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs
new file mode 100644
index 00000000000..9a3dabc74dd
--- /dev/null
+++ b/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs
@@ -0,0 +1,366 @@
+//@ revisions: all strong basic none missing
+//@ assembly-output: emit-asm
+//@ only-windows
+//@ only-msvc
+//@ ignore-32bit 64-bit table based SEH has slightly different behaviors than classic SEH
+//@ [all] compile-flags: -Z stack-protector=all
+//@ [strong] compile-flags: -Z stack-protector=strong
+//@ [basic] compile-flags: -Z stack-protector=basic
+//@ [none] compile-flags: -Z stack-protector=none
+//@ compile-flags: -C opt-level=2 -Z merge-functions=disabled
+
+#![crate_type = "lib"]
+#![feature(unsized_fn_params)]
+
+// CHECK-LABEL: emptyfn:
+#[no_mangle]
+pub fn emptyfn() {
+    // all: __security_check_cookie
+    // strong-NOT: __security_check_cookie
+    // basic-NOT: __security_check_cookie
+    // none-NOT: __security_check_cookie
+    // missing-NOT: __security_check_cookie
+}
+
+// CHECK-LABEL: array_char
+#[no_mangle]
+pub fn array_char(f: fn(*const char)) {
+    let a = ['c'; 1];
+    let b = ['d'; 3];
+    let c = ['e'; 15];
+
+    f(&a as *const _);
+    f(&b as *const _);
+    f(&c as *const _);
+
+    // all: __security_check_cookie
+    // strong: __security_check_cookie
+    // basic: __security_check_cookie
+    // none-NOT: __security_check_cookie
+    // missing-NOT: __security_check_cookie
+}
+
+// CHECK-LABEL: array_u8_1
+#[no_mangle]
+pub fn array_u8_1(f: fn(*const u8)) {
+    let a = [0u8; 1];
+    f(&a as *const _);
+
+    // The 'strong' heuristic adds stack protection to functions with local
+    // array variables regardless of their size.
+
+    // all: __security_check_cookie
+    // strong: __security_check_cookie
+    // basic-NOT: __security_check_cookie
+    // none-NOT: __security_check_cookie
+    // missing-NOT: __security_check_cookie
+}
+
+// CHECK-LABEL: array_u8_small:
+#[no_mangle]
+pub fn array_u8_small(f: fn(*const u8)) {
+    let a = [0u8; 2];
+    let b = [0u8; 7];
+    f(&a as *const _);
+    f(&b as *const _);
+
+    // Small arrays do not lead to stack protection by the 'basic' heuristic.
+
+    // all: __security_check_cookie
+    // strong: __security_check_cookie
+    // basic-NOT: __security_check_cookie
+    // none-NOT: __security_check_cookie
+    // missing-NOT: __security_check_cookie
+}
+
+// CHECK-LABEL: array_u8_large:
+#[no_mangle]
+pub fn array_u8_large(f: fn(*const u8)) {
+    let a = [0u8; 9];
+    f(&a as *const _);
+
+    // Since `a` is a byte array with size greater than 8, the basic heuristic
+    // will also protect this function.
+
+    // all: __security_check_cookie
+    // strong: __security_check_cookie
+    // basic: __security_check_cookie
+    // none-NOT: __security_check_cookie
+    // missing-NOT: __security_check_cookie
+}
+
+#[derive(Copy, Clone)]
+pub struct ByteSizedNewtype(u8);
+
+// CHECK-LABEL: array_bytesizednewtype_9:
+#[no_mangle]
+pub fn array_bytesizednewtype_9(f: fn(*const ByteSizedNewtype)) {
+    let a = [ByteSizedNewtype(0); 9];
+    f(&a as *const _);
+
+    // Since `a` is a byte array in the LLVM output, the basic heuristic will
+    // also protect this function.
+
+    // all: __security_check_cookie
+    // strong: __security_check_cookie
+    // basic: __security_check_cookie
+    // none-NOT: __security_check_cookie
+    // missing-NOT: __security_check_cookie
+}
+
+// CHECK-LABEL: local_var_addr_used_indirectly
+#[no_mangle]
+pub fn local_var_addr_used_indirectly(f: fn(bool)) {
+    let a = 5;
+    let a_addr = &a as *const _ as usize;
+    f(a_addr & 0x10 == 0);
+
+    // This function takes the address of a local variable taken. Although this
+    // address is never used as a way to refer to stack memory, the `strong`
+    // heuristic adds stack smash protection. This is also the case in C++:
+    // ```
+    // cat << EOF | clang++ -O2 -fstack-protector-strong -S -x c++ - -o - | grep stack_chk
+    // #include <cstdint>
+    // void f(void (*g)(bool)) {
+    //     int32_t x;
+    //     g((reinterpret_cast<uintptr_t>(&x) & 0x10U) == 0);
+    // }
+    // EOF
+    // ```
+
+    // all: __security_check_cookie
+    // strong: __security_check_cookie
+    // basic-NOT: __security_check_cookie
+    // none-NOT: __security_check_cookie
+    // missing-NOT: __security_check_cookie
+}
+
+// CHECK-LABEL: local_string_addr_taken
+#[no_mangle]
+pub fn local_string_addr_taken(f: fn(&String)) {
+    // CHECK-DAG: .seh_endprologue
+    let x = String::new();
+    f(&x);
+
+    // Taking the address of the local variable `x` leads to stack smash
+    // protection with the `strong` heuristic, but not with the `basic`
+    // heuristic. It does not matter that the reference is not mut.
+    //
+    // An interesting note is that a similar function in C++ *would* be
+    // protected by the `basic` heuristic, because `std::string` has a char
+    // array internally as a small object optimization:
+    // ```
+    // cat <<EOF | clang++ -O2 -fstack-protector -S -x c++ - -o - | grep stack_chk
+    // #include <string>
+    // void f(void (*g)(const std::string&)) {
+    //     std::string x;
+    //     g(x);
+    // }
+    // EOF
+    // ```
+    //
+
+    // We should have a __security_check_cookie call in `all` and `strong` modes but
+    // LLVM does not support generating stack protectors in functions with funclet
+    // based EH personalities.
+    // https://github.com/llvm/llvm-project/blob/37fd3c96b917096d8a550038f6e61cdf0fc4174f/llvm/lib/CodeGen/StackProtector.cpp#L103C1-L109C4
+    // all-NOT: __security_check_cookie
+    // strong-NOT: __security_check_cookie
+
+    // basic-NOT: __security_check_cookie
+    // none-NOT: __security_check_cookie
+    // missing-NOT: __security_check_cookie
+
+    // CHECK-DAG: .seh_endproc
+}
+
+pub trait SelfByRef {
+    fn f(&self) -> i32;
+}
+
+impl SelfByRef for i32 {
+    fn f(&self) -> i32 {
+        return self + 1;
+    }
+}
+
+// CHECK-LABEL: local_var_addr_taken_used_locally_only
+#[no_mangle]
+pub fn local_var_addr_taken_used_locally_only(factory: fn() -> i32, sink: fn(i32)) {
+    let x = factory();
+    let g = x.f();
+    sink(g);
+
+    // Even though the local variable conceptually has its address taken, as
+    // it's passed by reference to the trait function, the use of the reference
+    // is easily inlined. There is therefore no stack smash protection even with
+    // the `strong` heuristic.
+
+    // all: __security_check_cookie
+    // strong-NOT: __security_check_cookie
+    // basic-NOT: __security_check_cookie
+    // none-NOT: __security_check_cookie
+    // missing-NOT: __security_check_cookie
+}
+
+pub struct Gigastruct {
+    does: u64,
+    not: u64,
+    have: u64,
+    array: u64,
+    members: u64,
+}
+
+// CHECK-LABEL: local_large_var_moved
+#[no_mangle]
+pub fn local_large_var_moved(f: fn(Gigastruct)) {
+    let x = Gigastruct { does: 0, not: 1, have: 2, array: 3, members: 4 };
+    f(x);
+
+    // Even though the local variable conceptually doesn't have its address
+    // taken, it's so large that the "move" is implemented with a reference to a
+    // stack-local variable in the ABI. Consequently, this function *is*
+    // protected. This is also the case for rvalue-references in C++,
+    // regardless of struct size:
+    // ```
+    // cat <<EOF | clang++ -O2 -fstack-protector-strong -S -x c++ - -o - | grep stack_chk
+    // #include <cstdint>
+    // #include <utility>
+    // void f(void (*g)(uint64_t&&)) {
+    //     uint64_t x;
+    //     g(std::move(x));
+    // }
+    // EOF
+    // ```
+
+    // all: __security_check_cookie
+    // strong: __security_check_cookie
+    // basic: __security_check_cookie
+    // none-NOT: __security_check_cookie
+    // missing-NOT: __security_check_cookie
+}
+
+// CHECK-LABEL: local_large_var_cloned
+#[no_mangle]
+pub fn local_large_var_cloned(f: fn(Gigastruct)) {
+    f(Gigastruct { does: 0, not: 1, have: 2, array: 3, members: 4 });
+
+    // A new instance of `Gigastruct` is passed to `f()`, without any apparent
+    // connection to this stack frame. Still, since instances of `Gigastruct`
+    // are sufficiently large, it is allocated in the caller stack frame and
+    // passed as a pointer. As such, this function is *also* protected, just
+    // like `local_large_var_moved`. This is also the case for pass-by-value
+    // of sufficiently large structs in C++:
+    // ```
+    // cat <<EOF | clang++ -O2 -fstack-protector-strong -S -x c++ - -o - | grep stack_chk
+    // #include <cstdint>
+    // #include <utility>
+    // struct Gigastruct { uint64_t a, b, c, d, e; };
+    // void f(void (*g)(Gigastruct)) {
+    //     g(Gigastruct{});
+    // }
+    // EOF
+    // ```
+
+    // all: __security_check_cookie
+    // strong: __security_check_cookie
+    // basic: __security_check_cookie
+    // none-NOT: __security_check_cookie
+    // missing-NOT: __security_check_cookie
+}
+
+extern "C" {
+    // A call to an external `alloca` function is *not* recognized as an
+    // `alloca(3)` operation. This function is a compiler built-in, as the
+    // man page explains. Clang translates it to an LLVM `alloca`
+    // instruction with a count argument, which is also what the LLVM stack
+    // protector heuristics looks for. The man page for `alloca(3)` details
+    // a way to avoid using the compiler built-in: pass a -std=c11
+    // argument, *and* don't include <alloca.h>. Though this leads to an
+    // external alloca() function being called, it doesn't lead to stack
+    // protection being included. It even fails with a linker error
+    // "undefined reference to `alloca'". Example:
+    // ```
+    // cat<<EOF | clang -fstack-protector-strong -x c -std=c11 - -o /dev/null
+    // #include <stdlib.h>
+    // void * alloca(size_t);
+    // void f(void (*g)(void*)) {
+    //     void * p = alloca(10);
+    //     g(p);
+    // }
+    // int main() { return 0; }
+    // EOF
+    // ```
+    // The following tests demonstrate that calls to an external `alloca`
+    // function in Rust also doesn't trigger stack protection.
+
+    fn alloca(size: usize) -> *mut ();
+}
+
+// CHECK-LABEL: alloca_small_compile_time_constant_arg
+#[no_mangle]
+pub fn alloca_small_compile_time_constant_arg(f: fn(*mut ())) {
+    f(unsafe { alloca(8) });
+
+    // all: __security_check_cookie
+    // strong-NOT: __security_check_cookie
+    // basic-NOT: __security_check_cookie
+    // none-NOT: __security_check_cookie
+    // missing-NOT: __security_check_cookie
+}
+
+// CHECK-LABEL: alloca_large_compile_time_constant_arg
+#[no_mangle]
+pub fn alloca_large_compile_time_constant_arg(f: fn(*mut ())) {
+    f(unsafe { alloca(9) });
+
+    // all: __security_check_cookie
+    // strong-NOT: __security_check_cookie
+    // basic-NOT: __security_check_cookie
+    // none-NOT: __security_check_cookie
+    // missing-NOT: __security_check_cookie
+}
+
+// CHECK-LABEL: alloca_dynamic_arg
+#[no_mangle]
+pub fn alloca_dynamic_arg(f: fn(*mut ()), n: usize) {
+    f(unsafe { alloca(n) });
+
+    // all: __security_check_cookie
+    // strong-NOT: __security_check_cookie
+    // basic-NOT: __security_check_cookie
+    // none-NOT: __security_check_cookie
+    // missing-NOT: __security_check_cookie
+}
+
+// The question then is: in what ways can Rust code generate array-`alloca`
+// LLVM instructions? This appears to only be generated by
+// rustc_codegen_ssa::traits::Builder::array_alloca() through
+// rustc_codegen_ssa::mir::operand::OperandValue::store_unsized(). FWICT
+// this is support for the "unsized locals" unstable feature:
+// https://doc.rust-lang.org/unstable-book/language-features/unsized-locals.html.
+
+// CHECK-LABEL: unsized_fn_param
+#[no_mangle]
+pub fn unsized_fn_param(s: [u8], l: bool, f: fn([u8])) {
+    let n = if l { 1 } else { 2 };
+    f(*Box::<[u8]>::from(&s[0..n])); // slice-copy with Box::from
+
+    // Even though slices are conceptually passed by-value both into this
+    // function and into `f()`, this is implemented with pass-by-reference
+    // using a suitably constructed fat-pointer (as if the functions
+    // accepted &[u8]). This function therefore doesn't need dynamic array
+    // alloca, and is therefore not protected by the `strong` or `basic`
+    // heuristics.
+
+    // We should have a __security_check_cookie call in `all` and `strong` modes but
+    // LLVM does not support generating stack protectors in functions with funclet
+    // based EH personalities.
+    // https://github.com/llvm/llvm-project/blob/37fd3c96b917096d8a550038f6e61cdf0fc4174f/llvm/lib/CodeGen/StackProtector.cpp#L103C1-L109C4
+    // all-NOT: __security_check_cookie
+    // strong-NOT: __security_check_cookie
+
+    // basic-NOT: __security_check_cookie
+    // none-NOT: __security_check_cookie
+    // missing-NOT: __security_check_cookie
+}
diff --git a/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect.rs b/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect.rs
new file mode 100644
index 00000000000..ae281cb95da
--- /dev/null
+++ b/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect.rs
@@ -0,0 +1,345 @@
+//@ revisions: all strong basic none missing
+//@ assembly-output: emit-asm
+//@ ignore-apple slightly different policy on stack protection of arrays
+//@ ignore-msvc stack check code uses different function names
+//@ ignore-nvptx64 stack protector is not supported
+//@ ignore-wasm32-bare
+//@ [all] compile-flags: -Z stack-protector=all
+//@ [strong] compile-flags: -Z stack-protector=strong
+//@ [basic] compile-flags: -Z stack-protector=basic
+//@ [none] compile-flags: -Z stack-protector=none
+//@ compile-flags: -C opt-level=2 -Z merge-functions=disabled
+
+// NOTE: the heuristics for stack smash protection inappropriately rely on types in LLVM IR,
+// despite those types having no semantic meaning. This means that the `basic` and `strong`
+// settings do not behave in a coherent way. This is a known issue in LLVM.
+// See comments on https://github.com/rust-lang/rust/issues/114903.
+
+#![crate_type = "lib"]
+#![allow(internal_features)]
+#![feature(unsized_fn_params)]
+
+// CHECK-LABEL: emptyfn{{:|\[}}
+#[no_mangle]
+pub fn emptyfn() {
+    // all: __stack_chk_fail
+    // strong-NOT: __stack_chk_fail
+    // basic-NOT: __stack_chk_fail
+    // none-NOT: __stack_chk_fail
+    // missing-NOT: __stack_chk_fail
+}
+
+// CHECK-LABEL: array_char{{:|\[}}
+#[no_mangle]
+pub fn array_char(f: fn(*const char)) {
+    let a = ['c'; 1];
+    let b = ['d'; 3];
+    let c = ['e'; 15];
+
+    f(&a as *const _);
+    f(&b as *const _);
+    f(&c as *const _);
+
+    // all: __stack_chk_fail
+    // strong: __stack_chk_fail
+    // basic: __stack_chk_fail
+    // none-NOT: __stack_chk_fail
+    // missing-NOT: __stack_chk_fail
+}
+
+// CHECK-LABEL: array_u8_1{{:|\[}}
+#[no_mangle]
+pub fn array_u8_1(f: fn(*const u8)) {
+    let a = [0u8; 1];
+    f(&a as *const _);
+
+    // The 'strong' heuristic adds stack protection to functions with local
+    // array variables regardless of their size.
+
+    // all: __stack_chk_fail
+    // strong: __stack_chk_fail
+    // basic-NOT: __stack_chk_fail
+    // none-NOT: __stack_chk_fail
+    // missing-NOT: __stack_chk_fail
+}
+
+// CHECK-LABEL: array_u8_small{{:|\[}}
+#[no_mangle]
+pub fn array_u8_small(f: fn(*const u8)) {
+    let a = [0u8; 2];
+    let b = [0u8; 7];
+    f(&a as *const _);
+    f(&b as *const _);
+
+    // Small arrays do not lead to stack protection by the 'basic' heuristic.
+
+    // all: __stack_chk_fail
+    // strong: __stack_chk_fail
+    // basic-NOT: __stack_chk_fail
+    // none-NOT: __stack_chk_fail
+    // missing-NOT: __stack_chk_fail
+}
+
+// CHECK-LABEL: array_u8_large{{:|\[}}
+#[no_mangle]
+pub fn array_u8_large(f: fn(*const u8)) {
+    let a = [0u8; 9];
+    f(&a as *const _);
+
+    // Since `a` is a byte array with size greater than 8, the basic heuristic
+    // will also protect this function.
+
+    // all: __stack_chk_fail
+    // strong: __stack_chk_fail
+    // basic: __stack_chk_fail
+    // none-NOT: __stack_chk_fail
+    // missing-NOT: __stack_chk_fail
+}
+
+#[derive(Copy, Clone)]
+pub struct ByteSizedNewtype(u8);
+
+// CHECK-LABEL: array_bytesizednewtype_9{{:|\[}}
+#[no_mangle]
+pub fn array_bytesizednewtype_9(f: fn(*const ByteSizedNewtype)) {
+    let a = [ByteSizedNewtype(0); 9];
+    f(&a as *const _);
+
+    // Since `a` is a byte array in the LLVM output, the basic heuristic will
+    // also protect this function.
+
+    // all: __stack_chk_fail
+    // strong: __stack_chk_fail
+    // basic: __stack_chk_fail
+    // none-NOT: __stack_chk_fail
+    // missing-NOT: __stack_chk_fail
+}
+
+// CHECK-LABEL: local_var_addr_used_indirectly{{:|\[}}
+#[no_mangle]
+pub fn local_var_addr_used_indirectly(f: fn(bool)) {
+    let a = 5;
+    let a_addr = &a as *const _ as usize;
+    f(a_addr & 0x10 == 0);
+
+    // This function takes the address of a local variable taken. Although this
+    // address is never used as a way to refer to stack memory, the `strong`
+    // heuristic adds stack smash protection. This is also the case in C++:
+    // ```
+    // cat << EOF | clang++ -O2 -fstack-protector-strong -S -x c++ - -o - | grep stack_chk
+    // #include <cstdint>
+    // void f(void (*g)(bool)) {
+    //     int32_t x;
+    //     g((reinterpret_cast<uintptr_t>(&x) & 0x10U) == 0);
+    // }
+    // EOF
+    // ```
+
+    // all: __stack_chk_fail
+    // strong: __stack_chk_fail
+    // basic-NOT: __stack_chk_fail
+    // none-NOT: __stack_chk_fail
+    // missing-NOT: __stack_chk_fail
+}
+
+// CHECK-LABEL: local_string_addr_taken{{:|\[}}
+#[no_mangle]
+pub fn local_string_addr_taken(f: fn(&String)) {
+    let x = String::new();
+    f(&x);
+
+    // Taking the address of the local variable `x` leads to stack smash
+    // protection. It does not matter that the reference is not mut.
+
+    // all: __stack_chk_fail
+    // strong: __stack_chk_fail
+    // basic: __stack_chk_fail
+    // none-NOT: __stack_chk_fail
+    // missing-NOT: __stack_chk_fail
+}
+
+pub trait SelfByRef {
+    fn f(&self) -> i32;
+}
+
+impl SelfByRef for i32 {
+    fn f(&self) -> i32 {
+        return self + 1;
+    }
+}
+
+// CHECK-LABEL: local_var_addr_taken_used_locally_only{{:|\[}}
+#[no_mangle]
+pub fn local_var_addr_taken_used_locally_only(factory: fn() -> i32, sink: fn(i32)) {
+    let x = factory();
+    let g = x.f();
+    sink(g);
+
+    // Even though the local variable conceptually has its address taken, as
+    // it's passed by reference to the trait function, the use of the reference
+    // is easily inlined. There is therefore no stack smash protection even with
+    // the `strong` heuristic.
+
+    // all: __stack_chk_fail
+    // strong-NOT: __stack_chk_fail
+    // basic-NOT: __stack_chk_fail
+    // none-NOT: __stack_chk_fail
+    // missing-NOT: __stack_chk_fail
+}
+
+pub struct Gigastruct {
+    does: u64,
+    not: u64,
+    have: u64,
+    array: u64,
+    members: u64,
+}
+
+// CHECK-LABEL: local_large_var_moved{{:|\[}}
+#[no_mangle]
+pub fn local_large_var_moved(f: fn(Gigastruct)) {
+    let x = Gigastruct { does: 0, not: 1, have: 2, array: 3, members: 4 };
+    f(x);
+
+    // Even though the local variable conceptually doesn't have its address
+    // taken, it's so large that the "move" is implemented with a reference to a
+    // stack-local variable in the ABI. Consequently, this function *is*
+    // protected. This is also the case for rvalue-references in C++,
+    // regardless of struct size:
+    // ```
+    // cat <<EOF | clang++ -O2 -fstack-protector-strong -S -x c++ - -o - | grep stack_chk
+    // #include <cstdint>
+    // #include <utility>
+    // void f(void (*g)(uint64_t&&)) {
+    //     uint64_t x;
+    //     g(std::move(x));
+    // }
+    // EOF
+    // ```
+
+    // all: __stack_chk_fail
+    // strong: __stack_chk_fail
+    // basic: __stack_chk_fail
+    // none-NOT: __stack_chk_fail
+    // missing-NOT: __stack_chk_fail
+}
+
+// CHECK-LABEL: local_large_var_cloned{{:|\[}}
+#[no_mangle]
+pub fn local_large_var_cloned(f: fn(Gigastruct)) {
+    f(Gigastruct { does: 0, not: 1, have: 2, array: 3, members: 4 });
+
+    // A new instance of `Gigastruct` is passed to `f()`, without any apparent
+    // connection to this stack frame. Still, since instances of `Gigastruct`
+    // are sufficiently large, it is allocated in the caller stack frame and
+    // passed as a pointer. As such, this function is *also* protected, just
+    // like `local_large_var_moved`. This is also the case for pass-by-value
+    // of sufficiently large structs in C++:
+    // ```
+    // cat <<EOF | clang++ -O2 -fstack-protector-strong -S -x c++ - -o - | grep stack_chk
+    // #include <cstdint>
+    // #include <utility>
+    // struct Gigastruct { uint64_t a, b, c, d, e; };
+    // void f(void (*g)(Gigastruct)) {
+    //     g(Gigastruct{});
+    // }
+    // EOF
+    // ```
+
+    // all: __stack_chk_fail
+    // strong: __stack_chk_fail
+    // basic: __stack_chk_fail
+    // none-NOT: __stack_chk_fail
+    // missing-NOT: __stack_chk_fail
+}
+
+extern "C" {
+    // A call to an external `alloca` function is *not* recognized as an
+    // `alloca(3)` operation. This function is a compiler built-in, as the
+    // man page explains. Clang translates it to an LLVM `alloca`
+    // instruction with a count argument, which is also what the LLVM stack
+    // protector heuristics looks for. The man page for `alloca(3)` details
+    // a way to avoid using the compiler built-in: pass a -std=c11
+    // argument, *and* don't include <alloca.h>. Though this leads to an
+    // external alloca() function being called, it doesn't lead to stack
+    // protection being included. It even fails with a linker error
+    // "undefined reference to `alloca'". Example:
+    // ```
+    // cat<<EOF | clang -fstack-protector-strong -x c -std=c11 - -o /dev/null
+    // #include <stdlib.h>
+    // void * alloca(size_t);
+    // void f(void (*g)(void*)) {
+    //     void * p = alloca(10);
+    //     g(p);
+    // }
+    // int main() { return 0; }
+    // EOF
+    // ```
+    // The following tests demonstrate that calls to an external `alloca`
+    // function in Rust also doesn't trigger stack protection.
+
+    fn alloca(size: usize) -> *mut ();
+}
+
+// CHECK-LABEL: alloca_small_compile_time_constant_arg{{:|\[}}
+#[no_mangle]
+pub fn alloca_small_compile_time_constant_arg(f: fn(*mut ())) {
+    f(unsafe { alloca(8) });
+
+    // all: __stack_chk_fail
+    // strong-NOT: __stack_chk_fail
+    // basic-NOT: __stack_chk_fail
+    // none-NOT: __stack_chk_fail
+    // missing-NOT: __stack_chk_fail
+}
+
+// CHECK-LABEL: alloca_large_compile_time_constant_arg{{:|\[}}
+#[no_mangle]
+pub fn alloca_large_compile_time_constant_arg(f: fn(*mut ())) {
+    f(unsafe { alloca(9) });
+
+    // all: __stack_chk_fail
+    // strong-NOT: __stack_chk_fail
+    // basic-NOT: __stack_chk_fail
+    // none-NOT: __stack_chk_fail
+    // missing-NOT: __stack_chk_fail
+}
+
+// CHECK-LABEL: alloca_dynamic_arg{{:|\[}}
+#[no_mangle]
+pub fn alloca_dynamic_arg(f: fn(*mut ()), n: usize) {
+    f(unsafe { alloca(n) });
+
+    // all: __stack_chk_fail
+    // strong-NOT: __stack_chk_fail
+    // basic-NOT: __stack_chk_fail
+    // none-NOT: __stack_chk_fail
+    // missing-NOT: __stack_chk_fail
+}
+
+// The question then is: in what ways can Rust code generate array-`alloca`
+// LLVM instructions? This appears to only be generated by
+// rustc_codegen_ssa::traits::Builder::array_alloca() through
+// rustc_codegen_ssa::mir::operand::OperandValue::store_unsized(). FWICT
+// this is support for the "unsized locals" unstable feature:
+// https://doc.rust-lang.org/unstable-book/language-features/unsized-locals.html.
+
+// CHECK-LABEL: unsized_fn_param{{:|\[}}
+#[no_mangle]
+pub fn unsized_fn_param(s: [u8], l: bool, f: fn([u8])) {
+    let n = if l { 1 } else { 2 };
+    f(*Box::<[u8]>::from(&s[0..n])); // slice-copy with Box::from
+
+    // Even though slices are conceptually passed by-value both into this
+    // function and into `f()`, this is implemented with pass-by-reference
+    // using a suitably constructed fat-pointer (as if the functions
+    // accepted &[u8]). This function therefore doesn't need dynamic array
+    // alloca, and is therefore not protected by the `strong` or `basic`
+    // heuristics.
+
+    // all: __stack_chk_fail
+    // strong-NOT: __stack_chk_fail
+    // basic-NOT: __stack_chk_fail
+    // none-NOT: __stack_chk_fail
+    // missing-NOT: __stack_chk_fail
+}
diff --git a/tests/assembly-llvm/stack-protector/stack-protector-target-support.rs b/tests/assembly-llvm/stack-protector/stack-protector-target-support.rs
new file mode 100644
index 00000000000..a937256a60f
--- /dev/null
+++ b/tests/assembly-llvm/stack-protector/stack-protector-target-support.rs
@@ -0,0 +1,281 @@
+// Test that stack smash protection code is emitted for all tier1 and tier2
+// targets, with the exception of nvptx64-nvidia-cuda
+//
+//@ add-core-stubs
+//@ revisions: r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 r15 r16 r17 r18 r19 r20 r21 r22 r23
+//@ revisions: r24 r25 r26 r27 r28 r29 r30 r31 r32 r33         r36 r37 r38 r39 r40 r41 r42 r43 r44
+//@ revisions: r45 r46 r47 r48 r49 r50 r51 r52 r53 r54 r55 r56 r57 r58 r59 r60 r61 r62 r63 r64 r65
+//@ revisions: r66 r67 r68 r69 r70 r71 r72 r73 r74 r75 r76 r77 r78 r79 r80 r81 r82 r83 r84 r85
+//@ assembly-output: emit-asm
+//@ [r1] compile-flags: --target aarch64-unknown-linux-gnu
+//@ [r1] needs-llvm-components: aarch64
+//@ [r2] compile-flags: --target i686-pc-windows-gnu
+//@ [r2] needs-llvm-components: x86
+//@ [r3] compile-flags: --target i686-pc-windows-msvc
+//@ [r3] needs-llvm-components: x86
+//@ [r4] compile-flags: --target i686-unknown-linux-gnu
+//@ [r4] needs-llvm-components: x86
+//@ [r5] compile-flags: --target x86_64-apple-darwin
+//@ [r5] needs-llvm-components: x86
+//@ [r6] compile-flags: --target x86_64-pc-windows-gnu
+//@ [r6] needs-llvm-components: x86
+//@ [r7] compile-flags: --target x86_64-pc-windows-msvc
+//@ [r7] needs-llvm-components: x86
+//@ [r8] compile-flags: --target x86_64-unknown-linux-gnu
+//@ [r8] needs-llvm-components: x86
+//@ [r9] compile-flags: --target aarch64-apple-darwin
+//@ [r9] needs-llvm-components: aarch64
+//@ [r10] compile-flags: --target aarch64-apple-ios
+//@ [r10] needs-llvm-components: aarch64
+//@ [r11] compile-flags: --target aarch64-unknown-fuchsia
+//@ [r11] needs-llvm-components: aarch64
+//@ [r12] compile-flags: --target aarch64-linux-android
+//@ [r12] needs-llvm-components: aarch64
+//@ [r13] compile-flags: --target aarch64-pc-windows-msvc
+//@ [r13] needs-llvm-components: aarch64
+//@ [r14] compile-flags: --target aarch64-unknown-linux-musl
+//@ [r14] needs-llvm-components: aarch64
+//@ [r15] compile-flags: --target aarch64-unknown-none
+//@ [r15] needs-llvm-components: aarch64
+//@ [r16] compile-flags: --target aarch64-unknown-none-softfloat
+//@ [r16] needs-llvm-components: aarch64
+//@ [r17] compile-flags: --target arm-linux-androideabi
+//@ [r17] needs-llvm-components: arm
+//@ [r18] compile-flags: --target arm-unknown-linux-gnueabi
+//@ [r18] needs-llvm-components: arm
+//@ [r19] compile-flags: --target arm-unknown-linux-gnueabihf
+//@ [r19] needs-llvm-components: arm
+//@ [r20] compile-flags: --target arm-unknown-linux-musleabi
+//@ [r20] needs-llvm-components: arm
+//@ [r21] compile-flags: --target arm-unknown-linux-musleabihf
+//@ [r21] needs-llvm-components: arm
+//@ [r22] compile-flags: --target armebv7r-none-eabi
+//@ [r22] needs-llvm-components: arm
+//@ [r23] compile-flags: --target armebv7r-none-eabihf
+//@ [r23] needs-llvm-components: arm
+//@ [r24] compile-flags: --target armv5te-unknown-linux-gnueabi
+//@ [r24] needs-llvm-components: arm
+//@ [r25] compile-flags: --target armv5te-unknown-linux-musleabi
+//@ [r25] needs-llvm-components: arm
+//@ [r26] compile-flags: --target armv7-linux-androideabi
+//@ [r26] needs-llvm-components: arm
+//@ [r27] compile-flags: --target armv7a-none-eabi
+//@ [r27] needs-llvm-components: arm
+//@ [r28] compile-flags: --target armv7r-none-eabi
+//@ [r28] needs-llvm-components: arm
+//@ [r29] compile-flags: --target armv7r-none-eabihf
+//@ [r29] needs-llvm-components: arm
+//@ [r30] compile-flags: --target armv7-unknown-linux-gnueabi
+//@ [r30] needs-llvm-components: arm
+//@ [r31] compile-flags: --target armv7-unknown-linux-gnueabihf
+//@ [r31] needs-llvm-components: arm
+//@ [r32] compile-flags: --target armv7-unknown-linux-musleabi
+//@ [r32] needs-llvm-components: arm
+//@ [r33] compile-flags: --target armv7-unknown-linux-musleabihf
+//@ [r33] needs-llvm-components: arm
+//@ [r36] compile-flags: --target i586-unknown-linux-gnu
+//@ [r36] needs-llvm-components: x86
+//@ [r37] compile-flags: --target i586-unknown-linux-musl
+//@ [r37] needs-llvm-components: x86
+//@ [r38] compile-flags: --target i686-linux-android
+//@ [r38] needs-llvm-components: x86
+//@ [r39] compile-flags: --target i686-unknown-freebsd
+//@ [r39] needs-llvm-components: x86
+//@ [r40] compile-flags: --target i686-unknown-linux-musl
+//@ [r40] needs-llvm-components: x86
+//@ [r41] compile-flags: --target mips-unknown-linux-gnu
+//@ [r41] needs-llvm-components: mips
+//@ [r42] compile-flags: --target mips-unknown-linux-musl
+//@ [r42] needs-llvm-components: mips
+//@ [r43] compile-flags: --target mips64-unknown-linux-gnuabi64
+//@ [r43] needs-llvm-components: mips
+//@ [r44] compile-flags: --target mips64-unknown-linux-muslabi64
+//@ [r44] needs-llvm-components: mips
+//@ [r45] compile-flags: --target mips64el-unknown-linux-gnuabi64
+//@ [r45] needs-llvm-components: mips
+//@ [r46] compile-flags: --target mips64el-unknown-linux-muslabi64
+//@ [r46] needs-llvm-components: mips
+//@ [r47] compile-flags: --target mipsel-unknown-linux-gnu
+//@ [r47] needs-llvm-components: mips
+//@ [r48] compile-flags: --target mipsel-unknown-linux-musl
+//@ [r48] needs-llvm-components: mips
+//@ [r49] compile-flags: --target nvptx64-nvidia-cuda
+//@ [r49] needs-llvm-components: nvptx
+//@ [r50] compile-flags: --target powerpc-unknown-linux-gnu
+//@ [r50] needs-llvm-components: powerpc
+//@ [r51] compile-flags: --target powerpc64-unknown-linux-gnu
+//@ [r51] needs-llvm-components: powerpc
+//@ [r52] compile-flags: --target powerpc64le-unknown-linux-gnu
+//@ [r52] needs-llvm-components: powerpc
+//@ [r53] compile-flags: --target riscv32i-unknown-none-elf
+//@ [r53] needs-llvm-components: riscv
+//@ [r54] compile-flags: --target riscv32imac-unknown-none-elf
+//@ [r54] needs-llvm-components: riscv
+//@ [r55] compile-flags:--target riscv32imc-unknown-none-elf
+//@ [r55] needs-llvm-components: riscv
+//@ [r56] compile-flags:--target riscv64gc-unknown-linux-gnu
+//@ [r56] needs-llvm-components: riscv
+//@ [r57] compile-flags:--target riscv64gc-unknown-none-elf
+//@ [r57] needs-llvm-components: riscv
+//@ [r58] compile-flags:--target riscv64imac-unknown-none-elf
+//@ [r58] needs-llvm-components: riscv
+//@ [r59] compile-flags:--target s390x-unknown-linux-gnu
+//@ [r59] needs-llvm-components: systemz
+//@ [r60] compile-flags:--target sparc64-unknown-linux-gnu
+//@ [r60] needs-llvm-components: sparc
+//@ [r61] compile-flags:--target sparcv9-sun-solaris
+//@ [r61] needs-llvm-components: sparc
+//@ [r62] compile-flags:--target thumbv6m-none-eabi
+//@ [r62] needs-llvm-components: arm
+//@ [r63] compile-flags:--target thumbv7em-none-eabi
+//@ [r63] needs-llvm-components: arm
+//@ [r64] compile-flags:--target thumbv7em-none-eabihf
+//@ [r64] needs-llvm-components: arm
+//@ [r65] compile-flags:--target thumbv7m-none-eabi
+//@ [r65] needs-llvm-components: arm
+//@ [r66] compile-flags:--target thumbv7neon-linux-androideabi
+//@ [r66] needs-llvm-components: arm
+//@ [r67] compile-flags:--target thumbv7neon-unknown-linux-gnueabihf
+//@ [r67] needs-llvm-components: arm
+//@ [r68] compile-flags:--target thumbv8m.base-none-eabi
+//@ [r68] needs-llvm-components: arm
+//@ [r69] compile-flags:--target thumbv8m.main-none-eabi
+//@ [r69] needs-llvm-components: arm
+//@ [r70] compile-flags:--target thumbv8m.main-none-eabihf
+//@ [r70] needs-llvm-components: arm
+//@ [r71] compile-flags:--target wasm32-unknown-emscripten
+//@ [r71] needs-llvm-components: webassembly
+//@ [r72] compile-flags:--target wasm32-unknown-unknown
+//@ [r72] needs-llvm-components: webassembly
+//@ [r73] compile-flags:--target wasm32-wasip1
+//@ [r73] needs-llvm-components: webassembly
+//@ [r74] compile-flags:--target wasm32-wasip1-threads
+//@ [r74] needs-llvm-components: webassembly
+//@ [r75] compile-flags:--target x86_64-apple-ios
+//@ [r75] needs-llvm-components: x86
+//@ [r76] compile-flags:--target x86_64-fortanix-unknown-sgx
+//@ [r76] needs-llvm-components: x86
+//@ [r77] compile-flags:--target x86_64-unknown-fuchsia
+//@ [r77] needs-llvm-components: x86
+//@ [r78] compile-flags:--target x86_64-linux-android
+//@ [r78] needs-llvm-components: x86
+//@ [r79] compile-flags:--target x86_64-pc-solaris
+//@ [r79] needs-llvm-components: x86
+//@ [r80] compile-flags:--target x86_64-unknown-freebsd
+//@ [r80] needs-llvm-components: x86
+//@ [r81] compile-flags:--target x86_64-unknown-illumos
+//@ [r81] needs-llvm-components: x86
+//@ [r82] compile-flags:--target x86_64-unknown-linux-gnux32
+//@ [r82] needs-llvm-components: x86
+//@ [r83] compile-flags:--target x86_64-unknown-linux-musl
+//@ [r83] needs-llvm-components: x86
+//@ [r84] compile-flags:--target x86_64-unknown-netbsd
+//@ [r84] needs-llvm-components: x86
+//@ [r85] compile-flags: --target x86_64-unknown-redox
+//@ [r85] needs-llvm-components: x86
+//@ compile-flags: -Z stack-protector=all
+//@ compile-flags: -C opt-level=2
+
+#![crate_type = "lib"]
+#![feature(no_core, lang_items)]
+#![crate_type = "lib"]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
+
+#[no_mangle]
+pub fn foo() {
+    // CHECK: foo{{:|()}}
+
+    // MSVC does the stack checking within a stack-check function:
+    // r3: calll @__security_check_cookie
+    // r7: callq __security_check_cookie
+    // r13: bl __security_check_cookie
+
+    // cuda doesn't support stack-smash protection
+    // r49-NOT: __security_check_cookie
+    // r49-NOT: __stack_chk_fail
+
+    // Other targets do stack checking within the function, and call a failure function on error
+    // r1: __stack_chk_fail
+    // r2: __stack_chk_fail
+    // r4: __stack_chk_fail
+    // r5: __stack_chk_fail
+    // r6: __stack_chk_fail
+    // r8: __stack_chk_fail
+    // r9: __stack_chk_fail
+    // r10: __stack_chk_fail
+    // r11: __stack_chk_fail
+    // r12: __stack_chk_fail
+    // r14: __stack_chk_fail
+    // r15: __stack_chk_fail
+    // r16: __stack_chk_fail
+    // r17: __stack_chk_fail
+    // r18: __stack_chk_fail
+    // r19: __stack_chk_fail
+    // r20: __stack_chk_fail
+    // r21: __stack_chk_fail
+    // r22: __stack_chk_fail
+    // r23: __stack_chk_fail
+    // r24: __stack_chk_fail
+    // r25: __stack_chk_fail
+    // r26: __stack_chk_fail
+    // r27: __stack_chk_fail
+    // r28: __stack_chk_fail
+    // r29: __stack_chk_fail
+    // r30: __stack_chk_fail
+    // r31: __stack_chk_fail
+    // r32: __stack_chk_fail
+    // r33: __stack_chk_fail
+    // r34: __stack_chk_fail
+    // r36: __stack_chk_fail
+    // r37: __stack_chk_fail
+    // r38: __stack_chk_fail
+    // r39: __stack_chk_fail
+    // r40: __stack_chk_fail
+    // r41: __stack_chk_fail
+    // r42: __stack_chk_fail
+    // r43: __stack_chk_fail
+    // r44: __stack_chk_fail
+    // r45: __stack_chk_fail
+    // r46: __stack_chk_fail
+    // r47: __stack_chk_fail
+    // r48: __stack_chk_fail
+    // r50: __stack_chk_fail
+    // r51: __stack_chk_fail
+    // r52: __stack_chk_fail
+    // r53: __stack_chk_fail
+    // r54: __stack_chk_fail
+    // r55: __stack_chk_fail
+    // r56: __stack_chk_fail
+    // r57: __stack_chk_fail
+    // r58: __stack_chk_fail
+    // r59: __stack_chk_fail
+    // r60: __stack_chk_fail
+    // r61: __stack_chk_fail
+    // r62: __stack_chk_fail
+    // r63: __stack_chk_fail
+    // r64: __stack_chk_fail
+    // r65: __stack_chk_fail
+    // r66: __stack_chk_fail
+    // r67: __stack_chk_fail
+    // r68: __stack_chk_fail
+    // r69: __stack_chk_fail
+    // r70: __stack_chk_fail
+    // r71: __stack_chk_fail
+    // r72: __stack_chk_fail
+    // r73: __stack_chk_fail
+    // r74: __stack_chk_fail
+    // r75: __stack_chk_fail
+    // r76: __stack_chk_fail
+    // r77: __stack_chk_fail
+    // r78: __stack_chk_fail
+    // r79: __stack_chk_fail
+    // r80: __stack_chk_fail
+    // r81: __stack_chk_fail
+    // r82: __stack_chk_fail
+    // r83: __stack_chk_fail
+    // r84: __stack_chk_fail
+    // r85: __stack_chk_fail
+}
diff --git a/tests/assembly-llvm/static-relocation-model.rs b/tests/assembly-llvm/static-relocation-model.rs
new file mode 100644
index 00000000000..35ad94133b2
--- /dev/null
+++ b/tests/assembly-llvm/static-relocation-model.rs
@@ -0,0 +1,69 @@
+//@ add-core-stubs
+//@ revisions: x64 A64 ppc64le
+//@ assembly-output: emit-asm
+//@ [x64] compile-flags: --target x86_64-unknown-linux-gnu -Crelocation-model=static
+//@ [x64] needs-llvm-components: x86
+//@ [A64] compile-flags: --target aarch64-unknown-linux-gnu -Crelocation-model=static
+//@ [A64] needs-llvm-components: aarch64
+//@ [ppc64le] compile-flags: --target powerpc64le-unknown-linux-gnu -Crelocation-model=static
+//@ [ppc64le] needs-llvm-components: powerpc
+
+#![feature(no_core, lang_items)]
+#![no_core]
+#![crate_type = "rlib"]
+
+extern crate minicore;
+use minicore::*;
+
+#[no_mangle]
+pub static PIERIS: u8 = 42;
+
+extern "C" {
+    static EXOCHORDA: *mut u8;
+
+    fn chaenomeles();
+}
+
+// CHECK-LABEL: banana:
+// LLVM may produce either kind of `mov` here, depending on version and optimization level.
+// x64: {{movb|movzbl}}   chaenomeles{{(\(%[a-z0-9]+\))?}}, %{{[a-z0-9]+}}
+// A64:      adrp    [[REG:[a-z0-9]+]], chaenomeles
+// A64-NEXT: ldrb    {{[a-z0-9]+}}, {{\[}}[[REG]], :lo12:chaenomeles]
+#[no_mangle]
+pub fn banana() -> u8 {
+    unsafe { *(chaenomeles as *mut u8) }
+}
+
+// CHECK-LABEL: peach:
+// x64: {{movb|movzbl}}    banana{{(\(%[a-z0-9]+\))?}}, %{{[a-z0-9]+}}
+// A64:      adrp    [[REG2:[a-z0-9]+]], banana
+// A64-NEXT: ldrb    {{[a-z0-9]+}}, {{\[}}[[REG2]], :lo12:banana]
+#[no_mangle]
+pub fn peach() -> u8 {
+    unsafe { *(banana as *mut u8) }
+}
+
+// CHECK-LABEL: mango:
+// x64:      movq    EXOCHORDA{{(\(%[a-z0-9]+\))?}}, %[[REG:[a-z0-9]+]]
+// x64-NEXT: {{movb|movzbl}}   (%[[REG]]), %{{[a-z0-9]+}}
+// A64:      adrp    [[REG2:[a-z0-9]+]], EXOCHORDA
+// A64-NEXT: ldr     {{[a-z0-9]+}}, {{\[}}[[REG2]], :lo12:EXOCHORDA]
+#[no_mangle]
+pub fn mango() -> u8 {
+    unsafe { *EXOCHORDA }
+}
+
+// CHECK-LABEL: orange:
+// x64: mov{{l|absq}}    $PIERIS, %{{[a-z0-9]+}}
+// A64:      adrp    [[REG2:[a-z0-9]+]], PIERIS
+// A64-NEXT: add     {{[a-z0-9]+}}, [[REG2]], :lo12:PIERIS
+#[no_mangle]
+pub fn orange() -> &'static u8 {
+    &PIERIS
+}
+
+// For ppc64 we need to make sure to generate TOC entries even with the static relocation model
+// ppc64le: .tc chaenomeles[TC],chaenomeles
+// ppc64le: .tc banana[TC],banana
+// ppc64le: .tc EXOCHORDA[TC],EXOCHORDA
+// ppc64le: .tc PIERIS[TC],PIERIS
diff --git a/tests/assembly-llvm/strict_provenance.rs b/tests/assembly-llvm/strict_provenance.rs
new file mode 100644
index 00000000000..1a797670962
--- /dev/null
+++ b/tests/assembly-llvm/strict_provenance.rs
@@ -0,0 +1,37 @@
+//@ assembly-output: emit-asm
+//@ compile-flags: -Copt-level=1
+//@ only-x86_64
+//@ ignore-sgx
+#![crate_type = "rlib"]
+
+// CHECK-LABEL: old_style
+// CHECK: movq %{{.*}}, %rax
+// CHECK: orq $1, %rax
+// CHECK: retq
+#[no_mangle]
+pub fn old_style(a: *mut u8) -> *mut u8 {
+    (a as usize | 1) as *mut u8
+}
+
+// CHECK-LABEL: cheri_compat
+// CHECK: movq %{{.*}}, %rax
+// CHECK: orq $1, %rax
+// CHECK: retq
+#[no_mangle]
+pub fn cheri_compat(a: *mut u8) -> *mut u8 {
+    let old = a as usize;
+    let new = old | 1;
+    let diff = new.wrapping_sub(old);
+    a.wrapping_add(diff)
+}
+
+// CHECK-LABEL: definitely_not_a_null_pointer
+// CHECK: movq %{{.*}}, %rax
+// CHECK: orq $1, %rax
+// CHECK: retq
+#[no_mangle]
+pub fn definitely_not_a_null_pointer(a: *mut u8) -> *mut u8 {
+    let old = a as usize;
+    let new = old | 1;
+    a.wrapping_sub(old).wrapping_add(new)
+}
diff --git a/tests/assembly-llvm/target-feature-multiple.rs b/tests/assembly-llvm/target-feature-multiple.rs
new file mode 100644
index 00000000000..9a941c52bda
--- /dev/null
+++ b/tests/assembly-llvm/target-feature-multiple.rs
@@ -0,0 +1,40 @@
+//@ add-core-stubs
+//@ assembly-output: emit-asm
+//@ needs-llvm-components: x86
+//@ revisions: TWOFLAGS SINGLEFLAG
+//@ compile-flags: --target=x86_64-unknown-linux-gnu
+//@ [TWOFLAGS] compile-flags: -C target-feature=+rdrnd -C target-feature=+rdseed
+//@ [SINGLEFLAG] compile-flags: -C target-feature=+rdrnd,+rdseed
+
+// Target features set via flags aren't necessarily reflected in the IR, so the only way to test
+// them is to build code that requires the features to be enabled to work.
+//
+// In this particular test if `rdrnd,rdseed` somehow didn't make it to LLVM, the instruction
+// selection should crash.
+//
+// > LLVM ERROR: Cannot select: 0x7f00f400c010: i32,i32,ch = X86ISD::RDSEED 0x7f00f400bfa8:2
+// > In function: foo
+//
+// See also tests/codegen-llvm/target-feature-overrides.rs
+#![feature(no_core, lang_items, link_llvm_intrinsics, abi_unadjusted)]
+#![crate_type = "lib"]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
+
+// Use of these requires target features to be enabled
+extern "unadjusted" {
+    #[link_name = "llvm.x86.rdrand.32"]
+    fn x86_rdrand32_step() -> (u32, i32);
+    #[link_name = "llvm.x86.rdseed.32"]
+    fn x86_rdseed32_step() -> (u32, i32);
+}
+
+#[no_mangle]
+pub unsafe fn foo() -> (u32, u32) {
+    // CHECK-LABEL: foo:
+    // CHECK: rdrand
+    // CHECK: rdseed
+    (x86_rdrand32_step().0, x86_rdseed32_step().0)
+}
diff --git a/tests/assembly-llvm/targets/targets-amdgpu.rs b/tests/assembly-llvm/targets/targets-amdgpu.rs
new file mode 100644
index 00000000000..1d10b8fc315
--- /dev/null
+++ b/tests/assembly-llvm/targets/targets-amdgpu.rs
@@ -0,0 +1,22 @@
+//@ add-core-stubs
+//@ assembly-output: emit-asm
+// ignore-tidy-linelength
+//@ revisions: amdgcn_amd_amdhsa
+//@ [amdgcn_amd_amdhsa] compile-flags: --target amdgcn-amd-amdhsa -Ctarget-cpu=gfx900
+//@ [amdgcn_amd_amdhsa] needs-llvm-components: amdgpu
+
+// Sanity-check that each target can produce assembly code.
+
+#![feature(no_core, lang_items)]
+#![no_std]
+#![no_core]
+#![crate_type = "lib"]
+
+extern crate minicore;
+use minicore::*;
+
+pub fn test() -> u8 {
+    42
+}
+
+// CHECK: .version
diff --git a/tests/assembly-llvm/targets/targets-elf.rs b/tests/assembly-llvm/targets/targets-elf.rs
new file mode 100644
index 00000000000..edf16548e7d
--- /dev/null
+++ b/tests/assembly-llvm/targets/targets-elf.rs
@@ -0,0 +1,734 @@
+//@ add-core-stubs
+//@ assembly-output: emit-asm
+// ignore-tidy-linelength
+//@ revisions: aarch64_be_unknown_linux_gnu
+//@ [aarch64_be_unknown_linux_gnu] compile-flags: --target aarch64_be-unknown-linux-gnu
+//@ [aarch64_be_unknown_linux_gnu] needs-llvm-components: aarch64
+//@ revisions: aarch64_be_unknown_linux_gnu_ilp32
+//@ [aarch64_be_unknown_linux_gnu_ilp32] compile-flags: --target aarch64_be-unknown-linux-gnu_ilp32
+//@ [aarch64_be_unknown_linux_gnu_ilp32] needs-llvm-components: aarch64
+//@ revisions: aarch64_be_unknown_netbsd
+//@ [aarch64_be_unknown_netbsd] compile-flags: --target aarch64_be-unknown-netbsd
+//@ [aarch64_be_unknown_netbsd] needs-llvm-components: aarch64
+//@ revisions: aarch64_kmc_solid_asp3
+//@ [aarch64_kmc_solid_asp3] compile-flags: --target aarch64-kmc-solid_asp3
+//@ [aarch64_kmc_solid_asp3] needs-llvm-components: aarch64
+//@ revisions: aarch64_linux_android
+//@ [aarch64_linux_android] compile-flags: --target aarch64-linux-android
+//@ [aarch64_linux_android] needs-llvm-components: aarch64
+//@ revisions: aarch64_nintendo_switch_freestanding
+//@ [aarch64_nintendo_switch_freestanding] compile-flags: --target aarch64-nintendo-switch-freestanding
+//@ [aarch64_nintendo_switch_freestanding] needs-llvm-components: aarch64
+//@ revisions: aarch64_unknown_freebsd
+//@ [aarch64_unknown_freebsd] compile-flags: --target aarch64-unknown-freebsd
+//@ [aarch64_unknown_freebsd] needs-llvm-components: aarch64
+//@ revisions: aarch64_unknown_fuchsia
+//@ [aarch64_unknown_fuchsia] compile-flags: --target aarch64-unknown-fuchsia
+//@ [aarch64_unknown_fuchsia] needs-llvm-components: aarch64
+//@ revisions: aarch64_unknown_hermit
+//@ [aarch64_unknown_hermit] compile-flags: --target aarch64-unknown-hermit
+//@ [aarch64_unknown_hermit] needs-llvm-components: aarch64
+//@ revisions: aarch64_unknown_illumos
+//@ [aarch64_unknown_illumos] compile-flags: --target aarch64-unknown-illumos
+//@ [aarch64_unknown_illumos] needs-llvm-components: aarch64
+//@ revisions: aarch64_unknown_linux_gnu
+//@ [aarch64_unknown_linux_gnu] compile-flags: --target aarch64-unknown-linux-gnu
+//@ [aarch64_unknown_linux_gnu] needs-llvm-components: aarch64
+//@ revisions: aarch64_unknown_linux_gnu_ilp32
+//@ [aarch64_unknown_linux_gnu_ilp32] compile-flags: --target aarch64-unknown-linux-gnu_ilp32
+//@ [aarch64_unknown_linux_gnu_ilp32] needs-llvm-components: aarch64
+//@ revisions: aarch64_unknown_linux_musl
+//@ [aarch64_unknown_linux_musl] compile-flags: --target aarch64-unknown-linux-musl
+//@ [aarch64_unknown_linux_musl] needs-llvm-components: aarch64
+//@ revisions: aarch64_unknown_linux_ohos
+//@ [aarch64_unknown_linux_ohos] compile-flags: --target aarch64-unknown-linux-ohos
+//@ [aarch64_unknown_linux_ohos] needs-llvm-components: aarch64
+//@ revisions: aarch64_unknown_netbsd
+//@ [aarch64_unknown_netbsd] compile-flags: --target aarch64-unknown-netbsd
+//@ [aarch64_unknown_netbsd] needs-llvm-components: aarch64
+//@ revisions: aarch64_unknown_none
+//@ [aarch64_unknown_none] compile-flags: --target aarch64-unknown-none
+//@ [aarch64_unknown_none] needs-llvm-components: aarch64
+//@ revisions: aarch64_unknown_none_softfloat
+//@ [aarch64_unknown_none_softfloat] compile-flags: --target aarch64-unknown-none-softfloat
+//@ [aarch64_unknown_none_softfloat] needs-llvm-components: aarch64
+//@ revisions: aarch64_unknown_nto_qnx700
+//@ [aarch64_unknown_nto_qnx700] compile-flags: --target aarch64-unknown-nto-qnx700
+//@ [aarch64_unknown_nto_qnx700] needs-llvm-components: aarch64
+//@ revisions: aarch64_unknown_nto_qnx710
+//@ [aarch64_unknown_nto_qnx710] compile-flags: --target aarch64-unknown-nto-qnx710
+//@ [aarch64_unknown_nto_qnx710] needs-llvm-components: aarch64
+//@ revisions: aarch64_unknown_nto_qnx710_iosock
+//@ [aarch64_unknown_nto_qnx710_iosock] compile-flags: --target aarch64-unknown-nto-qnx710_iosock
+//@ [aarch64_unknown_nto_qnx710_iosock] needs-llvm-components: aarch64
+//@ revisions: aarch64_unknown_nto_qnx800
+//@ [aarch64_unknown_nto_qnx800] compile-flags: --target aarch64-unknown-nto-qnx800
+//@ [aarch64_unknown_nto_qnx800] needs-llvm-components: aarch64
+//@ revisions: aarch64_unknown_openbsd
+//@ [aarch64_unknown_openbsd] compile-flags: --target aarch64-unknown-openbsd
+//@ [aarch64_unknown_openbsd] needs-llvm-components: aarch64
+//@ revisions: aarch64_unknown_redox
+//@ [aarch64_unknown_redox] compile-flags: --target aarch64-unknown-redox
+//@ [aarch64_unknown_redox] needs-llvm-components: aarch64
+//@ revisions: aarch64_unknown_teeos
+//@ [aarch64_unknown_teeos] compile-flags: --target aarch64-unknown-teeos
+//@ [aarch64_unknown_teeos] needs-llvm-components: aarch64
+//@ revisions: aarch64_unknown_nuttx
+//@ [aarch64_unknown_nuttx] compile-flags: --target aarch64-unknown-nuttx
+//@ [aarch64_unknown_nuttx] needs-llvm-components: aarch64
+//@ revisions: aarch64_unknown_trusty
+//@ [aarch64_unknown_trusty] compile-flags: --target aarch64-unknown-trusty
+//@ [aarch64_unknown_trusty] needs-llvm-components: aarch64
+//@ revisions: aarch64_wrs_vxworks
+//@ [aarch64_wrs_vxworks] compile-flags: --target aarch64-wrs-vxworks
+//@ [aarch64_wrs_vxworks] needs-llvm-components: aarch64
+//@ revisions: arm_linux_androideabi
+//@ [arm_linux_androideabi] compile-flags: --target arm-linux-androideabi
+//@ [arm_linux_androideabi] needs-llvm-components: arm
+//@ revisions: arm_unknown_linux_gnueabi
+//@ [arm_unknown_linux_gnueabi] compile-flags: --target arm-unknown-linux-gnueabi
+//@ [arm_unknown_linux_gnueabi] needs-llvm-components: arm
+//@ revisions: arm_unknown_linux_gnueabihf
+//@ [arm_unknown_linux_gnueabihf] compile-flags: --target arm-unknown-linux-gnueabihf
+//@ [arm_unknown_linux_gnueabihf] needs-llvm-components: arm
+//@ revisions: arm_unknown_linux_musleabi
+//@ [arm_unknown_linux_musleabi] compile-flags: --target arm-unknown-linux-musleabi
+//@ [arm_unknown_linux_musleabi] needs-llvm-components: arm
+//@ revisions: arm_unknown_linux_musleabihf
+//@ [arm_unknown_linux_musleabihf] compile-flags: --target arm-unknown-linux-musleabihf
+//@ [arm_unknown_linux_musleabihf] needs-llvm-components: arm
+//@ revisions: armeb_unknown_linux_gnueabi
+//@ [armeb_unknown_linux_gnueabi] compile-flags: --target armeb-unknown-linux-gnueabi
+//@ [armeb_unknown_linux_gnueabi] needs-llvm-components: arm
+//@ revisions: armebv7r_none_eabi
+//@ [armebv7r_none_eabi] compile-flags: --target armebv7r-none-eabi
+//@ [armebv7r_none_eabi] needs-llvm-components: arm
+//@ revisions: armebv7r_none_eabihf
+//@ [armebv7r_none_eabihf] compile-flags: --target armebv7r-none-eabihf
+//@ [armebv7r_none_eabihf] needs-llvm-components: arm
+//@ revisions: armv4t_none_eabi
+//@ [armv4t_none_eabi] compile-flags: --target armv4t-none-eabi
+//@ [armv4t_none_eabi] needs-llvm-components: arm
+//@ revisions: armv4t_unknown_linux_gnueabi
+//@ [armv4t_unknown_linux_gnueabi] compile-flags: --target armv4t-unknown-linux-gnueabi
+//@ [armv4t_unknown_linux_gnueabi] needs-llvm-components: arm
+//@ revisions: armv5te_none_eabi
+//@ [armv5te_none_eabi] compile-flags: --target armv5te-none-eabi
+//@ [armv5te_none_eabi] needs-llvm-components: arm
+//@ revisions: armv5te_unknown_linux_gnueabi
+//@ [armv5te_unknown_linux_gnueabi] compile-flags: --target armv5te-unknown-linux-gnueabi
+//@ [armv5te_unknown_linux_gnueabi] needs-llvm-components: arm
+//@ revisions: armv5te_unknown_linux_musleabi
+//@ [armv5te_unknown_linux_musleabi] compile-flags: --target armv5te-unknown-linux-musleabi
+//@ [armv5te_unknown_linux_musleabi] needs-llvm-components: arm
+//@ revisions: armv5te_unknown_linux_uclibceabi
+//@ [armv5te_unknown_linux_uclibceabi] compile-flags: --target armv5te-unknown-linux-uclibceabi
+//@ [armv5te_unknown_linux_uclibceabi] needs-llvm-components: arm
+//@ revisions: armv6_unknown_freebsd
+//@ [armv6_unknown_freebsd] compile-flags: --target armv6-unknown-freebsd
+//@ [armv6_unknown_freebsd] needs-llvm-components: arm
+//@ revisions: armv6_unknown_netbsd_eabihf
+//@ [armv6_unknown_netbsd_eabihf] compile-flags: --target armv6-unknown-netbsd-eabihf
+//@ [armv6_unknown_netbsd_eabihf] needs-llvm-components: arm
+//@ revisions: armv6k_nintendo_3ds
+//@ [armv6k_nintendo_3ds] compile-flags: --target armv6k-nintendo-3ds
+//@ [armv6k_nintendo_3ds] needs-llvm-components: arm
+//@ revisions: armv7_linux_androideabi
+//@ [armv7_linux_androideabi] compile-flags: --target armv7-linux-androideabi
+//@ [armv7_linux_androideabi] needs-llvm-components: arm
+//@ revisions: armv7_rtems_eabihf
+//@ [armv7_rtems_eabihf] compile-flags: --target armv7-rtems-eabihf
+//@ [armv7_rtems_eabihf] needs-llvm-components: arm
+//@ revisions: armv7_sony_vita_newlibeabihf
+//@ [armv7_sony_vita_newlibeabihf] compile-flags: --target armv7-sony-vita-newlibeabihf
+//@ [armv7_sony_vita_newlibeabihf] needs-llvm-components: arm
+//@ revisions: armv7_unknown_freebsd
+//@ [armv7_unknown_freebsd] compile-flags: --target armv7-unknown-freebsd
+//@ [armv7_unknown_freebsd] needs-llvm-components: arm
+//@ revisions: armv7_unknown_linux_gnueabi
+//@ [armv7_unknown_linux_gnueabi] compile-flags: --target armv7-unknown-linux-gnueabi
+//@ [armv7_unknown_linux_gnueabi] needs-llvm-components: arm
+//@ revisions: armv7_unknown_linux_gnueabihf
+//@ [armv7_unknown_linux_gnueabihf] compile-flags: --target armv7-unknown-linux-gnueabihf
+//@ [armv7_unknown_linux_gnueabihf] needs-llvm-components: arm
+//@ revisions: armv7_unknown_linux_musleabi
+//@ [armv7_unknown_linux_musleabi] compile-flags: --target armv7-unknown-linux-musleabi
+//@ [armv7_unknown_linux_musleabi] needs-llvm-components: arm
+//@ revisions: armv7_unknown_linux_musleabihf
+//@ [armv7_unknown_linux_musleabihf] compile-flags: --target armv7-unknown-linux-musleabihf
+//@ [armv7_unknown_linux_musleabihf] needs-llvm-components: arm
+//@ revisions: armv7_unknown_linux_ohos
+//@ [armv7_unknown_linux_ohos] compile-flags: --target armv7-unknown-linux-ohos
+//@ [armv7_unknown_linux_ohos] needs-llvm-components: arm
+//@ revisions: armv7_unknown_linux_uclibceabi
+//@ [armv7_unknown_linux_uclibceabi] compile-flags: --target armv7-unknown-linux-uclibceabi
+//@ [armv7_unknown_linux_uclibceabi] needs-llvm-components: arm
+//@ revisions: armv7_unknown_linux_uclibceabihf
+//@ [armv7_unknown_linux_uclibceabihf] compile-flags: --target armv7-unknown-linux-uclibceabihf
+//@ [armv7_unknown_linux_uclibceabihf] needs-llvm-components: arm
+//@ revisions: armv7_unknown_netbsd_eabihf
+//@ [armv7_unknown_netbsd_eabihf] compile-flags: --target armv7-unknown-netbsd-eabihf
+//@ [armv7_unknown_netbsd_eabihf] needs-llvm-components: arm
+//@ revisions: armv7_unknown_trusty
+//@ [armv7_unknown_trusty] compile-flags: --target armv7-unknown-trusty
+//@ [armv7_unknown_trusty] needs-llvm-components: arm
+//@ revisions: armv7_wrs_vxworks_eabihf
+//@ [armv7_wrs_vxworks_eabihf] compile-flags: --target armv7-wrs-vxworks-eabihf
+//@ [armv7_wrs_vxworks_eabihf] needs-llvm-components: arm
+//@ revisions: armv7a_kmc_solid_asp3_eabi
+//@ [armv7a_kmc_solid_asp3_eabi] compile-flags: --target armv7a-kmc-solid_asp3-eabi
+//@ [armv7a_kmc_solid_asp3_eabi] needs-llvm-components: arm
+//@ revisions: armv7a_kmc_solid_asp3_eabihf
+//@ [armv7a_kmc_solid_asp3_eabihf] compile-flags: --target armv7a-kmc-solid_asp3-eabihf
+//@ [armv7a_kmc_solid_asp3_eabihf] needs-llvm-components: arm
+//@ revisions: armv7a_none_eabi
+//@ [armv7a_none_eabi] compile-flags: --target armv7a-none-eabi
+//@ [armv7a_none_eabi] needs-llvm-components: arm
+//@ revisions: armv7a_none_eabihf
+//@ [armv7a_none_eabihf] compile-flags: --target armv7a-none-eabihf
+//@ [armv7a_none_eabihf] needs-llvm-components: arm
+//@ revisions: armv7a_nuttx_eabi
+//@ [armv7a_nuttx_eabi] compile-flags: --target armv7a-nuttx-eabi
+//@ [armv7a_nuttx_eabi] needs-llvm-components: arm
+//@ revisions: armv7a_nuttx_eabihf
+//@ [armv7a_nuttx_eabihf] compile-flags: --target armv7a-nuttx-eabihf
+//@ [armv7a_nuttx_eabihf] needs-llvm-components: arm
+//@ revisions: armv7r_none_eabi
+//@ [armv7r_none_eabi] compile-flags: --target armv7r-none-eabi
+//@ [armv7r_none_eabi] needs-llvm-components: arm
+//@ revisions: armv7r_none_eabihf
+//@ [armv7r_none_eabihf] compile-flags: --target armv7r-none-eabihf
+//@ [armv7r_none_eabihf] needs-llvm-components: arm
+//@ revisions: armv8r_none_eabihf
+//@ [armv8r_none_eabihf] compile-flags: --target armv8r-none-eabihf
+//@ [armv8r_none_eabihf] needs-llvm-components: arm
+// FIXME: disabled since it fails on CI saying the csky component is missing
+/*
+    revisions: csky_unknown_linux_gnuabiv2
+    [csky_unknown_linux_gnuabiv2] compile-flags: --target csky-unknown-linux-gnuabiv2
+    [csky_unknown_linux_gnuabiv2] needs-llvm-components: csky
+    revisions: csky_unknown_linux_gnuabiv2hf
+    [csky_unknown_linux_gnuabiv2hf] compile-flags: --target csky-unknown-linux-gnuabiv2hf
+    [csky_unknown_linux_gnuabiv2hf] needs-llvm-components: csky
+*/
+//@ revisions: hexagon_unknown_linux_musl
+//@ [hexagon_unknown_linux_musl] compile-flags: --target hexagon-unknown-linux-musl
+//@ [hexagon_unknown_linux_musl] needs-llvm-components: hexagon
+//@ revisions: hexagon_unknown_none_elf
+//@ [hexagon_unknown_none_elf] compile-flags: --target hexagon-unknown-none-elf
+//@ [hexagon_unknown_none_elf] needs-llvm-components: hexagon
+//@ revisions: i686_pc_nto_qnx700
+//@ [i686_pc_nto_qnx700] compile-flags: --target i686-pc-nto-qnx700
+//@ [i686_pc_nto_qnx700] needs-llvm-components: x86
+//@ revisions: i586_unknown_linux_gnu
+//@ [i586_unknown_linux_gnu] compile-flags: --target i586-unknown-linux-gnu
+//@ [i586_unknown_linux_gnu] needs-llvm-components: x86
+//@ revisions: i586_unknown_linux_musl
+//@ [i586_unknown_linux_musl] compile-flags: --target i586-unknown-linux-musl
+//@ [i586_unknown_linux_musl] needs-llvm-components: x86
+//@ revisions: i586_unknown_netbsd
+//@ [i586_unknown_netbsd] compile-flags: --target i586-unknown-netbsd
+//@ [i586_unknown_netbsd] needs-llvm-components: x86
+//@ revisions: i586_unknown_redox
+//@ [i586_unknown_redox] compile-flags: --target i586-unknown-redox
+//@ [i586_unknown_redox] needs-llvm-components: x86
+//@ revisions: i686_linux_android
+//@ [i686_linux_android] compile-flags: --target i686-linux-android
+//@ [i686_linux_android] needs-llvm-components: x86
+//@ revisions: i686_unknown_freebsd
+//@ [i686_unknown_freebsd] compile-flags: --target i686-unknown-freebsd
+//@ [i686_unknown_freebsd] needs-llvm-components: x86
+//@ revisions: i686_unknown_haiku
+//@ [i686_unknown_haiku] compile-flags: --target i686-unknown-haiku
+//@ [i686_unknown_haiku] needs-llvm-components: x86
+//@ revisions: i686_unknown_hurd_gnu
+//@ [i686_unknown_hurd_gnu] compile-flags: --target i686-unknown-hurd-gnu
+//@ [i686_unknown_hurd_gnu] needs-llvm-components: x86
+//@ revisions: i686_unknown_linux_gnu
+//@ [i686_unknown_linux_gnu] compile-flags: --target i686-unknown-linux-gnu
+//@ [i686_unknown_linux_gnu] needs-llvm-components: x86
+//@ revisions: i686_unknown_linux_musl
+//@ [i686_unknown_linux_musl] compile-flags: --target i686-unknown-linux-musl
+//@ [i686_unknown_linux_musl] needs-llvm-components: x86
+//@ revisions: i686_unknown_netbsd
+//@ [i686_unknown_netbsd] compile-flags: --target i686-unknown-netbsd
+//@ [i686_unknown_netbsd] needs-llvm-components: x86
+//@ revisions: i686_unknown_openbsd
+//@ [i686_unknown_openbsd] compile-flags: --target i686-unknown-openbsd
+//@ [i686_unknown_openbsd] needs-llvm-components: x86
+//@ revisions: i686_wrs_vxworks
+//@ [i686_wrs_vxworks] compile-flags: --target i686-wrs-vxworks
+//@ [i686_wrs_vxworks] needs-llvm-components: x86
+//@ revisions: loongarch32_unknown_none
+//@ [loongarch32_unknown_none] compile-flags: --target loongarch32-unknown-none
+//@ [loongarch32_unknown_none] needs-llvm-components: loongarch
+//@ revisions: loongarch32_unknown_none_softfloat
+//@ [loongarch32_unknown_none_softfloat] compile-flags: --target loongarch32-unknown-none-softfloat
+//@ [loongarch32_unknown_none_softfloat] needs-llvm-components: loongarch
+//@ revisions: loongarch64_unknown_linux_gnu
+//@ [loongarch64_unknown_linux_gnu] compile-flags: --target loongarch64-unknown-linux-gnu
+//@ [loongarch64_unknown_linux_gnu] needs-llvm-components: loongarch
+//@ revisions: loongarch64_unknown_linux_musl
+//@ [loongarch64_unknown_linux_musl] compile-flags: --target loongarch64-unknown-linux-musl
+//@ [loongarch64_unknown_linux_musl] needs-llvm-components: loongarch
+//@ revisions: loongarch64_unknown_linux_ohos
+//@ [loongarch64_unknown_linux_ohos] compile-flags: --target loongarch64-unknown-linux-ohos
+//@ [loongarch64_unknown_linux_ohos] needs-llvm-components: loongarch
+//@ revisions: loongarch64_unknown_none
+//@ [loongarch64_unknown_none] compile-flags: --target loongarch64-unknown-none
+//@ [loongarch64_unknown_none] needs-llvm-components: loongarch
+//@ revisions: loongarch64_unknown_none_softfloat
+//@ [loongarch64_unknown_none_softfloat] compile-flags: --target loongarch64-unknown-none-softfloat
+//@ [loongarch64_unknown_none_softfloat] needs-llvm-components: loongarch
+//@ revisions: m68k_unknown_linux_gnu
+//@ [m68k_unknown_linux_gnu] compile-flags: --target m68k-unknown-linux-gnu
+//@ [m68k_unknown_linux_gnu] needs-llvm-components: m68k
+//@ revisions: m68k_unknown_none_elf
+//@ [m68k_unknown_none_elf] compile-flags: --target m68k-unknown-none-elf
+//@ [m68k_unknown_none_elf] needs-llvm-components: m68k
+//@ revisions: mips64_openwrt_linux_musl
+//@ [mips64_openwrt_linux_musl] compile-flags: --target mips64-openwrt-linux-musl
+//@ [mips64_openwrt_linux_musl] needs-llvm-components: mips
+//@ revisions: mips64_unknown_linux_gnuabi64
+//@ [mips64_unknown_linux_gnuabi64] compile-flags: --target mips64-unknown-linux-gnuabi64
+//@ [mips64_unknown_linux_gnuabi64] needs-llvm-components: mips
+//@ revisions: mips64_unknown_linux_muslabi64
+//@ [mips64_unknown_linux_muslabi64] compile-flags: --target mips64-unknown-linux-muslabi64
+//@ [mips64_unknown_linux_muslabi64] needs-llvm-components: mips
+//@ revisions: mips64el_unknown_linux_gnuabi64
+//@ [mips64el_unknown_linux_gnuabi64] compile-flags: --target mips64el-unknown-linux-gnuabi64
+//@ [mips64el_unknown_linux_gnuabi64] needs-llvm-components: mips
+//@ revisions: mips64el_unknown_linux_muslabi64
+//@ [mips64el_unknown_linux_muslabi64] compile-flags: --target mips64el-unknown-linux-muslabi64
+//@ [mips64el_unknown_linux_muslabi64] needs-llvm-components: mips
+//@ revisions: mips_unknown_linux_gnu
+//@ [mips_unknown_linux_gnu] compile-flags: --target mips-unknown-linux-gnu
+//@ [mips_unknown_linux_gnu] needs-llvm-components: mips
+//@ revisions: mips_unknown_linux_musl
+//@ [mips_unknown_linux_musl] compile-flags: --target mips-unknown-linux-musl
+//@ [mips_unknown_linux_musl] needs-llvm-components: mips
+//@ revisions: mips_unknown_linux_uclibc
+//@ [mips_unknown_linux_uclibc] compile-flags: --target mips-unknown-linux-uclibc
+//@ [mips_unknown_linux_uclibc] needs-llvm-components: mips
+//@ revisions: mips_mti_none_elf
+//@ [mips_mti_none_elf] compile-flags: --target mips-mti-none-elf
+//@ [mips_mti_none_elf] needs-llvm-components: mips
+//@ revisions: mipsel_mti_none_elf
+//@ [mipsel_mti_none_elf] compile-flags: --target mipsel-mti-none-elf
+//@ [mipsel_mti_none_elf] needs-llvm-components: mips
+//@ revisions: mipsel_sony_psp
+//@ [mipsel_sony_psp] compile-flags: --target mipsel-sony-psp
+//@ [mipsel_sony_psp] needs-llvm-components: mips
+//@ revisions: mipsel_sony_psx
+//@ [mipsel_sony_psx] compile-flags: --target mipsel-sony-psx
+//@ [mipsel_sony_psx] needs-llvm-components: mips
+//@ revisions: mipsel_unknown_linux_gnu
+//@ [mipsel_unknown_linux_gnu] compile-flags: --target mipsel-unknown-linux-gnu
+//@ [mipsel_unknown_linux_gnu] needs-llvm-components: mips
+//@ revisions: mipsel_unknown_linux_musl
+//@ [mipsel_unknown_linux_musl] compile-flags: --target mipsel-unknown-linux-musl
+//@ [mipsel_unknown_linux_musl] needs-llvm-components: mips
+//@ revisions: mipsel_unknown_linux_uclibc
+//@ [mipsel_unknown_linux_uclibc] compile-flags: --target mipsel-unknown-linux-uclibc
+//@ [mipsel_unknown_linux_uclibc] needs-llvm-components: mips
+//@ revisions: mipsel_unknown_netbsd
+//@ [mipsel_unknown_netbsd] compile-flags: --target mipsel-unknown-netbsd
+//@ [mipsel_unknown_netbsd] needs-llvm-components: mips
+//@ revisions: mipsel_unknown_none
+//@ [mipsel_unknown_none] compile-flags: --target mipsel-unknown-none
+//@ [mipsel_unknown_none] needs-llvm-components: mips
+//@ revisions: mipsisa32r6_unknown_linux_gnu
+//@ [mipsisa32r6_unknown_linux_gnu] compile-flags: --target mipsisa32r6-unknown-linux-gnu
+//@ [mipsisa32r6_unknown_linux_gnu] needs-llvm-components: mips
+//@ revisions: mipsisa32r6el_unknown_linux_gnu
+//@ [mipsisa32r6el_unknown_linux_gnu] compile-flags: --target mipsisa32r6el-unknown-linux-gnu
+//@ [mipsisa32r6el_unknown_linux_gnu] needs-llvm-components: mips
+//@ revisions: mipsisa64r6_unknown_linux_gnuabi64
+//@ [mipsisa64r6_unknown_linux_gnuabi64] compile-flags: --target mipsisa64r6-unknown-linux-gnuabi64
+//@ [mipsisa64r6_unknown_linux_gnuabi64] needs-llvm-components: mips
+//@ revisions: mipsisa64r6el_unknown_linux_gnuabi64
+//@ [mipsisa64r6el_unknown_linux_gnuabi64] compile-flags: --target mipsisa64r6el-unknown-linux-gnuabi64
+//@ [mipsisa64r6el_unknown_linux_gnuabi64] needs-llvm-components: mips
+//@ revisions: msp430_none_elf
+//@ [msp430_none_elf] compile-flags: --target msp430-none-elf
+//@ [msp430_none_elf] needs-llvm-components: msp430
+//@ revisions: powerpc64_unknown_freebsd
+//@ [powerpc64_unknown_freebsd] compile-flags: --target powerpc64-unknown-freebsd
+//@ [powerpc64_unknown_freebsd] needs-llvm-components: powerpc
+//@ revisions: powerpc64_unknown_linux_gnu
+//@ [powerpc64_unknown_linux_gnu] compile-flags: --target powerpc64-unknown-linux-gnu
+//@ [powerpc64_unknown_linux_gnu] needs-llvm-components: powerpc
+//@ revisions: powerpc64_unknown_linux_musl
+//@ [powerpc64_unknown_linux_musl] compile-flags: --target powerpc64-unknown-linux-musl
+//@ [powerpc64_unknown_linux_musl] needs-llvm-components: powerpc
+//@ revisions: powerpc64_unknown_openbsd
+//@ [powerpc64_unknown_openbsd] compile-flags: --target powerpc64-unknown-openbsd
+//@ [powerpc64_unknown_openbsd] needs-llvm-components: powerpc
+//@ revisions: powerpc64_wrs_vxworks
+//@ [powerpc64_wrs_vxworks] compile-flags: --target powerpc64-wrs-vxworks
+//@ [powerpc64_wrs_vxworks] needs-llvm-components: powerpc
+//@ revisions: powerpc64le_unknown_freebsd
+//@ [powerpc64le_unknown_freebsd] compile-flags: --target powerpc64le-unknown-freebsd
+//@ [powerpc64le_unknown_freebsd] needs-llvm-components: powerpc
+//@ revisions: powerpc64le_unknown_linux_gnu
+//@ [powerpc64le_unknown_linux_gnu] compile-flags: --target powerpc64le-unknown-linux-gnu
+//@ [powerpc64le_unknown_linux_gnu] needs-llvm-components: powerpc
+//@ revisions: powerpc64le_unknown_linux_musl
+//@ [powerpc64le_unknown_linux_musl] compile-flags: --target powerpc64le-unknown-linux-musl
+//@ [powerpc64le_unknown_linux_musl] needs-llvm-components: powerpc
+//@ revisions: powerpc_unknown_freebsd
+//@ [powerpc_unknown_freebsd] compile-flags: --target powerpc-unknown-freebsd
+//@ [powerpc_unknown_freebsd] needs-llvm-components: powerpc
+//@ revisions: powerpc_unknown_linux_gnu
+//@ [powerpc_unknown_linux_gnu] compile-flags: --target powerpc-unknown-linux-gnu
+//@ [powerpc_unknown_linux_gnu] needs-llvm-components: powerpc
+//@ revisions: powerpc_unknown_linux_gnuspe
+//@ [powerpc_unknown_linux_gnuspe] compile-flags: --target powerpc-unknown-linux-gnuspe
+//@ [powerpc_unknown_linux_gnuspe] needs-llvm-components: powerpc
+//@ revisions: powerpc_unknown_linux_musl
+//@ [powerpc_unknown_linux_musl] compile-flags: --target powerpc-unknown-linux-musl
+//@ [powerpc_unknown_linux_musl] needs-llvm-components: powerpc
+//@ revisions: powerpc_unknown_linux_muslspe
+//@ [powerpc_unknown_linux_muslspe] compile-flags: --target powerpc-unknown-linux-muslspe
+//@ [powerpc_unknown_linux_muslspe] needs-llvm-components: powerpc
+//@ revisions: powerpc_unknown_netbsd
+//@ [powerpc_unknown_netbsd] compile-flags: --target powerpc-unknown-netbsd
+//@ [powerpc_unknown_netbsd] needs-llvm-components: powerpc
+//@ revisions: powerpc_unknown_openbsd
+//@ [powerpc_unknown_openbsd] compile-flags: --target powerpc-unknown-openbsd
+//@ [powerpc_unknown_openbsd] needs-llvm-components: powerpc
+//@ revisions: powerpc_wrs_vxworks
+//@ [powerpc_wrs_vxworks] compile-flags: --target powerpc-wrs-vxworks
+//@ [powerpc_wrs_vxworks] needs-llvm-components: powerpc
+//@ revisions: powerpc_wrs_vxworks_spe
+//@ [powerpc_wrs_vxworks_spe] compile-flags: --target powerpc-wrs-vxworks-spe
+//@ [powerpc_wrs_vxworks_spe] needs-llvm-components: powerpc
+//@ revisions: riscv32_wrs_vxworks
+//@ [riscv32_wrs_vxworks] compile-flags: --target riscv32-wrs-vxworks
+//@ [riscv32_wrs_vxworks] needs-llvm-components: riscv
+//@ revisions: riscv32e_unknown_none_elf
+//@ [riscv32e_unknown_none_elf] compile-flags: --target riscv32e-unknown-none-elf
+//@ [riscv32e_unknown_none_elf] needs-llvm-components: riscv
+//@ revisions: riscv32em_unknown_none_elf
+//@ [riscv32em_unknown_none_elf] compile-flags: --target riscv32em-unknown-none-elf
+//@ [riscv32em_unknown_none_elf] needs-llvm-components: riscv
+//@ revisions: riscv32emc_unknown_none_elf
+//@ [riscv32emc_unknown_none_elf] compile-flags: --target riscv32emc-unknown-none-elf
+//@ [riscv32emc_unknown_none_elf] needs-llvm-components: riscv
+//@ revisions: riscv32gc_unknown_linux_gnu
+//@ [riscv32gc_unknown_linux_gnu] compile-flags: --target riscv32gc-unknown-linux-gnu
+//@ [riscv32gc_unknown_linux_gnu] needs-llvm-components: riscv
+//@ revisions: riscv32gc_unknown_linux_musl
+//@ [riscv32gc_unknown_linux_musl] compile-flags: --target riscv32gc-unknown-linux-musl
+//@ [riscv32gc_unknown_linux_musl] needs-llvm-components: riscv
+//@ revisions: riscv32i_unknown_none_elf
+//@ [riscv32i_unknown_none_elf] compile-flags: --target riscv32i-unknown-none-elf
+//@ [riscv32i_unknown_none_elf] needs-llvm-components: riscv
+//@ revisions: riscv32im_risc0_zkvm_elf
+//@ [riscv32im_risc0_zkvm_elf] compile-flags: --target riscv32im-risc0-zkvm-elf
+//@ [riscv32im_risc0_zkvm_elf] needs-llvm-components: riscv
+//@ revisions: riscv32im_unknown_none_elf
+//@ [riscv32im_unknown_none_elf] compile-flags: --target riscv32im-unknown-none-elf
+//@ [riscv32im_unknown_none_elf] needs-llvm-components: riscv
+//@ revisions: riscv32ima_unknown_none_elf
+//@ [riscv32ima_unknown_none_elf] compile-flags: --target riscv32ima-unknown-none-elf
+//@ [riscv32ima_unknown_none_elf] needs-llvm-components: riscv
+//@ revisions: riscv32imac_esp_espidf
+//@ [riscv32imac_esp_espidf] compile-flags: --target riscv32imac-esp-espidf
+//@ [riscv32imac_esp_espidf] needs-llvm-components: riscv
+//@ revisions: riscv32imac_unknown_none_elf
+//@ [riscv32imac_unknown_none_elf] compile-flags: --target riscv32imac-unknown-none-elf
+//@ [riscv32imac_unknown_none_elf] needs-llvm-components: riscv
+//@ revisions: riscv32imac_unknown_xous_elf
+//@ [riscv32imac_unknown_xous_elf] compile-flags: --target riscv32imac-unknown-xous-elf
+//@ [riscv32imac_unknown_xous_elf] needs-llvm-components: riscv
+//@ revisions: riscv32imafc_unknown_none_elf
+//@ [riscv32imafc_unknown_none_elf] compile-flags: --target riscv32imafc-unknown-none-elf
+//@ [riscv32imafc_unknown_none_elf] needs-llvm-components: riscv
+//@ revisions: riscv32imafc_esp_espidf
+//@ [riscv32imafc_esp_espidf] compile-flags: --target riscv32imafc-esp-espidf
+//@ [riscv32imafc_esp_espidf] needs-llvm-components: riscv
+//@ revisions: riscv32imc_esp_espidf
+//@ [riscv32imc_esp_espidf] compile-flags: --target riscv32imc-esp-espidf
+//@ [riscv32imc_esp_espidf] needs-llvm-components: riscv
+//@ revisions: riscv32imc_unknown_none_elf
+//@ [riscv32imc_unknown_none_elf] compile-flags: --target riscv32imc-unknown-none-elf
+//@ [riscv32imc_unknown_none_elf] needs-llvm-components: riscv
+//@ revisions: riscv64_linux_android
+//@ [riscv64_linux_android] compile-flags: --target riscv64-linux-android
+//@ [riscv64_linux_android] needs-llvm-components: riscv
+//@ revisions: riscv64_wrs_vxworks
+//@ [riscv64_wrs_vxworks] compile-flags: --target riscv64-wrs-vxworks
+//@ [riscv64_wrs_vxworks] needs-llvm-components: riscv
+//@ revisions: riscv64gc_unknown_freebsd
+//@ [riscv64gc_unknown_freebsd] compile-flags: --target riscv64gc-unknown-freebsd
+//@ [riscv64gc_unknown_freebsd] needs-llvm-components: riscv
+//@ revisions: riscv64gc_unknown_fuchsia
+//@ [riscv64gc_unknown_fuchsia] compile-flags: --target riscv64gc-unknown-fuchsia
+//@ [riscv64gc_unknown_fuchsia] needs-llvm-components: riscv
+//@ revisions: riscv64gc_unknown_hermit
+//@ [riscv64gc_unknown_hermit] compile-flags: --target riscv64gc-unknown-hermit
+//@ [riscv64gc_unknown_hermit] needs-llvm-components: riscv
+//@ revisions: riscv64gc_unknown_linux_gnu
+//@ [riscv64gc_unknown_linux_gnu] compile-flags: --target riscv64gc-unknown-linux-gnu
+//@ [riscv64gc_unknown_linux_gnu] needs-llvm-components: riscv
+//@ revisions: riscv64gc_unknown_linux_musl
+//@ [riscv64gc_unknown_linux_musl] compile-flags: --target riscv64gc-unknown-linux-musl
+//@ [riscv64gc_unknown_linux_musl] needs-llvm-components: riscv
+//@ revisions: riscv64gc_unknown_netbsd
+//@ [riscv64gc_unknown_netbsd] compile-flags: --target riscv64gc-unknown-netbsd
+//@ [riscv64gc_unknown_netbsd] needs-llvm-components: riscv
+//@ revisions: riscv64gc_unknown_none_elf
+//@ [riscv64gc_unknown_none_elf] compile-flags: --target riscv64gc-unknown-none-elf
+//@ [riscv64gc_unknown_none_elf] needs-llvm-components: riscv
+//@ revisions: riscv64gc_unknown_openbsd
+//@ [riscv64gc_unknown_openbsd] compile-flags: --target riscv64gc-unknown-openbsd
+//@ [riscv64gc_unknown_openbsd] needs-llvm-components: riscv
+//@ revisions: riscv64imac_unknown_none_elf
+//@ [riscv64imac_unknown_none_elf] compile-flags: --target riscv64imac-unknown-none-elf
+//@ [riscv64imac_unknown_none_elf] needs-llvm-components: riscv
+//@ revisions: s390x_unknown_linux_gnu
+//@ [s390x_unknown_linux_gnu] compile-flags: --target s390x-unknown-linux-gnu
+//@ [s390x_unknown_linux_gnu] needs-llvm-components: systemz
+//@ revisions: s390x_unknown_linux_musl
+//@ [s390x_unknown_linux_musl] compile-flags: --target s390x-unknown-linux-musl
+//@ [s390x_unknown_linux_musl] needs-llvm-components: systemz
+//@ revisions: sparc64_unknown_linux_gnu
+//@ [sparc64_unknown_linux_gnu] compile-flags: --target sparc64-unknown-linux-gnu
+//@ [sparc64_unknown_linux_gnu] needs-llvm-components: sparc
+//@ revisions: sparc64_unknown_netbsd
+//@ [sparc64_unknown_netbsd] compile-flags: --target sparc64-unknown-netbsd
+//@ [sparc64_unknown_netbsd] needs-llvm-components: sparc
+//@ revisions: sparc64_unknown_openbsd
+//@ [sparc64_unknown_openbsd] compile-flags: --target sparc64-unknown-openbsd
+//@ [sparc64_unknown_openbsd] needs-llvm-components: sparc
+//@ revisions: sparc_unknown_linux_gnu
+//@ [sparc_unknown_linux_gnu] compile-flags: --target sparc-unknown-linux-gnu
+//@ [sparc_unknown_linux_gnu] needs-llvm-components: sparc
+//@ revisions: sparc_unknown_none_elf
+//@ [sparc_unknown_none_elf] compile-flags: --target sparc-unknown-none-elf
+//@ [sparc_unknown_none_elf] needs-llvm-components: sparc
+//@ revisions: sparcv9_sun_solaris
+//@ [sparcv9_sun_solaris] compile-flags: --target sparcv9-sun-solaris
+//@ [sparcv9_sun_solaris] needs-llvm-components: sparc
+//@ revisions: thumbv4t_none_eabi
+//@ [thumbv4t_none_eabi] compile-flags: --target thumbv4t-none-eabi
+//@ [thumbv4t_none_eabi] needs-llvm-components: arm
+//@ revisions: thumbv5te_none_eabi
+//@ [thumbv5te_none_eabi] compile-flags: --target thumbv5te-none-eabi
+//@ [thumbv5te_none_eabi] needs-llvm-components: arm
+//@ revisions: thumbv6m_none_eabi
+//@ [thumbv6m_none_eabi] compile-flags: --target thumbv6m-none-eabi
+//@ [thumbv6m_none_eabi] needs-llvm-components: arm
+//@ revisions: thumbv7em_none_eabi
+//@ [thumbv7em_none_eabi] compile-flags: --target thumbv7em-none-eabi
+//@ [thumbv7em_none_eabi] needs-llvm-components: arm
+//@ revisions: thumbv7em_none_eabihf
+//@ [thumbv7em_none_eabihf] compile-flags: --target thumbv7em-none-eabihf
+//@ [thumbv7em_none_eabihf] needs-llvm-components: arm
+//@ revisions: thumbv7m_none_eabi
+//@ [thumbv7m_none_eabi] compile-flags: --target thumbv7m-none-eabi
+//@ [thumbv7m_none_eabi] needs-llvm-components: arm
+//@ revisions: thumbv7neon_linux_androideabi
+//@ [thumbv7neon_linux_androideabi] compile-flags: --target thumbv7neon-linux-androideabi
+//@ [thumbv7neon_linux_androideabi] needs-llvm-components: arm
+//@ revisions: thumbv7neon_unknown_linux_gnueabihf
+//@ [thumbv7neon_unknown_linux_gnueabihf] compile-flags: --target thumbv7neon-unknown-linux-gnueabihf
+//@ [thumbv7neon_unknown_linux_gnueabihf] needs-llvm-components: arm
+//@ revisions: thumbv7neon_unknown_linux_musleabihf
+//@ [thumbv7neon_unknown_linux_musleabihf] compile-flags: --target thumbv7neon-unknown-linux-musleabihf
+//@ [thumbv7neon_unknown_linux_musleabihf] needs-llvm-components: arm
+//@ revisions: thumbv8m_base_none_eabi
+//@ [thumbv8m_base_none_eabi] compile-flags: --target thumbv8m.base-none-eabi
+//@ [thumbv8m_base_none_eabi] needs-llvm-components: arm
+//@ revisions: thumbv8m_main_none_eabi
+//@ [thumbv8m_main_none_eabi] compile-flags: --target thumbv8m.main-none-eabi
+//@ [thumbv8m_main_none_eabi] needs-llvm-components: arm
+//@ revisions: thumbv8m_main_none_eabihf
+//@ [thumbv8m_main_none_eabihf] compile-flags: --target thumbv8m.main-none-eabihf
+//@ [thumbv8m_main_none_eabihf] needs-llvm-components: arm
+//@ revisions: wasm32_unknown_emscripten
+//@ [wasm32_unknown_emscripten] compile-flags: --target wasm32-unknown-emscripten
+//@ [wasm32_unknown_emscripten] needs-llvm-components: webassembly
+//@ revisions: wasm32_unknown_unknown
+//@ [wasm32_unknown_unknown] compile-flags: --target wasm32-unknown-unknown
+//@ [wasm32_unknown_unknown] needs-llvm-components: webassembly
+//@ revisions: wasm32v1_none
+//@ [wasm32v1_none] compile-flags: --target wasm32v1-none
+//@ [wasm32v1_none] needs-llvm-components: webassembly
+//@ revisions: wasm32_wasip1
+//@ [wasm32_wasip1] compile-flags: --target wasm32-wasip1
+//@ [wasm32_wasip1] needs-llvm-components: webassembly
+//@ revisions: wasm32_wasip1_threads
+//@ [wasm32_wasip1_threads] compile-flags: --target wasm32-wasip1-threads
+//@ [wasm32_wasip1_threads] needs-llvm-components: webassembly
+//@ revisions: wasm32_wasip2
+//@ [wasm32_wasip2] compile-flags: --target wasm32-wasip2
+//@ [wasm32_wasip2] needs-llvm-components: webassembly
+//@ revisions: wasm32_wali_linux_musl
+//@ [wasm32_wali_linux_musl] compile-flags: --target wasm32-wali-linux-musl
+//@ [wasm32_wali_linux_musl] needs-llvm-components: webassembly
+//@ revisions: wasm64_unknown_unknown
+//@ [wasm64_unknown_unknown] compile-flags: --target wasm64-unknown-unknown
+//@ [wasm64_unknown_unknown] needs-llvm-components: webassembly
+//@ revisions: x86_64_fortanix_unknown_sgx
+//@ [x86_64_fortanix_unknown_sgx] compile-flags: --target x86_64-fortanix-unknown-sgx
+//@ [x86_64_fortanix_unknown_sgx] needs-llvm-components: x86
+//@ revisions: x86_64_linux_android
+//@ [x86_64_linux_android] compile-flags: --target x86_64-linux-android
+//@ [x86_64_linux_android] needs-llvm-components: x86
+//@ revisions: x86_64_lynx_lynxos178
+//@ [x86_64_lynx_lynxos178] compile-flags: --target x86_64-lynx-lynxos178
+//@ [x86_64_lynx_lynxos178] needs-llvm-components: x86
+//@ revisions: x86_64_pc_nto_qnx710
+//@ [x86_64_pc_nto_qnx710] compile-flags: --target x86_64-pc-nto-qnx710
+//@ [x86_64_pc_nto_qnx710] needs-llvm-components: x86
+//@ revisions: x86_64_pc_nto_qnx710_iosock
+//@ [x86_64_pc_nto_qnx710_iosock] compile-flags: --target x86_64-pc-nto-qnx710_iosock
+//@ [x86_64_pc_nto_qnx710_iosock] needs-llvm-components: x86
+//@ revisions: x86_64_pc_nto_qnx800
+//@ [x86_64_pc_nto_qnx800] compile-flags: --target x86_64-pc-nto-qnx800
+//@ [x86_64_pc_nto_qnx800] needs-llvm-components: x86
+//@ revisions: x86_64_pc_solaris
+//@ [x86_64_pc_solaris] compile-flags: --target x86_64-pc-solaris
+//@ [x86_64_pc_solaris] needs-llvm-components: x86
+//@ revisions: x86_64_unikraft_linux_musl
+//@ [x86_64_unikraft_linux_musl] compile-flags: --target x86_64-unikraft-linux-musl
+//@ [x86_64_unikraft_linux_musl] needs-llvm-components: x86
+//@ revisions: x86_64_unknown_dragonfly
+//@ [x86_64_unknown_dragonfly] compile-flags: --target x86_64-unknown-dragonfly
+//@ [x86_64_unknown_dragonfly] needs-llvm-components: x86
+//@ revisions: x86_64_unknown_freebsd
+//@ [x86_64_unknown_freebsd] compile-flags: --target x86_64-unknown-freebsd
+//@ [x86_64_unknown_freebsd] needs-llvm-components: x86
+//@ revisions: x86_64_unknown_fuchsia
+//@ [x86_64_unknown_fuchsia] compile-flags: --target x86_64-unknown-fuchsia
+//@ [x86_64_unknown_fuchsia] needs-llvm-components: x86
+//@ revisions: x86_64_unknown_haiku
+//@ [x86_64_unknown_haiku] compile-flags: --target x86_64-unknown-haiku
+//@ [x86_64_unknown_haiku] needs-llvm-components: x86
+//@ revisions: x86_64_unknown_hurd_gnu
+//@ [x86_64_unknown_hurd_gnu] compile-flags: --target x86_64-unknown-hurd-gnu
+//@ [x86_64_unknown_hurd_gnu] needs-llvm-components: x86
+//@ revisions: x86_64_unknown_hermit
+//@ [x86_64_unknown_hermit] compile-flags: --target x86_64-unknown-hermit
+//@ [x86_64_unknown_hermit] needs-llvm-components: x86
+//@ revisions: x86_64_unknown_illumos
+//@ [x86_64_unknown_illumos] compile-flags: --target x86_64-unknown-illumos
+//@ [x86_64_unknown_illumos] needs-llvm-components: x86
+//@ revisions: x86_64_unknown_l4re_uclibc
+//@ [x86_64_unknown_l4re_uclibc] compile-flags: --target x86_64-unknown-l4re-uclibc
+//@ [x86_64_unknown_l4re_uclibc] needs-llvm-components: x86
+//@ revisions: x86_64_unknown_linux_gnu
+//@ [x86_64_unknown_linux_gnu] compile-flags: --target x86_64-unknown-linux-gnu
+//@ [x86_64_unknown_linux_gnu] needs-llvm-components: x86
+//@ revisions: x86_64_unknown_linux_gnux32
+//@ [x86_64_unknown_linux_gnux32] compile-flags: --target x86_64-unknown-linux-gnux32
+//@ [x86_64_unknown_linux_gnux32] needs-llvm-components: x86
+//@ revisions: x86_64_unknown_linux_musl
+//@ [x86_64_unknown_linux_musl] compile-flags: --target x86_64-unknown-linux-musl
+//@ [x86_64_unknown_linux_musl] needs-llvm-components: x86
+//@ revisions: x86_64_unknown_linux_ohos
+//@ [x86_64_unknown_linux_ohos] compile-flags: --target x86_64-unknown-linux-ohos
+//@ [x86_64_unknown_linux_ohos] needs-llvm-components: x86
+//@ revisions: x86_64_unknown_linux_none
+//@ [x86_64_unknown_linux_none] compile-flags: --target x86_64-unknown-linux-none
+//@ [x86_64_unknown_linux_none] needs-llvm-components: x86
+//@ revisions: x86_64_unknown_netbsd
+//@ [x86_64_unknown_netbsd] compile-flags: --target x86_64-unknown-netbsd
+//@ [x86_64_unknown_netbsd] needs-llvm-components: x86
+//@ revisions: x86_64_unknown_none
+//@ [x86_64_unknown_none] compile-flags: --target x86_64-unknown-none
+//@ [x86_64_unknown_none] needs-llvm-components: x86
+//@ revisions: x86_64_unknown_openbsd
+//@ [x86_64_unknown_openbsd] compile-flags: --target x86_64-unknown-openbsd
+//@ [x86_64_unknown_openbsd] needs-llvm-components: x86
+//@ revisions: x86_64_unknown_redox
+//@ [x86_64_unknown_redox] compile-flags: --target x86_64-unknown-redox
+//@ [x86_64_unknown_redox] needs-llvm-components: x86
+//@ revisions: x86_64_unknown_trusty
+//@ [x86_64_unknown_trusty] compile-flags: --target x86_64-unknown-trusty
+//@ [x86_64_unknown_trusty] needs-llvm-components: x86
+//@ revisions: x86_64_wrs_vxworks
+//@ [x86_64_wrs_vxworks] compile-flags: --target x86_64-wrs-vxworks
+//@ [x86_64_wrs_vxworks] needs-llvm-components: x86
+//@ revisions: thumbv6m_nuttx_eabi
+//@ [thumbv6m_nuttx_eabi] compile-flags: --target thumbv6m-nuttx-eabi
+//@ [thumbv6m_nuttx_eabi] needs-llvm-components: arm
+//@ revisions: thumbv7a_nuttx_eabi
+//@ [thumbv7a_nuttx_eabi] compile-flags: --target thumbv7a-nuttx-eabi
+//@ [thumbv7a_nuttx_eabi] needs-llvm-components: arm
+//@ revisions: thumbv7a_nuttx_eabihf
+//@ [thumbv7a_nuttx_eabihf] compile-flags: --target thumbv7a-nuttx-eabihf
+//@ [thumbv7a_nuttx_eabihf] needs-llvm-components: arm
+//@ revisions: thumbv7m_nuttx_eabi
+//@ [thumbv7m_nuttx_eabi] compile-flags: --target thumbv7m-nuttx-eabi
+//@ [thumbv7m_nuttx_eabi] needs-llvm-components: arm
+//@ revisions: thumbv7em_nuttx_eabi
+//@ [thumbv7em_nuttx_eabi] compile-flags: --target thumbv7em-nuttx-eabi
+//@ [thumbv7em_nuttx_eabi] needs-llvm-components: arm
+//@ revisions: thumbv7em_nuttx_eabihf
+//@ [thumbv7em_nuttx_eabihf] compile-flags: --target thumbv7em-nuttx-eabihf
+//@ [thumbv7em_nuttx_eabihf] needs-llvm-components: arm
+//@ revisions: thumbv8m_base_nuttx_eabi
+//@ [thumbv8m_base_nuttx_eabi] compile-flags: --target thumbv8m.base-nuttx-eabi
+//@ [thumbv8m_base_nuttx_eabi] needs-llvm-components: arm
+//@ revisions: thumbv8m_main_nuttx_eabi
+//@ [thumbv8m_main_nuttx_eabi] compile-flags: --target thumbv8m.main-nuttx-eabi
+//@ [thumbv8m_main_nuttx_eabi] needs-llvm-components: arm
+//@ revisions: thumbv8m_main_nuttx_eabihf
+//@ [thumbv8m_main_nuttx_eabihf] compile-flags: --target thumbv8m.main-nuttx-eabihf
+//@ [thumbv8m_main_nuttx_eabihf] needs-llvm-components: arm
+//@ revisions: riscv32imc_unknown_nuttx_elf
+//@ [riscv32imc_unknown_nuttx_elf] compile-flags: --target riscv32imc-unknown-nuttx-elf
+//@ [riscv32imc_unknown_nuttx_elf] needs-llvm-components: riscv
+//@ revisions: riscv32imac_unknown_nuttx_elf
+//@ [riscv32imac_unknown_nuttx_elf] compile-flags: --target riscv32imac-unknown-nuttx-elf
+//@ [riscv32imac_unknown_nuttx_elf] needs-llvm-components: riscv
+//@ revisions: riscv32imafc_unknown_nuttx_elf
+//@ [riscv32imafc_unknown_nuttx_elf] compile-flags: --target riscv32imafc-unknown-nuttx-elf
+//@ [riscv32imafc_unknown_nuttx_elf] needs-llvm-components: riscv
+//@ revisions: riscv64imac_unknown_nuttx_elf
+//@ [riscv64imac_unknown_nuttx_elf] compile-flags: --target riscv64imac-unknown-nuttx-elf
+//@ [riscv64imac_unknown_nuttx_elf] needs-llvm-components: riscv
+//@ revisions: riscv64gc_unknown_nuttx_elf
+//@ [riscv64gc_unknown_nuttx_elf] compile-flags: --target riscv64gc-unknown-nuttx-elf
+//@ [riscv64gc_unknown_nuttx_elf] needs-llvm-components: riscv
+// FIXME: disabled since it requires a custom LLVM until the upstream LLVM adds support for the target (https://github.com/espressif/llvm-project/issues/4)
+/*
+    revisions: xtensa_esp32_none_elf
+    [xtensa_esp32_none_elf] compile-flags: --target xtensa-esp32-none-elf
+    [xtensa_esp32_none_elf] needs-llvm-components: xtensa
+    revisions: xtensa_esp32_espidf
+    [xtensa_esp32_espidf] compile-flags: --target xtensa-esp32s2-espidf
+    [xtensa_esp32_espidf] needs-llvm-components: xtensa
+    revisions: xtensa_esp32s2_none_elf
+    [xtensa_esp32s2_none_elf] compile-flags: --target xtensa-esp32s2-none-elf
+    [xtensa_esp32s2_none_elf] needs-llvm-components: xtensa
+    revisions: xtensa_esp32s2_espidf
+    [xtensa_esp32s2_espidf] compile-flags: --target xtensa-esp32s2-espidf
+    [xtensa_esp32s2_espidf] needs-llvm-components: xtensa
+    revisions: xtensa_esp32s3_none_elf
+    [xtensa_esp32s3_none_elf] compile-flags: --target xtensa-esp32s3-none-elf
+    [xtensa_esp32s3_none_elf] needs-llvm-components: xtensa
+    revisions: xtensa_esp32s3_espidf
+    [xtensa_esp32s3_espidf] compile-flags: --target xtensa-esp32s3-espidf
+    [xtensa_esp32s3_espidf] needs-llvm-components: xtensa
+*/
+// Sanity-check that each target can produce assembly code.
+
+#![feature(no_core, lang_items)]
+#![no_std]
+#![no_core]
+#![crate_type = "lib"]
+
+extern crate minicore;
+use minicore::*;
+
+// Force linkage to ensure code is actually generated
+#[no_mangle]
+pub fn test() -> u8 {
+    42
+}
+
+// CHECK: .text
diff --git a/tests/assembly-llvm/targets/targets-macho.rs b/tests/assembly-llvm/targets/targets-macho.rs
new file mode 100644
index 00000000000..92bde1c6971
--- /dev/null
+++ b/tests/assembly-llvm/targets/targets-macho.rs
@@ -0,0 +1,93 @@
+//@ add-core-stubs
+//@ assembly-output: emit-asm
+// ignore-tidy-linelength
+//@ revisions: aarch64_apple_darwin
+//@ [aarch64_apple_darwin] compile-flags: --target aarch64-apple-darwin
+//@ [aarch64_apple_darwin] needs-llvm-components: aarch64
+//@ revisions: aarch64_apple_ios
+//@ [aarch64_apple_ios] compile-flags: --target aarch64-apple-ios
+//@ [aarch64_apple_ios] needs-llvm-components: aarch64
+//@ revisions: aarch64_apple_ios_macabi
+//@ [aarch64_apple_ios_macabi] compile-flags: --target aarch64-apple-ios-macabi
+//@ [aarch64_apple_ios_macabi] needs-llvm-components: aarch64
+//@ revisions: aarch64_apple_ios_sim
+//@ [aarch64_apple_ios_sim] compile-flags: --target aarch64-apple-ios-sim
+//@ [aarch64_apple_ios_sim] needs-llvm-components: aarch64
+//@ revisions: aarch64_apple_tvos
+//@ [aarch64_apple_tvos] compile-flags: --target aarch64-apple-tvos
+//@ [aarch64_apple_tvos] needs-llvm-components: aarch64
+//@ revisions: aarch64_apple_tvos_sim
+//@ [aarch64_apple_tvos_sim] compile-flags: --target aarch64-apple-tvos-sim
+//@ [aarch64_apple_tvos_sim] needs-llvm-components: aarch64
+//@ revisions: arm64e_apple_tvos
+//@ [arm64e_apple_tvos] compile-flags: --target arm64e-apple-tvos
+//@ [arm64e_apple_tvos] needs-llvm-components: aarch64
+//@ revisions: aarch64_apple_watchos
+//@ [aarch64_apple_watchos] compile-flags: --target aarch64-apple-watchos
+//@ [aarch64_apple_watchos] needs-llvm-components: aarch64
+//@ revisions: aarch64_apple_watchos_sim
+//@ [aarch64_apple_watchos_sim] compile-flags: --target aarch64-apple-watchos-sim
+//@ [aarch64_apple_watchos_sim] needs-llvm-components: aarch64
+//@ revisions: arm64_32_apple_watchos
+//@ [arm64_32_apple_watchos] compile-flags: --target arm64_32-apple-watchos
+//@ [arm64_32_apple_watchos] needs-llvm-components: aarch64
+//@ revisions: aarch64_apple_visionos
+//@ [aarch64_apple_visionos] compile-flags: --target aarch64-apple-visionos
+//@ [aarch64_apple_visionos] needs-llvm-components: aarch64
+//@ revisions: aarch64_apple_visionos_sim
+//@ [aarch64_apple_visionos_sim] compile-flags: --target aarch64-apple-visionos-sim
+//@ [aarch64_apple_visionos_sim] needs-llvm-components: aarch64
+//@ revisions: arm64e_apple_darwin
+//@ [arm64e_apple_darwin] compile-flags: --target arm64e-apple-darwin
+//@ [arm64e_apple_darwin] needs-llvm-components: aarch64
+//@ revisions: arm64e_apple_ios
+//@ [arm64e_apple_ios] compile-flags: --target arm64e-apple-ios
+//@ [arm64e_apple_ios] needs-llvm-components: aarch64
+//@ revisions: armv7k_apple_watchos
+//@ [armv7k_apple_watchos] compile-flags: --target armv7k-apple-watchos
+//@ [armv7k_apple_watchos] needs-llvm-components: arm
+//@ revisions: armv7s_apple_ios
+//@ [armv7s_apple_ios] compile-flags: --target armv7s-apple-ios
+//@ [armv7s_apple_ios] needs-llvm-components: arm
+//@ revisions: i386_apple_ios
+//@ [i386_apple_ios] compile-flags: --target i386-apple-ios
+//@ [i386_apple_ios] needs-llvm-components: x86
+//@ revisions: i686_apple_darwin
+//@ [i686_apple_darwin] compile-flags: --target i686-apple-darwin
+//@ [i686_apple_darwin] needs-llvm-components: x86
+//@ revisions: x86_64_apple_darwin
+//@ [x86_64_apple_darwin] compile-flags: --target x86_64-apple-darwin
+//@ [x86_64_apple_darwin] needs-llvm-components: x86
+//@ revisions: x86_64_apple_ios
+//@ [x86_64_apple_ios] compile-flags: --target x86_64-apple-ios
+//@ [x86_64_apple_ios] needs-llvm-components: x86
+//@ revisions: x86_64_apple_ios_macabi
+//@ [x86_64_apple_ios_macabi] compile-flags: --target x86_64-apple-ios-macabi
+//@ [x86_64_apple_ios_macabi] needs-llvm-components: x86
+//@ revisions: x86_64_apple_tvos
+//@ [x86_64_apple_tvos] compile-flags: --target x86_64-apple-tvos
+//@ [x86_64_apple_tvos] needs-llvm-components: x86
+//@ revisions: x86_64_apple_watchos_sim
+//@ [x86_64_apple_watchos_sim] compile-flags: --target x86_64-apple-watchos-sim
+//@ [x86_64_apple_watchos_sim] needs-llvm-components: x86
+//@ revisions: x86_64h_apple_darwin
+//@ [x86_64h_apple_darwin] compile-flags: --target x86_64h-apple-darwin
+//@ [x86_64h_apple_darwin] needs-llvm-components: x86
+
+// Sanity-check that each target can produce assembly code.
+
+#![feature(no_core, lang_items)]
+#![no_std]
+#![no_core]
+#![crate_type = "lib"]
+
+extern crate minicore;
+use minicore::*;
+
+// Force linkage to ensure code is actually generated
+#[no_mangle]
+pub fn test() -> u8 {
+    42
+}
+
+// CHECK: .section __TEXT,__text
diff --git a/tests/assembly-llvm/targets/targets-nvptx.rs b/tests/assembly-llvm/targets/targets-nvptx.rs
new file mode 100644
index 00000000000..49c12aebaaa
--- /dev/null
+++ b/tests/assembly-llvm/targets/targets-nvptx.rs
@@ -0,0 +1,22 @@
+//@ add-core-stubs
+//@ assembly-output: emit-asm
+// ignore-tidy-linelength
+//@ revisions: nvptx64_nvidia_cuda
+//@ [nvptx64_nvidia_cuda] compile-flags: --target nvptx64-nvidia-cuda
+//@ [nvptx64_nvidia_cuda] needs-llvm-components: nvptx
+
+// Sanity-check that each target can produce assembly code.
+
+#![feature(no_core, lang_items)]
+#![no_std]
+#![no_core]
+#![crate_type = "lib"]
+
+extern crate minicore;
+use minicore::*;
+
+pub fn test() -> u8 {
+    42
+}
+
+// CHECK: .version
diff --git a/tests/assembly-llvm/targets/targets-pe.rs b/tests/assembly-llvm/targets/targets-pe.rs
new file mode 100644
index 00000000000..de29b9af502
--- /dev/null
+++ b/tests/assembly-llvm/targets/targets-pe.rs
@@ -0,0 +1,103 @@
+//@ add-core-stubs
+//@ assembly-output: emit-asm
+// ignore-tidy-linelength
+//@ revisions: aarch64_pc_windows_msvc
+//@ [aarch64_pc_windows_msvc] compile-flags: --target aarch64-pc-windows-msvc
+//@ [aarch64_pc_windows_msvc] needs-llvm-components: aarch64
+//@ revisions: aarch64_pc_windows_gnullvm
+//@ [aarch64_pc_windows_gnullvm] compile-flags: --target aarch64-pc-windows-gnullvm
+//@ [aarch64_pc_windows_gnullvm] needs-llvm-components: aarch64
+//@ revisions: aarch64_unknown_uefi
+//@ [aarch64_unknown_uefi] compile-flags: --target aarch64-unknown-uefi
+//@ [aarch64_unknown_uefi] needs-llvm-components: aarch64
+//@ revisions: aarch64_uwp_windows_msvc
+//@ [aarch64_uwp_windows_msvc] compile-flags: --target aarch64-uwp-windows-msvc
+//@ [aarch64_uwp_windows_msvc] needs-llvm-components: aarch64
+//@ revisions: arm64ec_pc_windows_msvc
+//@ [arm64ec_pc_windows_msvc] compile-flags: --target arm64ec-pc-windows-msvc
+//@ [arm64ec_pc_windows_msvc] needs-llvm-components: aarch64
+//@ revisions: avr_none
+//@ [avr_none] compile-flags: --target avr-none -C target-cpu=atmega328p
+//@ [avr_none] needs-llvm-components: avr
+//@ revisions: bpfeb_unknown_none
+//@ [bpfeb_unknown_none] compile-flags: --target bpfeb-unknown-none
+//@ [bpfeb_unknown_none] needs-llvm-components: bpf
+//@ revisions: bpfel_unknown_none
+//@ [bpfel_unknown_none] compile-flags: --target bpfel-unknown-none
+//@ [bpfel_unknown_none] needs-llvm-components: bpf
+//@ revisions: i686_pc_windows_gnu
+//@ [i686_pc_windows_gnu] compile-flags: --target i686-pc-windows-gnu
+//@ [i686_pc_windows_gnu] needs-llvm-components: x86
+//@ revisions: i686_pc_windows_msvc
+//@ [i686_pc_windows_msvc] compile-flags: --target i686-pc-windows-msvc
+//@ [i686_pc_windows_msvc] needs-llvm-components: x86
+//@ revisions: i686_pc_windows_gnullvm
+//@ [i686_pc_windows_gnullvm] compile-flags: --target i686-pc-windows-gnullvm
+//@ [i686_pc_windows_gnullvm] needs-llvm-components: x86
+//@ revisions: i686_uwp_windows_gnu
+//@ [i686_uwp_windows_gnu] compile-flags: --target i686-uwp-windows-gnu
+//@ [i686_uwp_windows_gnu] needs-llvm-components: x86
+//@ revisions: i686_win7_windows_gnu
+//@ [i686_win7_windows_gnu] compile-flags: --target i686-win7-windows-gnu
+//@ [i686_win7_windows_gnu] needs-llvm-components: x86
+//@ revisions: i686_unknown_uefi
+//@ [i686_unknown_uefi] compile-flags: --target i686-unknown-uefi
+//@ [i686_unknown_uefi] needs-llvm-components: x86
+//@ revisions: i686_uwp_windows_msvc
+//@ [i686_uwp_windows_msvc] compile-flags: --target i686-uwp-windows-msvc
+//@ [i686_uwp_windows_msvc] needs-llvm-components: x86
+//@ revisions: i686_win7_windows_msvc
+//@ [i686_win7_windows_msvc] compile-flags: --target i686-win7-windows-msvc
+//@ [i686_win7_windows_msvc] needs-llvm-components: x86
+//@ revisions: powerpc64_ibm_aix
+//@ [powerpc64_ibm_aix] compile-flags: --target powerpc64-ibm-aix
+//@ [powerpc64_ibm_aix] needs-llvm-components: powerpc
+//@ revisions: thumbv7a_uwp_windows_msvc
+//@ [thumbv7a_uwp_windows_msvc] compile-flags: --target thumbv7a-uwp-windows-msvc
+//@ [thumbv7a_uwp_windows_msvc] needs-llvm-components: arm
+//@ revisions: thumbv7a_pc_windows_msvc
+//@ [thumbv7a_pc_windows_msvc] compile-flags: --target thumbv7a-pc-windows-msvc
+//@ [thumbv7a_pc_windows_msvc] needs-llvm-components: arm
+//@ revisions: x86_64_pc_windows_gnu
+//@ [x86_64_pc_windows_gnu] compile-flags: --target x86_64-pc-windows-gnu
+//@ [x86_64_pc_windows_gnu] needs-llvm-components: x86
+//@ revisions: x86_64_pc_windows_gnullvm
+//@ [x86_64_pc_windows_gnullvm] compile-flags: --target x86_64-pc-windows-gnullvm
+//@ [x86_64_pc_windows_gnullvm] needs-llvm-components: x86
+//@ revisions: x86_64_pc_windows_msvc
+//@ [x86_64_pc_windows_msvc] compile-flags: --target x86_64-pc-windows-msvc
+//@ [x86_64_pc_windows_msvc] needs-llvm-components: x86
+//@ revisions: x86_64_unknown_uefi
+//@ [x86_64_unknown_uefi] compile-flags: --target x86_64-unknown-uefi
+//@ [x86_64_unknown_uefi] needs-llvm-components: x86
+//@ revisions: x86_64_uwp_windows_gnu
+//@ [x86_64_uwp_windows_gnu] compile-flags: --target x86_64-uwp-windows-gnu
+//@ [x86_64_uwp_windows_gnu] needs-llvm-components: x86
+//@ revisions: x86_64_win7_windows_gnu
+//@ [x86_64_win7_windows_gnu] compile-flags: --target x86_64-win7-windows-gnu
+//@ [x86_64_win7_windows_gnu] needs-llvm-components: x86
+//@ revisions: x86_64_uwp_windows_msvc
+//@ [x86_64_uwp_windows_msvc] compile-flags: --target x86_64-uwp-windows-msvc
+//@ [x86_64_uwp_windows_msvc] needs-llvm-components: x86
+//@ revisions: x86_64_win7_windows_msvc
+//@ [x86_64_win7_windows_msvc] compile-flags: --target x86_64-win7-windows-msvc
+//@ [x86_64_win7_windows_msvc] needs-llvm-components: x86
+//@ revisions: x86_64_pc_cygwin
+//@ [x86_64_pc_cygwin] compile-flags: --target x86_64-pc-cygwin
+//@ [x86_64_pc_cygwin] needs-llvm-components: x86
+
+// Sanity-check that each target can produce assembly code.
+
+#![feature(no_core, lang_items)]
+#![no_std]
+#![no_core]
+#![crate_type = "lib"]
+
+extern crate minicore;
+use minicore::*;
+
+pub fn test() -> u8 {
+    42
+}
+
+// CHECK: .file
diff --git a/tests/assembly-llvm/wasm_exceptions.rs b/tests/assembly-llvm/wasm_exceptions.rs
new file mode 100644
index 00000000000..704e8026f3f
--- /dev/null
+++ b/tests/assembly-llvm/wasm_exceptions.rs
@@ -0,0 +1,67 @@
+//@ only-wasm32
+//@ assembly-output: emit-asm
+//@ compile-flags: -C target-feature=+exception-handling
+//@ compile-flags: -C panic=unwind
+
+#![crate_type = "lib"]
+#![feature(core_intrinsics)]
+
+extern "C-unwind" {
+    fn may_panic();
+}
+
+extern "C" {
+    fn log_number(number: usize);
+}
+
+struct LogOnDrop;
+
+impl Drop for LogOnDrop {
+    fn drop(&mut self) {
+        unsafe {
+            log_number(0);
+        }
+    }
+}
+
+// CHECK-LABEL: test_cleanup:
+#[no_mangle]
+pub fn test_cleanup() {
+    let _log_on_drop = LogOnDrop;
+    unsafe {
+        may_panic();
+    }
+
+    // CHECK-NOT: call
+    // CHECK: try
+    // CHECK: call may_panic
+    // CHECK: catch_all
+    // CHECK: rethrow
+    // CHECK: end_try
+}
+
+// CHECK-LABEL: test_rtry:
+#[no_mangle]
+pub fn test_rtry() {
+    unsafe {
+        core::intrinsics::catch_unwind(
+            |_| {
+                may_panic();
+            },
+            core::ptr::null_mut(),
+            |data, exception| {
+                log_number(data as usize);
+                log_number(exception as usize);
+            },
+        );
+    }
+
+    // CHECK-NOT: call
+    // CHECK: try
+    // CHECK: call may_panic
+    // CHECK: catch
+    // CHECK: call log_number
+    // CHECK: call log_number
+    // CHECK-NOT: rethrow
+    // CHECK: end_try
+}
diff --git a/tests/assembly-llvm/x86-return-float.rs b/tests/assembly-llvm/x86-return-float.rs
new file mode 100644
index 00000000000..165c11d2280
--- /dev/null
+++ b/tests/assembly-llvm/x86-return-float.rs
@@ -0,0 +1,343 @@
+//@ assembly-output: emit-asm
+// FIXME(#114479): LLVM miscompiles loading and storing `f32` and `f64` when SSE is disabled.
+// There's no compiletest directive to ignore a test on i586 only, so just always explicitly enable
+// SSE2.
+// Use the same target CPU as `i686` so that LLVM orders the instructions in the same order.
+//@ compile-flags: -Ctarget-feature=+sse2 -Ctarget-cpu=pentium4
+// Force frame pointers to make ASM more consistent between targets
+//@ compile-flags: -C force-frame-pointers
+// At opt-level=3, LLVM can merge two movss into one movsd, and we aren't testing for that.
+//@ compile-flags: -Copt-level=2
+//@ filecheck-flags: --implicit-check-not fld --implicit-check-not fst
+//@ revisions: linux win
+//@ add-core-stubs
+//@[linux] needs-llvm-components: x86
+//@[win] needs-llvm-components: x86
+//@[linux] compile-flags: --target i686-unknown-linux-gnu
+//@[win] compile-flags: --target i686-pc-windows-msvc
+
+#![crate_type = "lib"]
+#![feature(f16, f128)]
+#![feature(no_core)]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
+
+// Tests that returning `f32` and `f64` with the "Rust" ABI on 32-bit x86 doesn't use the x87
+// floating point stack, as loading and storing `f32`s and `f64`s to and from the x87 stack quietens
+// signalling NaNs.
+
+// Returning individual floats
+
+// CHECK-LABEL: return_f32:
+#[no_mangle]
+pub fn return_f32(x: f32) -> f32 {
+    // CHECK: movss {{.*}}(%ebp), %xmm0
+    // CHECK-NEXT: popl %ebp
+    // linux-NEXT: .cfi_def_cfa
+    // CHECK-NEXT: retl
+    x
+}
+
+// CHECK-LABEL: return_f64:
+#[no_mangle]
+pub fn return_f64(x: f64) -> f64 {
+    // CHECK: movsd {{.*}}(%ebp), %xmm0
+    // CHECK-NEXT: popl %ebp
+    // linux-NEXT: .cfi_def_cfa
+    // CHECK-NEXT: retl
+    x
+}
+
+// Returning scalar pairs containing floats
+
+// CHECK-LABEL: return_f32_f32:
+#[no_mangle]
+pub fn return_f32_f32(x: (f32, f32)) -> (f32, f32) {
+    // CHECK: movl [[#%d,OFFSET:]](%ebp), %[[PTR:.*]]
+    // CHECK-NEXT: movss [[#%d,OFFSET+4]](%ebp), %[[VAL1:.*]]
+    // CHECK-NEXT: movss [[#%d,OFFSET+8]](%ebp), %[[VAL2:.*]]
+    // CHECK-NEXT: movss %[[VAL1]], (%[[PTR]])
+    // CHECK-NEXT: movss %[[VAL2]], 4(%[[PTR]])
+    // CHECK: retl
+    x
+}
+
+// CHECK-LABEL: return_f64_f64:
+#[no_mangle]
+pub fn return_f64_f64(x: (f64, f64)) -> (f64, f64) {
+    // CHECK: movl [[#%d,OFFSET:]](%ebp), %[[PTR:.*]]
+    // CHECK-NEXT: movsd [[#%d,OFFSET+4]](%ebp), %[[VAL1:.*]]
+    // CHECK-NEXT: movsd [[#%d,OFFSET+12]](%ebp), %[[VAL2:.*]]
+    // CHECK-NEXT: movsd %[[VAL1]], (%[[PTR]])
+    // CHECK-NEXT: movsd %[[VAL2]], 8(%[[PTR]])
+    // CHECK: retl
+    x
+}
+
+// CHECK-LABEL: return_f32_f64:
+#[no_mangle]
+pub fn return_f32_f64(x: (f32, f64)) -> (f32, f64) {
+    // CHECK: movl [[#%d,OFFSET:]](%ebp), %[[PTR:.*]]
+    // CHECK-NEXT: movss [[#%d,OFFSET+4]](%ebp), %[[VAL1:.*]]
+    // CHECK-NEXT: movsd [[#%d,OFFSET+8]](%ebp), %[[VAL2:.*]]
+    // CHECK-NEXT: movss %[[VAL1]], (%[[PTR]])
+    // CHECK-NEXT: movsd %[[VAL2]], {{4|8}}(%[[PTR]])
+    // CHECK: retl
+    x
+}
+
+// CHECK-LABEL: return_f64_f32:
+#[no_mangle]
+pub fn return_f64_f32(x: (f64, f32)) -> (f64, f32) {
+    // CHECK: movl [[#%d,OFFSET:]](%ebp), %[[PTR:.*]]
+    // CHECK-NEXT: movsd [[#%d,OFFSET+4]](%ebp), %[[VAL1:.*]]
+    // CHECK-NEXT: movss [[#%d,OFFSET+12]](%ebp), %[[VAL2:.*]]
+    // CHECK-NEXT: movsd %[[VAL1]], (%[[PTR]])
+    // CHECK-NEXT: movss %[[VAL2]], 8(%[[PTR]])
+    // CHECK: retl
+    x
+}
+
+// CHECK-LABEL: return_f32_other:
+#[no_mangle]
+pub fn return_f32_other(x: (f32, usize)) -> (f32, usize) {
+    // CHECK: movl [[#%d,OFFSET:]](%ebp), %[[PTR:.*]]
+    // CHECK-NEXT: movss [[#%d,OFFSET+4]](%ebp), %[[VAL1:.*]]
+    // CHECK-NEXT: movl [[#%d,OFFSET+8]](%ebp), %[[VAL2:.*]]
+    // CHECK-NEXT: movss %[[VAL1]], (%[[PTR]])
+    // CHECK-NEXT: movl %[[VAL2]], 4(%[[PTR]])
+    // CHECK: retl
+    x
+}
+
+// CHECK-LABEL: return_f64_other:
+#[no_mangle]
+pub fn return_f64_other(x: (f64, usize)) -> (f64, usize) {
+    // CHECK: movl [[#%d,OFFSET:]](%ebp), %[[PTR:.*]]
+    // CHECK-NEXT: movsd [[#%d,OFFSET+4]](%ebp), %[[VAL1:.*]]
+    // CHECK-NEXT: movl [[#%d,OFFSET+12]](%ebp), %[[VAL2:.*]]
+    // CHECK-NEXT: movsd %[[VAL1]], (%[[PTR]])
+    // CHECK-NEXT: movl %[[VAL2]], 8(%[[PTR]])
+    // CHECK: retl
+    x
+}
+
+// CHECK-LABEL: return_other_f32:
+#[no_mangle]
+pub fn return_other_f32(x: (usize, f32)) -> (usize, f32) {
+    // CHECK: movl [[#%d,OFFSET:]](%ebp), %[[PTR:.*]]
+    // CHECK-NEXT: movl [[#%d,OFFSET+4]](%ebp), %[[VAL1:.*]]
+    // CHECK-NEXT: movss [[#%d,OFFSET+8]](%ebp), %[[VAL2:.*]]
+    // CHECK-NEXT: movl %[[VAL1]], (%[[PTR]])
+    // CHECK-NEXT: movss %[[VAL2]], 4(%[[PTR]])
+    // CHECK: retl
+    x
+}
+
+// CHECK-LABEL: return_other_f64:
+#[no_mangle]
+pub fn return_other_f64(x: (usize, f64)) -> (usize, f64) {
+    // CHECK: movl [[#%d,OFFSET:]](%ebp), %[[PTR:.*]]
+    // CHECK-NEXT: movl [[#%d,OFFSET+4]](%ebp), %[[VAL1:.*]]
+    // CHECK-NEXT: movsd [[#%d,OFFSET+8]](%ebp), %[[VAL2:.*]]
+    // CHECK-NEXT: movl %[[VAL1]], (%[[PTR]])
+    // CHECK-NEXT: movsd %[[VAL2]], {{4|8}}(%[[PTR]])
+    // CHECK: retl
+    x
+}
+
+// Calling functions returning floats
+
+// CHECK-LABEL: call_f32:
+#[no_mangle]
+pub unsafe fn call_f32(x: &mut f32) {
+    extern "Rust" {
+        fn get_f32() -> f32;
+    }
+    // CHECK: movl {{.*}}(%ebp), %[[PTR:.*]]
+    // CHECK: calll {{()|_}}get_f32
+    // CHECK-NEXT: movss %xmm0, (%[[PTR]])
+    *x = get_f32();
+}
+
+// CHECK-LABEL: call_f64:
+#[no_mangle]
+pub unsafe fn call_f64(x: &mut f64) {
+    extern "Rust" {
+        fn get_f64() -> f64;
+    }
+    // CHECK: movl {{.*}}(%ebp), %[[PTR:.*]]
+    // CHECK: calll {{()|_}}get_f64
+    // CHECK-NEXT: movlps %xmm0, (%[[PTR]])
+    *x = get_f64();
+}
+
+// Calling functions returning scalar pairs containing floats
+
+// CHECK-LABEL: call_f32_f32:
+#[no_mangle]
+pub unsafe fn call_f32_f32(x: &mut (f32, f32)) {
+    extern "Rust" {
+        fn get_f32_f32() -> (f32, f32);
+    }
+    // CHECK: movl {{.*}}(%ebp), %[[PTR:.*]]
+    // CHECK: calll {{()|_}}get_f32_f32
+    // CHECK: movss [[#%d,OFFSET:]](%ebp), %[[VAL1:.*]]
+    // CHECK-NEXT: movss [[#%d,OFFSET+4]](%ebp), %[[VAL2:.*]]
+    // CHECK-NEXT: movss %[[VAL1]], (%[[PTR]])
+    // CHECK-NEXT: movss %[[VAL2]], 4(%[[PTR]])
+    *x = get_f32_f32();
+}
+
+// CHECK-LABEL: call_f64_f64:
+#[no_mangle]
+pub unsafe fn call_f64_f64(x: &mut (f64, f64)) {
+    extern "Rust" {
+        fn get_f64_f64() -> (f64, f64);
+    }
+    // CHECK: movl {{.*}}(%ebp), %[[PTR:.*]]
+    // CHECK: calll {{()|_}}get_f64_f64
+    // linux: movsd [[#%d,OFFSET:]](%ebp), %[[VAL1:.*]]
+    // linux-NEXT: movsd [[#%d,OFFSET+8]](%ebp), %[[VAL2:.*]]
+    // win: movsd (%esp), %[[VAL1:.*]]
+    // win-NEXT: movsd 8(%esp), %[[VAL2:.*]]
+    // CHECK-NEXT: movsd %[[VAL1]], (%[[PTR]])
+    // CHECK-NEXT: movsd %[[VAL2]], 8(%[[PTR]])
+    *x = get_f64_f64();
+}
+
+// CHECK-LABEL: call_f32_f64:
+#[no_mangle]
+pub unsafe fn call_f32_f64(x: &mut (f32, f64)) {
+    extern "Rust" {
+        fn get_f32_f64() -> (f32, f64);
+    }
+    // CHECK: movl {{.*}}(%ebp), %[[PTR:.*]]
+    // CHECK: calll {{()|_}}get_f32_f64
+    // linux: movss [[#%d,OFFSET:]](%ebp), %[[VAL1:.*]]
+    // linux-NEXT: movsd [[#%d,OFFSET+4]](%ebp), %[[VAL2:.*]]
+    // win: movss (%esp), %[[VAL1:.*]]
+    // win-NEXT: movsd 8(%esp), %[[VAL2:.*]]
+    // CHECK-NEXT: movss %[[VAL1]], (%[[PTR]])
+    // linux-NEXT: movsd %[[VAL2]], 4(%[[PTR]])
+    // win-NEXT: movsd %[[VAL2]], 8(%[[PTR]])
+    *x = get_f32_f64();
+}
+
+// CHECK-LABEL: call_f64_f32:
+#[no_mangle]
+pub unsafe fn call_f64_f32(x: &mut (f64, f32)) {
+    extern "Rust" {
+        fn get_f64_f32() -> (f64, f32);
+    }
+    // CHECK: movl {{.*}}(%ebp), %[[PTR:.*]]
+    // CHECK: calll {{()|_}}get_f64_f32
+    // linux: movsd [[#%d,OFFSET:]](%ebp), %[[VAL1:.*]]
+    // linux-NEXT: movss [[#%d,OFFSET+8]](%ebp), %[[VAL2:.*]]
+    // win: movsd (%esp), %[[VAL1:.*]]
+    // win-NEXT: movss 8(%esp), %[[VAL2:.*]]
+    // CHECK-NEXT: movsd %[[VAL1]], (%[[PTR]])
+    // CHECK-NEXT: movss %[[VAL2]], 8(%[[PTR]])
+    *x = get_f64_f32();
+}
+
+// CHECK-LABEL: call_f32_other:
+#[no_mangle]
+pub unsafe fn call_f32_other(x: &mut (f32, usize)) {
+    extern "Rust" {
+        fn get_f32_other() -> (f32, usize);
+    }
+    // CHECK: movl {{.*}}(%ebp), %[[PTR:.*]]
+    // CHECK: calll {{()|_}}get_f32_other
+    // CHECK: movss [[#%d,OFFSET:]](%ebp), %[[VAL1:.*]]
+    // CHECK-NEXT: movl [[#%d,OFFSET+4]](%ebp), %[[VAL2:.*]]
+    // CHECK-NEXT: movss %[[VAL1]], (%[[PTR]])
+    // CHECK-NEXT: movl %[[VAL2]], 4(%[[PTR]])
+    *x = get_f32_other();
+}
+
+// CHECK-LABEL: call_f64_other:
+#[no_mangle]
+pub unsafe fn call_f64_other(x: &mut (f64, usize)) {
+    extern "Rust" {
+        fn get_f64_other() -> (f64, usize);
+    }
+    // CHECK: movl {{.*}}(%ebp), %[[PTR:.*]]
+    // CHECK: calll {{()|_}}get_f64_other
+    // linux: movsd [[#%d,OFFSET:]](%ebp), %[[VAL1:.*]]
+    // linux-NEXT: movl [[#%d,OFFSET+8]](%ebp), %[[VAL2:.*]]
+    // win: movsd (%esp), %[[VAL1:.*]]
+    // win-NEXT: movl 8(%esp), %[[VAL2:.*]]
+    // CHECK-NEXT: movsd %[[VAL1]], (%[[PTR]])
+    // CHECK-NEXT: movl %[[VAL2]], 8(%[[PTR]])
+    *x = get_f64_other();
+}
+
+// CHECK-LABEL: call_other_f32:
+#[no_mangle]
+pub unsafe fn call_other_f32(x: &mut (usize, f32)) {
+    extern "Rust" {
+        fn get_other_f32() -> (usize, f32);
+    }
+    // CHECK: movl {{.*}}(%ebp), %[[PTR:.*]]
+    // CHECK: calll {{()|_}}get_other_f32
+    // CHECK: movl [[#%d,OFFSET:]](%ebp), %[[VAL1:.*]]
+    // CHECK-NEXT: movss [[#%d,OFFSET+4]](%ebp), %[[VAL2:.*]]
+    // CHECK-NEXT: movl %[[VAL1]], (%[[PTR]])
+    // CHECK-NEXT: movss %[[VAL2]], 4(%[[PTR]])
+    *x = get_other_f32();
+}
+
+// CHECK-LABEL: call_other_f64:
+#[no_mangle]
+pub unsafe fn call_other_f64(x: &mut (usize, f64)) {
+    extern "Rust" {
+        fn get_other_f64() -> (usize, f64);
+    }
+    // CHECK: movl {{.*}}(%ebp), %[[PTR:.*]]
+    // CHECK: calll {{()|_}}get_other_f64
+    // linux: movl [[#%d,OFFSET:]](%ebp), %[[VAL1:.*]]
+    // linux-NEXT: movsd [[#%d,OFFSET+4]](%ebp), %[[VAL2:.*]]
+    // win: movl (%esp), %[[VAL1:.*]]
+    // win-NEXT: movsd 8(%esp), %[[VAL2:.*]]
+    // CHECK-NEXT: movl %[[VAL1]], (%[[PTR]])
+    // linux-NEXT: movsd %[[VAL2]], 4(%[[PTR]])
+    // win-NEXT: movsd %[[VAL2]], 8(%[[PTR]])
+    *x = get_other_f64();
+}
+
+// The "C" ABI for `f16` and `f128` on x86 has never used the x87 floating point stack. Do some
+// basic checks to ensure this remains the case for the "Rust" ABI.
+
+// CHECK-LABEL: return_f16:
+#[no_mangle]
+pub fn return_f16(x: f16) -> f16 {
+    // CHECK: pushl %ebp
+    // linux-NEXT: .cfi_def_cfa_offset
+    // linux-NEXT: .cfi_offset
+    // CHECK-NEXT: movl %esp, %ebp
+    // linux-NEXT: .cfi_def_cfa_register
+    // CHECK-NEXT: pinsrw $0, 8(%ebp), %xmm0
+    // CHECK-NEXT: popl %ebp
+    // linux-NEXT: .cfi_def_cfa
+    // CHECK-NEXT: retl
+    x
+}
+
+// CHECK-LABEL: return_f128:
+#[no_mangle]
+pub fn return_f128(x: f128) -> f128 {
+    // CHECK: pushl %ebp
+    // linux-NEXT: .cfi_def_cfa_offset
+    // linux-NEXT: .cfi_offset
+    // CHECK-NEXT: movl %esp, %ebp
+    // linux-NEXT: .cfi_def_cfa_register
+    // linux-NEXT: movaps 8(%ebp), %xmm0
+    // win-NEXT: movups 8(%ebp), %xmm0
+    // CHECK-NEXT: popl %ebp
+    // linux-NEXT: .cfi_def_cfa
+    // CHECK-NEXT: retl
+    x
+}
diff --git a/tests/assembly-llvm/x86_64-array-pair-load-store-merge.rs b/tests/assembly-llvm/x86_64-array-pair-load-store-merge.rs
new file mode 100644
index 00000000000..56a1a9e8206
--- /dev/null
+++ b/tests/assembly-llvm/x86_64-array-pair-load-store-merge.rs
@@ -0,0 +1,20 @@
+//@ assembly-output: emit-asm
+//@ compile-flags: --crate-type=lib -Copt-level=3 -C llvm-args=-x86-asm-syntax=intel
+//@ only-x86_64
+//@ ignore-sgx
+//@ ignore-apple (manipulates rsp too)
+
+// Depending on various codegen choices, this might end up copying
+// a `<2 x i8>`, an `i16`, or two `i8`s.
+// Regardless of those choices, make sure the instructions use (2-byte) words.
+
+// CHECK-LABEL: array_copy_2_elements:
+#[no_mangle]
+pub fn array_copy_2_elements(a: &[u8; 2], p: &mut [u8; 2]) {
+    // CHECK-NOT: byte
+    // CHECK-NOT: mov
+    // CHECK: mov{{.+}}, word ptr
+    // CHECK-NEXT: mov word ptr
+    // CHECK-NEXT: ret
+    *p = *a;
+}
diff --git a/tests/assembly-llvm/x86_64-bigint-helpers.rs b/tests/assembly-llvm/x86_64-bigint-helpers.rs
new file mode 100644
index 00000000000..58785932bc2
--- /dev/null
+++ b/tests/assembly-llvm/x86_64-bigint-helpers.rs
@@ -0,0 +1,61 @@
+//@ only-x86_64
+//@ assembly-output: emit-asm
+//@ compile-flags: --crate-type=lib -Copt-level=3 -C target-cpu=x86-64-v4
+//@ compile-flags: -C llvm-args=-x86-asm-syntax=intel
+//@ revisions: llvm-pre-20 llvm-20
+//@ [llvm-20] min-llvm-version: 20
+//@ [llvm-pre-20] max-llvm-major-version: 19
+
+#![no_std]
+#![feature(bigint_helper_methods)]
+
+// This checks that the `carrying_add` and `borrowing_sub` implementation successfully chain,
+// to catch issues like <https://github.com/rust-lang/rust/issues/85532#issuecomment-2495119815>
+
+// This forces the ABI to avoid the windows-vs-linux ABI differences.
+
+// CHECK-LABEL: bigint_chain_carrying_add:
+#[no_mangle]
+pub unsafe extern "sysv64" fn bigint_chain_carrying_add(
+    dest: *mut u64,
+    src1: *const u64,
+    src2: *const u64,
+    n: usize,
+    mut carry: bool,
+) -> bool {
+    // llvm-pre-20: mov [[TEMP:r..]], qword ptr [rsi + 8*[[IND:r..]] + 8]
+    // llvm-pre-20: adc [[TEMP]], qword ptr [rdx + 8*[[IND]] + 8]
+    // llvm-pre-20: mov qword ptr [rdi + 8*[[IND]] + 8], [[TEMP]]
+    // llvm-pre-20: mov [[TEMP]], qword ptr [rsi + 8*[[IND]] + 16]
+    // llvm-pre-20: adc [[TEMP]], qword ptr [rdx + 8*[[IND]] + 16]
+    // llvm-pre-20: mov qword ptr [rdi + 8*[[IND]] + 16], [[TEMP]]
+    // llvm-20: adc [[TEMP:r..]], qword ptr [rdx + 8*[[IND:r..]]]
+    // llvm-20: mov qword ptr [rdi + 8*[[IND]]], [[TEMP]]
+    // llvm-20: mov [[TEMP]], qword ptr [rsi + 8*[[IND]] + 8]
+    // llvm-20: adc [[TEMP]], qword ptr [rdx + 8*[[IND]] + 8]
+    for i in 0..n {
+        (*dest.add(i), carry) = u64::carrying_add(*src1.add(i), *src2.add(i), carry);
+    }
+    carry
+}
+
+// CHECK-LABEL: bigint_chain_borrowing_sub:
+#[no_mangle]
+pub unsafe extern "sysv64" fn bigint_chain_borrowing_sub(
+    dest: *mut u64,
+    src1: *const u64,
+    src2: *const u64,
+    n: usize,
+    mut carry: bool,
+) -> bool {
+    // CHECK: mov [[TEMP:r..]], qword ptr [rsi + 8*[[IND:r..]] + 8]
+    // CHECK: sbb [[TEMP]], qword ptr [rdx + 8*[[IND]] + 8]
+    // CHECK: mov qword ptr [rdi + 8*[[IND]] + 8], [[TEMP]]
+    // CHECK: mov [[TEMP]], qword ptr [rsi + 8*[[IND]] + 16]
+    // CHECK: sbb [[TEMP]], qword ptr [rdx + 8*[[IND]] + 16]
+    // CHECK: mov qword ptr [rdi + 8*[[IND]] + 16], [[TEMP]]
+    for i in 0..n {
+        (*dest.add(i), carry) = u64::borrowing_sub(*src1.add(i), *src2.add(i), carry);
+    }
+    carry
+}
diff --git a/tests/assembly-llvm/x86_64-cmp.rs b/tests/assembly-llvm/x86_64-cmp.rs
new file mode 100644
index 00000000000..26c9013d96f
--- /dev/null
+++ b/tests/assembly-llvm/x86_64-cmp.rs
@@ -0,0 +1,79 @@
+//@ revisions: LLVM-PRE-20-DEBUG LLVM-20-DEBUG LLVM-PRE-20-OPTIM LLVM-20-OPTIM
+//@ [LLVM-PRE-20-DEBUG] compile-flags: -C opt-level=0
+//@ [LLVM-PRE-20-DEBUG] max-llvm-major-version: 19
+//@ [LLVM-20-DEBUG] compile-flags: -C opt-level=0
+//@ [LLVM-20-DEBUG] min-llvm-version: 20
+//@ [LLVM-PRE-20-OPTIM] compile-flags: -C opt-level=3
+//@ [LLVM-PRE-20-OPTIM] max-llvm-major-version: 19
+//@ [LLVM-20-OPTIM] compile-flags: -C opt-level=3
+//@ [LLVM-20-OPTIM] min-llvm-version: 20
+//@ assembly-output: emit-asm
+//@ compile-flags: --crate-type=lib -C llvm-args=-x86-asm-syntax=intel
+//@ only-x86_64
+//@ ignore-sgx
+
+#![feature(core_intrinsics)]
+
+use std::intrinsics::three_way_compare;
+
+#[no_mangle]
+// CHECK-LABEL: signed_cmp:
+pub fn signed_cmp(a: i16, b: i16) -> std::cmp::Ordering {
+    // LLVM-PRE-20-DEBUG: cmp
+    // LLVM-PRE-20-DEBUG: setg
+    // LLVM-PRE-20-DEBUG: and
+    // LLVM-PRE-20-DEBUG: cmp
+    // LLVM-PRE-20-DEBUG: setl
+    // LLVM-PRE-20-DEBUG: and
+    // LLVM-PRE-20-DEBUG: sub
+    //
+    // LLVM-20-DEBUG: sub
+    // LLVM-20-DEBUG: setl
+    // LLVM-20-DEBUG: setg
+    // LLVM-20-DEBUG: sub
+    // LLVM-20-DEBUG: ret
+
+    // LLVM-PRE-20-OPTIM: xor
+    // LLVM-PRE-20-OPTIM: cmp
+    // LLVM-PRE-20-OPTIM: setne
+    // LLVM-PRE-20-OPTIM: mov
+    // LLVM-PRE-20-OPTIM: cmovge
+    // LLVM-PRE-20-OPTIM: ret
+    //
+    // LLVM-20-OPTIM: cmp
+    // LLVM-20-OPTIM: setl
+    // LLVM-20-OPTIM: setg
+    // LLVM-20-OPTIM: sub
+    // LLVM-20-OPTIM: ret
+    three_way_compare(a, b)
+}
+
+#[no_mangle]
+// CHECK-LABEL: unsigned_cmp:
+pub fn unsigned_cmp(a: u16, b: u16) -> std::cmp::Ordering {
+    // LLVM-PRE-20-DEBUG: cmp
+    // LLVM-PRE-20-DEBUG: seta
+    // LLVM-PRE-20-DEBUG: and
+    // LLVM-PRE-20-DEBUG: cmp
+    // LLVM-PRE-20-DEBUG: setb
+    // LLVM-PRE-20-DEBUG: and
+    // LLVM-PRE-20-DEBUG: sub
+    //
+    // LLVM-20-DEBUG: sub
+    // LLVM-20-DEBUG: seta
+    // LLVM-20-DEBUG: sbb
+    // LLVM-20-DEBUG: ret
+
+    // LLVM-PRE-20-OPTIM: xor
+    // LLVM-PRE-20-OPTIM: cmp
+    // LLVM-PRE-20-OPTIM: setne
+    // LLVM-PRE-20-OPTIM: mov
+    // LLVM-PRE-20-OPTIM: cmovae
+    // LLVM-PRE-20-OPTIM: ret
+    //
+    // LLVM-20-OPTIM: cmp
+    // LLVM-20-OPTIM: seta
+    // LLVM-20-OPTIM: sbb
+    // LLVM-20-OPTIM: ret
+    three_way_compare(a, b)
+}
diff --git a/tests/assembly-llvm/x86_64-floating-point-clamp.rs b/tests/assembly-llvm/x86_64-floating-point-clamp.rs
new file mode 100644
index 00000000000..6b0c29c5f21
--- /dev/null
+++ b/tests/assembly-llvm/x86_64-floating-point-clamp.rs
@@ -0,0 +1,27 @@
+// Floating-point clamp is designed to be implementable as max+min,
+// so check to make sure that's what it's actually emitting.
+
+//@ assembly-output: emit-asm
+// Set the base cpu explicitly, in case the default has been changed.
+//@ compile-flags: --crate-type=lib -Copt-level=3 -C llvm-args=-x86-asm-syntax=intel -C target-cpu=x86-64
+//@ only-x86_64
+//@ ignore-sgx
+
+// CHECK-LABEL: clamp_demo:
+#[no_mangle]
+pub fn clamp_demo(a: f32, x: f32, y: f32) -> f32 {
+    // CHECK: maxss
+    // CHECK: minss
+    a.clamp(x, y)
+}
+
+// CHECK-LABEL: clamp12_demo:
+#[no_mangle]
+pub fn clamp12_demo(a: f32) -> f32 {
+    // CHECK: movss   xmm1
+    // CHECK-NEXT: maxss   xmm1, xmm0
+    // CHECK-NEXT: movss   xmm0
+    // CHECK-NEXT: minss   xmm0, xmm1
+    // CHECK: ret
+    a.clamp(1.0, 2.0)
+}
diff --git a/tests/assembly-llvm/x86_64-fortanix-unknown-sgx-lvi-generic-load.rs b/tests/assembly-llvm/x86_64-fortanix-unknown-sgx-lvi-generic-load.rs
new file mode 100644
index 00000000000..f5e2f18e68e
--- /dev/null
+++ b/tests/assembly-llvm/x86_64-fortanix-unknown-sgx-lvi-generic-load.rs
@@ -0,0 +1,17 @@
+// Test LVI load hardening on SGX enclave code
+
+//@ assembly-output: emit-asm
+//@ compile-flags: --crate-type staticlib
+//@ only-x86_64-fortanix-unknown-sgx
+
+#[no_mangle]
+pub extern "C" fn plus_one(r: &mut u64) {
+    *r = *r + 1;
+}
+
+// CHECK: plus_one
+// CHECK: lfence
+// CHECK-NEXT: incq
+// CHECK: popq [[REGISTER:%[a-z]+]]
+// CHECK-NEXT: lfence
+// CHECK-NEXT: jmpq *[[REGISTER]]
diff --git a/tests/assembly-llvm/x86_64-fortanix-unknown-sgx-lvi-generic-ret.rs b/tests/assembly-llvm/x86_64-fortanix-unknown-sgx-lvi-generic-ret.rs
new file mode 100644
index 00000000000..f16d68fa255
--- /dev/null
+++ b/tests/assembly-llvm/x86_64-fortanix-unknown-sgx-lvi-generic-ret.rs
@@ -0,0 +1,12 @@
+// Test LVI ret hardening on generic rust code
+
+//@ assembly-output: emit-asm
+//@ compile-flags: --crate-type staticlib
+//@ only-x86_64-fortanix-unknown-sgx
+
+#[no_mangle]
+pub extern "C" fn myret() {}
+// CHECK: myret:
+// CHECK: popq [[REGISTER:%[a-z]+]]
+// CHECK-NEXT: lfence
+// CHECK-NEXT: jmpq *[[REGISTER]]
diff --git a/tests/assembly-llvm/x86_64-fortanix-unknown-sgx-lvi-inline-assembly.rs b/tests/assembly-llvm/x86_64-fortanix-unknown-sgx-lvi-inline-assembly.rs
new file mode 100644
index 00000000000..a729df8e166
--- /dev/null
+++ b/tests/assembly-llvm/x86_64-fortanix-unknown-sgx-lvi-inline-assembly.rs
@@ -0,0 +1,34 @@
+// Test LVI load hardening on SGX inline assembly code
+
+//@ assembly-output: emit-asm
+//@ compile-flags: --crate-type staticlib
+//@ only-x86_64-fortanix-unknown-sgx
+
+use std::arch::asm;
+
+#[no_mangle]
+pub extern "C" fn get(ptr: *const u64) -> u64 {
+    let value: u64;
+    unsafe {
+        asm!("mov {}, [{}]",
+            out(reg) value,
+            in(reg) ptr);
+    }
+    value
+}
+
+// CHECK: get
+// CHECK: movq
+// CHECK-NEXT: lfence
+
+#[no_mangle]
+pub extern "C" fn myret() {
+    unsafe {
+        asm!("ret");
+    }
+}
+
+// CHECK: myret
+// CHECK: shlq $0, (%rsp)
+// CHECK-NEXT: lfence
+// CHECK-NEXT: retq
diff --git a/tests/assembly-llvm/x86_64-function-return.rs b/tests/assembly-llvm/x86_64-function-return.rs
new file mode 100644
index 00000000000..7fd57200a9e
--- /dev/null
+++ b/tests/assembly-llvm/x86_64-function-return.rs
@@ -0,0 +1,30 @@
+// Test that the function return is (not) converted into a jump to the thunk
+// when the `-Zfunction-return={keep,thunk-extern}` flag is (not) set.
+
+//@ revisions: unset keep thunk-extern keep-thunk-extern thunk-extern-keep
+//@ assembly-output: emit-asm
+//@ compile-flags: -Copt-level=3
+//@ [keep] compile-flags: -Zfunction-return=keep
+//@ [thunk-extern] compile-flags: -Zfunction-return=thunk-extern
+//@ [keep-thunk-extern] compile-flags: -Zfunction-return=keep -Zfunction-return=thunk-extern
+//@ [thunk-extern-keep] compile-flags: -Zfunction-return=thunk-extern -Zfunction-return=keep
+//@ only-x86_64
+//@ ignore-apple Symbol is called `___x86_return_thunk` (Darwin's extra underscore)
+//@ ignore-sgx Tests incompatible with LVI mitigations
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: foo:
+#[no_mangle]
+pub unsafe fn foo() {
+    // unset: ret
+    // unset-NOT: jmp __x86_return_thunk
+    // keep: ret
+    // keep-NOT: jmp __x86_return_thunk
+    // thunk-extern: jmp __x86_return_thunk
+    // thunk-extern-NOT: ret
+    // keep-thunk-extern: jmp __x86_return_thunk
+    // keep-thunk-extern-NOT: ret
+    // thunk-extern-keep: ret
+    // thunk-extern-keep-NOT: jmp __x86_return_thunk
+}
diff --git a/tests/assembly-llvm/x86_64-no-jump-tables.rs b/tests/assembly-llvm/x86_64-no-jump-tables.rs
new file mode 100644
index 00000000000..bb10042d8f6
--- /dev/null
+++ b/tests/assembly-llvm/x86_64-no-jump-tables.rs
@@ -0,0 +1,35 @@
+// Test that jump tables are (not) emitted when the `-Zno-jump-tables`
+// flag is (not) set.
+
+//@ revisions: unset set
+//@ assembly-output: emit-asm
+//@ compile-flags: -Copt-level=3
+//@ [set] compile-flags: -Zno-jump-tables
+//@ only-x86_64
+//@ ignore-sgx
+
+#![crate_type = "lib"]
+
+extern "C" {
+    fn bar1();
+    fn bar2();
+    fn bar3();
+    fn bar4();
+    fn bar5();
+    fn bar6();
+}
+
+// CHECK-LABEL: foo:
+#[no_mangle]
+pub unsafe fn foo(x: i32) {
+    // unset: LJTI0_0
+    // set-NOT: LJTI0_0
+    match x {
+        1 => bar1(),
+        2 => bar2(),
+        3 => bar3(),
+        4 => bar4(),
+        5 => bar5(),
+        _ => bar6(),
+    }
+}
diff --git a/tests/assembly-llvm/x86_64-sse_crc.rs b/tests/assembly-llvm/x86_64-sse_crc.rs
new file mode 100644
index 00000000000..bde58955a21
--- /dev/null
+++ b/tests/assembly-llvm/x86_64-sse_crc.rs
@@ -0,0 +1,12 @@
+//@ only-x86_64
+//@ assembly-output: emit-asm
+//@ compile-flags: --crate-type staticlib -Ctarget-feature=+sse4.2
+
+// CHECK-LABEL: banana
+// CHECK: crc32
+#[no_mangle]
+pub unsafe fn banana(v: u8) -> u32 {
+    use std::arch::x86_64::*;
+    let out = !0u32;
+    _mm_crc32_u8(out, v)
+}
diff --git a/tests/assembly-llvm/x86_64-typed-swap.rs b/tests/assembly-llvm/x86_64-typed-swap.rs
new file mode 100644
index 00000000000..a6753011d36
--- /dev/null
+++ b/tests/assembly-llvm/x86_64-typed-swap.rs
@@ -0,0 +1,81 @@
+//@ revisions: WIN LIN
+//@ [WIN] only-windows
+//@ [LIN] only-linux
+//@ only-x86_64
+//@ assembly-output: emit-asm
+//@ compile-flags: --crate-type=lib -Copt-level=3
+
+use std::arch::x86_64::__m128;
+use std::mem::swap;
+
+// CHECK-LABEL: swap_i32:
+#[no_mangle]
+pub fn swap_i32(x: &mut i32, y: &mut i32) {
+    // CHECK: movl (%[[ARG1:.+]]), %[[T1:.+]]
+    // CHECK-NEXT: movl (%[[ARG2:.+]]), %[[T2:.+]]
+    // CHECK-DAG: movl %[[T2]], (%[[ARG1]])
+    // CHECK-DAG: movl %[[T1]], (%[[ARG2]])
+    // CHECK-NEXT: retq
+    swap(x, y)
+}
+
+// CHECK-LABEL: swap_pair:
+#[no_mangle]
+pub fn swap_pair(x: &mut (i32, u32), y: &mut (i32, u32)) {
+    // CHECK: movq (%[[ARG1:r..?]]), %[[T1:.+]]
+    // CHECK-NEXT: movq (%[[ARG2:r..?]]), %[[T2:.+]]
+    // CHECK-DAG: movq %[[T2]], (%[[ARG1]])
+    // CHECK-DAG: movq %[[T1]], (%[[ARG2]])
+    // CHECK-NEXT: retq
+    swap(x, y)
+}
+
+// CHECK-LABEL: swap_str:
+#[no_mangle]
+pub fn swap_str<'a>(x: &mut &'a str, y: &mut &'a str) {
+    // CHECK: movups (%[[ARG1:r..?]]), %[[T1:xmm.]]
+    // CHECK-NEXT: movups (%[[ARG2:r..?]]), %[[T2:xmm.]]
+    // CHECK-DAG: movups %[[T2]], (%[[ARG1]])
+    // CHECK-DAG: movups %[[T1]], (%[[ARG2]])
+    // CHECK-NEXT: retq
+    swap(x, y)
+}
+
+// CHECK-LABEL: swap_simd:
+#[no_mangle]
+pub fn swap_simd(x: &mut __m128, y: &mut __m128) {
+    // CHECK: movaps (%[[ARG1:r..?]]), %[[T1:xmm.]]
+    // CHECK-NEXT: movaps (%[[ARG2:r..?]]), %[[T2:xmm.]]
+    // CHECK-DAG: movaps %[[T2]], (%[[ARG1]])
+    // CHECK-DAG: movaps %[[T1]], (%[[ARG2]])
+    // CHECK-NEXT: retq
+    swap(x, y)
+}
+
+// CHECK-LABEL: swap_string:
+#[no_mangle]
+pub fn swap_string(x: &mut String, y: &mut String) {
+    // CHECK-NOT: mov
+    // CHECK-COUNT-4: movups
+    // CHECK-NOT: mov
+    // CHECK-COUNT-4: movq
+    // CHECK-NOT: mov
+    swap(x, y)
+}
+
+// CHECK-LABEL: swap_44_bytes:
+#[no_mangle]
+pub fn swap_44_bytes(x: &mut [u8; 44], y: &mut [u8; 44]) {
+    // Ensure we do better than a long run of byte copies,
+    // see <https://github.com/rust-lang/rust/issues/134946>
+
+    // CHECK-NOT: movb
+    // CHECK-COUNT-8: movups{{.+}}xmm
+    // CHECK-NOT: movb
+    // CHECK-COUNT-4: movq
+    // CHECK-NOT: movb
+    // CHECK-COUNT-4: movl
+    // CHECK-NOT: movb
+    // CHECK: retq
+    swap(x, y)
+}
diff --git a/tests/assembly-llvm/x86_64-windows-float-abi.rs b/tests/assembly-llvm/x86_64-windows-float-abi.rs
new file mode 100644
index 00000000000..cbc80910851
--- /dev/null
+++ b/tests/assembly-llvm/x86_64-windows-float-abi.rs
@@ -0,0 +1,46 @@
+//@ assembly-output: emit-asm
+//@ compile-flags: -Copt-level=3
+//@ compile-flags: --target x86_64-pc-windows-msvc
+//@ needs-llvm-components: x86
+//@ add-core-stubs
+
+#![feature(f16, f128)]
+#![feature(no_core)]
+#![no_core]
+#![crate_type = "lib"]
+
+extern crate minicore;
+use minicore::*;
+
+// CHECK-LABEL: second_f16
+// CHECK: movaps %xmm1, %xmm0
+// CHECK-NEXT: retq
+#[no_mangle]
+pub extern "C" fn second_f16(_: f16, x: f16) -> f16 {
+    x
+}
+
+// CHECK-LABEL: second_f32
+// CHECK: movaps %xmm1, %xmm0
+// CHECK-NEXT: retq
+#[no_mangle]
+pub extern "C" fn second_f32(_: f32, x: f32) -> f32 {
+    x
+}
+
+// CHECK-LABEL: second_f64
+// CHECK: movaps %xmm1, %xmm0
+// CHECK-NEXT: retq
+#[no_mangle]
+pub extern "C" fn second_f64(_: f64, x: f64) -> f64 {
+    x
+}
+
+// CHECK-LABEL: second_f128
+// FIXME(llvm21): this can be just %rdx instead of the regex once we don't test on LLVM 20
+// CHECK: movaps {{(%xmm1|\(%rdx\))}}, %xmm0
+// CHECK-NEXT: retq
+#[no_mangle]
+pub extern "C" fn second_f128(_: f128, x: f128) -> f128 {
+    x
+}
diff --git a/tests/assembly-llvm/x86_64-windows-i128-abi.rs b/tests/assembly-llvm/x86_64-windows-i128-abi.rs
new file mode 100644
index 00000000000..d2aefb7daa6
--- /dev/null
+++ b/tests/assembly-llvm/x86_64-windows-i128-abi.rs
@@ -0,0 +1,26 @@
+//@ assembly-output: emit-asm
+//@ add-core-stubs
+//@ revisions: msvc softfloat
+//@ compile-flags: -Copt-level=3
+//@[msvc] compile-flags: --target x86_64-pc-windows-msvc
+//@[msvc] needs-llvm-components: x86
+//@[softfloat] compile-flags: --target x86_64-unknown-uefi
+//@[softfloat] needs-llvm-components: x86
+
+#![feature(no_core)]
+#![no_core]
+#![crate_type = "lib"]
+
+extern crate minicore;
+use minicore::*;
+
+// CHECK-LABEL: ret_i128
+// Hardfloat targets return via xmm0, softfloat targets via rax and rdx.
+// msvc: movaps {{.*}}, %xmm0
+// softfloat: movq (%[[INPUT:.*]]), %rax
+// softfloat-NEXT: movq 8(%[[INPUT]]), %rdx
+// CHECK-NEXT: retq
+#[no_mangle]
+pub extern "C" fn ret_i128(x: &i128) -> i128 {
+    *x
+}
diff --git a/tests/assembly-llvm/x86_64-xray.rs b/tests/assembly-llvm/x86_64-xray.rs
new file mode 100644
index 00000000000..4cf3e8cda13
--- /dev/null
+++ b/tests/assembly-llvm/x86_64-xray.rs
@@ -0,0 +1,25 @@
+//@ assembly-output: emit-asm
+//@ compile-flags: -Zinstrument-xray=always -Cllvm-args=-x86-asm-syntax=intel
+
+//@ revisions: x86_64-linux
+//@[x86_64-linux] compile-flags: --target=x86_64-unknown-linux-gnu
+//@[x86_64-linux] needs-llvm-components: x86
+//@[x86_64-linux] only-x86_64-unknown-linux-gnu
+
+//@ revisions: x86_64-darwin
+//@[x86_64-darwin] compile-flags: --target=x86_64-apple-darwin
+//@[x86_64-darwin] needs-llvm-components: x86
+//@[x86_64-darwin] only-x86_64-apple-darwin
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: xray_func:
+#[no_mangle]
+pub fn xray_func() {
+    // CHECK: nop word ptr [rax + rax + 512]
+
+    std::hint::black_box(());
+
+    // CHECK: ret
+    // CHECK-NEXT: nop word ptr cs:[rax + rax + 512]
+}