about summary refs log tree commit diff
path: root/tests/assembly
diff options
context:
space:
mode:
authorAlbert Larsan <74931857+albertlarsan68@users.noreply.github.com>2023-01-05 09:13:28 +0100
committerAlbert Larsan <74931857+albertlarsan68@users.noreply.github.com>2023-01-11 09:32:08 +0000
commitcf2dff2b1e3fa55fa5415d524200070d0d7aacfe (patch)
tree40a88d9a46aaf3e8870676eb2538378b75a263eb /tests/assembly
parentca855e6e42787ecd062d81d53336fe6788ef51a9 (diff)
downloadrust-cf2dff2b1e3fa55fa5415d524200070d0d7aacfe.tar.gz
rust-cf2dff2b1e3fa55fa5415d524200070d0d7aacfe.zip
Move /src/test to /tests
Diffstat (limited to 'tests/assembly')
-rw-r--r--tests/assembly/aarch64-naked-fn-no-bti-prolog.rs21
-rw-r--r--tests/assembly/aarch64-pointer-auth.rs21
-rw-r--r--tests/assembly/align_offset.rs48
-rw-r--r--tests/assembly/asm/aarch64-el2vmsa.rs37
-rw-r--r--tests/assembly/asm/aarch64-modifiers.rs145
-rw-r--r--tests/assembly/asm/aarch64-outline-atomics.rs16
-rw-r--r--tests/assembly/asm/aarch64-types.rs565
-rw-r--r--tests/assembly/asm/arm-modifiers.rs144
-rw-r--r--tests/assembly/asm/arm-types.rs530
-rw-r--r--tests/assembly/asm/avr-modifiers.rs59
-rw-r--r--tests/assembly/asm/avr-types.rs221
-rw-r--r--tests/assembly/asm/bpf-types.rs153
-rw-r--r--tests/assembly/asm/global_asm.rs33
-rw-r--r--tests/assembly/asm/hexagon-types.rs181
-rw-r--r--tests/assembly/asm/mips-types.rs237
-rw-r--r--tests/assembly/asm/msp430-types.rs157
-rw-r--r--tests/assembly/asm/nvptx-types.rs133
-rw-r--r--tests/assembly/asm/powerpc-types.rs207
-rw-r--r--tests/assembly/asm/riscv-types.rs210
-rw-r--r--tests/assembly/asm/s390x-types.rs167
-rw-r--r--tests/assembly/asm/wasm-types.rs149
-rw-r--r--tests/assembly/asm/x86-modifiers.rs205
-rw-r--r--tests/assembly/asm/x86-types.rs1093
-rw-r--r--tests/assembly/auxiliary/breakpoint-panic-handler.rs8
-rw-r--r--tests/assembly/auxiliary/non-inline-dependency.rs14
-rw-r--r--tests/assembly/dwarf5.rs20
-rw-r--r--tests/assembly/is_aligned.rs58
-rw-r--r--tests/assembly/niche-prefer-zero.rs25
-rw-r--r--tests/assembly/nvptx-arch-default.rs13
-rw-r--r--tests/assembly/nvptx-arch-emit-asm.rs10
-rw-r--r--tests/assembly/nvptx-arch-link-arg.rs13
-rw-r--r--tests/assembly/nvptx-arch-target-cpu.rs13
-rw-r--r--tests/assembly/nvptx-atomics.rs86
-rw-r--r--tests/assembly/nvptx-internalizing.rs27
-rw-r--r--tests/assembly/nvptx-kernel-abi/nvptx-kernel-args-abi-v7.rs254
-rw-r--r--tests/assembly/nvptx-linking-binary.rs40
-rw-r--r--tests/assembly/nvptx-linking-cdylib.rs39
-rw-r--r--tests/assembly/nvptx-safe-naming.rs38
-rw-r--r--tests/assembly/panic-no-unwind-no-uwtable.rs8
-rw-r--r--tests/assembly/panic-unwind-no-uwtable.rs12
-rw-r--r--tests/assembly/pic-relocation-model.rs35
-rw-r--r--tests/assembly/pie-relocation-model.rs38
-rw-r--r--tests/assembly/sparc-struct-abi.rs70
-rw-r--r--tests/assembly/stack-protector/stack-protector-heuristics-effect.rs396
-rw-r--r--tests/assembly/stack-protector/stack-protector-target-support.rs285
-rw-r--r--tests/assembly/static-relocation-model.rs86
-rw-r--r--tests/assembly/strict_provenance.rs37
-rw-r--r--tests/assembly/target-feature-multiple.rs42
-rw-r--r--tests/assembly/x86-stack-probes.rs42
-rw-r--r--tests/assembly/x86_64-floating-point-clamp.rs25
-rw-r--r--tests/assembly/x86_64-fortanix-unknown-sgx-lvi-generic-load.rs17
-rw-r--r--tests/assembly/x86_64-fortanix-unknown-sgx-lvi-generic-ret.rs12
-rw-r--r--tests/assembly/x86_64-fortanix-unknown-sgx-lvi-inline-assembly.rs43
-rw-r--r--tests/assembly/x86_64-naked-fn-no-cet-prolog.rs24
-rw-r--r--tests/assembly/x86_64-no-jump-tables.rs34
-rw-r--r--tests/assembly/x86_64-sse_crc.rs12
56 files changed, 6608 insertions, 0 deletions
diff --git a/tests/assembly/aarch64-naked-fn-no-bti-prolog.rs b/tests/assembly/aarch64-naked-fn-no-bti-prolog.rs
new file mode 100644
index 00000000000..79b0bb2d7ee
--- /dev/null
+++ b/tests/assembly/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"]
+#![feature(naked_functions)]
+use std::arch::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]
+#[naked]
+pub unsafe extern "C" fn _hlt() -> ! {
+    // CHECK-NOT: hint #34
+    // CHECK: hlt #0x1
+    asm!("hlt #1", options(noreturn))
+}
diff --git a/tests/assembly/aarch64-pointer-auth.rs b/tests/assembly/aarch64-pointer-auth.rs
new file mode 100644
index 00000000000..da14cd02678
--- /dev/null
+++ b/tests/assembly/aarch64-pointer-auth.rs
@@ -0,0 +1,21 @@
+// Test that PAC instructions are emitted when branch-protection is specified.
+
+// assembly-output: emit-asm
+// compile-flags: --target aarch64-unknown-linux-gnu
+// compile-flags: -Z branch-protection=pac-ret,leaf
+// needs-llvm-components: aarch64
+
+#![feature(no_core, lang_items)]
+#![no_std]
+#![no_core]
+#![crate_type = "lib"]
+
+#[lang = "sized"]
+trait Sized {}
+
+// CHECK: hint #25
+// CHECK: hint #29
+#[no_mangle]
+pub fn test() -> u8 {
+    42
+}
diff --git a/tests/assembly/align_offset.rs b/tests/assembly/align_offset.rs
new file mode 100644
index 00000000000..c5eefca3467
--- /dev/null
+++ b/tests/assembly/align_offset.rs
@@ -0,0 +1,48 @@
+// assembly-output: emit-asm
+// compile-flags: -Copt-level=1
+// only-x86_64
+// min-llvm-version: 14.0
+#![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/asm/aarch64-el2vmsa.rs b/tests/assembly/asm/aarch64-el2vmsa.rs
new file mode 100644
index 00000000000..1908ffb8ff3
--- /dev/null
+++ b/tests/assembly/asm/aarch64-el2vmsa.rs
@@ -0,0 +1,37 @@
+// assembly-output: emit-asm
+// compile-flags: --target aarch64-unknown-linux-gnu
+// needs-llvm-components: aarch64
+
+#![feature(no_core, lang_items, rustc_attrs)]
+#![crate_type = "rlib"]
+#![no_core]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+    () => {};
+}
+
+#[lang = "sized"]
+trait Sized {}
+
+// 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/asm/aarch64-modifiers.rs b/tests/assembly/asm/aarch64-modifiers.rs
new file mode 100644
index 00000000000..5196aa9fa17
--- /dev/null
+++ b/tests/assembly/asm/aarch64-modifiers.rs
@@ -0,0 +1,145 @@
+// assembly-output: emit-asm
+// compile-flags: -O
+// compile-flags: --target aarch64-unknown-linux-gnu
+// needs-llvm-components: aarch64
+
+#![feature(no_core, lang_items, rustc_attrs)]
+#![crate_type = "rlib"]
+#![no_core]
+#![allow(asm_sub_register)]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+    () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! stringify {
+    () => {};
+}
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+impl Copy for i32 {}
+
+macro_rules! check {
+    ($func:ident $reg:ident $code:literal) => {
+        // -O and extern "C" guarantee that the selected register is always r0/s0/d0/q0
+        #[no_mangle]
+        pub unsafe extern "C" fn $func() -> i32 {
+            // Hack to avoid function merging
+            extern "Rust" {
+                fn dont_merge(s: &str);
+            }
+            dont_merge(stringify!($func));
+
+            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/asm/aarch64-outline-atomics.rs b/tests/assembly/asm/aarch64-outline-atomics.rs
new file mode 100644
index 00000000000..c2ec4e911b9
--- /dev/null
+++ b/tests/assembly/asm/aarch64-outline-atomics.rs
@@ -0,0 +1,16 @@
+// assembly-output: emit-asm
+// compile-flags: -O
+// compile-flags: --target aarch64-unknown-linux-gnu
+// needs-llvm-components: aarch64
+// only-aarch64
+// only-linux
+
+#![crate_type = "rlib"]
+
+use std::sync::atomic::{AtomicI32, 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/asm/aarch64-types.rs b/tests/assembly/asm/aarch64-types.rs
new file mode 100644
index 00000000000..66c39a48c6e
--- /dev/null
+++ b/tests/assembly/asm/aarch64-types.rs
@@ -0,0 +1,565 @@
+// assembly-output: emit-asm
+// compile-flags: --target aarch64-unknown-linux-gnu
+// needs-llvm-components: aarch64
+
+#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
+#![crate_type = "rlib"]
+#![no_core]
+#![allow(asm_sub_register, non_camel_case_types)]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+    () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! concat {
+    () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! stringify {
+    () => {};
+}
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+type ptr = *mut u8;
+
+#[repr(simd)]
+pub struct i8x8(i8, i8, i8, i8, i8, i8, i8, i8);
+#[repr(simd)]
+pub struct i16x4(i16, i16, i16, i16);
+#[repr(simd)]
+pub struct i32x2(i32, i32);
+#[repr(simd)]
+pub struct i64x1(i64);
+#[repr(simd)]
+pub struct f32x2(f32, f32);
+#[repr(simd)]
+pub struct f64x1(f64);
+#[repr(simd)]
+pub struct i8x16(i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8);
+#[repr(simd)]
+pub struct i16x8(i16, i16, i16, i16, i16, i16, i16, i16);
+#[repr(simd)]
+pub struct i32x4(i32, i32, i32, i32);
+#[repr(simd)]
+pub struct i64x2(i64, i64);
+#[repr(simd)]
+pub struct f32x4(f32, f32, f32, f32);
+#[repr(simd)]
+pub struct f64x2(f64, f64);
+
+impl Copy for i8 {}
+impl Copy for i16 {}
+impl Copy for i32 {}
+impl Copy for f32 {}
+impl Copy for i64 {}
+impl Copy for f64 {}
+impl Copy for ptr {}
+impl Copy for i8x8 {}
+impl Copy for i16x4 {}
+impl Copy for i32x2 {}
+impl Copy for i64x1 {}
+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 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:
+// CHECK: str {{.*}}x30
+// CHECK: //APP
+// CHECK: //NO_APP
+// CHECK: ldr {{.*}}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) => {
+        #[no_mangle]
+        pub unsafe fn $func(x: $ty) -> $ty {
+            // Hack to avoid function merging
+            extern "Rust" {
+                fn dont_merge(s: &str);
+            }
+            dont_merge(stringify!($func));
+
+            let y;
+            asm!(
+                concat!($mov, " {:", $modifier, "}, {:", $modifier, "}"),
+                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 {
+            // Hack to avoid function merging
+            extern "Rust" {
+                fn dont_merge(s: &str);
+            }
+            dont_merge(stringify!($func));
+
+            let y;
+            asm!(concat!($mov, " ", $reg, ", ", $reg), lateout($reg) y, in($reg) x);
+            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_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_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_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_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_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_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_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_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_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_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_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_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_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_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/asm/arm-modifiers.rs b/tests/assembly/asm/arm-modifiers.rs
new file mode 100644
index 00000000000..88ffeaecfec
--- /dev/null
+++ b/tests/assembly/asm/arm-modifiers.rs
@@ -0,0 +1,144 @@
+// assembly-output: emit-asm
+// compile-flags: -O
+// compile-flags: --target armv7-unknown-linux-gnueabihf
+// compile-flags: -C target-feature=+neon
+// needs-llvm-components: arm
+
+#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
+#![crate_type = "rlib"]
+#![no_core]
+#![allow(asm_sub_register, non_camel_case_types)]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+    () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! concat {
+    () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! stringify {
+    () => {};
+}
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+#[repr(simd)]
+pub struct f32x4(f32, f32, f32, f32);
+
+impl Copy for i32 {}
+impl Copy for f32 {}
+impl Copy for f64 {}
+impl Copy for f32x4 {}
+
+macro_rules! check {
+    ($func:ident $modifier:literal $reg:ident $ty:ident $mov:literal) => {
+        // -O and extern "C" guarantee that the selected register is always r0/s0/d0/q0
+        #[no_mangle]
+        pub unsafe extern "C" fn $func() -> $ty {
+            // Hack to avoid function merging
+            extern "Rust" {
+                fn dont_merge(s: &str);
+            }
+            dont_merge(stringify!($func));
+
+            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/asm/arm-types.rs b/tests/assembly/asm/arm-types.rs
new file mode 100644
index 00000000000..b22a26ce36f
--- /dev/null
+++ b/tests/assembly/asm/arm-types.rs
@@ -0,0 +1,530 @@
+// assembly-output: emit-asm
+// compile-flags: --target armv7-unknown-linux-gnueabihf
+// compile-flags: -C target-feature=+neon
+// needs-llvm-components: arm
+
+#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
+#![crate_type = "rlib"]
+#![no_core]
+#![allow(asm_sub_register, non_camel_case_types)]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+    () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! concat {
+    () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! stringify {
+    () => {};
+}
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+type ptr = *mut u8;
+
+#[repr(simd)]
+pub struct i8x8(i8, i8, i8, i8, i8, i8, i8, i8);
+#[repr(simd)]
+pub struct i16x4(i16, i16, i16, i16);
+#[repr(simd)]
+pub struct i32x2(i32, i32);
+#[repr(simd)]
+pub struct i64x1(i64);
+#[repr(simd)]
+pub struct f32x2(f32, f32);
+#[repr(simd)]
+pub struct i8x16(i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8);
+#[repr(simd)]
+pub struct i16x8(i16, i16, i16, i16, i16, i16, i16, i16);
+#[repr(simd)]
+pub struct i32x4(i32, i32, i32, i32);
+#[repr(simd)]
+pub struct i64x2(i64, i64);
+#[repr(simd)]
+pub struct f32x4(f32, f32, f32, f32);
+
+impl Copy for i8 {}
+impl Copy for i16 {}
+impl Copy for i32 {}
+impl Copy for f32 {}
+impl Copy for i64 {}
+impl Copy for f64 {}
+impl Copy for ptr {}
+impl Copy for i8x8 {}
+impl Copy for i16x4 {}
+impl Copy for i32x2 {}
+impl Copy for i64x1 {}
+impl Copy for f32x2 {}
+impl Copy for i8x16 {}
+impl Copy for i16x8 {}
+impl Copy for i32x4 {}
+impl Copy for i64x2 {}
+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 {
+            // Hack to avoid function merging
+            extern "Rust" {
+                fn dont_merge(s: &str);
+            }
+            dont_merge(stringify!($func));
+
+            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 {
+            // Hack to avoid function merging
+            extern "Rust" {
+                fn dont_merge(s: &str);
+            }
+            dont_merge(stringify!($func));
+
+            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_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_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_f32:
+// CHECK: @APP
+// CHECK: vmov.f32 s{{[0-9]+}}, s{{[0-9]+}}
+// CHECK: @NO_APP
+check!(sreg_low16_f32 f32 sreg_low16 "vmov.f32");
+
+// CHECK-LABEL: dreg_i64:
+// CHECK: @APP
+// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// CHECK: @NO_APP
+check!(dreg_i64 i64 dreg "vmov.f64");
+
+// CHECK-LABEL: dreg_f64:
+// CHECK: @APP
+// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// CHECK: @NO_APP
+check!(dreg_f64 f64 dreg "vmov.f64");
+
+// CHECK-LABEL: dreg_i8x8:
+// CHECK: @APP
+// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// CHECK: @NO_APP
+check!(dreg_i8x8 i8x8 dreg "vmov.f64");
+
+// CHECK-LABEL: dreg_i16x4:
+// CHECK: @APP
+// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// CHECK: @NO_APP
+check!(dreg_i16x4 i16x4 dreg "vmov.f64");
+
+// CHECK-LABEL: dreg_i32x2:
+// CHECK: @APP
+// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// CHECK: @NO_APP
+check!(dreg_i32x2 i32x2 dreg "vmov.f64");
+
+// CHECK-LABEL: dreg_i64x1:
+// CHECK: @APP
+// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// CHECK: @NO_APP
+check!(dreg_i64x1 i64x1 dreg "vmov.f64");
+
+// CHECK-LABEL: dreg_f32x2:
+// CHECK: @APP
+// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// CHECK: @NO_APP
+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");
+
+// CHECK-LABEL: dreg_low16_i8x8:
+// CHECK: @APP
+// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// CHECK: @NO_APP
+check!(dreg_low16_i8x8 i8x8 dreg_low16 "vmov.f64");
+
+// CHECK-LABEL: dreg_low16_i16x4:
+// CHECK: @APP
+// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// CHECK: @NO_APP
+check!(dreg_low16_i16x4 i16x4 dreg_low16 "vmov.f64");
+
+// CHECK-LABEL: dreg_low16_i32x2:
+// CHECK: @APP
+// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// CHECK: @NO_APP
+check!(dreg_low16_i32x2 i32x2 dreg_low16 "vmov.f64");
+
+// CHECK-LABEL: dreg_low16_i64x1:
+// CHECK: @APP
+// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// CHECK: @NO_APP
+check!(dreg_low16_i64x1 i64x1 dreg_low16 "vmov.f64");
+
+// CHECK-LABEL: dreg_low16_f32x2:
+// CHECK: @APP
+// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// CHECK: @NO_APP
+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");
+
+// CHECK-LABEL: dreg_low8_i8x8:
+// CHECK: @APP
+// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// CHECK: @NO_APP
+check!(dreg_low8_i8x8 i8x8 dreg_low8 "vmov.f64");
+
+// CHECK-LABEL: dreg_low8_i16x4:
+// CHECK: @APP
+// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// CHECK: @NO_APP
+check!(dreg_low8_i16x4 i16x4 dreg_low8 "vmov.f64");
+
+// CHECK-LABEL: dreg_low8_i32x2:
+// CHECK: @APP
+// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// CHECK: @NO_APP
+check!(dreg_low8_i32x2 i32x2 dreg_low8 "vmov.f64");
+
+// CHECK-LABEL: dreg_low8_i64x1:
+// CHECK: @APP
+// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// CHECK: @NO_APP
+check!(dreg_low8_i64x1 i64x1 dreg_low8 "vmov.f64");
+
+// CHECK-LABEL: dreg_low8_f32x2:
+// CHECK: @APP
+// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// CHECK: @NO_APP
+check!(dreg_low8_f32x2 f32x2 dreg_low8 "vmov.f64");
+
+// CHECK-LABEL: qreg_i8x16:
+// CHECK: @APP
+// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}}
+// CHECK: @NO_APP
+check!(qreg_i8x16 i8x16 qreg "vmov");
+
+// CHECK-LABEL: qreg_i16x8:
+// CHECK: @APP
+// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}}
+// CHECK: @NO_APP
+check!(qreg_i16x8 i16x8 qreg "vmov");
+
+// CHECK-LABEL: qreg_i32x4:
+// CHECK: @APP
+// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}}
+// CHECK: @NO_APP
+check!(qreg_i32x4 i32x4 qreg "vmov");
+
+// CHECK-LABEL: qreg_i64x2:
+// CHECK: @APP
+// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}}
+// CHECK: @NO_APP
+check!(qreg_i64x2 i64x2 qreg "vmov");
+
+// CHECK-LABEL: qreg_f32x4:
+// CHECK: @APP
+// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}}
+// CHECK: @NO_APP
+check!(qreg_f32x4 f32x4 qreg "vmov");
+
+// CHECK-LABEL: qreg_low8_i8x16:
+// CHECK: @APP
+// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}}
+// CHECK: @NO_APP
+check!(qreg_low8_i8x16 i8x16 qreg_low8 "vmov");
+
+// CHECK-LABEL: qreg_low8_i16x8:
+// CHECK: @APP
+// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}}
+// CHECK: @NO_APP
+check!(qreg_low8_i16x8 i16x8 qreg_low8 "vmov");
+
+// CHECK-LABEL: qreg_low8_i32x4:
+// CHECK: @APP
+// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}}
+// CHECK: @NO_APP
+check!(qreg_low8_i32x4 i32x4 qreg_low8 "vmov");
+
+// CHECK-LABEL: qreg_low8_i64x2:
+// CHECK: @APP
+// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}}
+// CHECK: @NO_APP
+check!(qreg_low8_i64x2 i64x2 qreg_low8 "vmov");
+
+// CHECK-LABEL: qreg_low8_f32x4:
+// CHECK: @APP
+// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}}
+// CHECK: @NO_APP
+check!(qreg_low8_f32x4 f32x4 qreg_low8 "vmov");
+
+// CHECK-LABEL: qreg_low4_i8x16:
+// CHECK: @APP
+// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}}
+// CHECK: @NO_APP
+check!(qreg_low4_i8x16 i8x16 qreg_low4 "vmov");
+
+// CHECK-LABEL: qreg_low4_i16x8:
+// CHECK: @APP
+// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}}
+// CHECK: @NO_APP
+check!(qreg_low4_i16x8 i16x8 qreg_low4 "vmov");
+
+// CHECK-LABEL: qreg_low4_i32x4:
+// CHECK: @APP
+// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}}
+// CHECK: @NO_APP
+check!(qreg_low4_i32x4 i32x4 qreg_low4 "vmov");
+
+// CHECK-LABEL: qreg_low4_i64x2:
+// CHECK: @APP
+// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}}
+// CHECK: @NO_APP
+check!(qreg_low4_i64x2 i64x2 qreg_low4 "vmov");
+
+// CHECK-LABEL: qreg_low4_f32x4:
+// CHECK: @APP
+// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}}
+// CHECK: @NO_APP
+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_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_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");
+
+// CHECK-LABEL: d0_i64:
+// CHECK: @APP
+// CHECK: vmov.f64 d0, d0
+// CHECK: @NO_APP
+check_reg!(d0_i64 i64 "d0" "vmov.f64");
+
+// CHECK-LABEL: d0_f64:
+// CHECK: @APP
+// CHECK: vmov.f64 d0, d0
+// CHECK: @NO_APP
+check_reg!(d0_f64 f64 "d0" "vmov.f64");
+
+// CHECK-LABEL: d0_i8x8:
+// CHECK: @APP
+// CHECK: vmov.f64 d0, d0
+// CHECK: @NO_APP
+check_reg!(d0_i8x8 i8x8 "d0" "vmov.f64");
+
+// CHECK-LABEL: d0_i16x4:
+// CHECK: @APP
+// CHECK: vmov.f64 d0, d0
+// CHECK: @NO_APP
+check_reg!(d0_i16x4 i16x4 "d0" "vmov.f64");
+
+// CHECK-LABEL: d0_i32x2:
+// CHECK: @APP
+// CHECK: vmov.f64 d0, d0
+// CHECK: @NO_APP
+check_reg!(d0_i32x2 i32x2 "d0" "vmov.f64");
+
+// CHECK-LABEL: d0_i64x1:
+// CHECK: @APP
+// CHECK: vmov.f64 d0, d0
+// CHECK: @NO_APP
+check_reg!(d0_i64x1 i64x1 "d0" "vmov.f64");
+
+// CHECK-LABEL: d0_f32x2:
+// CHECK: @APP
+// CHECK: vmov.f64 d0, d0
+// CHECK: @NO_APP
+check_reg!(d0_f32x2 f32x2 "d0" "vmov.f64");
+
+// CHECK-LABEL: q0_i8x16:
+// CHECK: @APP
+// CHECK: vorr q0, q0, q0
+// CHECK: @NO_APP
+check_reg!(q0_i8x16 i8x16 "q0" "vmov");
+
+// CHECK-LABEL: q0_i16x8:
+// CHECK: @APP
+// CHECK: vorr q0, q0, q0
+// CHECK: @NO_APP
+check_reg!(q0_i16x8 i16x8 "q0" "vmov");
+
+// CHECK-LABEL: q0_i32x4:
+// CHECK: @APP
+// CHECK: vorr q0, q0, q0
+// CHECK: @NO_APP
+check_reg!(q0_i32x4 i32x4 "q0" "vmov");
+
+// CHECK-LABEL: q0_i64x2:
+// CHECK: @APP
+// CHECK: vorr q0, q0, q0
+// CHECK: @NO_APP
+check_reg!(q0_i64x2 i64x2 "q0" "vmov");
+
+// CHECK-LABEL: q0_f32x4:
+// CHECK: @APP
+// CHECK: vorr q0, q0, q0
+// CHECK: @NO_APP
+check_reg!(q0_f32x4 f32x4 "q0" "vmov");
diff --git a/tests/assembly/asm/avr-modifiers.rs b/tests/assembly/asm/avr-modifiers.rs
new file mode 100644
index 00000000000..ffdc8f2e351
--- /dev/null
+++ b/tests/assembly/asm/avr-modifiers.rs
@@ -0,0 +1,59 @@
+// assembly-output: emit-asm
+// compile-flags: --target avr-unknown-gnu-atmega328
+// needs-llvm-components: avr
+
+#![feature(no_core, lang_items, rustc_attrs, asm_experimental_arch)]
+#![crate_type = "rlib"]
+#![no_core]
+#![allow(non_camel_case_types)]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+    () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! concat {
+    () => {};
+}
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+type ptr = *const u64;
+
+impl Copy for i8 {}
+impl Copy for i16 {}
+impl Copy for i32 {}
+impl Copy for i64 {}
+impl Copy for ptr {}
+
+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/asm/avr-types.rs b/tests/assembly/asm/avr-types.rs
new file mode 100644
index 00000000000..b2d11a8826f
--- /dev/null
+++ b/tests/assembly/asm/avr-types.rs
@@ -0,0 +1,221 @@
+// assembly-output: emit-asm
+// compile-flags: --target avr-unknown-gnu-atmega328
+// needs-llvm-components: avr
+
+#![feature(no_core, lang_items, rustc_attrs, asm_experimental_arch)]
+#![crate_type = "rlib"]
+#![no_core]
+#![allow(non_camel_case_types)]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+    () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! concat {
+    () => {};
+}
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+type ptr = *const u64;
+
+impl Copy for i8 {}
+impl Copy for i16 {}
+impl Copy for i32 {}
+impl Copy for i64 {}
+impl Copy for ptr {}
+
+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/asm/bpf-types.rs b/tests/assembly/asm/bpf-types.rs
new file mode 100644
index 00000000000..e177b8d0dbe
--- /dev/null
+++ b/tests/assembly/asm/bpf-types.rs
@@ -0,0 +1,153 @@
+// assembly-output: emit-asm
+// compile-flags: --target bpfel-unknown-none -C target_feature=+alu32
+// needs-llvm-components: bpf
+
+#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)]
+#![crate_type = "rlib"]
+#![no_core]
+#![allow(asm_sub_register, non_camel_case_types)]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+    () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! concat {
+    () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! stringify {
+    () => {};
+}
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+type ptr = *const u64;
+
+impl Copy for i8 {}
+impl Copy for i16 {}
+impl Copy for i32 {}
+impl Copy for i64 {}
+impl Copy for ptr {}
+
+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/asm/global_asm.rs b/tests/assembly/asm/global_asm.rs
new file mode 100644
index 00000000000..0b361a7ed96
--- /dev/null
+++ b/tests/assembly/asm/global_asm.rs
@@ -0,0 +1,33 @@
+// 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
+
+#![feature(asm_const)]
+#![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 _RNvCsiubXh4Yz005_10global_asm6foobar
+global_asm!("call {}", sym foobar);
+// CHECK: _RNvCsiubXh4Yz005_10global_asm6foobar:
+fn foobar() {
+    loop {}
+}
diff --git a/tests/assembly/asm/hexagon-types.rs b/tests/assembly/asm/hexagon-types.rs
new file mode 100644
index 00000000000..af16faedbc4
--- /dev/null
+++ b/tests/assembly/asm/hexagon-types.rs
@@ -0,0 +1,181 @@
+// assembly-output: emit-asm
+// compile-flags: --target hexagon-unknown-linux-musl
+// needs-llvm-components: hexagon
+
+#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)]
+#![crate_type = "rlib"]
+#![no_core]
+#![allow(asm_sub_register, non_camel_case_types)]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+    () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! concat {
+    () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! stringify {
+    () => {};
+}
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+type ptr = *const i32;
+
+impl Copy for i8 {}
+impl Copy for i16 {}
+impl Copy for i32 {}
+impl Copy for f32 {}
+impl Copy for ptr {}
+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 {
+            // Hack to avoid function merging
+            extern "Rust" {
+                fn dont_merge(s: &str);
+            }
+            dont_merge(stringify!($func));
+
+            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 {
+            // Hack to avoid function merging
+            extern "Rust" {
+                fn dont_merge(s: &str);
+            }
+            dont_merge(stringify!($func));
+
+            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() {
+    // Hack to avoid function merging
+    extern "Rust" {
+        fn dont_merge(s: &str);
+    }
+    dont_merge(stringify!($func));
+
+    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() {
+    // Hack to avoid function merging
+    extern "Rust" {
+        fn dont_merge(s: &str);
+    }
+    dont_merge(stringify!($func));
+
+    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/asm/mips-types.rs b/tests/assembly/asm/mips-types.rs
new file mode 100644
index 00000000000..6aa28b062db
--- /dev/null
+++ b/tests/assembly/asm/mips-types.rs
@@ -0,0 +1,237 @@
+// 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
+
+#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)]
+#![crate_type = "rlib"]
+#![no_core]
+#![allow(asm_sub_register, non_camel_case_types)]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+    () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! concat {
+    () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! stringify {
+    () => {};
+}
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+type ptr = *const i32;
+
+impl Copy for i8 {}
+impl Copy for u8 {}
+impl Copy for i16 {}
+impl Copy for i32 {}
+impl Copy for i64 {}
+impl Copy for f32 {}
+impl Copy for f64 {}
+impl Copy for ptr {}
+extern "C" {
+    fn extern_func();
+    static extern_static: u8;
+}
+
+// Hack to avoid function merging
+extern "Rust" {
+    fn dont_merge(s: &str);
+}
+
+macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => {
+    #[no_mangle]
+    pub unsafe fn $func(x: $ty) -> $ty {
+        dont_merge(stringify!($func));
+
+        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 {
+        dont_merge(stringify!($func));
+
+        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)
+// 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)
+// 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: ld $3, %got_disp(extern_static)
+// 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: ld $3, %got_disp(extern_func)
+// 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/asm/msp430-types.rs b/tests/assembly/asm/msp430-types.rs
new file mode 100644
index 00000000000..2c73b3b098d
--- /dev/null
+++ b/tests/assembly/asm/msp430-types.rs
@@ -0,0 +1,157 @@
+// assembly-output: emit-asm
+// compile-flags: --target msp430-none-elf
+// needs-llvm-components: msp430
+
+#![feature(no_core, lang_items, rustc_attrs, asm_experimental_arch, asm_const)]
+#![crate_type = "rlib"]
+#![no_core]
+#![allow(non_camel_case_types)]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+    () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! concat {
+    () => {};
+}
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+type ptr = *const i16;
+
+impl Copy for i8 {}
+impl Copy for i16 {}
+impl Copy for i32 {}
+impl Copy for i64 {}
+impl Copy for ptr {}
+
+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/asm/nvptx-types.rs b/tests/assembly/asm/nvptx-types.rs
new file mode 100644
index 00000000000..c319946b5f5
--- /dev/null
+++ b/tests/assembly/asm/nvptx-types.rs
@@ -0,0 +1,133 @@
+// assembly-output: emit-asm
+// compile-flags: --target nvptx64-nvidia-cuda
+// compile-flags: --crate-type cdylib
+// needs-llvm-components: nvptx
+
+#![feature(no_core, lang_items, rustc_attrs, asm_experimental_arch)]
+#![no_core]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+    () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! concat {
+    () => {};
+}
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+type ptr = *mut u8;
+
+impl Copy for i8 {}
+impl Copy for i16 {}
+impl Copy for i32 {}
+impl Copy for f32 {}
+impl Copy for i64 {}
+impl Copy for f64 {}
+impl Copy for ptr {}
+
+// 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/asm/powerpc-types.rs b/tests/assembly/asm/powerpc-types.rs
new file mode 100644
index 00000000000..e27b0052068
--- /dev/null
+++ b/tests/assembly/asm/powerpc-types.rs
@@ -0,0 +1,207 @@
+// revisions: powerpc powerpc64
+// assembly-output: emit-asm
+//[powerpc] compile-flags: --target powerpc-unknown-linux-gnu
+//[powerpc] needs-llvm-components: powerpc
+//[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu
+//[powerpc64] needs-llvm-components: powerpc
+
+#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)]
+#![crate_type = "rlib"]
+#![no_core]
+#![allow(asm_sub_register, non_camel_case_types)]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+    () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! concat {
+    () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! stringify {
+    () => {};
+}
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+type ptr = *const i32;
+
+impl Copy for i8 {}
+impl Copy for u8 {}
+impl Copy for i16 {}
+impl Copy for i32 {}
+impl Copy for i64 {}
+impl Copy for f32 {}
+impl Copy for f64 {}
+impl Copy for ptr {}
+extern "C" {
+    fn extern_func();
+    static extern_static: u8;
+}
+
+// Hack to avoid function merging
+extern "Rust" {
+    fn dont_merge(s: &str);
+}
+
+macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => {
+    #[no_mangle]
+    pub unsafe fn $func(x: $ty) -> $ty {
+        dont_merge(stringify!($func));
+
+        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 {
+        dont_merge(stringify!($func));
+
+        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");
+
+// 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");
diff --git a/tests/assembly/asm/riscv-types.rs b/tests/assembly/asm/riscv-types.rs
new file mode 100644
index 00000000000..f18ba294d0c
--- /dev/null
+++ b/tests/assembly/asm/riscv-types.rs
@@ -0,0 +1,210 @@
+// revisions: riscv64 riscv32
+// 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
+// compile-flags: -C target-feature=+d
+
+#![feature(no_core, lang_items, rustc_attrs)]
+#![crate_type = "rlib"]
+#![no_core]
+#![allow(asm_sub_register)]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+    () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! concat {
+    () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! stringify {
+    () => {};
+}
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+type ptr = *mut u8;
+
+impl Copy for i8 {}
+impl Copy for i16 {}
+impl Copy for i32 {}
+impl Copy for f32 {}
+impl Copy for i64 {}
+impl Copy for f64 {}
+impl Copy for ptr {}
+
+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 {
+            // Hack to avoid function merging
+            extern "Rust" {
+                fn dont_merge(s: &str);
+            }
+            dont_merge(stringify!($func));
+
+            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 {
+            // Hack to avoid function merging
+            extern "Rust" {
+                fn dont_merge(s: &str);
+            }
+            dont_merge(stringify!($func));
+
+            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_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_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_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_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/asm/s390x-types.rs b/tests/assembly/asm/s390x-types.rs
new file mode 100644
index 00000000000..2fb404dd9b2
--- /dev/null
+++ b/tests/assembly/asm/s390x-types.rs
@@ -0,0 +1,167 @@
+// revisions: s390x
+// assembly-output: emit-asm
+//[s390x] compile-flags: --target s390x-unknown-linux-gnu
+//[s390x] needs-llvm-components: systemz
+
+#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)]
+#![crate_type = "rlib"]
+#![no_core]
+#![allow(asm_sub_register, non_camel_case_types)]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+    () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! concat {
+    () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! stringify {
+    () => {};
+}
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+type ptr = *const i32;
+
+impl Copy for i8 {}
+impl Copy for u8 {}
+impl Copy for i16 {}
+impl Copy for i32 {}
+impl Copy for i64 {}
+impl Copy for f32 {}
+impl Copy for f64 {}
+impl Copy for ptr {}
+
+extern "C" {
+    fn extern_func();
+    static extern_static: u8;
+}
+
+// Hack to avoid function merging
+extern "Rust" {
+    fn dont_merge(s: &str);
+}
+
+macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => {
+    #[no_mangle]
+    pub unsafe fn $func(x: $ty) -> $ty {
+        dont_merge(stringify!($func));
+
+        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 {
+        dont_merge(stringify!($func));
+
+        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
+#[cfg(s390x)]
+#[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_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");
+
+// 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");
diff --git a/tests/assembly/asm/wasm-types.rs b/tests/assembly/asm/wasm-types.rs
new file mode 100644
index 00000000000..3b1ac1b455a
--- /dev/null
+++ b/tests/assembly/asm/wasm-types.rs
@@ -0,0 +1,149 @@
+// assembly-output: emit-asm
+// compile-flags: --target wasm32-unknown-unknown
+// compile-flags: --crate-type cdylib
+// needs-llvm-components: webassembly
+
+#![feature(no_core, lang_items, rustc_attrs, asm_experimental_arch)]
+#![no_core]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+    () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! concat {
+    () => {};
+}
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+type ptr = *mut u8;
+
+impl Copy for i8 {}
+impl Copy for i16 {}
+impl Copy for i32 {}
+impl Copy for f32 {}
+impl Copy for i64 {}
+impl Copy for f64 {}
+impl Copy for ptr {}
+
+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/asm/x86-modifiers.rs b/tests/assembly/asm/x86-modifiers.rs
new file mode 100644
index 00000000000..574fdf12cd0
--- /dev/null
+++ b/tests/assembly/asm/x86-modifiers.rs
@@ -0,0 +1,205 @@
+// revisions: x86_64 i686
+// assembly-output: emit-asm
+// compile-flags: -O
+//[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
+
+#![feature(no_core, lang_items, rustc_attrs)]
+#![crate_type = "rlib"]
+#![no_core]
+#![allow(asm_sub_register)]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+    () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! concat {
+    () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! stringify {
+    () => {};
+}
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+impl Copy for i32 {}
+
+macro_rules! check {
+    ($func:ident $modifier:literal $reg:ident $mov:literal) => {
+        // -O and extern "C" guarantee that the selected register is always ax/xmm0
+        #[no_mangle]
+        pub unsafe extern "C" fn $func() -> i32 {
+            // Hack to avoid function merging
+            extern "Rust" {
+                fn dont_merge(s: &str);
+            }
+            dont_merge(stringify!($func));
+
+            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/asm/x86-types.rs b/tests/assembly/asm/x86-types.rs
new file mode 100644
index 00000000000..81be79cbaac
--- /dev/null
+++ b/tests/assembly/asm/x86-types.rs
@@ -0,0 +1,1093 @@
+// 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
+
+#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
+#![crate_type = "rlib"]
+#![no_core]
+#![allow(asm_sub_register, non_camel_case_types)]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+    () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! concat {
+    () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! stringify {
+    () => {};
+}
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+type ptr = *mut u8;
+
+#[repr(simd)]
+pub struct i8x16(i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8);
+#[repr(simd)]
+pub struct i16x8(i16, i16, i16, i16, i16, i16, i16, i16);
+#[repr(simd)]
+pub struct i32x4(i32, i32, i32, i32);
+#[repr(simd)]
+pub struct i64x2(i64, i64);
+#[repr(simd)]
+pub struct f32x4(f32, f32, f32, f32);
+#[repr(simd)]
+pub struct f64x2(f64, f64);
+
+#[repr(simd)]
+pub struct i8x32(
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+);
+#[repr(simd)]
+pub struct i16x16(i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16);
+#[repr(simd)]
+pub struct i32x8(i32, i32, i32, i32, i32, i32, i32, i32);
+#[repr(simd)]
+pub struct i64x4(i64, i64, i64, i64);
+#[repr(simd)]
+pub struct f32x8(f32, f32, f32, f32, f32, f32, f32, f32);
+#[repr(simd)]
+pub struct f64x4(f64, f64, f64, f64);
+
+#[repr(simd)]
+pub struct i8x64(
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+    i8,
+);
+#[repr(simd)]
+pub struct i16x32(
+    i16,
+    i16,
+    i16,
+    i16,
+    i16,
+    i16,
+    i16,
+    i16,
+    i16,
+    i16,
+    i16,
+    i16,
+    i16,
+    i16,
+    i16,
+    i16,
+    i16,
+    i16,
+    i16,
+    i16,
+    i16,
+    i16,
+    i16,
+    i16,
+    i16,
+    i16,
+    i16,
+    i16,
+    i16,
+    i16,
+    i16,
+    i16,
+);
+#[repr(simd)]
+pub struct i32x16(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32);
+#[repr(simd)]
+pub struct i64x8(i64, i64, i64, i64, i64, i64, i64, i64);
+#[repr(simd)]
+pub struct f32x16(f32, f32, f32, f32, f32, f32, f32, f32, f32, f32, f32, f32, f32, f32, f32, f32);
+#[repr(simd)]
+pub struct f64x8(f64, f64, f64, f64, f64, f64, f64, f64);
+
+impl Copy for i8 {}
+impl Copy for i16 {}
+impl Copy for i32 {}
+impl Copy for f32 {}
+impl Copy for i64 {}
+impl Copy for f64 {}
+impl Copy for ptr {}
+impl Copy for i8x16 {}
+impl Copy for i16x8 {}
+impl Copy for i32x4 {}
+impl Copy for i64x2 {}
+impl Copy for f32x4 {}
+impl Copy for f64x2 {}
+impl Copy for i8x32 {}
+impl Copy for i16x16 {}
+impl Copy for i32x8 {}
+impl Copy for i64x4 {}
+impl Copy for f32x8 {}
+impl Copy for f64x4 {}
+impl Copy for i8x64 {}
+impl Copy for i16x32 {}
+impl Copy for i32x16 {}
+impl Copy for i64x8 {}
+impl Copy for f32x16 {}
+impl Copy for 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 {
+            // Hack to avoid function merging
+            extern "Rust" {
+                fn dont_merge(s: &str);
+            }
+            dont_merge(stringify!($func));
+
+            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 {
+            // Hack to avoid function merging
+            extern "Rust" {
+                fn dont_merge(s: &str);
+            }
+            dont_merge(stringify!($func));
+
+            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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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/auxiliary/breakpoint-panic-handler.rs b/tests/assembly/auxiliary/breakpoint-panic-handler.rs
new file mode 100644
index 00000000000..d54c1181e1a
--- /dev/null
+++ b/tests/assembly/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/auxiliary/non-inline-dependency.rs b/tests/assembly/auxiliary/non-inline-dependency.rs
new file mode 100644
index 00000000000..57f3ee87cdb
--- /dev/null
+++ b/tests/assembly/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/dwarf5.rs b/tests/assembly/dwarf5.rs
new file mode 100644
index 00000000000..f41e6bd55be
--- /dev/null
+++ b/tests/assembly/dwarf5.rs
@@ -0,0 +1,20 @@
+// Makes sure that `-Z dwarf-version=5` causes `rustc` to emit DWARF version 5.
+// assembly-output: emit-asm
+// compile-flags: -g --target x86_64-unknown-linux-gnu -Z dwarf-version=5
+// needs-llvm-components: x86
+
+#![feature(no_core, lang_items)]
+#![crate_type = "rlib"]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+pub fn wibble() {}
+
+// CHECK: .section .debug_info
+// CHECK-NOT: .short 2
+// CHECK-NOT: .short 4
+// CHECK: .short 5
diff --git a/tests/assembly/is_aligned.rs b/tests/assembly/is_aligned.rs
new file mode 100644
index 00000000000..04b5de83423
--- /dev/null
+++ b/tests/assembly/is_aligned.rs
@@ -0,0 +1,58 @@
+// assembly-output: emit-asm
+// min-llvm-version: 14.0
+// only-x86_64
+// revisions: opt-speed opt-size
+// [opt-speed] compile-flags: -Copt-level=1
+// [opt-size] compile-flags: -Copt-level=s
+#![crate_type="rlib"]
+
+#![feature(core_intrinsics)]
+#![feature(pointer_is_aligned)]
+
+// 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/niche-prefer-zero.rs b/tests/assembly/niche-prefer-zero.rs
new file mode 100644
index 00000000000..0ab37a618da
--- /dev/null
+++ b/tests/assembly/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/nvptx-arch-default.rs b/tests/assembly/nvptx-arch-default.rs
new file mode 100644
index 00000000000..8a71a6370f1
--- /dev/null
+++ b/tests/assembly/nvptx-arch-default.rs
@@ -0,0 +1,13 @@
+// assembly-output: ptx-linker
+// compile-flags: --crate-type cdylib
+// only-nvptx64
+// ignore-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/nvptx-arch-emit-asm.rs b/tests/assembly/nvptx-arch-emit-asm.rs
new file mode 100644
index 00000000000..b252b450fa7
--- /dev/null
+++ b/tests/assembly/nvptx-arch-emit-asm.rs
@@ -0,0 +1,10 @@
+// assembly-output: emit-asm
+// compile-flags: --crate-type rlib
+// only-nvptx64
+// ignore-nvptx64
+
+#![no_std]
+
+// Verify default arch without ptx-linker involved.
+// CHECK: .target sm_30
+// CHECK: .address_size 64
diff --git a/tests/assembly/nvptx-arch-link-arg.rs b/tests/assembly/nvptx-arch-link-arg.rs
new file mode 100644
index 00000000000..025a9ad4987
--- /dev/null
+++ b/tests/assembly/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/nvptx-arch-target-cpu.rs b/tests/assembly/nvptx-arch-target-cpu.rs
new file mode 100644
index 00000000000..824ee9cd897
--- /dev/null
+++ b/tests/assembly/nvptx-arch-target-cpu.rs
@@ -0,0 +1,13 @@
+// assembly-output: ptx-linker
+// compile-flags: --crate-type cdylib -C target-cpu=sm_50
+// only-nvptx64
+// ignore-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/nvptx-atomics.rs b/tests/assembly/nvptx-atomics.rs
new file mode 100644
index 00000000000..f9639806449
--- /dev/null
+++ b/tests/assembly/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/nvptx-internalizing.rs b/tests/assembly/nvptx-internalizing.rs
new file mode 100644
index 00000000000..0004fcea7a2
--- /dev/null
+++ b/tests/assembly/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/nvptx-kernel-abi/nvptx-kernel-args-abi-v7.rs b/tests/assembly/nvptx-kernel-abi/nvptx-kernel-args-abi-v7.rs
new file mode 100644
index 00000000000..5bf44f949fd
--- /dev/null
+++ b/tests/assembly/nvptx-kernel-abi/nvptx-kernel-args-abi-v7.rs
@@ -0,0 +1,254 @@
+// assembly-output: ptx-linker
+// compile-flags: --crate-type cdylib -C target-cpu=sm_86
+// only-nvptx64
+// ignore-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 = "sized"]
+trait Sized {}
+#[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 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_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]) {}
+
+// CHECK: .visible .entry f_u128_array_arg(
+// 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 .u64 f_u32_slice_arg_param_0
+// CHECK: .param .u64 f_u32_slice_arg_param_1
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn f_u32_slice_arg(_a: &[u32]) {}
+
+// CHECK: .visible .entry f_tuple_u8_u8_arg(
+// CHECK: .param .align 1 .b8 f_tuple_u8_u8_arg_param_0[2]
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn f_tuple_u8_u8_arg(_a: (u8, u8)) {}
+
+// CHECK: .visible .entry f_tuple_u32_u32_arg(
+// CHECK: .param .align 4 .b8 f_tuple_u32_u32_arg_param_0[8]
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn f_tuple_u32_u32_arg(_a: (u32, u32)) {}
+
+
+// CHECK: .visible .entry f_tuple_u8_u8_u32_arg(
+// CHECK: .param .align 4 .b8 f_tuple_u8_u8_u32_arg_param_0[8]
+#[no_mangle]
+pub unsafe extern "ptx-kernel" fn f_tuple_u8_u8_u32_arg(_a: (u8, u8, u32)) {}
diff --git a/tests/assembly/nvptx-linking-binary.rs b/tests/assembly/nvptx-linking-binary.rs
new file mode 100644
index 00000000000..64b9c2f17aa
--- /dev/null
+++ b/tests/assembly/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/nvptx-linking-cdylib.rs b/tests/assembly/nvptx-linking-cdylib.rs
new file mode 100644
index 00000000000..bdbc30ea97f
--- /dev/null
+++ b/tests/assembly/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/nvptx-safe-naming.rs b/tests/assembly/nvptx-safe-naming.rs
new file mode 100644
index 00000000000..80bb04fc0f2
--- /dev/null
+++ b/tests/assembly/nvptx-safe-naming.rs
@@ -0,0 +1,38 @@
+// 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;
+
+// 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/panic-no-unwind-no-uwtable.rs b/tests/assembly/panic-no-unwind-no-uwtable.rs
new file mode 100644
index 00000000000..499d4e69867
--- /dev/null
+++ b/tests/assembly/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 -O
+
+#![crate_type = "lib"]
+
+// CHECK-NOT: .cfi_startproc
+pub fn foo() {}
diff --git a/tests/assembly/panic-unwind-no-uwtable.rs b/tests/assembly/panic-unwind-no-uwtable.rs
new file mode 100644
index 00000000000..8eed72b2fca
--- /dev/null
+++ b/tests/assembly/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/pic-relocation-model.rs b/tests/assembly/pic-relocation-model.rs
new file mode 100644
index 00000000000..72471ffcdb0
--- /dev/null
+++ b/tests/assembly/pic-relocation-model.rs
@@ -0,0 +1,35 @@
+// 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"]
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+// 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:       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/pie-relocation-model.rs b/tests/assembly/pie-relocation-model.rs
new file mode 100644
index 00000000000..e40797e038d
--- /dev/null
+++ b/tests/assembly/pie-relocation-model.rs
@@ -0,0 +1,38 @@
+// 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"]
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+// 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:       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/sparc-struct-abi.rs b/tests/assembly/sparc-struct-abi.rs
new file mode 100644
index 00000000000..6309dd420ff
--- /dev/null
+++ b/tests/assembly/sparc-struct-abi.rs
@@ -0,0 +1,70 @@
+// Test SPARC64 ABI
+// - float structure members are passes in floating point registers
+// (#86163)
+
+// 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]
+
+#[lang = "sized"]
+pub trait Sized {}
+#[lang = "copy"]
+pub trait Copy {}
+impl Copy for f32 {}
+
+#[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/stack-protector/stack-protector-heuristics-effect.rs b/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs
new file mode 100644
index 00000000000..7c2b6055090
--- /dev/null
+++ b/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs
@@ -0,0 +1,396 @@
+// revisions: all strong basic none missing
+// assembly-output: emit-asm
+// ignore-macos slightly different policy on stack protection of arrays
+// ignore-windows stack check code uses different function names
+// ignore-nvptx64 stack protector is not supported
+// [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(incomplete_features)]
+
+#![feature(unsized_locals, 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 _);
+
+    // Any type of local array variable leads to stack protection with the
+    // "strong" heuristic. The 'basic' heuristic only adds stack protection to
+    // functions with local array variables of a byte-sized type, however. Since
+    // 'char' is 4 bytes in Rust, this function is not protected by the 'basic'
+    // heuristic
+    //
+    // (This test *also* takes the address of the local stack variables. We
+    // cannot know that this isn't what triggers the `strong` heuristic.
+    // However, the test strategy of passing the address of a stack array to an
+    // external function is sufficient to trigger the `basic` heuristic (see
+    // test `array_u8_large()`). Since the `basic` heuristic only checks for the
+    // presence of stack-local array variables, we can be confident that this
+    // test also captures this part of the `strong` heuristic specification.)
+
+    // 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_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 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: __stack_chk_fail
+    // strong: __stack_chk_fail
+    // basic-NOT: __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 by the `strong` heuristic. 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-NOT: __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 by the
+    // `strong` heuristic, 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-NOT: __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
+}
+
+// CHECK-LABEL: unsized_local
+#[no_mangle]
+pub fn unsized_local(s: &[u8], l: bool, f: fn(&mut [u8])) {
+    let n = if l { 1 } else { 2 };
+    let mut a: [u8] = *Box::<[u8]>::from(&s[0..n]); // slice-copy with Box::from
+    f(&mut a);
+
+    // This function allocates a slice as a local variable in its stack
+    // frame. Since the size is not a compile-time constant, an array
+    // alloca is required, and the function is protected by both the
+    // `strong` and `basic` heuristic.
+
+    // all: __stack_chk_fail
+    // strong: __stack_chk_fail
+    // basic: __stack_chk_fail
+    // none-NOT: __stack_chk_fail
+    // missing-NOT: __stack_chk_fail
+}
diff --git a/tests/assembly/stack-protector/stack-protector-target-support.rs b/tests/assembly/stack-protector/stack-protector-target-support.rs
new file mode 100644
index 00000000000..d5b48105ef2
--- /dev/null
+++ b/tests/assembly/stack-protector/stack-protector-target-support.rs
@@ -0,0 +1,285 @@
+// Test that stack smash protection code is emitted for all tier1 and tier2
+// targets, with the exception of nvptx64-nvidia-cuda
+//
+// 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 r34 r35 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
+// 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
+// [r34] compile-flags: --target asmjs-unknown-emscripten
+// [r34] needs-llvm-components: webassembly
+// [r35] compile-flags: --target i586-pc-windows-msvc
+// [r35] needs-llvm-components: x86
+// [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-wasi
+// [r73] needs-llvm-components: webassembly
+// [r74] compile-flags:--target x86_64-apple-ios
+// [r74] needs-llvm-components: x86
+// [r75] compile-flags:--target x86_64-fortanix-unknown-sgx
+// [r75] needs-llvm-components: x86
+// [r76] compile-flags:--target x86_64-unknown-fuchsia
+// [r76] needs-llvm-components: x86
+// [r77] compile-flags:--target x86_64-linux-android
+// [r77] needs-llvm-components: x86
+// [r78] compile-flags:--target x86_64-sun-solaris
+// [r78] needs-llvm-components: x86
+// [r79] compile-flags:--target x86_64-unknown-freebsd
+// [r79] needs-llvm-components: x86
+// [r80] compile-flags:--target x86_64-unknown-illumos
+// [r80] needs-llvm-components: x86
+// [r81] compile-flags:--target x86_64-unknown-linux-gnux32
+// [r81] needs-llvm-components: x86
+// [r82] compile-flags:--target x86_64-unknown-linux-musl
+// [r82] needs-llvm-components: x86
+// [r83] compile-flags:--target x86_64-unknown-netbsd
+// [r83] needs-llvm-components: x86
+// [r84] compile-flags: --target x86_64-unknown-redox
+// [r84] 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]
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+#[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
+    // r35: calll @__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
+}
diff --git a/tests/assembly/static-relocation-model.rs b/tests/assembly/static-relocation-model.rs
new file mode 100644
index 00000000000..faa2e395209
--- /dev/null
+++ b/tests/assembly/static-relocation-model.rs
@@ -0,0 +1,86 @@
+// 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"]
+
+#[lang="sized"]
+trait Sized {}
+
+#[lang="copy"]
+trait Copy {}
+
+#[lang="sync"]
+trait Sync {}
+
+#[lang = "drop_in_place"]
+fn drop_in_place<T>(_: *mut T) {}
+
+impl Copy for u8 {}
+impl Sync for u8 {}
+
+#[no_mangle]
+pub static PIERIS: u8 = 42;
+
+extern "C" {
+    static EXOCHORDA: *mut u8;
+
+    fn chaenomeles();
+}
+
+// CHECK-LABEL: banana:
+// On the next line LLVM 14 produces a `movb`, whereas LLVM 15+ produces a `movzbl`.
+// 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/strict_provenance.rs b/tests/assembly/strict_provenance.rs
new file mode 100644
index 00000000000..01f1957d5f6
--- /dev/null
+++ b/tests/assembly/strict_provenance.rs
@@ -0,0 +1,37 @@
+// assembly-output: emit-asm
+// compile-flags: -Copt-level=1
+// only-x86_64
+// min-llvm-version: 15.0
+#![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/target-feature-multiple.rs b/tests/assembly/target-feature-multiple.rs
new file mode 100644
index 00000000000..18d896e86b2
--- /dev/null
+++ b/tests/assembly/target-feature-multiple.rs
@@ -0,0 +1,42 @@
+// 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 src/test/codegen/target-feature-overrides.rs
+#![feature(no_core, lang_items, link_llvm_intrinsics, abi_unadjusted)]
+#![crate_type = "lib"]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+impl Copy for u32 {}
+
+// 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/x86-stack-probes.rs b/tests/assembly/x86-stack-probes.rs
new file mode 100644
index 00000000000..c7141fb208a
--- /dev/null
+++ b/tests/assembly/x86-stack-probes.rs
@@ -0,0 +1,42 @@
+// min-llvm-version: 16
+// 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
+
+#![feature(no_core, lang_items)]
+#![crate_type = "lib"]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+impl Copy for u8 {}
+
+// 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
+    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
+    f(&mut [x; 65536]);
+}
diff --git a/tests/assembly/x86_64-floating-point-clamp.rs b/tests/assembly/x86_64-floating-point-clamp.rs
new file mode 100644
index 00000000000..0f3b465d08d
--- /dev/null
+++ b/tests/assembly/x86_64-floating-point-clamp.rs
@@ -0,0 +1,25 @@
+// 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
+// compile-flags: --crate-type=lib -O -C llvm-args=-x86-asm-syntax=intel
+// only-x86_64
+
+// 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/x86_64-fortanix-unknown-sgx-lvi-generic-load.rs b/tests/assembly/x86_64-fortanix-unknown-sgx-lvi-generic-load.rs
new file mode 100644
index 00000000000..79d82cf70d3
--- /dev/null
+++ b/tests/assembly/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 fn plus_one(r: &mut u64) {
+    *r = *r + 1;
+}
+
+// CHECK: plus_one
+// CHECK: lfence
+// CHECK-NEXT: addq
+// CHECK: popq [[REGISTER:%[a-z]+]]
+// CHECK-NEXT: lfence
+// CHECK-NEXT: jmpq *[[REGISTER]]
diff --git a/tests/assembly/x86_64-fortanix-unknown-sgx-lvi-generic-ret.rs b/tests/assembly/x86_64-fortanix-unknown-sgx-lvi-generic-ret.rs
new file mode 100644
index 00000000000..a21ef6b7589
--- /dev/null
+++ b/tests/assembly/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 fn myret() {}
+// CHECK: myret:
+// CHECK: popq [[REGISTER:%[a-z]+]]
+// CHECK-NEXT: lfence
+// CHECK-NEXT: jmpq *[[REGISTER]]
diff --git a/tests/assembly/x86_64-fortanix-unknown-sgx-lvi-inline-assembly.rs b/tests/assembly/x86_64-fortanix-unknown-sgx-lvi-inline-assembly.rs
new file mode 100644
index 00000000000..c316379d5b1
--- /dev/null
+++ b/tests/assembly/x86_64-fortanix-unknown-sgx-lvi-inline-assembly.rs
@@ -0,0 +1,43 @@
+// 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!(".start_inline_asm:",
+            "mov {}, [{}]",
+            ".end_inline_asm:",
+            out(reg) value,
+            in(reg) ptr);
+    }
+    value
+}
+
+// CHECK: get
+// CHECK: .start_inline_asm
+// CHECK-NEXT: movq
+// CHECK-NEXT: lfence
+// CHECK-NEXT: .end_inline_asm
+
+#[no_mangle]
+pub extern "C" fn myret() {
+    unsafe {
+        asm!(
+            ".start_myret_inline_asm:",
+            "ret",
+            ".end_myret_inline_asm:",
+        );
+    }
+}
+
+// CHECK: myret
+// CHECK: .start_myret_inline_asm
+// CHECK-NEXT: shlq $0, (%rsp)
+// CHECK-NEXT: lfence
+// CHECK-NEXT: retq
diff --git a/tests/assembly/x86_64-naked-fn-no-cet-prolog.rs b/tests/assembly/x86_64-naked-fn-no-cet-prolog.rs
new file mode 100644
index 00000000000..bedcded731d
--- /dev/null
+++ b/tests/assembly/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"]
+#![feature(naked_functions)]
+use std::arch::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]
+#[naked]
+pub unsafe extern "sysv64" fn will_halt() -> ! {
+    // CHECK-NOT: endbr{{32|64}}
+    // CHECK: hlt
+    asm!("hlt", options(noreturn))
+}
+
+// what about aarch64?
+// "branch-protection"=false
diff --git a/tests/assembly/x86_64-no-jump-tables.rs b/tests/assembly/x86_64-no-jump-tables.rs
new file mode 100644
index 00000000000..007c3591a4a
--- /dev/null
+++ b/tests/assembly/x86_64-no-jump-tables.rs
@@ -0,0 +1,34 @@
+// 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: -O
+// [set] compile-flags: -Zno-jump-tables
+// only-x86_64
+
+#![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/x86_64-sse_crc.rs b/tests/assembly/x86_64-sse_crc.rs
new file mode 100644
index 00000000000..cdbf057b80b
--- /dev/null
+++ b/tests/assembly/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)
+}