about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAmanieu d'Antras <amanieu@gmail.com>2020-02-20 09:19:48 +0000
committerAmanieu d'Antras <amanieu@gmail.com>2020-05-18 14:41:32 +0100
commit8ab0f2d3c5a85563b98c4896116e3d53154fff9c (patch)
tree9e4ac5efac12844c17ec1a89ff05bcb539a0d6c0
parentabed45ff9fa3e68f2a32ca12e012f95b9153f4df (diff)
downloadrust-8ab0f2d3c5a85563b98c4896116e3d53154fff9c.tar.gz
rust-8ab0f2d3c5a85563b98c4896116e3d53154fff9c.zip
Add tests for asm!
-rw-r--r--src/test/assembly/asm/aarch64-modifiers.rs144
-rw-r--r--src/test/assembly/asm/aarch64-types.rs380
-rw-r--r--src/test/assembly/asm/arm-modifiers.rs149
-rw-r--r--src/test/assembly/asm/arm-types.rs413
-rw-r--r--src/test/assembly/asm/riscv-modifiers.rs58
-rw-r--r--src/test/assembly/asm/riscv-types.rs134
-rw-r--r--src/test/assembly/asm/x86-modifiers.rs210
-rw-r--r--src/test/assembly/asm/x86-types.rs701
-rw-r--r--src/test/codegen/asm-options.rs96
-rw-r--r--src/test/pretty/asm.pp25
-rw-r--r--src/test/pretty/asm.rs19
-rw-r--r--src/test/pretty/llvm-asm-clobbers.rs (renamed from src/test/pretty/asm-clobbers.rs)0
-rw-r--r--src/test/pretty/llvm-asm-options.rs (renamed from src/test/pretty/asm-options.rs)0
-rw-r--r--src/test/ui/asm/bad-options.rs18
-rw-r--r--src/test/ui/asm/bad-options.stderr32
-rw-r--r--src/test/ui/asm/bad-reg.rs57
-rw-r--r--src/test/ui/asm/bad-reg.stderr148
-rw-r--r--src/test/ui/asm/bad-template.rs26
-rw-r--r--src/test/ui/asm/bad-template.stderr86
-rw-r--r--src/test/ui/asm/noreturn.rs17
-rw-r--r--src/test/ui/asm/parse-error.rs53
-rw-r--r--src/test/ui/asm/parse-error.stderr146
-rw-r--r--src/test/ui/asm/rustfix-asm.fixed16
-rw-r--r--src/test/ui/asm/rustfix-asm.rs16
-rw-r--r--src/test/ui/asm/rustfix-asm.stderr18
-rw-r--r--src/test/ui/asm/type-check-1.rs25
-rw-r--r--src/test/ui/asm/type-check-1.stderr45
-rw-r--r--src/test/ui/asm/type-check-2.rs104
-rw-r--r--src/test/ui/asm/type-check-2.stderr133
-rw-r--r--src/test/ui/asm/type-check-3.rs68
-rw-r--r--src/test/ui/asm/type-check-3.stderr123
-rw-r--r--src/test/ui/feature-gates/feature-gate-asm.rs1
-rw-r--r--src/test/ui/feature-gates/feature-gate-asm.stderr12
-rw-r--r--src/test/ui/feature-gates/feature-gate-asm2.rs1
-rw-r--r--src/test/ui/feature-gates/feature-gate-asm2.stderr12
-rw-r--r--src/test/ui/llvm-asm/llvm-asm-concat-src.rs (renamed from src/test/ui/asm-concat-src.rs)0
-rw-r--r--src/test/ui/llvm-asm/llvm-asm-in-moved.rs (renamed from src/test/ui/asm-in-moved.rs)0
-rw-r--r--src/test/ui/llvm-asm/llvm-asm-in-out-operand.rs (renamed from src/test/ui/asm-in-out-operand.rs)0
-rw-r--r--src/test/ui/llvm-asm/llvm-asm-indirect-memory.rs (renamed from src/test/ui/asm-indirect-memory.rs)0
-rw-r--r--src/test/ui/llvm-asm/llvm-asm-out-assign.rs (renamed from src/test/ui/asm-out-assign.rs)0
-rw-r--r--src/test/ui/macros/macro-expanded-include/foo/mod.rs2
-rw-r--r--src/test/ui/macros/macro-expanded-include/test.rs2
-rw-r--r--src/test/ui/macros/macros-nonfatal-errors.rs3
-rw-r--r--src/test/ui/macros/macros-nonfatal-errors.stderr34
-rw-r--r--src/test/ui/target-feature/gate.stderr2
45 files changed, 3489 insertions, 40 deletions
diff --git a/src/test/assembly/asm/aarch64-modifiers.rs b/src/test/assembly/asm/aarch64-modifiers.rs
new file mode 100644
index 00000000000..d4519ca7ffa
--- /dev/null
+++ b/src/test/assembly/asm/aarch64-modifiers.rs
@@ -0,0 +1,144 @@
+// assembly-output: emit-asm
+// compile-flags: -O
+// compile-flags: --target aarch64-unknown-linux-gnu
+
+#![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/src/test/assembly/asm/aarch64-types.rs b/src/test/assembly/asm/aarch64-types.rs
new file mode 100644
index 00000000000..8b763462e4a
--- /dev/null
+++ b/src/test/assembly/asm/aarch64-types.rs
@@ -0,0 +1,380 @@
+// assembly-output: emit-asm
+// compile-flags: --target aarch64-unknown-linux-gnu
+
+#![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);
+}
+
+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
+        }
+    };
+}
+
+// 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");
diff --git a/src/test/assembly/asm/arm-modifiers.rs b/src/test/assembly/asm/arm-modifiers.rs
new file mode 100644
index 00000000000..cefab9c4a67
--- /dev/null
+++ b/src/test/assembly/asm/arm-modifiers.rs
@@ -0,0 +1,149 @@
+// assembly-output: emit-asm
+// compile-flags: -O
+// compile-flags: --target armv7-unknown-linux-gnueabihf
+// compile-flags: -C target-feature=+neon
+
+#![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: reg_thumb:
+// CHECK: @APP
+// CHECK: mov r0, r0
+// CHECK: @NO_APP
+check!(reg_thumb "" reg_thumb 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/src/test/assembly/asm/arm-types.rs b/src/test/assembly/asm/arm-types.rs
new file mode 100644
index 00000000000..729adae66f6
--- /dev/null
+++ b/src/test/assembly/asm/arm-types.rs
@@ -0,0 +1,413 @@
+// assembly-output: emit-asm
+// compile-flags: --target armv7-unknown-linux-gnueabihf
+// compile-flags: -C target-feature=+neon
+
+#![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);
+}
+
+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
+        }
+    };
+}
+
+// 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: reg_thumb_i8:
+// CHECK: @APP
+// CHECK: mov {{[a-z0-9]+}}, {{[a-z0-9]+}}
+// CHECK: @NO_APP
+check!(reg_thumb_i8 i8 reg_thumb "mov");
+
+// CHECK-LABEL: reg_thumb_i16:
+// CHECK: @APP
+// CHECK: mov {{[a-z0-9]+}}, {{[a-z0-9]+}}
+// CHECK: @NO_APP
+check!(reg_thumb_i16 i16 reg_thumb "mov");
+
+// CHECK-LABEL: reg_thumb_i32:
+// CHECK: @APP
+// CHECK: mov {{[a-z0-9]+}}, {{[a-z0-9]+}}
+// CHECK: @NO_APP
+check!(reg_thumb_i32 i32 reg_thumb "mov");
+
+// CHECK-LABEL: reg_thumb_f32:
+// CHECK: @APP
+// CHECK: mov {{[a-z0-9]+}}, {{[a-z0-9]+}}
+// CHECK: @NO_APP
+check!(reg_thumb_f32 f32 reg_thumb "mov");
+
+// CHECK-LABEL: reg_thumb_ptr:
+// CHECK: @APP
+// CHECK: mov {{[a-z0-9]+}}, {{[a-z0-9]+}}
+// CHECK: @NO_APP
+check!(reg_thumb_ptr ptr reg_thumb "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");
diff --git a/src/test/assembly/asm/riscv-modifiers.rs b/src/test/assembly/asm/riscv-modifiers.rs
new file mode 100644
index 00000000000..622d0c0dc5e
--- /dev/null
+++ b/src/test/assembly/asm/riscv-modifiers.rs
@@ -0,0 +1,58 @@
+// assembly-output: emit-asm
+// compile-flags: -O
+// compile-flags: --target riscv64gc-unknown-linux-gnu
+// compile-flags: -C target-feature=+f
+
+#![feature(no_core, lang_items, rustc_attrs)]
+#![crate_type = "rlib"]
+#![no_core]
+
+#[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 f32 {}
+
+macro_rules! check {
+    ($func:ident $modifier:literal $reg: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() -> f32 {
+            // 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: mv a0, a0
+// CHECK: #NO_APP
+check!(reg "" reg "mv");
+
+// CHECK-LABEL: freg:
+// CHECK: #APP
+// CHECK: fmv.s fa0, fa0
+// CHECK: #NO_APP
+check!(freg "" freg "fmv.s");
diff --git a/src/test/assembly/asm/riscv-types.rs b/src/test/assembly/asm/riscv-types.rs
new file mode 100644
index 00000000000..5c10753c765
--- /dev/null
+++ b/src/test/assembly/asm/riscv-types.rs
@@ -0,0 +1,134 @@
+// revisions: riscv64 riscv32
+// assembly-output: emit-asm
+//[riscv64] compile-flags: --target riscv64imac-unknown-none-elf
+//[riscv32] compile-flags: --target riscv32imac-unknown-none-elf
+// 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: lb t0, extern_static
+// 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
+        }
+    };
+}
+
+// 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");
diff --git a/src/test/assembly/asm/x86-modifiers.rs b/src/test/assembly/asm/x86-modifiers.rs
new file mode 100644
index 00000000000..460e22aa69e
--- /dev/null
+++ b/src/test/assembly/asm/x86-modifiers.rs
@@ -0,0 +1,210 @@
+// revisions: x86_64 i686
+// assembly-output: emit-asm
+// compile-flags: -O
+//[x86_64] compile-flags: --target x86_64-unknown-linux-gnu
+//[i686] compile-flags: --target i686-unknown-linux-gnu
+// 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");
+
+// x86_64-LABEL: reg_h:
+// x86_64: #APP
+// x86_64: mov ah, ah
+// x86_64: #NO_APP
+#[cfg(x86_64)]
+check!(reg_h "h" 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/src/test/assembly/asm/x86-types.rs b/src/test/assembly/asm/x86-types.rs
new file mode 100644
index 00000000000..d2819ac88e7
--- /dev/null
+++ b/src/test/assembly/asm/x86-types.rs
@@ -0,0 +1,701 @@
+// revisions: x86_64 i686
+// assembly-output: emit-asm
+//[x86_64] compile-flags: --target x86_64-unknown-linux-gnu
+//[i686] compile-flags: --target i686-unknown-linux-gnu
+// 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, " {}, {}"), out($class) y, in($class) x);
+            y
+        }
+    };
+}
+
+// CHECK-LABEL: reg_i8:
+// 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_i8 i8 reg "mov");
+
+// 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_i8:
+// 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_i8 i8 reg_abcd "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: 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");
diff --git a/src/test/codegen/asm-options.rs b/src/test/codegen/asm-options.rs
new file mode 100644
index 00000000000..21e7eb43796
--- /dev/null
+++ b/src/test/codegen/asm-options.rs
@@ -0,0 +1,96 @@
+// compile-flags: -O
+// only-x86_64
+
+#![crate_type = "rlib"]
+#![feature(asm)]
+
+// CHECK-LABEL: @pure
+// CHECK-NOT: asm
+// CHECK: ret void
+#[no_mangle]
+pub unsafe fn pure(x: i32) {
+    let y: i32;
+    asm!("", out("ax") y, in("bx") x, options(pure, nomem));
+}
+
+// CHECK-LABEL: @noreturn
+// CHECK: call void asm
+// CHECK-NEXT: unreachable
+#[no_mangle]
+pub unsafe fn noreturn() {
+    asm!("", options(noreturn));
+}
+
+pub static mut VAR: i32 = 0;
+pub static mut DUMMY_OUTPUT: i32 = 0;
+
+// CHECK-LABEL: @readonly
+// CHECK: call i32 asm
+// CHECK: ret i32 1
+#[no_mangle]
+pub unsafe fn readonly() -> i32 {
+    VAR = 1;
+    asm!("", out("ax") DUMMY_OUTPUT, options(pure, readonly));
+    VAR
+}
+
+// CHECK-LABEL: @not_readonly
+// CHECK: call i32 asm
+// CHECK: ret i32 %
+#[no_mangle]
+pub unsafe fn not_readonly() -> i32 {
+    VAR = 1;
+    asm!("", out("ax") DUMMY_OUTPUT, options());
+    VAR
+}
+
+// CHECK-LABEL: @nomem
+// CHECK-NOT: store
+// CHECK: call i32 asm
+// CHECK: store
+// CHECK: ret i32 2
+#[no_mangle]
+pub unsafe fn nomem() -> i32 {
+    VAR = 1;
+    asm!("", out("ax") DUMMY_OUTPUT, options(pure, nomem));
+    VAR = 2;
+    VAR
+}
+
+// CHECK-LABEL: @nomem_nopure
+// CHECK-NOT: store
+// CHECK: call i32 asm
+// CHECK: store
+// CHECK: ret i32 2
+#[no_mangle]
+pub unsafe fn nomem_nopure() -> i32 {
+    VAR = 1;
+    asm!("", out("ax") DUMMY_OUTPUT, options(nomem));
+    VAR = 2;
+    VAR
+}
+
+// CHECK-LABEL: @not_nomem
+// CHECK: store
+// CHECK: call i32 asm
+// CHECK: store
+// CHECK: ret i32 2
+#[no_mangle]
+pub unsafe fn not_nomem() -> i32 {
+    VAR = 1;
+    asm!("", out("ax") DUMMY_OUTPUT, options(pure, readonly));
+    VAR = 2;
+    VAR
+}
+
+// CHECK-LABEL: @dont_remove_nonpure
+// CHECK: call void asm
+// CHECK: call void asm
+// CHECK: call void asm
+// CHECK: ret void
+#[no_mangle]
+pub unsafe fn dont_remove_nonpure() {
+    asm!("", options());
+    asm!("", options(nomem));
+    asm!("", options(readonly));
+}
diff --git a/src/test/pretty/asm.pp b/src/test/pretty/asm.pp
new file mode 100644
index 00000000000..1723e1cc1cb
--- /dev/null
+++ b/src/test/pretty/asm.pp
@@ -0,0 +1,25 @@
+#![feature(prelude_import)]
+#![no_std]
+#![feature(asm)]
+#[prelude_import]
+use ::std::prelude::v1::*;
+#[macro_use]
+extern crate std;
+
+// pretty-mode:expanded
+// pp-exact:asm.pp
+
+pub fn main() {
+    let a: i32;
+    let mut b = 4i32;
+    unsafe {
+        asm!("");
+        asm!("");
+        asm!("", options(nomem, nostack));
+        asm!("{0}", in(reg) 4);
+        asm!("{0}", out(reg) a);
+        asm!("{0}", inout(reg) b);
+        asm!("{0} {1}", out(reg) _, inlateout(reg) b => _);
+        asm!("", out("al") _, lateout("rbx") _);
+    }
+}
diff --git a/src/test/pretty/asm.rs b/src/test/pretty/asm.rs
new file mode 100644
index 00000000000..9812f1d97e5
--- /dev/null
+++ b/src/test/pretty/asm.rs
@@ -0,0 +1,19 @@
+#![feature(asm)]
+
+// pretty-mode:expanded
+// pp-exact:asm.pp
+
+pub fn main() {
+    let a: i32;
+    let mut b = 4i32;
+    unsafe {
+        asm!("");
+        asm!("", options());
+        asm!("", options(nostack, nomem));
+        asm!("{}", in(reg) 4);
+        asm!("{0}", out(reg) a);
+        asm!("{name}", name = inout(reg) b);
+        asm!("{} {}", out(reg) _, inlateout(reg) b => _);
+        asm!("", out("al") _, lateout("rbx") _);
+    }
+}
diff --git a/src/test/pretty/asm-clobbers.rs b/src/test/pretty/llvm-asm-clobbers.rs
index 2c09646e47e..2c09646e47e 100644
--- a/src/test/pretty/asm-clobbers.rs
+++ b/src/test/pretty/llvm-asm-clobbers.rs
diff --git a/src/test/pretty/asm-options.rs b/src/test/pretty/llvm-asm-options.rs
index 86a881bfbd1..86a881bfbd1 100644
--- a/src/test/pretty/asm-options.rs
+++ b/src/test/pretty/llvm-asm-options.rs
diff --git a/src/test/ui/asm/bad-options.rs b/src/test/ui/asm/bad-options.rs
new file mode 100644
index 00000000000..755fc2ca238
--- /dev/null
+++ b/src/test/ui/asm/bad-options.rs
@@ -0,0 +1,18 @@
+// only-x86_64
+
+#![feature(asm)]
+
+fn main() {
+    let mut foo = 0;
+    unsafe {
+        asm!("", options(nomem, readonly));
+        //~^ ERROR the `nomem` and `readonly` options are mutually exclusive
+        asm!("", options(pure, nomem, noreturn));
+        //~^ ERROR the `pure` and `noreturn` options are mutually exclusive
+        //~^^ ERROR asm with `pure` option must have at least one output
+        asm!("{}", in(reg) foo, options(pure, nomem));
+        //~^ ERROR asm with `pure` option must have at least one output
+        asm!("{}", out(reg) foo, options(noreturn));
+        //~^ ERROR asm outputs are not allowed with the `noreturn` option
+    }
+}
diff --git a/src/test/ui/asm/bad-options.stderr b/src/test/ui/asm/bad-options.stderr
new file mode 100644
index 00000000000..c5e8e2ccf44
--- /dev/null
+++ b/src/test/ui/asm/bad-options.stderr
@@ -0,0 +1,32 @@
+error: the `nomem` and `readonly` options are mutually exclusive
+  --> $DIR/bad-options.rs:8:18
+   |
+LL |         asm!("", options(nomem, readonly));
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the `pure` and `noreturn` options are mutually exclusive
+  --> $DIR/bad-options.rs:10:18
+   |
+LL |         asm!("", options(pure, nomem, noreturn));
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: asm with `pure` option must have at least one output
+  --> $DIR/bad-options.rs:10:18
+   |
+LL |         asm!("", options(pure, nomem, noreturn));
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: asm with `pure` option must have at least one output
+  --> $DIR/bad-options.rs:13:33
+   |
+LL |         asm!("{}", in(reg) foo, options(pure, nomem));
+   |                                 ^^^^^^^^^^^^^^^^^^^^
+
+error: asm outputs are not allowed with the `noreturn` option
+  --> $DIR/bad-options.rs:15:20
+   |
+LL |         asm!("{}", out(reg) foo, options(noreturn));
+   |                    ^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/asm/bad-reg.rs b/src/test/ui/asm/bad-reg.rs
new file mode 100644
index 00000000000..ed7faa4b156
--- /dev/null
+++ b/src/test/ui/asm/bad-reg.rs
@@ -0,0 +1,57 @@
+// only-x86_64
+// compile-flags: -C target-feature=+avx2
+
+#![feature(asm)]
+
+fn main() {
+    let mut foo = 0;
+    let mut bar = 0;
+    unsafe {
+        // Bad register/register class
+
+        asm!("{}", in(foo) foo);
+        //~^ ERROR invalid register class `foo`: unknown register class
+        asm!("", in("foo") foo);
+        //~^ ERROR invalid register `foo`: unknown register
+        asm!("{:z}", in(reg) foo);
+        //~^ ERROR invalid asm template modifier for this register class
+        asm!("{:r}", in(xmm_reg) foo);
+        //~^ ERROR invalid asm template modifier for this register class
+        asm!("{:a}", const 0);
+        //~^ ERROR asm template modifiers are not allowed for `const` arguments
+        asm!("{:a}", sym main);
+        //~^ ERROR asm template modifiers are not allowed for `sym` arguments
+        asm!("{}", in(zmm_reg) foo);
+        //~^ ERROR register class `zmm_reg` requires the `avx512f` target feature
+        asm!("", in("zmm0") foo);
+        //~^ ERROR register class `zmm_reg` requires the `avx512f` target feature
+        asm!("", in("ah") foo);
+        //~^ ERROR invalid register `ah`: high byte registers are not currently supported
+        asm!("", in("ebp") foo);
+        //~^ ERROR invalid register `ebp`: the frame pointer cannot be used as an operand
+        asm!("", in("rsp") foo);
+        //~^ ERROR invalid register `rsp`: the stack pointer cannot be used as an operand
+        asm!("", in("ip") foo);
+        //~^ ERROR invalid register `ip`: the instruction pointer cannot be used as an operand
+        asm!("", in("st(2)") foo);
+        //~^ ERROR invalid register `st(2)`: x87 registers are not currently supported as operands
+        asm!("", in("mm0") foo);
+        //~^ ERROR invalid register `mm0`: MMX registers are not currently supported as operands
+        asm!("", in("k0") foo);
+        //~^ ERROR invalid register `k0`: the k0 AVX mask register cannot be used as an operand
+
+        // Explicit register conflicts
+        // (except in/lateout which don't conflict)
+
+        asm!("", in("eax") foo, in("al") bar);
+        //~^ ERROR register `ax` conflicts with register `ax`
+        asm!("", in("rax") foo, out("rax") bar);
+        //~^ ERROR register `ax` conflicts with register `ax`
+        asm!("", in("al") foo, lateout("al") bar);
+        asm!("", in("xmm0") foo, in("ymm0") bar);
+        //~^ ERROR register `ymm0` conflicts with register `xmm0`
+        asm!("", in("xmm0") foo, out("ymm0") bar);
+        //~^ ERROR register `ymm0` conflicts with register `xmm0`
+        asm!("", in("xmm0") foo, lateout("ymm0") bar);
+    }
+}
diff --git a/src/test/ui/asm/bad-reg.stderr b/src/test/ui/asm/bad-reg.stderr
new file mode 100644
index 00000000000..a9d872dae41
--- /dev/null
+++ b/src/test/ui/asm/bad-reg.stderr
@@ -0,0 +1,148 @@
+error: invalid register class `foo`: unknown register class
+  --> $DIR/bad-reg.rs:12:20
+   |
+LL |         asm!("{}", in(foo) foo);
+   |                    ^^^^^^^^^^^
+
+error: invalid register `foo`: unknown register
+  --> $DIR/bad-reg.rs:14:18
+   |
+LL |         asm!("", in("foo") foo);
+   |                  ^^^^^^^^^^^^^
+
+error: invalid asm template modifier for this register class
+  --> $DIR/bad-reg.rs:16:15
+   |
+LL |         asm!("{:z}", in(reg) foo);
+   |               ^^^^   ----------- argument
+   |               |
+   |               template modifier
+   |
+   = note: the `reg` register class supports the following template modifiers: `l`, `h`, `x`, `e`, `r`
+
+error: invalid asm template modifier for this register class
+  --> $DIR/bad-reg.rs:18:15
+   |
+LL |         asm!("{:r}", in(xmm_reg) foo);
+   |               ^^^^   --------------- argument
+   |               |
+   |               template modifier
+   |
+   = note: the `xmm_reg` register class supports the following template modifiers: `x`, `y`, `z`
+
+error: asm template modifiers are not allowed for `const` arguments
+  --> $DIR/bad-reg.rs:20:15
+   |
+LL |         asm!("{:a}", const 0);
+   |               ^^^^   ------- argument
+   |               |
+   |               template modifier
+
+error: asm template modifiers are not allowed for `sym` arguments
+  --> $DIR/bad-reg.rs:22:15
+   |
+LL |         asm!("{:a}", sym main);
+   |               ^^^^   -------- argument
+   |               |
+   |               template modifier
+
+error: register class `zmm_reg` requires the `avx512f` target feature
+  --> $DIR/bad-reg.rs:24:20
+   |
+LL |         asm!("{}", in(zmm_reg) foo);
+   |                    ^^^^^^^^^^^^^^^
+
+error: register class `zmm_reg` requires the `avx512f` target feature
+  --> $DIR/bad-reg.rs:26:18
+   |
+LL |         asm!("", in("zmm0") foo);
+   |                  ^^^^^^^^^^^^^^
+
+error: invalid register `ah`: high byte registers are not currently supported as operands for inline asm
+  --> $DIR/bad-reg.rs:28:18
+   |
+LL |         asm!("", in("ah") foo);
+   |                  ^^^^^^^^^^^^
+
+error: invalid register `ebp`: the frame pointer cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:30:18
+   |
+LL |         asm!("", in("ebp") foo);
+   |                  ^^^^^^^^^^^^^
+
+error: invalid register `rsp`: the stack pointer cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:32:18
+   |
+LL |         asm!("", in("rsp") foo);
+   |                  ^^^^^^^^^^^^^
+
+error: invalid register `ip`: the instruction pointer cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:34:18
+   |
+LL |         asm!("", in("ip") foo);
+   |                  ^^^^^^^^^^^^
+
+error: invalid register `st(2)`: x87 registers are not currently supported as operands for inline asm
+  --> $DIR/bad-reg.rs:36:18
+   |
+LL |         asm!("", in("st(2)") foo);
+   |                  ^^^^^^^^^^^^^^^
+
+error: invalid register `mm0`: MMX registers are not currently supported as operands for inline asm
+  --> $DIR/bad-reg.rs:38:18
+   |
+LL |         asm!("", in("mm0") foo);
+   |                  ^^^^^^^^^^^^^
+
+error: invalid register `k0`: the k0 AVX mask register cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:40:18
+   |
+LL |         asm!("", in("k0") foo);
+   |                  ^^^^^^^^^^^^
+
+error: register `ax` conflicts with register `ax`
+  --> $DIR/bad-reg.rs:46:33
+   |
+LL |         asm!("", in("eax") foo, in("al") bar);
+   |                  -------------  ^^^^^^^^^^^^ register `ax`
+   |                  |
+   |                  register `ax`
+
+error: register `ax` conflicts with register `ax`
+  --> $DIR/bad-reg.rs:48:33
+   |
+LL |         asm!("", in("rax") foo, out("rax") bar);
+   |                  -------------  ^^^^^^^^^^^^^^ register `ax`
+   |                  |
+   |                  register `ax`
+   |
+help: use `lateout` instead of `out` to avoid conflict
+  --> $DIR/bad-reg.rs:48:18
+   |
+LL |         asm!("", in("rax") foo, out("rax") bar);
+   |                  ^^^^^^^^^^^^^
+
+error: register `ymm0` conflicts with register `xmm0`
+  --> $DIR/bad-reg.rs:51:34
+   |
+LL |         asm!("", in("xmm0") foo, in("ymm0") bar);
+   |                  --------------  ^^^^^^^^^^^^^^ register `ymm0`
+   |                  |
+   |                  register `xmm0`
+
+error: register `ymm0` conflicts with register `xmm0`
+  --> $DIR/bad-reg.rs:53:34
+   |
+LL |         asm!("", in("xmm0") foo, out("ymm0") bar);
+   |                  --------------  ^^^^^^^^^^^^^^^ register `ymm0`
+   |                  |
+   |                  register `xmm0`
+   |
+help: use `lateout` instead of `out` to avoid conflict
+  --> $DIR/bad-reg.rs:53:18
+   |
+LL |         asm!("", in("xmm0") foo, out("ymm0") bar);
+   |                  ^^^^^^^^^^^^^^
+
+error: aborting due to 19 previous errors
+
diff --git a/src/test/ui/asm/bad-template.rs b/src/test/ui/asm/bad-template.rs
new file mode 100644
index 00000000000..0b333eca1ab
--- /dev/null
+++ b/src/test/ui/asm/bad-template.rs
@@ -0,0 +1,26 @@
+// only-x86_64
+
+#![feature(asm)]
+
+fn main() {
+    let mut foo = 0;
+    unsafe {
+        asm!("{}");
+        //~^ ERROR invalid reference to argument at index 0
+        asm!("{1}", in(reg) foo);
+        //~^ ERROR invalid reference to argument at index 1
+        //~^^ ERROR argument never used
+        asm!("{a}");
+        //~^ ERROR there is no argument named `a`
+        asm!("{}", a = in(reg) foo);
+        //~^ ERROR invalid reference to argument at index 0
+        //~^^ ERROR argument never used
+        asm!("{1}", a = in(reg) foo);
+        //~^ ERROR invalid reference to argument at index 1
+        //~^^ ERROR named argument never used
+        asm!("{}", in("eax") foo);
+        //~^ ERROR invalid reference to argument at index 0
+        asm!("{:foo}", in(reg) foo);
+        //~^ ERROR asm template modifier must be a single character
+    }
+}
diff --git a/src/test/ui/asm/bad-template.stderr b/src/test/ui/asm/bad-template.stderr
new file mode 100644
index 00000000000..2de76ef8241
--- /dev/null
+++ b/src/test/ui/asm/bad-template.stderr
@@ -0,0 +1,86 @@
+error: invalid reference to argument at index 0
+  --> $DIR/bad-template.rs:8:15
+   |
+LL |         asm!("{}");
+   |               ^^ from here
+   |
+   = note: no arguments were given
+
+error: invalid reference to argument at index 1
+  --> $DIR/bad-template.rs:10:15
+   |
+LL |         asm!("{1}", in(reg) foo);
+   |               ^^^ from here
+   |
+   = note: there is 1 argument
+
+error: argument never used
+  --> $DIR/bad-template.rs:10:21
+   |
+LL |         asm!("{1}", in(reg) foo);
+   |                     ^^^^^^^^^^^ argument never used
+
+error: there is no argument named `a`
+  --> $DIR/bad-template.rs:13:15
+   |
+LL |         asm!("{a}");
+   |               ^^^
+
+error: invalid reference to argument at index 0
+  --> $DIR/bad-template.rs:15:15
+   |
+LL |         asm!("{}", a = in(reg) foo);
+   |               ^^   --------------- named argument
+   |               |
+   |               from here
+   |
+   = note: no positional arguments were given
+note: named arguments cannot be referenced by position
+  --> $DIR/bad-template.rs:15:20
+   |
+LL |         asm!("{}", a = in(reg) foo);
+   |                    ^^^^^^^^^^^^^^^
+
+error: named argument never used
+  --> $DIR/bad-template.rs:15:20
+   |
+LL |         asm!("{}", a = in(reg) foo);
+   |                    ^^^^^^^^^^^^^^^ named argument never used
+
+error: invalid reference to argument at index 1
+  --> $DIR/bad-template.rs:18:15
+   |
+LL |         asm!("{1}", a = in(reg) foo);
+   |               ^^^ from here
+   |
+   = note: no positional arguments were given
+
+error: named argument never used
+  --> $DIR/bad-template.rs:18:21
+   |
+LL |         asm!("{1}", a = in(reg) foo);
+   |                     ^^^^^^^^^^^^^^^ named argument never used
+
+error: invalid reference to argument at index 0
+  --> $DIR/bad-template.rs:21:15
+   |
+LL |         asm!("{}", in("eax") foo);
+   |               ^^   ------------- explicit register argument
+   |               |
+   |               from here
+   |
+   = note: no positional arguments were given
+note: explicit register arguments cannot be used in the asm template
+  --> $DIR/bad-template.rs:21:20
+   |
+LL |         asm!("{}", in("eax") foo);
+   |                    ^^^^^^^^^^^^^
+
+error: asm template modifier must be a single character
+  --> $DIR/bad-template.rs:23:17
+   |
+LL |         asm!("{:foo}", in(reg) foo);
+   |                 ^^^
+
+error: aborting due to 10 previous errors
+
diff --git a/src/test/ui/asm/noreturn.rs b/src/test/ui/asm/noreturn.rs
new file mode 100644
index 00000000000..5e1ee93bfb0
--- /dev/null
+++ b/src/test/ui/asm/noreturn.rs
@@ -0,0 +1,17 @@
+// only-x86_64
+// check-pass
+
+#![feature(asm, never_type)]
+#![crate_type = "rlib"]
+
+pub unsafe fn asm1() {
+    let _: () = asm!("");
+}
+
+pub unsafe fn asm2() {
+    let _: ! = asm!("", options(noreturn));
+}
+
+pub unsafe fn asm3() -> ! {
+    asm!("", options(noreturn));
+}
diff --git a/src/test/ui/asm/parse-error.rs b/src/test/ui/asm/parse-error.rs
new file mode 100644
index 00000000000..e6566866b22
--- /dev/null
+++ b/src/test/ui/asm/parse-error.rs
@@ -0,0 +1,53 @@
+// only-x86_64
+
+#![feature(asm)]
+
+fn main() {
+    let mut foo = 0;
+    let mut bar = 0;
+    unsafe {
+        asm!();
+        //~^ ERROR requires at least a template string argument
+        asm!(foo);
+        //~^ ERROR asm template must be a string literal
+        asm!("{}" foo);
+        //~^ ERROR expected token: `,`
+        asm!("{}", foo);
+        //~^ ERROR expected one of
+        asm!("{}", in foo);
+        //~^ ERROR expected `(`, found `foo`
+        asm!("{}", in(reg foo));
+        //~^ ERROR expected `)`, found `foo`
+        asm!("{}", in(reg));
+        //~^ ERROR expected expression, found end of macro arguments
+        asm!("{}", inout(=) foo => bar);
+        //~^ ERROR expected register class or explicit register
+        asm!("{}", inout(reg) foo =>);
+        //~^ ERROR expected expression, found end of macro arguments
+        asm!("{}", in(reg) foo => bar);
+        //~^ ERROR expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `=>`
+        asm!("{}", sym foo + bar);
+        //~^ ERROR argument to `sym` must be a path expression
+        asm!("", options(foo));
+        //~^ ERROR expected one of
+        asm!("", options(nomem foo));
+        //~^ ERROR expected one of
+        asm!("", options(nomem, foo));
+        //~^ ERROR expected one of
+        asm!("", options(), options());
+        //~^ ERROR asm options cannot be specified twice
+        asm!("{}", options(), const foo);
+        //~^ ERROR arguments are not allowed after options
+        asm!("{a}", a = const foo, a = const bar);
+        //~^ ERROR duplicate argument named `a`
+        //~^^ ERROR argument never used
+        asm!("", a = in("eax") foo);
+        //~^ ERROR explicit register arguments cannot have names
+        asm!("{a}", in("eax") foo, a = const bar);
+        //~^ ERROR named arguments cannot follow explicit register arguments
+        asm!("{a}", in("eax") foo, a = const bar);
+        //~^ ERROR named arguments cannot follow explicit register arguments
+        asm!("{1}", in("eax") foo, const bar);
+        //~^ ERROR positional arguments cannot follow named arguments or explicit register arguments
+    }
+}
diff --git a/src/test/ui/asm/parse-error.stderr b/src/test/ui/asm/parse-error.stderr
new file mode 100644
index 00000000000..a927ce13858
--- /dev/null
+++ b/src/test/ui/asm/parse-error.stderr
@@ -0,0 +1,146 @@
+error: requires at least a template string argument
+  --> $DIR/parse-error.rs:9:9
+   |
+LL |         asm!();
+   |         ^^^^^^^
+
+error: asm template must be a string literal
+  --> $DIR/parse-error.rs:11:14
+   |
+LL |         asm!(foo);
+   |              ^^^
+
+error: expected token: `,`
+  --> $DIR/parse-error.rs:13:19
+   |
+LL |         asm!("{}" foo);
+   |                   ^^^ expected `,`
+
+error: expected one of `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `foo`
+  --> $DIR/parse-error.rs:15:20
+   |
+LL |         asm!("{}", foo);
+   |                    ^^^ expected one of 8 possible tokens
+
+error: expected `(`, found `foo`
+  --> $DIR/parse-error.rs:17:23
+   |
+LL |         asm!("{}", in foo);
+   |                       ^^^ expected `(`
+
+error: expected `)`, found `foo`
+  --> $DIR/parse-error.rs:19:27
+   |
+LL |         asm!("{}", in(reg foo));
+   |                           ^^^ expected `)`
+
+error: expected expression, found end of macro arguments
+  --> $DIR/parse-error.rs:21:27
+   |
+LL |         asm!("{}", in(reg));
+   |                           ^ expected expression
+
+error: expected register class or explicit register
+  --> $DIR/parse-error.rs:23:26
+   |
+LL |         asm!("{}", inout(=) foo => bar);
+   |                          ^
+
+error: expected expression, found end of macro arguments
+  --> $DIR/parse-error.rs:25:37
+   |
+LL |         asm!("{}", inout(reg) foo =>);
+   |                                     ^ expected expression
+
+error: expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `=>`
+  --> $DIR/parse-error.rs:27:32
+   |
+LL |         asm!("{}", in(reg) foo => bar);
+   |                                ^^ expected one of 7 possible tokens
+
+error: argument to `sym` must be a path expression
+  --> $DIR/parse-error.rs:29:24
+   |
+LL |         asm!("{}", sym foo + bar);
+   |                        ^^^^^^^^^
+
+error: expected one of `)`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, or `readonly`, found `foo`
+  --> $DIR/parse-error.rs:31:26
+   |
+LL |         asm!("", options(foo));
+   |                          ^^^ expected one of 7 possible tokens
+
+error: expected one of `)` or `,`, found `foo`
+  --> $DIR/parse-error.rs:33:32
+   |
+LL |         asm!("", options(nomem foo));
+   |                                ^^^ expected one of `)` or `,`
+
+error: expected one of `)`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, or `readonly`, found `foo`
+  --> $DIR/parse-error.rs:35:33
+   |
+LL |         asm!("", options(nomem, foo));
+   |                                 ^^^ expected one of 7 possible tokens
+
+error: asm options cannot be specified twice
+  --> $DIR/parse-error.rs:37:29
+   |
+LL |         asm!("", options(), options());
+   |                  ---------  ^^^^^^^^^ duplicate options
+   |                  |
+   |                  previously here
+
+error: arguments are not allowed after options
+  --> $DIR/parse-error.rs:39:31
+   |
+LL |         asm!("{}", options(), const foo);
+   |                    ---------  ^^^^^^^^^ argument
+   |                    |
+   |                    previous options
+
+error: duplicate argument named `a`
+  --> $DIR/parse-error.rs:41:36
+   |
+LL |         asm!("{a}", a = const foo, a = const bar);
+   |                     -------------  ^^^^^^^^^^^^^ duplicate argument
+   |                     |
+   |                     previously here
+
+error: argument never used
+  --> $DIR/parse-error.rs:41:36
+   |
+LL |         asm!("{a}", a = const foo, a = const bar);
+   |                                    ^^^^^^^^^^^^^ argument never used
+
+error: explicit register arguments cannot have names
+  --> $DIR/parse-error.rs:44:18
+   |
+LL |         asm!("", a = in("eax") foo);
+   |                  ^^^^^^^^^^^^^^^^^
+
+error: named arguments cannot follow explicit register arguments
+  --> $DIR/parse-error.rs:46:36
+   |
+LL |         asm!("{a}", in("eax") foo, a = const bar);
+   |                     -------------  ^^^^^^^^^^^^^ named argument
+   |                     |
+   |                     explicit register argument
+
+error: named arguments cannot follow explicit register arguments
+  --> $DIR/parse-error.rs:48:36
+   |
+LL |         asm!("{a}", in("eax") foo, a = const bar);
+   |                     -------------  ^^^^^^^^^^^^^ named argument
+   |                     |
+   |                     explicit register argument
+
+error: positional arguments cannot follow named arguments or explicit register arguments
+  --> $DIR/parse-error.rs:50:36
+   |
+LL |         asm!("{1}", in("eax") foo, const bar);
+   |                     -------------  ^^^^^^^^^ positional argument
+   |                     |
+   |                     explicit register argument
+
+error: aborting due to 22 previous errors
+
diff --git a/src/test/ui/asm/rustfix-asm.fixed b/src/test/ui/asm/rustfix-asm.fixed
new file mode 100644
index 00000000000..c9271059810
--- /dev/null
+++ b/src/test/ui/asm/rustfix-asm.fixed
@@ -0,0 +1,16 @@
+// run-rustfix
+// only-x86_64
+
+#![feature(asm, llvm_asm)]
+
+fn main() {
+    unsafe {
+        let x = 1;
+        let y: i32;
+        llvm_asm!("" :: "r" (x));
+        //~^ ERROR legacy asm! syntax is no longer supported
+        llvm_asm!("" : "=r" (y));
+        //~^ ERROR legacy asm! syntax is no longer supported
+        let _ = y;
+    }
+}
diff --git a/src/test/ui/asm/rustfix-asm.rs b/src/test/ui/asm/rustfix-asm.rs
new file mode 100644
index 00000000000..a108595ca1b
--- /dev/null
+++ b/src/test/ui/asm/rustfix-asm.rs
@@ -0,0 +1,16 @@
+// run-rustfix
+// only-x86_64
+
+#![feature(asm, llvm_asm)]
+
+fn main() {
+    unsafe {
+        let x = 1;
+        let y: i32;
+        asm!("" :: "r" (x));
+        //~^ ERROR legacy asm! syntax is no longer supported
+        asm!("" : "=r" (y));
+        //~^ ERROR legacy asm! syntax is no longer supported
+        let _ = y;
+    }
+}
diff --git a/src/test/ui/asm/rustfix-asm.stderr b/src/test/ui/asm/rustfix-asm.stderr
new file mode 100644
index 00000000000..28675b51d15
--- /dev/null
+++ b/src/test/ui/asm/rustfix-asm.stderr
@@ -0,0 +1,18 @@
+error: legacy asm! syntax is no longer supported
+  --> $DIR/rustfix-asm.rs:10:9
+   |
+LL |         asm!("" :: "r" (x));
+   |         ----^^^^^^^^^^^^^^^^
+   |         |
+   |         help: replace with: `llvm_asm!`
+
+error: legacy asm! syntax is no longer supported
+  --> $DIR/rustfix-asm.rs:12:9
+   |
+LL |         asm!("" : "=r" (y));
+   |         ----^^^^^^^^^^^^^^^^
+   |         |
+   |         help: replace with: `llvm_asm!`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/asm/type-check-1.rs b/src/test/ui/asm/type-check-1.rs
new file mode 100644
index 00000000000..7880382c3b7
--- /dev/null
+++ b/src/test/ui/asm/type-check-1.rs
@@ -0,0 +1,25 @@
+// only-x86_64
+
+#![feature(asm)]
+
+fn main() {
+    unsafe {
+        // Outputs must be place expressions
+
+        asm!("{}", in(reg) 1 + 2);
+        asm!("{}", out(reg) 1 + 2);
+        //~^ ERROR invalid asm output
+        asm!("{}", inout(reg) 1 + 2);
+        //~^ ERROR invalid asm output
+
+        // Operands must be sized
+
+        let v: [u64; 3] = [0, 1, 2];
+        asm!("{}", in(reg) v[..]);
+        //~^ ERROR the size for values of type `[u64]` cannot be known at compilation time
+        asm!("{}", out(reg) v[..]);
+        //~^ ERROR the size for values of type `[u64]` cannot be known at compilation time
+        asm!("{}", inout(reg) v[..]);
+        //~^ ERROR the size for values of type `[u64]` cannot be known at compilation time
+    }
+}
diff --git a/src/test/ui/asm/type-check-1.stderr b/src/test/ui/asm/type-check-1.stderr
new file mode 100644
index 00000000000..7c9c041f457
--- /dev/null
+++ b/src/test/ui/asm/type-check-1.stderr
@@ -0,0 +1,45 @@
+error: invalid asm output
+  --> $DIR/type-check-1.rs:10:29
+   |
+LL |         asm!("{}", out(reg) 1 + 2);
+   |                             ^^^^^ cannot assign to this expression
+
+error: invalid asm output
+  --> $DIR/type-check-1.rs:12:31
+   |
+LL |         asm!("{}", inout(reg) 1 + 2);
+   |                               ^^^^^ cannot assign to this expression
+
+error[E0277]: the size for values of type `[u64]` cannot be known at compilation time
+  --> $DIR/type-check-1.rs:18:28
+   |
+LL |         asm!("{}", in(reg) v[..]);
+   |                            ^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `[u64]`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: all inline asm arguments must have a statically known size
+
+error[E0277]: the size for values of type `[u64]` cannot be known at compilation time
+  --> $DIR/type-check-1.rs:20:29
+   |
+LL |         asm!("{}", out(reg) v[..]);
+   |                             ^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `[u64]`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: all inline asm arguments must have a statically known size
+
+error[E0277]: the size for values of type `[u64]` cannot be known at compilation time
+  --> $DIR/type-check-1.rs:22:31
+   |
+LL |         asm!("{}", inout(reg) v[..]);
+   |                               ^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `[u64]`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: all inline asm arguments must have a statically known size
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/asm/type-check-2.rs b/src/test/ui/asm/type-check-2.rs
new file mode 100644
index 00000000000..1652e9e4c9f
--- /dev/null
+++ b/src/test/ui/asm/type-check-2.rs
@@ -0,0 +1,104 @@
+// only-x86_64
+
+#![feature(asm, repr_simd, never_type)]
+
+#[repr(simd)]
+struct SimdNonCopy(f32, f32, f32, f32);
+
+fn main() {
+    unsafe {
+        // Inputs must be initialized
+
+        let x: u64;
+        asm!("{}", in(reg) x);
+        //~^ ERROR use of possibly-uninitialized variable: `x`
+        let mut y: u64;
+        asm!("{}", inout(reg) y);
+        //~^ ERROR use of possibly-uninitialized variable: `y`
+        let _ = y;
+
+        // Outputs require mutable places
+
+        let v: Vec<u64> = vec![0, 1, 2];
+        asm!("{}", in(reg) v[0]);
+        asm!("{}", out(reg) v[0]);
+        //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable
+        asm!("{}", inout(reg) v[0]);
+        //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable
+
+        // Const operands must be integer or floats, and must be constants.
+
+        let x = 0;
+        const C: i32 = 0;
+        const fn const_foo(x: i32) -> i32 {
+            x
+        }
+        const fn const_bar<T>(x: T) -> T {
+            x
+        }
+        asm!("{}", const 0i32);
+        asm!("{}", const 0f32);
+        asm!("{}", const 0 as *mut u8);
+        //~^ ERROR asm `const` arguments must be integer or floating-point values
+        asm!("{}", const &0);
+        //~^ ERROR asm `const` arguments must be integer or floating-point values
+        asm!("{}", const x);
+        //~^ ERROR argument 1 is required to be a constant
+        asm!("{}", const const_foo(0));
+        asm!("{}", const const_foo(x));
+        //~^ ERROR argument 1 is required to be a constant
+        asm!("{}", const const_bar(0));
+        asm!("{}", const const_bar(x));
+        //~^ ERROR argument 1 is required to be a constant
+
+        // Sym operands must point to a function or static
+
+        static S: i32 = 0;
+        asm!("{}", sym S);
+        asm!("{}", sym main);
+        asm!("{}", sym C);
+        //~^ ERROR asm `sym` operand must point to a fn or static
+        asm!("{}", sym x);
+        //~^ ERROR asm `sym` operand must point to a fn or static
+
+        // Register operands must be Copy
+
+        asm!("{}", in(xmm_reg) SimdNonCopy(0.0, 0.0, 0.0, 0.0));
+        //~^ ERROR arguments for inline assembly must be copyable
+
+        // Register operands must be integers, floats, SIMD vectors, pointers or
+        // function pointers.
+
+        asm!("{}", in(reg) 0i64);
+        asm!("{}", in(reg) 0f64);
+        asm!("{}", in(xmm_reg) std::arch::x86_64::_mm_setzero_ps());
+        asm!("{}", in(reg) 0 as *const u8);
+        asm!("{}", in(reg) 0 as *mut u8);
+        asm!("{}", in(reg) main as fn());
+        asm!("{}", in(reg) |x: i32| x);
+        //~^ ERROR cannot use value of type
+        asm!("{}", in(reg) vec![0]);
+        //~^ ERROR cannot use value of type `std::vec::Vec<i32>` for inline assembly
+        asm!("{}", in(reg) (1, 2, 3));
+        //~^ ERROR cannot use value of type `(i32, i32, i32)` for inline assembly
+        asm!("{}", in(reg) [1, 2, 3]);
+        //~^ ERROR cannot use value of type `[i32; 3]` for inline assembly
+
+        // Register inputs (but not outputs) allow references and function types
+
+        let mut f = main;
+        let mut r = &mut 0;
+        asm!("{}", in(reg) f);
+        asm!("{}", inout(reg) f);
+        //~^ ERROR cannot use value of type `fn() {main}` for inline assembly
+        asm!("{}", in(reg) r);
+        asm!("{}", inout(reg) r);
+        //~^ ERROR cannot use value of type `&mut i32` for inline assembly
+        let _ = (f, r);
+
+        // Type checks ignore never type
+
+        let u: ! = unreachable!();
+        asm!("{}", in(reg) u);
+    }
+}
diff --git a/src/test/ui/asm/type-check-2.stderr b/src/test/ui/asm/type-check-2.stderr
new file mode 100644
index 00000000000..dc7949534f1
--- /dev/null
+++ b/src/test/ui/asm/type-check-2.stderr
@@ -0,0 +1,133 @@
+error: asm `const` arguments must be integer or floating-point values
+  --> $DIR/type-check-2.rs:41:26
+   |
+LL |         asm!("{}", const 0 as *mut u8);
+   |                          ^^^^^^^^^^^^
+
+error: asm `const` arguments must be integer or floating-point values
+  --> $DIR/type-check-2.rs:43:26
+   |
+LL |         asm!("{}", const &0);
+   |                          ^^
+
+error: arguments for inline assembly must be copyable
+  --> $DIR/type-check-2.rs:66:32
+   |
+LL |         asm!("{}", in(xmm_reg) SimdNonCopy(0.0, 0.0, 0.0, 0.0));
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `SimdNonCopy` does not implement the Copy trait
+
+error: cannot use value of type `[closure@$DIR/type-check-2.rs:78:28: 78:38]` for inline assembly
+  --> $DIR/type-check-2.rs:78:28
+   |
+LL |         asm!("{}", in(reg) |x: i32| x);
+   |                            ^^^^^^^^^^
+   |
+   = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
+
+error: cannot use value of type `std::vec::Vec<i32>` for inline assembly
+  --> $DIR/type-check-2.rs:80:28
+   |
+LL |         asm!("{}", in(reg) vec![0]);
+   |                            ^^^^^^^
+   |
+   = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: cannot use value of type `(i32, i32, i32)` for inline assembly
+  --> $DIR/type-check-2.rs:82:28
+   |
+LL |         asm!("{}", in(reg) (1, 2, 3));
+   |                            ^^^^^^^^^
+   |
+   = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
+
+error: cannot use value of type `[i32; 3]` for inline assembly
+  --> $DIR/type-check-2.rs:84:28
+   |
+LL |         asm!("{}", in(reg) [1, 2, 3]);
+   |                            ^^^^^^^^^
+   |
+   = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
+
+error: cannot use value of type `fn() {main}` for inline assembly
+  --> $DIR/type-check-2.rs:92:31
+   |
+LL |         asm!("{}", inout(reg) f);
+   |                               ^
+   |
+   = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
+
+error: cannot use value of type `&mut i32` for inline assembly
+  --> $DIR/type-check-2.rs:95:31
+   |
+LL |         asm!("{}", inout(reg) r);
+   |                               ^
+   |
+   = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
+
+error: asm `sym` operand must point to a fn or static
+  --> $DIR/type-check-2.rs:59:24
+   |
+LL |         asm!("{}", sym C);
+   |                        ^
+
+error: asm `sym` operand must point to a fn or static
+  --> $DIR/type-check-2.rs:61:24
+   |
+LL |         asm!("{}", sym x);
+   |                        ^
+
+error: argument 1 is required to be a constant
+  --> $DIR/type-check-2.rs:45:9
+   |
+LL |         asm!("{}", const x);
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: argument 1 is required to be a constant
+  --> $DIR/type-check-2.rs:48:9
+   |
+LL |         asm!("{}", const const_foo(x));
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: argument 1 is required to be a constant
+  --> $DIR/type-check-2.rs:51:9
+   |
+LL |         asm!("{}", const const_bar(x));
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0381]: use of possibly-uninitialized variable: `x`
+  --> $DIR/type-check-2.rs:13:28
+   |
+LL |         asm!("{}", in(reg) x);
+   |                            ^ use of possibly-uninitialized `x`
+
+error[E0381]: use of possibly-uninitialized variable: `y`
+  --> $DIR/type-check-2.rs:16:9
+   |
+LL |         asm!("{}", inout(reg) y);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ use of possibly-uninitialized `y`
+
+error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
+  --> $DIR/type-check-2.rs:24:29
+   |
+LL |         let v: Vec<u64> = vec![0, 1, 2];
+   |             - help: consider changing this to be mutable: `mut v`
+LL |         asm!("{}", in(reg) v[0]);
+LL |         asm!("{}", out(reg) v[0]);
+   |                             ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
+  --> $DIR/type-check-2.rs:26:31
+   |
+LL |         let v: Vec<u64> = vec![0, 1, 2];
+   |             - help: consider changing this to be mutable: `mut v`
+...
+LL |         asm!("{}", inout(reg) v[0]);
+   |                               ^ cannot borrow as mutable
+
+error: aborting due to 18 previous errors
+
+Some errors have detailed explanations: E0381, E0596.
+For more information about an error, try `rustc --explain E0381`.
diff --git a/src/test/ui/asm/type-check-3.rs b/src/test/ui/asm/type-check-3.rs
new file mode 100644
index 00000000000..750d28026d7
--- /dev/null
+++ b/src/test/ui/asm/type-check-3.rs
@@ -0,0 +1,68 @@
+// only-x86_64
+// compile-flags: -C target-feature=+avx512f
+
+#![feature(asm)]
+
+use std::arch::x86_64::{_mm256_setzero_ps, _mm_setzero_ps};
+
+fn main() {
+    unsafe {
+        // Types must be in the whitelist for the register class
+
+        asm!("{}", in(reg) 0i128);
+        //~^ ERROR type `i128` cannot be used with this register class
+        asm!("{}", in(reg) _mm_setzero_ps());
+        //~^ ERROR type `std::arch::x86_64::__m128` cannot be used with this register class
+        asm!("{}", in(reg) _mm256_setzero_ps());
+        //~^ ERROR type `std::arch::x86_64::__m256` cannot be used with this register class
+        asm!("{}", in(xmm_reg) 0u8);
+        //~^ ERROR type `u8` cannot be used with this register class
+        asm!("{:e}", in(reg) 0i32);
+        asm!("{}", in(xmm_reg) 0i32);
+        asm!("{:e}", in(reg) 0f32);
+        asm!("{}", in(xmm_reg) 0f32);
+        asm!("{}", in(xmm_reg) _mm_setzero_ps());
+        asm!("{:x}", in(ymm_reg) _mm_setzero_ps());
+        asm!("{}", in(kreg) 0u16);
+        asm!("{}", in(kreg) 0u64);
+        //~^ ERROR `avx512bw` target feature is not enabled
+
+        // Template modifier suggestions for sub-registers
+
+        asm!("{0} {0}", in(reg) 0i8);
+        //~^ WARN formatting may not be suitable for sub-register argument
+        asm!("{0} {0:x}", in(reg) 0i16);
+        //~^ WARN formatting may not be suitable for sub-register argument
+        asm!("{}", in(reg) 0i32);
+        //~^ WARN formatting may not be suitable for sub-register argument
+        asm!("{}", in(reg) 0i64);
+        asm!("{}", in(ymm_reg) 0i64);
+        //~^ WARN formatting may not be suitable for sub-register argument
+        asm!("{}", in(ymm_reg) _mm256_setzero_ps());
+        asm!("{:l}", in(reg) 0i8);
+        asm!("{:l}", in(reg) 0i16);
+        asm!("{:l}", in(reg) 0i32);
+        asm!("{:l}", in(reg) 0i64);
+        asm!("{:x}", in(ymm_reg) 0i64);
+        asm!("{:x}", in(ymm_reg) _mm256_setzero_ps());
+
+        // Split inout operands must have compatible types
+
+        let mut val_i8: i8;
+        let mut val_f32: f32;
+        let mut val_u32: u32;
+        let mut val_u64: u64;
+        let mut val_ptr: *mut u8;
+        asm!("{:r}", inout(reg) 0u8 => val_i8);
+        asm!("{:r}", inout(reg) 0u16 => val_i8);
+        //~^ ERROR incompatible types for asm inout argument
+        asm!("{:r}", inout(reg) 0u32 => val_f32);
+        //~^ ERROR incompatible types for asm inout argument
+        asm!("{:r}", inout(reg) 0u32 => val_ptr);
+        //~^ ERROR incompatible types for asm inout argument
+        asm!("{:r}", inout(reg) main => val_u32);
+        //~^ ERROR incompatible types for asm inout argument
+        asm!("{:r}", inout(reg) 0u64 => val_ptr);
+        asm!("{:r}", inout(reg) main => val_u64);
+    }
+}
diff --git a/src/test/ui/asm/type-check-3.stderr b/src/test/ui/asm/type-check-3.stderr
new file mode 100644
index 00000000000..e4018ca1d42
--- /dev/null
+++ b/src/test/ui/asm/type-check-3.stderr
@@ -0,0 +1,123 @@
+error: type `i128` cannot be used with this register class
+  --> $DIR/type-check-3.rs:12:28
+   |
+LL |         asm!("{}", in(reg) 0i128);
+   |                            ^^^^^
+   |
+   = note: register class `reg` supports these types: i8, i16, i32, i64, f32, f64
+
+error: type `std::arch::x86_64::__m128` cannot be used with this register class
+  --> $DIR/type-check-3.rs:14:28
+   |
+LL |         asm!("{}", in(reg) _mm_setzero_ps());
+   |                            ^^^^^^^^^^^^^^^^
+   |
+   = note: register class `reg` supports these types: i8, i16, i32, i64, f32, f64
+
+error: type `std::arch::x86_64::__m256` cannot be used with this register class
+  --> $DIR/type-check-3.rs:16:28
+   |
+LL |         asm!("{}", in(reg) _mm256_setzero_ps());
+   |                            ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: register class `reg` supports these types: i8, i16, i32, i64, f32, f64
+
+error: type `u8` cannot be used with this register class
+  --> $DIR/type-check-3.rs:18:32
+   |
+LL |         asm!("{}", in(xmm_reg) 0u8);
+   |                                ^^^
+   |
+   = note: register class `xmm_reg` supports these types: i32, i64, f32, f64, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2
+
+error: `avx512bw` target feature is not enabled
+  --> $DIR/type-check-3.rs:27:29
+   |
+LL |         asm!("{}", in(kreg) 0u64);
+   |                             ^^^^
+   |
+   = note: this is required to use type `u64` with register class `kreg`
+
+warning: formatting may not be suitable for sub-register argument
+  --> $DIR/type-check-3.rs:32:15
+   |
+LL |         asm!("{0} {0}", in(reg) 0i8);
+   |               ^^^ ^^^           --- for this argument
+   |
+   = note: `#[warn(asm_sub_register)]` on by default
+   = help: use the `l` modifier to have the register formatted as `al`
+   = help: or use the `r` modifier to keep the default formatting of `rax`
+
+warning: formatting may not be suitable for sub-register argument
+  --> $DIR/type-check-3.rs:34:15
+   |
+LL |         asm!("{0} {0:x}", in(reg) 0i16);
+   |               ^^^                 ---- for this argument
+   |
+   = help: use the `x` modifier to have the register formatted as `ax`
+   = help: or use the `r` modifier to keep the default formatting of `rax`
+
+warning: formatting may not be suitable for sub-register argument
+  --> $DIR/type-check-3.rs:36:15
+   |
+LL |         asm!("{}", in(reg) 0i32);
+   |               ^^           ---- for this argument
+   |
+   = help: use the `e` modifier to have the register formatted as `eax`
+   = help: or use the `r` modifier to keep the default formatting of `rax`
+
+warning: formatting may not be suitable for sub-register argument
+  --> $DIR/type-check-3.rs:39:15
+   |
+LL |         asm!("{}", in(ymm_reg) 0i64);
+   |               ^^               ---- for this argument
+   |
+   = help: use the `x` modifier to have the register formatted as `xmm0`
+   = help: or use the `y` modifier to keep the default formatting of `ymm0`
+
+error: incompatible types for asm inout argument
+  --> $DIR/type-check-3.rs:57:33
+   |
+LL |         asm!("{:r}", inout(reg) 0u16 => val_i8);
+   |                                 ^^^^    ^^^^^^ type `i8`
+   |                                 |
+   |                                 type `u16`
+   |
+   = note: asm inout arguments must have the same type
+   = note: unless they are both pointers or integers of the same size
+
+error: incompatible types for asm inout argument
+  --> $DIR/type-check-3.rs:59:33
+   |
+LL |         asm!("{:r}", inout(reg) 0u32 => val_f32);
+   |                                 ^^^^    ^^^^^^^ type `f32`
+   |                                 |
+   |                                 type `u32`
+   |
+   = note: asm inout arguments must have the same type
+   = note: unless they are both pointers or integers of the same size
+
+error: incompatible types for asm inout argument
+  --> $DIR/type-check-3.rs:61:33
+   |
+LL |         asm!("{:r}", inout(reg) 0u32 => val_ptr);
+   |                                 ^^^^    ^^^^^^^ type `*mut u8`
+   |                                 |
+   |                                 type `u32`
+   |
+   = note: asm inout arguments must have the same type
+   = note: unless they are both pointers or integers of the same size
+
+error: incompatible types for asm inout argument
+  --> $DIR/type-check-3.rs:63:33
+   |
+LL |         asm!("{:r}", inout(reg) main => val_u32);
+   |                                 ^^^^    ^^^^^^^ type `u32`
+   |                                 |
+   |                                 type `fn()`
+   |
+   = note: asm inout arguments must have the same type
+   = note: unless they are both pointers or integers of the same size
+
+error: aborting due to 9 previous errors; 4 warnings emitted
+
diff --git a/src/test/ui/feature-gates/feature-gate-asm.rs b/src/test/ui/feature-gates/feature-gate-asm.rs
index 70f5845550d..7eeeb4bc4e2 100644
--- a/src/test/ui/feature-gates/feature-gate-asm.rs
+++ b/src/test/ui/feature-gates/feature-gate-asm.rs
@@ -3,7 +3,6 @@
 fn main() {
     unsafe {
         asm!(""); //~ ERROR inline assembly is not stable enough
-        //~^ WARN use of deprecated item 'asm'
         llvm_asm!(""); //~ ERROR inline assembly is not stable enough
     }
 }
diff --git a/src/test/ui/feature-gates/feature-gate-asm.stderr b/src/test/ui/feature-gates/feature-gate-asm.stderr
index 9d4d7b53955..1f9eaa5632e 100644
--- a/src/test/ui/feature-gates/feature-gate-asm.stderr
+++ b/src/test/ui/feature-gates/feature-gate-asm.stderr
@@ -8,7 +8,7 @@ LL |         asm!("");
    = help: add `#![feature(asm)]` to the crate attributes to enable
 
 error[E0658]: use of unstable library feature 'llvm_asm': inline assembly is not stable enough for use and is subject to change
-  --> $DIR/feature-gate-asm.rs:7:9
+  --> $DIR/feature-gate-asm.rs:6:9
    |
 LL |         llvm_asm!("");
    |         ^^^^^^^^
@@ -16,14 +16,6 @@ LL |         llvm_asm!("");
    = note: see issue #70173 <https://github.com/rust-lang/rust/issues/70173> for more information
    = help: add `#![feature(llvm_asm)]` to the crate attributes to enable
 
-warning: use of deprecated item 'asm': the syntax of asm! will change soon, use llvm_asm! to avoid breakage
-  --> $DIR/feature-gate-asm.rs:5:9
-   |
-LL |         asm!("");
-   |         ^^^ help: replace the use of the deprecated item: `llvm_asm`
-   |
-   = note: `#[warn(deprecated)]` on by default
-
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-asm2.rs b/src/test/ui/feature-gates/feature-gate-asm2.rs
index e3e86592a48..666a4894f62 100644
--- a/src/test/ui/feature-gates/feature-gate-asm2.rs
+++ b/src/test/ui/feature-gates/feature-gate-asm2.rs
@@ -3,7 +3,6 @@
 fn main() {
     unsafe {
         println!("{:?}", asm!("")); //~ ERROR inline assembly is not stable
-        //~^ WARN use of deprecated item 'asm'
         println!("{:?}", llvm_asm!("")); //~ ERROR inline assembly is not stable
     }
 }
diff --git a/src/test/ui/feature-gates/feature-gate-asm2.stderr b/src/test/ui/feature-gates/feature-gate-asm2.stderr
index a3c8116d6b1..17ba66e9842 100644
--- a/src/test/ui/feature-gates/feature-gate-asm2.stderr
+++ b/src/test/ui/feature-gates/feature-gate-asm2.stderr
@@ -8,7 +8,7 @@ LL |         println!("{:?}", asm!(""));
    = help: add `#![feature(asm)]` to the crate attributes to enable
 
 error[E0658]: use of unstable library feature 'llvm_asm': inline assembly is not stable enough for use and is subject to change
-  --> $DIR/feature-gate-asm2.rs:7:26
+  --> $DIR/feature-gate-asm2.rs:6:26
    |
 LL |         println!("{:?}", llvm_asm!(""));
    |                          ^^^^^^^^
@@ -16,14 +16,6 @@ LL |         println!("{:?}", llvm_asm!(""));
    = note: see issue #70173 <https://github.com/rust-lang/rust/issues/70173> for more information
    = help: add `#![feature(llvm_asm)]` to the crate attributes to enable
 
-warning: use of deprecated item 'asm': the syntax of asm! will change soon, use llvm_asm! to avoid breakage
-  --> $DIR/feature-gate-asm2.rs:5:26
-   |
-LL |         println!("{:?}", asm!(""));
-   |                          ^^^ help: replace the use of the deprecated item: `llvm_asm`
-   |
-   = note: `#[warn(deprecated)]` on by default
-
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/asm-concat-src.rs b/src/test/ui/llvm-asm/llvm-asm-concat-src.rs
index 1dc1c859c6b..1dc1c859c6b 100644
--- a/src/test/ui/asm-concat-src.rs
+++ b/src/test/ui/llvm-asm/llvm-asm-concat-src.rs
diff --git a/src/test/ui/asm-in-moved.rs b/src/test/ui/llvm-asm/llvm-asm-in-moved.rs
index 35f4d92c8ff..35f4d92c8ff 100644
--- a/src/test/ui/asm-in-moved.rs
+++ b/src/test/ui/llvm-asm/llvm-asm-in-moved.rs
diff --git a/src/test/ui/asm-in-out-operand.rs b/src/test/ui/llvm-asm/llvm-asm-in-out-operand.rs
index acefabd8a66..acefabd8a66 100644
--- a/src/test/ui/asm-in-out-operand.rs
+++ b/src/test/ui/llvm-asm/llvm-asm-in-out-operand.rs
diff --git a/src/test/ui/asm-indirect-memory.rs b/src/test/ui/llvm-asm/llvm-asm-indirect-memory.rs
index 556ad83a4ea..556ad83a4ea 100644
--- a/src/test/ui/asm-indirect-memory.rs
+++ b/src/test/ui/llvm-asm/llvm-asm-indirect-memory.rs
diff --git a/src/test/ui/asm-out-assign.rs b/src/test/ui/llvm-asm/llvm-asm-out-assign.rs
index 321f28565ff..321f28565ff 100644
--- a/src/test/ui/asm-out-assign.rs
+++ b/src/test/ui/llvm-asm/llvm-asm-out-assign.rs
diff --git a/src/test/ui/macros/macro-expanded-include/foo/mod.rs b/src/test/ui/macros/macro-expanded-include/foo/mod.rs
index f0eb92b2be8..a8bfa0299f6 100644
--- a/src/test/ui/macros/macro-expanded-include/foo/mod.rs
+++ b/src/test/ui/macros/macro-expanded-include/foo/mod.rs
@@ -5,5 +5,5 @@ macro_rules! m {
 }
 
 macro_rules! n {
-    () => { unsafe { llvm_asm!(include_str!("file.txt")); } }
+    () => { unsafe { asm!(include_str!("file.txt")); } }
 }
diff --git a/src/test/ui/macros/macro-expanded-include/test.rs b/src/test/ui/macros/macro-expanded-include/test.rs
index abf83a5c6ff..f1a71059a89 100644
--- a/src/test/ui/macros/macro-expanded-include/test.rs
+++ b/src/test/ui/macros/macro-expanded-include/test.rs
@@ -1,6 +1,6 @@
 // ignore-emscripten no llvm_asm! support
 // build-pass (FIXME(62277): could be check-pass?)
-#![feature(llvm_asm)]
+#![feature(asm)]
 #![allow(unused)]
 
 #[macro_use]
diff --git a/src/test/ui/macros/macros-nonfatal-errors.rs b/src/test/ui/macros/macros-nonfatal-errors.rs
index cc96a5bff52..0a496c9dc3d 100644
--- a/src/test/ui/macros/macros-nonfatal-errors.rs
+++ b/src/test/ui/macros/macros-nonfatal-errors.rs
@@ -3,13 +3,14 @@
 // test that errors in a (selection) of macros don't kill compilation
 // immediately, so that we get more errors listed at a time.
 
-#![feature(llvm_asm)]
+#![feature(asm, llvm_asm)]
 #![feature(trace_macros, concat_idents)]
 
 #[derive(Default)] //~ ERROR
 enum OrDeriveThis {}
 
 fn main() {
+    asm!(invalid); //~ ERROR
     llvm_asm!(invalid); //~ ERROR
 
     concat_idents!("not", "idents"); //~ ERROR
diff --git a/src/test/ui/macros/macros-nonfatal-errors.stderr b/src/test/ui/macros/macros-nonfatal-errors.stderr
index f416c70123c..6ef757a55b8 100644
--- a/src/test/ui/macros/macros-nonfatal-errors.stderr
+++ b/src/test/ui/macros/macros-nonfatal-errors.stderr
@@ -6,44 +6,50 @@ LL | #[derive(Default)]
    |
    = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
+error: asm template must be a string literal
+  --> $DIR/macros-nonfatal-errors.rs:13:10
+   |
+LL |     asm!(invalid);
+   |          ^^^^^^^
+
 error: inline assembly must be a string literal
-  --> $DIR/macros-nonfatal-errors.rs:13:15
+  --> $DIR/macros-nonfatal-errors.rs:14:15
    |
 LL |     llvm_asm!(invalid);
    |               ^^^^^^^
 
 error: concat_idents! requires ident args.
-  --> $DIR/macros-nonfatal-errors.rs:15:5
+  --> $DIR/macros-nonfatal-errors.rs:16:5
    |
 LL |     concat_idents!("not", "idents");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: argument must be a string literal
-  --> $DIR/macros-nonfatal-errors.rs:17:17
+  --> $DIR/macros-nonfatal-errors.rs:18:17
    |
 LL |     option_env!(invalid);
    |                 ^^^^^^^
 
 error: expected string literal
-  --> $DIR/macros-nonfatal-errors.rs:18:10
+  --> $DIR/macros-nonfatal-errors.rs:19:10
    |
 LL |     env!(invalid);
    |          ^^^^^^^
 
 error: expected string literal
-  --> $DIR/macros-nonfatal-errors.rs:19:10
+  --> $DIR/macros-nonfatal-errors.rs:20:10
    |
 LL |     env!(foo, abr, baz);
    |          ^^^
 
 error: environment variable `RUST_HOPEFULLY_THIS_DOESNT_EXIST` not defined
-  --> $DIR/macros-nonfatal-errors.rs:20:5
+  --> $DIR/macros-nonfatal-errors.rs:21:5
    |
 LL |     env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: format argument must be a string literal
-  --> $DIR/macros-nonfatal-errors.rs:22:13
+  --> $DIR/macros-nonfatal-errors.rs:23:13
    |
 LL |     format!(invalid);
    |             ^^^^^^^
@@ -54,19 +60,19 @@ LL |     format!("{}", invalid);
    |             ^^^^^
 
 error: argument must be a string literal
-  --> $DIR/macros-nonfatal-errors.rs:24:14
+  --> $DIR/macros-nonfatal-errors.rs:25:14
    |
 LL |     include!(invalid);
    |              ^^^^^^^
 
 error: argument must be a string literal
-  --> $DIR/macros-nonfatal-errors.rs:26:18
+  --> $DIR/macros-nonfatal-errors.rs:27:18
    |
 LL |     include_str!(invalid);
    |                  ^^^^^^^
 
 error: couldn't read $DIR/i'd be quite surprised if a file with this name existed: $FILE_NOT_FOUND_MSG (os error 2)
-  --> $DIR/macros-nonfatal-errors.rs:27:5
+  --> $DIR/macros-nonfatal-errors.rs:28:5
    |
 LL |     include_str!("i'd be quite surprised if a file with this name existed");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -74,13 +80,13 @@ LL |     include_str!("i'd be quite surprised if a file with this name existed")
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: argument must be a string literal
-  --> $DIR/macros-nonfatal-errors.rs:28:20
+  --> $DIR/macros-nonfatal-errors.rs:29:20
    |
 LL |     include_bytes!(invalid);
    |                    ^^^^^^^
 
 error: couldn't read $DIR/i'd be quite surprised if a file with this name existed: $FILE_NOT_FOUND_MSG (os error 2)
-  --> $DIR/macros-nonfatal-errors.rs:29:5
+  --> $DIR/macros-nonfatal-errors.rs:30:5
    |
 LL |     include_bytes!("i'd be quite surprised if a file with this name existed");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -88,11 +94,11 @@ LL |     include_bytes!("i'd be quite surprised if a file with this name existed
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: trace_macros! accepts only `true` or `false`
-  --> $DIR/macros-nonfatal-errors.rs:31:5
+  --> $DIR/macros-nonfatal-errors.rs:32:5
    |
 LL |     trace_macros!(invalid);
    |     ^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 14 previous errors
+error: aborting due to 15 previous errors
 
 For more information about this error, try `rustc --explain E0665`.
diff --git a/src/test/ui/target-feature/gate.stderr b/src/test/ui/target-feature/gate.stderr
index 848538a4e92..2384a00aa47 100644
--- a/src/test/ui/target-feature/gate.stderr
+++ b/src/test/ui/target-feature/gate.stderr
@@ -1,5 +1,5 @@
 error[E0658]: the target feature `avx512bw` is currently unstable
-  --> $DIR/gate.rs:29:18
+  --> $DIR/gate.rs:30:18
    |
 LL | #[target_feature(enable = "avx512bw")]
    |                  ^^^^^^^^^^^^^^^^^^^