From 0f8ebba54a8e41a9daccbbedae88e8798f4557c3 Mon Sep 17 00:00:00 2001
From: Taiki Endo <te316e89@gmail.com>
Date: Fri, 29 Nov 2024 00:24:36 +0900
Subject: [PATCH 1/2] Support #[repr(simd)] types in input/output of PowerPC
 inline assembly

---
 compiler/rustc_codegen_gcc/src/asm.rs         |  10 +-
 compiler/rustc_codegen_llvm/src/asm.rs        |  10 +-
 compiler/rustc_span/src/symbol.rs             |   2 +
 compiler/rustc_target/src/asm/powerpc.rs      |   6 +-
 .../asm-experimental-arch.md                  |   6 +-
 tests/assembly/asm/powerpc-types.rs           | 237 +++++++++++++++++-
 tests/codegen/asm/powerpc-clobbers.rs         |  13 +-
 tests/ui/asm/powerpc/bad-reg.aix64.stderr     | 136 +++++-----
 tests/ui/asm/powerpc/bad-reg.powerpc.stderr   | 172 +++++++------
 tests/ui/asm/powerpc/bad-reg.powerpc64.stderr | 160 ++++++------
 .../ui/asm/powerpc/bad-reg.powerpc64le.stderr | 136 +++++-----
 tests/ui/asm/powerpc/bad-reg.rs               |  59 +++--
 12 files changed, 595 insertions(+), 352 deletions(-)

diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs
index 341d1b9c179b7..a1f9eab10e76b 100644
--- a/compiler/rustc_codegen_gcc/src/asm.rs
+++ b/compiler/rustc_codegen_gcc/src/asm.rs
@@ -656,9 +656,9 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister {
             InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg) => "r",
             InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => "b",
             InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => "f",
+            InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::vreg) => "v",
             InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr)
-            | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer)
-            | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::vreg) => {
+            | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => {
                 unreachable!("clobber-only")
             }
             InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => "r",
@@ -736,9 +736,11 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl
         InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg) => cx.type_i32(),
         InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => cx.type_i32(),
         InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => cx.type_f64(),
+        InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::vreg) => {
+            cx.type_vector(cx.type_i32(), 4)
+        }
         InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr)
-        | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer)
-        | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::vreg) => {
+        | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => {
             unreachable!("clobber-only")
         }
         InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(),
diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs
index 9aa01bd1b956c..1483d576362b2 100644
--- a/compiler/rustc_codegen_llvm/src/asm.rs
+++ b/compiler/rustc_codegen_llvm/src/asm.rs
@@ -656,9 +656,8 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) ->
             PowerPC(PowerPCInlineAsmRegClass::reg) => "r",
             PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => "b",
             PowerPC(PowerPCInlineAsmRegClass::freg) => "f",
-            PowerPC(PowerPCInlineAsmRegClass::cr)
-            | PowerPC(PowerPCInlineAsmRegClass::xer)
-            | PowerPC(PowerPCInlineAsmRegClass::vreg) => {
+            PowerPC(PowerPCInlineAsmRegClass::vreg) => "v",
+            PowerPC(PowerPCInlineAsmRegClass::cr) | PowerPC(PowerPCInlineAsmRegClass::xer) => {
                 unreachable!("clobber-only")
             }
             RiscV(RiscVInlineAsmRegClass::reg) => "r",
@@ -825,9 +824,8 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &'
         PowerPC(PowerPCInlineAsmRegClass::reg) => cx.type_i32(),
         PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => cx.type_i32(),
         PowerPC(PowerPCInlineAsmRegClass::freg) => cx.type_f64(),
-        PowerPC(PowerPCInlineAsmRegClass::cr)
-        | PowerPC(PowerPCInlineAsmRegClass::xer)
-        | PowerPC(PowerPCInlineAsmRegClass::vreg) => {
+        PowerPC(PowerPCInlineAsmRegClass::vreg) => cx.type_vector(cx.type_i32(), 4),
+        PowerPC(PowerPCInlineAsmRegClass::cr) | PowerPC(PowerPCInlineAsmRegClass::xer) => {
             unreachable!("clobber-only")
         }
         RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(),
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 3a07c283e0ebb..6cd754a47e940 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -392,6 +392,7 @@ symbols! {
         allow_fail,
         allow_internal_unsafe,
         allow_internal_unstable,
+        altivec,
         alu32,
         always,
         and,
@@ -2154,6 +2155,7 @@ symbols! {
         volatile_store,
         vreg,
         vreg_low16,
+        vsx,
         vtable_align,
         vtable_size,
         warn,
diff --git a/compiler/rustc_target/src/asm/powerpc.rs b/compiler/rustc_target/src/asm/powerpc.rs
index aa8b26170bee1..a5a96b87e367a 100644
--- a/compiler/rustc_target/src/asm/powerpc.rs
+++ b/compiler/rustc_target/src/asm/powerpc.rs
@@ -51,7 +51,11 @@ impl PowerPCInlineAsmRegClass {
                 }
             }
             Self::freg => types! { _: F32, F64; },
-            Self::vreg => &[],
+            // FIXME: vsx also supports integers and floats: https://github.com/rust-lang/rust/pull/131551#discussion_r1797651773
+            Self::vreg => types! {
+                altivec: VecI8(16), VecI16(8), VecI32(4), VecF32(4);
+                vsx: VecI64(2), VecF64(2);
+            },
             Self::cr | Self::xer => &[],
         }
     }
diff --git a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md
index 12a73f0508b21..f2d0caa5e37cc 100644
--- a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md
+++ b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md
@@ -34,7 +34,7 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
 | PowerPC      | `reg`          | `r0`, `r[3-12]`, `r[14-28]`        | `r`                  |
 | PowerPC      | `reg_nonzero`  | `r[3-12]`, `r[14-28]`              | `b`                  |
 | PowerPC      | `freg`         | `f[0-31]`                          | `f`                  |
-| PowerPC      | `vreg`         | `v[0-31]`                          | Only clobbers        |
+| PowerPC      | `vreg`         | `v[0-31]`                          | `v`                  |
 | PowerPC      | `cr`           | `cr[0-7]`, `cr`                    | Only clobbers        |
 | PowerPC      | `xer`          | `xer`                              | Only clobbers        |
 | wasm32       | `local`        | None\*                             | `r`                  |
@@ -75,7 +75,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
 | PowerPC      | `reg`                           | None           | `i8`, `i16`, `i32`, `i64` (powerpc64 only) |
 | PowerPC      | `reg_nonzero`                   | None           | `i8`, `i16`, `i32`, `i64` (powerpc64 only) |
 | PowerPC      | `freg`                          | None           | `f32`, `f64`                            |
-| PowerPC      | `vreg`                          | N/A            | Only clobbers                           |
+| PowerPC      | `vreg`                          | `altivec`      | `i8x16`, `i16x8`, `i32x4`, `f32x4`      |
+| PowerPC      | `vreg`                          | `vsx`          | `i64x2`, `f64x2`                        |
 | PowerPC      | `cr`                            | N/A            | Only clobbers                           |
 | PowerPC      | `xer`                           | N/A            | Only clobbers                           |
 | wasm32       | `local`                         | None           | `i8` `i16` `i32` `i64` `f32` `f64`      |
@@ -181,6 +182,7 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
 | PowerPC      | `reg`          | None     | `0`            | None          |
 | PowerPC      | `reg_nonzero`  | None     | `3`            | None          |
 | PowerPC      | `freg`         | None     | `0`            | None          |
+| PowerPC      | `vreg`         | None     | `0`            | None          |
 | SPARC        | `reg`          | None     | `%o0`          | None          |
 | CSKY         | `reg`          | None     | `r0`           | None          |
 | CSKY         | `freg`         | None     | `f0`           | None          |
diff --git a/tests/assembly/asm/powerpc-types.rs b/tests/assembly/asm/powerpc-types.rs
index 85321e5f345ad..d67e0f66f66f5 100644
--- a/tests/assembly/asm/powerpc-types.rs
+++ b/tests/assembly/asm/powerpc-types.rs
@@ -1,9 +1,15 @@
-//@ revisions: powerpc powerpc64
+//@ revisions: powerpc powerpc_altivec powerpc_vsx powerpc64 powerpc64_vsx
 //@ assembly-output: emit-asm
 //@[powerpc] compile-flags: --target powerpc-unknown-linux-gnu
 //@[powerpc] needs-llvm-components: powerpc
-//@[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu
+//@[powerpc_altivec] compile-flags: --target powerpc-unknown-linux-gnu -C target-feature=+altivec --cfg altivec
+//@[powerpc_altivec] needs-llvm-components: powerpc
+//@[powerpc_vsx] compile-flags: --target powerpc-unknown-linux-gnu -C target-feature=+altivec,+vsx --cfg altivec --cfg vsx
+//@[powerpc_vsx] needs-llvm-components: powerpc
+//@[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu --cfg altivec
 //@[powerpc64] needs-llvm-components: powerpc
+//@[powerpc64_vsx] compile-flags: --target powerpc64-unknown-linux-gnu -C target-feature=+vsx --cfg altivec --cfg vsx
+//@[powerpc64_vsx] needs-llvm-components: powerpc
 //@ compile-flags: -Zmerge-functions=disabled
 
 #![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)]
@@ -11,6 +17,13 @@
 #![no_core]
 #![allow(asm_sub_register, non_camel_case_types)]
 
+#[cfg_attr(altivec, cfg(not(target_feature = "altivec")))]
+#[cfg_attr(not(altivec), cfg(target_feature = "altivec"))]
+compile_error!("altivec cfg and target feature mismatch");
+#[cfg_attr(vsx, cfg(not(target_feature = "vsx")))]
+#[cfg_attr(not(vsx), cfg(target_feature = "vsx"))]
+compile_error!("vsx cfg and target feature mismatch");
+
 #[rustc_builtin_macro]
 macro_rules! asm {
     () => {};
@@ -29,8 +42,23 @@ trait Sized {}
 #[lang = "copy"]
 trait Copy {}
 
+impl<T: Copy, const N: usize> Copy for [T; N] {}
+
 type ptr = *const i32;
 
+#[repr(simd)]
+pub struct i8x16([i8; 16]);
+#[repr(simd)]
+pub struct i16x8([i16; 8]);
+#[repr(simd)]
+pub struct i32x4([i32; 4]);
+#[repr(simd)]
+pub struct i64x2([i64; 2]);
+#[repr(simd)]
+pub struct f32x4([f32; 4]);
+#[repr(simd)]
+pub struct f64x2([f64; 2]);
+
 impl Copy for i8 {}
 impl Copy for u8 {}
 impl Copy for i16 {}
@@ -39,6 +67,13 @@ impl Copy for i64 {}
 impl Copy for f32 {}
 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 {}
+
 extern "C" {
     fn extern_func();
     static extern_static: u8;
@@ -124,6 +159,72 @@ check!(reg_f32, f32, freg, "fmr");
 // CHECK: #NO_APP
 check!(reg_f64, f64, freg, "fmr");
 
+// powerpc_altivec-LABEL: vreg_i8x16:
+// powerpc_altivec: #APP
+// powerpc_altivec: vmr {{[0-9]+}}, {{[0-9]+}}
+// powerpc_altivec: #NO_APP
+// powerpc64-LABEL: vreg_i8x16:
+// powerpc64: #APP
+// powerpc64: vmr {{[0-9]+}}, {{[0-9]+}}
+// powerpc64: #NO_APP
+#[cfg(altivec)]
+check!(vreg_i8x16, i8x16, vreg, "vmr");
+
+// powerpc_altivec-LABEL: vreg_i16x8:
+// powerpc_altivec: #APP
+// powerpc_altivec: vmr {{[0-9]+}}, {{[0-9]+}}
+// powerpc_altivec: #NO_APP
+// powerpc64-LABEL: vreg_i16x8:
+// powerpc64: #APP
+// powerpc64: vmr {{[0-9]+}}, {{[0-9]+}}
+// powerpc64: #NO_APP
+#[cfg(altivec)]
+check!(vreg_i16x8, i16x8, vreg, "vmr");
+
+// powerpc_altivec-LABEL: vreg_i32x4:
+// powerpc_altivec: #APP
+// powerpc_altivec: vmr {{[0-9]+}}, {{[0-9]+}}
+// powerpc_altivec: #NO_APP
+// powerpc64-LABEL: vreg_i32x4:
+// powerpc64: #APP
+// powerpc64: vmr {{[0-9]+}}, {{[0-9]+}}
+// powerpc64: #NO_APP
+#[cfg(altivec)]
+check!(vreg_i32x4, i32x4, vreg, "vmr");
+
+// powerpc_vsx-LABEL: vreg_i64x2:
+// powerpc_vsx: #APP
+// powerpc_vsx: vmr {{[0-9]+}}, {{[0-9]+}}
+// powerpc_vsx: #NO_APP
+// powerpc64_vsx-LABEL: vreg_i64x2:
+// powerpc64_vsx: #APP
+// powerpc64_vsx: vmr {{[0-9]+}}, {{[0-9]+}}
+// powerpc64_vsx: #NO_APP
+#[cfg(vsx)]
+check!(vreg_i64x2, i64x2, vreg, "vmr");
+
+// powerpc_altivec-LABEL: vreg_f32x4:
+// powerpc_altivec: #APP
+// powerpc_altivec: vmr {{[0-9]+}}, {{[0-9]+}}
+// powerpc_altivec: #NO_APP
+// powerpc64-LABEL: vreg_f32x4:
+// powerpc64: #APP
+// powerpc64: vmr {{[0-9]+}}, {{[0-9]+}}
+// powerpc64: #NO_APP
+#[cfg(altivec)]
+check!(vreg_f32x4, f32x4, vreg, "vmr");
+
+// powerpc_vsx-LABEL: vreg_f64x2:
+// powerpc_vsx: #APP
+// powerpc_vsx: vmr {{[0-9]+}}, {{[0-9]+}}
+// powerpc_vsx: #NO_APP
+// powerpc64_vsx-LABEL: vreg_f64x2:
+// powerpc64_vsx: #APP
+// powerpc64_vsx: vmr {{[0-9]+}}, {{[0-9]+}}
+// powerpc64_vsx: #NO_APP
+#[cfg(vsx)]
+check!(vreg_f64x2, f64x2, vreg, "vmr");
+
 // CHECK-LABEL: reg_i8_r0:
 // CHECK: #APP
 // CHECK: mr 0, 0
@@ -197,3 +298,135 @@ check_reg!(reg_f32_f18, f32, "18", "f18", "fmr");
 // CHECK: fmr 18, 18
 // CHECK: #NO_APP
 check_reg!(reg_f64_f18, f64, "18", "f18", "fmr");
+
+// powerpc_altivec-LABEL: vreg_i8x16_v0:
+// powerpc_altivec: #APP
+// powerpc_altivec: vmr 0, 0
+// powerpc_altivec: #NO_APP
+// powerpc64-LABEL: vreg_i8x16_v0:
+// powerpc64: #APP
+// powerpc64: vmr 0, 0
+// powerpc64: #NO_APP
+#[cfg(altivec)]
+check_reg!(vreg_i8x16_v0, i8x16, "0", "v0", "vmr");
+
+// powerpc_altivec-LABEL: vreg_i16x8_v0:
+// powerpc_altivec: #APP
+// powerpc_altivec: vmr 0, 0
+// powerpc_altivec: #NO_APP
+// powerpc64-LABEL: vreg_i16x8_v0:
+// powerpc64: #APP
+// powerpc64: vmr 0, 0
+// powerpc64: #NO_APP
+#[cfg(altivec)]
+check_reg!(vreg_i16x8_v0, i16x8, "0", "v0", "vmr");
+
+// powerpc_altivec-LABEL: vreg_i32x4_v0:
+// powerpc_altivec: #APP
+// powerpc_altivec: vmr 0, 0
+// powerpc_altivec: #NO_APP
+// powerpc64-LABEL: vreg_i32x4_v0:
+// powerpc64: #APP
+// powerpc64: vmr 0, 0
+// powerpc64: #NO_APP
+#[cfg(altivec)]
+check_reg!(vreg_i32x4_v0, i32x4, "0", "v0", "vmr");
+
+// powerpc_vsx-LABEL: vreg_i64x2_v0:
+// powerpc_vsx: #APP
+// powerpc_vsx: vmr 0, 0
+// powerpc_vsx: #NO_APP
+// powerpc64_vsx-LABEL: vreg_i64x2_v0:
+// powerpc64_vsx: #APP
+// powerpc64_vsx: vmr 0, 0
+// powerpc64_vsx: #NO_APP
+#[cfg(vsx)]
+check_reg!(vreg_i64x2_v0, i64x2, "0", "v0", "vmr");
+
+// powerpc_altivec-LABEL: vreg_f32x4_v0:
+// powerpc_altivec: #APP
+// powerpc_altivec: vmr 0, 0
+// powerpc_altivec: #NO_APP
+// powerpc64-LABEL: vreg_f32x4_v0:
+// powerpc64: #APP
+// powerpc64: vmr 0, 0
+// powerpc64: #NO_APP
+#[cfg(altivec)]
+check_reg!(vreg_f32x4_v0, f32x4, "0", "v0", "vmr");
+
+// powerpc_vsx-LABEL: vreg_f64x2_v0:
+// powerpc_vsx: #APP
+// powerpc_vsx: vmr 0, 0
+// powerpc_vsx: #NO_APP
+// powerpc64_vsx-LABEL: vreg_f64x2_v0:
+// powerpc64_vsx: #APP
+// powerpc64_vsx: vmr 0, 0
+// powerpc64_vsx: #NO_APP
+#[cfg(vsx)]
+check_reg!(vreg_f64x2_v0, f64x2, "0", "v0", "vmr");
+
+// powerpc_altivec-LABEL: vreg_i8x16_v18:
+// powerpc_altivec: #APP
+// powerpc_altivec: vmr 18, 18
+// powerpc_altivec: #NO_APP
+// powerpc64-LABEL: vreg_i8x16_v18:
+// powerpc64: #APP
+// powerpc64: vmr 18, 18
+// powerpc64: #NO_APP
+#[cfg(altivec)]
+check_reg!(vreg_i8x16_v18, i8x16, "18", "v18", "vmr");
+
+// powerpc_altivec-LABEL: vreg_i16x8_v18:
+// powerpc_altivec: #APP
+// powerpc_altivec: vmr 18, 18
+// powerpc_altivec: #NO_APP
+// powerpc64-LABEL: vreg_i16x8_v18:
+// powerpc64: #APP
+// powerpc64: vmr 18, 18
+// powerpc64: #NO_APP
+#[cfg(altivec)]
+check_reg!(vreg_i16x8_v18, i16x8, "18", "v18", "vmr");
+
+// powerpc_altivec-LABEL: vreg_i32x4_v18:
+// powerpc_altivec: #APP
+// powerpc_altivec: vmr 18, 18
+// powerpc_altivec: #NO_APP
+// powerpc64-LABEL: vreg_i32x4_v18:
+// powerpc64: #APP
+// powerpc64: vmr 18, 18
+// powerpc64: #NO_APP
+#[cfg(altivec)]
+check_reg!(vreg_i32x4_v18, i32x4, "18", "v18", "vmr");
+
+// powerpc_vsx-LABEL: vreg_i64x2_v18:
+// powerpc_vsx: #APP
+// powerpc_vsx: vmr 18, 18
+// powerpc_vsx: #NO_APP
+// powerpc64_vsx-LABEL: vreg_i64x2_v18:
+// powerpc64_vsx: #APP
+// powerpc64_vsx: vmr 18, 18
+// powerpc64_vsx: #NO_APP
+#[cfg(vsx)]
+check_reg!(vreg_i64x2_v18, i64x2, "18", "v18", "vmr");
+
+// powerpc_altivec-LABEL: vreg_f32x4_v18:
+// powerpc_altivec: #APP
+// powerpc_altivec: vmr 18, 18
+// powerpc_altivec: #NO_APP
+// powerpc64-LABEL: vreg_f32x4_v18:
+// powerpc64: #APP
+// powerpc64: vmr 18, 18
+// powerpc64: #NO_APP
+#[cfg(altivec)]
+check_reg!(vreg_f32x4_v18, f32x4, "18", "v18", "vmr");
+
+// powerpc_vsx-LABEL: vreg_f64x2_v18:
+// powerpc_vsx: #APP
+// powerpc_vsx: vmr 18, 18
+// powerpc_vsx: #NO_APP
+// powerpc64_vsx-LABEL: vreg_f64x2_v18:
+// powerpc64_vsx: #APP
+// powerpc64_vsx: vmr 18, 18
+// powerpc64_vsx: #NO_APP
+#[cfg(vsx)]
+check_reg!(vreg_f64x2_v18, f64x2, "18", "v18", "vmr");
diff --git a/tests/codegen/asm/powerpc-clobbers.rs b/tests/codegen/asm/powerpc-clobbers.rs
index e97e8300ca74b..2832377cef00d 100644
--- a/tests/codegen/asm/powerpc-clobbers.rs
+++ b/tests/codegen/asm/powerpc-clobbers.rs
@@ -7,6 +7,7 @@
 //@[powerpc64le] needs-llvm-components: powerpc
 //@[aix64] compile-flags: --target powerpc64-ibm-aix
 //@[aix64] needs-llvm-components: powerpc
+// ignore-tidy-linelength
 
 #![crate_type = "rlib"]
 #![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)]
@@ -48,15 +49,23 @@ pub unsafe fn xer_clobber() {
     asm!("", out("xer") _, options(nostack, nomem, preserves_flags));
 }
 
+// Output format depends on the availability of altivec.
 // CHECK-LABEL: @v0_clobber
-// CHECK: call void asm sideeffect "", "~{v0}"()
+// powerpc: call void asm sideeffect "", "~{v0}"()
+// powerpc64: call <4 x i32> asm sideeffect "", "=&{v0}"()
+// powerpc64le: call <4 x i32> asm sideeffect "", "=&{v0}"()
+// aix64: call <4 x i32> asm sideeffect "", "=&{v0}"()
 #[no_mangle]
 pub unsafe fn v0_clobber() {
     asm!("", out("v0") _, options(nostack, nomem, preserves_flags));
 }
 
+// Output format depends on the availability of altivec.
 // CHECK-LABEL: @clobber_abi
-// CHECK: asm sideeffect "", "={r0},={r3},={r4},={r5},={r6},={r7},={r8},={r9},={r10},={r11},={r12},={f0},={f1},={f2},={f3},={f4},={f5},={f6},={f7},={f8},={f9},={f10},={f11},={f12},={f13},~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7},~{v8},~{v9},~{v10},~{v11},~{v12},~{v13},~{v14},~{v15},~{v16},~{v17},~{v18},~{v19},~{cr0},~{cr1},~{cr5},~{cr6},~{cr7},~{xer}"()
+// powerpc: asm sideeffect "", "={r0},={r3},={r4},={r5},={r6},={r7},={r8},={r9},={r10},={r11},={r12},={f0},={f1},={f2},={f3},={f4},={f5},={f6},={f7},={f8},={f9},={f10},={f11},={f12},={f13},~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7},~{v8},~{v9},~{v10},~{v11},~{v12},~{v13},~{v14},~{v15},~{v16},~{v17},~{v18},~{v19},~{cr0},~{cr1},~{cr5},~{cr6},~{cr7},~{xer}"()
+// powerpc64: asm sideeffect "", "={r0},={r3},={r4},={r5},={r6},={r7},={r8},={r9},={r10},={r11},={r12},={f0},={f1},={f2},={f3},={f4},={f5},={f6},={f7},={f8},={f9},={f10},={f11},={f12},={f13},={v0},={v1},={v2},={v3},={v4},={v5},={v6},={v7},={v8},={v9},={v10},={v11},={v12},={v13},={v14},={v15},={v16},={v17},={v18},={v19},~{cr0},~{cr1},~{cr5},~{cr6},~{cr7},~{xer}"()
+// powerpc64le: asm sideeffect "", "={r0},={r3},={r4},={r5},={r6},={r7},={r8},={r9},={r10},={r11},={r12},={f0},={f1},={f2},={f3},={f4},={f5},={f6},={f7},={f8},={f9},={f10},={f11},={f12},={f13},={v0},={v1},={v2},={v3},={v4},={v5},={v6},={v7},={v8},={v9},={v10},={v11},={v12},={v13},={v14},={v15},={v16},={v17},={v18},={v19},~{cr0},~{cr1},~{cr5},~{cr6},~{cr7},~{xer}"()
+// aix64: asm sideeffect "", "={r0},={r3},={r4},={r5},={r6},={r7},={r8},={r9},={r10},={r11},={r12},={f0},={f1},={f2},={f3},={f4},={f5},={f6},={f7},={f8},={f9},={f10},={f11},={f12},={f13},={v0},={v1},={v2},={v3},={v4},={v5},={v6},={v7},={v8},={v9},={v10},={v11},={v12},={v13},={v14},={v15},={v16},={v17},={v18},={v19},~{cr0},~{cr1},~{cr5},~{cr6},~{cr7},~{xer}"()
 #[no_mangle]
 pub unsafe fn clobber_abi() {
     asm!("", clobber_abi("C"), options(nostack, nomem, preserves_flags));
diff --git a/tests/ui/asm/powerpc/bad-reg.aix64.stderr b/tests/ui/asm/powerpc/bad-reg.aix64.stderr
index 34105ceac049b..332bdf0ff5469 100644
--- a/tests/ui/asm/powerpc/bad-reg.aix64.stderr
+++ b/tests/ui/asm/powerpc/bad-reg.aix64.stderr
@@ -1,125 +1,101 @@
 error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:32:18
+  --> $DIR/bad-reg.rs:45:18
    |
 LL |         asm!("", out("sp") _);
    |                  ^^^^^^^^^^^
 
 error: invalid register `r2`: r2 is a system reserved register and cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:34:18
+  --> $DIR/bad-reg.rs:47:18
    |
 LL |         asm!("", out("r2") _);
    |                  ^^^^^^^^^^^
 
 error: invalid register `r29`: r29 is used internally by LLVM and cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:38:18
+  --> $DIR/bad-reg.rs:51:18
    |
 LL |         asm!("", out("r29") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `r30`: r30 is used internally by LLVM and cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:40:18
+  --> $DIR/bad-reg.rs:53:18
    |
 LL |         asm!("", out("r30") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:42:18
+  --> $DIR/bad-reg.rs:55:18
    |
 LL |         asm!("", out("fp") _);
    |                  ^^^^^^^^^^^
 
 error: invalid register `lr`: the link register cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:44:18
+  --> $DIR/bad-reg.rs:57:18
    |
 LL |         asm!("", out("lr") _);
    |                  ^^^^^^^^^^^
 
 error: invalid register `ctr`: the counter register cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:46:18
+  --> $DIR/bad-reg.rs:59:18
    |
 LL |         asm!("", out("ctr") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:48:18
+  --> $DIR/bad-reg.rs:61:18
    |
 LL |         asm!("", out("vrsave") _);
    |                  ^^^^^^^^^^^^^^^
 
 error: register class `cr` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:66:18
+  --> $DIR/bad-reg.rs:109:18
    |
 LL |         asm!("", in("cr") x);
    |                  ^^^^^^^^^^
 
 error: register class `cr` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:69:18
+  --> $DIR/bad-reg.rs:112:18
    |
 LL |         asm!("", out("cr") x);
    |                  ^^^^^^^^^^^
 
 error: register class `cr` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:72:26
+  --> $DIR/bad-reg.rs:115:26
    |
 LL |         asm!("/* {} */", in(cr) x);
    |                          ^^^^^^^^
 
 error: register class `cr` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:75:26
+  --> $DIR/bad-reg.rs:118:26
    |
 LL |         asm!("/* {} */", out(cr) _);
    |                          ^^^^^^^^^
 
 error: register class `xer` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:79:18
+  --> $DIR/bad-reg.rs:122:18
    |
 LL |         asm!("", in("xer") x);
    |                  ^^^^^^^^^^^
 
 error: register class `xer` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:82:18
+  --> $DIR/bad-reg.rs:125:18
    |
 LL |         asm!("", out("xer") x);
    |                  ^^^^^^^^^^^^
 
 error: register class `xer` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:85:26
+  --> $DIR/bad-reg.rs:128:26
    |
 LL |         asm!("/* {} */", in(xer) x);
    |                          ^^^^^^^^^
 
 error: register class `xer` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:88:26
+  --> $DIR/bad-reg.rs:131:26
    |
 LL |         asm!("/* {} */", out(xer) _);
    |                          ^^^^^^^^^^
 
-error: register class `vreg` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:93:18
-   |
-LL |         asm!("", in("v0") x);
-   |                  ^^^^^^^^^^
-
-error: register class `vreg` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:96:18
-   |
-LL |         asm!("", out("v0") x);
-   |                  ^^^^^^^^^^^
-
-error: register class `vreg` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:99:26
-   |
-LL |         asm!("/* {} */", in(vreg) x);
-   |                          ^^^^^^^^^^
-
-error: register class `vreg` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:102:26
-   |
-LL |         asm!("/* {} */", out(vreg) _);
-   |                          ^^^^^^^^^^^
-
 error: register `cr0` conflicts with register `cr`
-  --> $DIR/bad-reg.rs:106:31
+  --> $DIR/bad-reg.rs:135:31
    |
 LL |         asm!("", out("cr") _, out("cr0") _);
    |                  -----------  ^^^^^^^^^^^^ register `cr0`
@@ -127,7 +103,7 @@ LL |         asm!("", out("cr") _, out("cr0") _);
    |                  register `cr`
 
 error: register `cr1` conflicts with register `cr`
-  --> $DIR/bad-reg.rs:108:31
+  --> $DIR/bad-reg.rs:137:31
    |
 LL |         asm!("", out("cr") _, out("cr1") _);
    |                  -----------  ^^^^^^^^^^^^ register `cr1`
@@ -135,7 +111,7 @@ LL |         asm!("", out("cr") _, out("cr1") _);
    |                  register `cr`
 
 error: register `cr2` conflicts with register `cr`
-  --> $DIR/bad-reg.rs:110:31
+  --> $DIR/bad-reg.rs:139:31
    |
 LL |         asm!("", out("cr") _, out("cr2") _);
    |                  -----------  ^^^^^^^^^^^^ register `cr2`
@@ -143,7 +119,7 @@ LL |         asm!("", out("cr") _, out("cr2") _);
    |                  register `cr`
 
 error: register `cr3` conflicts with register `cr`
-  --> $DIR/bad-reg.rs:112:31
+  --> $DIR/bad-reg.rs:141:31
    |
 LL |         asm!("", out("cr") _, out("cr3") _);
    |                  -----------  ^^^^^^^^^^^^ register `cr3`
@@ -151,7 +127,7 @@ LL |         asm!("", out("cr") _, out("cr3") _);
    |                  register `cr`
 
 error: register `cr4` conflicts with register `cr`
-  --> $DIR/bad-reg.rs:114:31
+  --> $DIR/bad-reg.rs:143:31
    |
 LL |         asm!("", out("cr") _, out("cr4") _);
    |                  -----------  ^^^^^^^^^^^^ register `cr4`
@@ -159,7 +135,7 @@ LL |         asm!("", out("cr") _, out("cr4") _);
    |                  register `cr`
 
 error: register `cr5` conflicts with register `cr`
-  --> $DIR/bad-reg.rs:116:31
+  --> $DIR/bad-reg.rs:145:31
    |
 LL |         asm!("", out("cr") _, out("cr5") _);
    |                  -----------  ^^^^^^^^^^^^ register `cr5`
@@ -167,7 +143,7 @@ LL |         asm!("", out("cr") _, out("cr5") _);
    |                  register `cr`
 
 error: register `cr6` conflicts with register `cr`
-  --> $DIR/bad-reg.rs:118:31
+  --> $DIR/bad-reg.rs:147:31
    |
 LL |         asm!("", out("cr") _, out("cr6") _);
    |                  -----------  ^^^^^^^^^^^^ register `cr6`
@@ -175,7 +151,7 @@ LL |         asm!("", out("cr") _, out("cr6") _);
    |                  register `cr`
 
 error: register `cr7` conflicts with register `cr`
-  --> $DIR/bad-reg.rs:120:31
+  --> $DIR/bad-reg.rs:149:31
    |
 LL |         asm!("", out("cr") _, out("cr7") _);
    |                  -----------  ^^^^^^^^^^^^ register `cr7`
@@ -183,13 +159,37 @@ LL |         asm!("", out("cr") _, out("cr7") _);
    |                  register `cr`
 
 error: cannot use register `r13`: r13 is a reserved register on this target
-  --> $DIR/bad-reg.rs:36:18
+  --> $DIR/bad-reg.rs:49:18
    |
 LL |         asm!("", out("r13") _);
    |                  ^^^^^^^^^^^^
 
 error: type `i32` cannot be used with this register class
-  --> $DIR/bad-reg.rs:66:27
+  --> $DIR/bad-reg.rs:76:27
+   |
+LL |         asm!("", in("v0") x); // FIXME: should be ok if vsx is available
+   |                           ^
+   |
+   = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:79:28
+   |
+LL |         asm!("", out("v0") x); // FIXME: should be ok if vsx is available
+   |                            ^
+   |
+   = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:87:35
+   |
+LL |         asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is available
+   |                                   ^
+   |
+   = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:109:27
    |
 LL |         asm!("", in("cr") x);
    |                           ^
@@ -197,7 +197,7 @@ LL |         asm!("", in("cr") x);
    = note: register class `cr` supports these types: 
 
 error: type `i32` cannot be used with this register class
-  --> $DIR/bad-reg.rs:69:28
+  --> $DIR/bad-reg.rs:112:28
    |
 LL |         asm!("", out("cr") x);
    |                            ^
@@ -205,7 +205,7 @@ LL |         asm!("", out("cr") x);
    = note: register class `cr` supports these types: 
 
 error: type `i32` cannot be used with this register class
-  --> $DIR/bad-reg.rs:72:33
+  --> $DIR/bad-reg.rs:115:33
    |
 LL |         asm!("/* {} */", in(cr) x);
    |                                 ^
@@ -213,7 +213,7 @@ LL |         asm!("/* {} */", in(cr) x);
    = note: register class `cr` supports these types: 
 
 error: type `i32` cannot be used with this register class
-  --> $DIR/bad-reg.rs:79:28
+  --> $DIR/bad-reg.rs:122:28
    |
 LL |         asm!("", in("xer") x);
    |                            ^
@@ -221,7 +221,7 @@ LL |         asm!("", in("xer") x);
    = note: register class `xer` supports these types: 
 
 error: type `i32` cannot be used with this register class
-  --> $DIR/bad-reg.rs:82:29
+  --> $DIR/bad-reg.rs:125:29
    |
 LL |         asm!("", out("xer") x);
    |                             ^
@@ -229,36 +229,12 @@ LL |         asm!("", out("xer") x);
    = note: register class `xer` supports these types: 
 
 error: type `i32` cannot be used with this register class
-  --> $DIR/bad-reg.rs:85:34
+  --> $DIR/bad-reg.rs:128:34
    |
 LL |         asm!("/* {} */", in(xer) x);
    |                                  ^
    |
    = note: register class `xer` supports these types: 
 
-error: type `i32` cannot be used with this register class
-  --> $DIR/bad-reg.rs:93:27
-   |
-LL |         asm!("", in("v0") x);
-   |                           ^
-   |
-   = note: register class `vreg` supports these types: 
-
-error: type `i32` cannot be used with this register class
-  --> $DIR/bad-reg.rs:96:28
-   |
-LL |         asm!("", out("v0") x);
-   |                            ^
-   |
-   = note: register class `vreg` supports these types: 
-
-error: type `i32` cannot be used with this register class
-  --> $DIR/bad-reg.rs:99:35
-   |
-LL |         asm!("/* {} */", in(vreg) x);
-   |                                   ^
-   |
-   = note: register class `vreg` supports these types: 
-
-error: aborting due to 38 previous errors
+error: aborting due to 34 previous errors
 
diff --git a/tests/ui/asm/powerpc/bad-reg.powerpc.stderr b/tests/ui/asm/powerpc/bad-reg.powerpc.stderr
index 34105ceac049b..13fc5a048d82f 100644
--- a/tests/ui/asm/powerpc/bad-reg.powerpc.stderr
+++ b/tests/ui/asm/powerpc/bad-reg.powerpc.stderr
@@ -1,125 +1,101 @@
 error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:32:18
+  --> $DIR/bad-reg.rs:45:18
    |
 LL |         asm!("", out("sp") _);
    |                  ^^^^^^^^^^^
 
 error: invalid register `r2`: r2 is a system reserved register and cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:34:18
+  --> $DIR/bad-reg.rs:47:18
    |
 LL |         asm!("", out("r2") _);
    |                  ^^^^^^^^^^^
 
 error: invalid register `r29`: r29 is used internally by LLVM and cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:38:18
+  --> $DIR/bad-reg.rs:51:18
    |
 LL |         asm!("", out("r29") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `r30`: r30 is used internally by LLVM and cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:40:18
+  --> $DIR/bad-reg.rs:53:18
    |
 LL |         asm!("", out("r30") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:42:18
+  --> $DIR/bad-reg.rs:55:18
    |
 LL |         asm!("", out("fp") _);
    |                  ^^^^^^^^^^^
 
 error: invalid register `lr`: the link register cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:44:18
+  --> $DIR/bad-reg.rs:57:18
    |
 LL |         asm!("", out("lr") _);
    |                  ^^^^^^^^^^^
 
 error: invalid register `ctr`: the counter register cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:46:18
+  --> $DIR/bad-reg.rs:59:18
    |
 LL |         asm!("", out("ctr") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:48:18
+  --> $DIR/bad-reg.rs:61:18
    |
 LL |         asm!("", out("vrsave") _);
    |                  ^^^^^^^^^^^^^^^
 
 error: register class `cr` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:66:18
+  --> $DIR/bad-reg.rs:109:18
    |
 LL |         asm!("", in("cr") x);
    |                  ^^^^^^^^^^
 
 error: register class `cr` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:69:18
+  --> $DIR/bad-reg.rs:112:18
    |
 LL |         asm!("", out("cr") x);
    |                  ^^^^^^^^^^^
 
 error: register class `cr` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:72:26
+  --> $DIR/bad-reg.rs:115:26
    |
 LL |         asm!("/* {} */", in(cr) x);
    |                          ^^^^^^^^
 
 error: register class `cr` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:75:26
+  --> $DIR/bad-reg.rs:118:26
    |
 LL |         asm!("/* {} */", out(cr) _);
    |                          ^^^^^^^^^
 
 error: register class `xer` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:79:18
+  --> $DIR/bad-reg.rs:122:18
    |
 LL |         asm!("", in("xer") x);
    |                  ^^^^^^^^^^^
 
 error: register class `xer` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:82:18
+  --> $DIR/bad-reg.rs:125:18
    |
 LL |         asm!("", out("xer") x);
    |                  ^^^^^^^^^^^^
 
 error: register class `xer` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:85:26
+  --> $DIR/bad-reg.rs:128:26
    |
 LL |         asm!("/* {} */", in(xer) x);
    |                          ^^^^^^^^^
 
 error: register class `xer` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:88:26
+  --> $DIR/bad-reg.rs:131:26
    |
 LL |         asm!("/* {} */", out(xer) _);
    |                          ^^^^^^^^^^
 
-error: register class `vreg` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:93:18
-   |
-LL |         asm!("", in("v0") x);
-   |                  ^^^^^^^^^^
-
-error: register class `vreg` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:96:18
-   |
-LL |         asm!("", out("v0") x);
-   |                  ^^^^^^^^^^^
-
-error: register class `vreg` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:99:26
-   |
-LL |         asm!("/* {} */", in(vreg) x);
-   |                          ^^^^^^^^^^
-
-error: register class `vreg` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:102:26
-   |
-LL |         asm!("/* {} */", out(vreg) _);
-   |                          ^^^^^^^^^^^
-
 error: register `cr0` conflicts with register `cr`
-  --> $DIR/bad-reg.rs:106:31
+  --> $DIR/bad-reg.rs:135:31
    |
 LL |         asm!("", out("cr") _, out("cr0") _);
    |                  -----------  ^^^^^^^^^^^^ register `cr0`
@@ -127,7 +103,7 @@ LL |         asm!("", out("cr") _, out("cr0") _);
    |                  register `cr`
 
 error: register `cr1` conflicts with register `cr`
-  --> $DIR/bad-reg.rs:108:31
+  --> $DIR/bad-reg.rs:137:31
    |
 LL |         asm!("", out("cr") _, out("cr1") _);
    |                  -----------  ^^^^^^^^^^^^ register `cr1`
@@ -135,7 +111,7 @@ LL |         asm!("", out("cr") _, out("cr1") _);
    |                  register `cr`
 
 error: register `cr2` conflicts with register `cr`
-  --> $DIR/bad-reg.rs:110:31
+  --> $DIR/bad-reg.rs:139:31
    |
 LL |         asm!("", out("cr") _, out("cr2") _);
    |                  -----------  ^^^^^^^^^^^^ register `cr2`
@@ -143,7 +119,7 @@ LL |         asm!("", out("cr") _, out("cr2") _);
    |                  register `cr`
 
 error: register `cr3` conflicts with register `cr`
-  --> $DIR/bad-reg.rs:112:31
+  --> $DIR/bad-reg.rs:141:31
    |
 LL |         asm!("", out("cr") _, out("cr3") _);
    |                  -----------  ^^^^^^^^^^^^ register `cr3`
@@ -151,7 +127,7 @@ LL |         asm!("", out("cr") _, out("cr3") _);
    |                  register `cr`
 
 error: register `cr4` conflicts with register `cr`
-  --> $DIR/bad-reg.rs:114:31
+  --> $DIR/bad-reg.rs:143:31
    |
 LL |         asm!("", out("cr") _, out("cr4") _);
    |                  -----------  ^^^^^^^^^^^^ register `cr4`
@@ -159,7 +135,7 @@ LL |         asm!("", out("cr") _, out("cr4") _);
    |                  register `cr`
 
 error: register `cr5` conflicts with register `cr`
-  --> $DIR/bad-reg.rs:116:31
+  --> $DIR/bad-reg.rs:145:31
    |
 LL |         asm!("", out("cr") _, out("cr5") _);
    |                  -----------  ^^^^^^^^^^^^ register `cr5`
@@ -167,7 +143,7 @@ LL |         asm!("", out("cr") _, out("cr5") _);
    |                  register `cr`
 
 error: register `cr6` conflicts with register `cr`
-  --> $DIR/bad-reg.rs:118:31
+  --> $DIR/bad-reg.rs:147:31
    |
 LL |         asm!("", out("cr") _, out("cr6") _);
    |                  -----------  ^^^^^^^^^^^^ register `cr6`
@@ -175,7 +151,7 @@ LL |         asm!("", out("cr") _, out("cr6") _);
    |                  register `cr`
 
 error: register `cr7` conflicts with register `cr`
-  --> $DIR/bad-reg.rs:120:31
+  --> $DIR/bad-reg.rs:149:31
    |
 LL |         asm!("", out("cr") _, out("cr7") _);
    |                  -----------  ^^^^^^^^^^^^ register `cr7`
@@ -183,13 +159,73 @@ LL |         asm!("", out("cr") _, out("cr7") _);
    |                  register `cr`
 
 error: cannot use register `r13`: r13 is a reserved register on this target
-  --> $DIR/bad-reg.rs:36:18
+  --> $DIR/bad-reg.rs:49:18
    |
 LL |         asm!("", out("r13") _);
    |                  ^^^^^^^^^^^^
 
+error: register class `vreg` requires at least one of the following target features: altivec, vsx
+  --> $DIR/bad-reg.rs:66:18
+   |
+LL |         asm!("", in("v0") v32x4); // requires altivec
+   |                  ^^^^^^^^^^^^^^
+
+error: register class `vreg` requires at least one of the following target features: altivec, vsx
+  --> $DIR/bad-reg.rs:68:18
+   |
+LL |         asm!("", out("v0") v32x4); // requires altivec
+   |                  ^^^^^^^^^^^^^^^
+
+error: register class `vreg` requires at least one of the following target features: altivec, vsx
+  --> $DIR/bad-reg.rs:70:18
+   |
+LL |         asm!("", in("v0") v64x2); // requires vsx
+   |                  ^^^^^^^^^^^^^^
+
+error: register class `vreg` requires at least one of the following target features: altivec, vsx
+  --> $DIR/bad-reg.rs:73:18
+   |
+LL |         asm!("", out("v0") v64x2); // requires vsx
+   |                  ^^^^^^^^^^^^^^^
+
+error: register class `vreg` requires at least one of the following target features: altivec, vsx
+  --> $DIR/bad-reg.rs:76:18
+   |
+LL |         asm!("", in("v0") x); // FIXME: should be ok if vsx is available
+   |                  ^^^^^^^^^^
+
+error: register class `vreg` requires at least one of the following target features: altivec, vsx
+  --> $DIR/bad-reg.rs:79:18
+   |
+LL |         asm!("", out("v0") x); // FIXME: should be ok if vsx is available
+   |                  ^^^^^^^^^^^
+
+error: register class `vreg` requires at least one of the following target features: altivec, vsx
+  --> $DIR/bad-reg.rs:82:26
+   |
+LL |         asm!("/* {} */", in(vreg) v32x4); // requires altivec
+   |                          ^^^^^^^^^^^^^^
+
+error: register class `vreg` requires at least one of the following target features: altivec, vsx
+  --> $DIR/bad-reg.rs:84:26
+   |
+LL |         asm!("/* {} */", in(vreg) v64x2); // requires vsx
+   |                          ^^^^^^^^^^^^^^
+
+error: register class `vreg` requires at least one of the following target features: altivec, vsx
+  --> $DIR/bad-reg.rs:87:26
+   |
+LL |         asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is available
+   |                          ^^^^^^^^^^
+
+error: register class `vreg` requires at least one of the following target features: altivec, vsx
+  --> $DIR/bad-reg.rs:90:26
+   |
+LL |         asm!("/* {} */", out(vreg) _); // requires altivec
+   |                          ^^^^^^^^^^^
+
 error: type `i32` cannot be used with this register class
-  --> $DIR/bad-reg.rs:66:27
+  --> $DIR/bad-reg.rs:109:27
    |
 LL |         asm!("", in("cr") x);
    |                           ^
@@ -197,7 +233,7 @@ LL |         asm!("", in("cr") x);
    = note: register class `cr` supports these types: 
 
 error: type `i32` cannot be used with this register class
-  --> $DIR/bad-reg.rs:69:28
+  --> $DIR/bad-reg.rs:112:28
    |
 LL |         asm!("", out("cr") x);
    |                            ^
@@ -205,7 +241,7 @@ LL |         asm!("", out("cr") x);
    = note: register class `cr` supports these types: 
 
 error: type `i32` cannot be used with this register class
-  --> $DIR/bad-reg.rs:72:33
+  --> $DIR/bad-reg.rs:115:33
    |
 LL |         asm!("/* {} */", in(cr) x);
    |                                 ^
@@ -213,7 +249,7 @@ LL |         asm!("/* {} */", in(cr) x);
    = note: register class `cr` supports these types: 
 
 error: type `i32` cannot be used with this register class
-  --> $DIR/bad-reg.rs:79:28
+  --> $DIR/bad-reg.rs:122:28
    |
 LL |         asm!("", in("xer") x);
    |                            ^
@@ -221,7 +257,7 @@ LL |         asm!("", in("xer") x);
    = note: register class `xer` supports these types: 
 
 error: type `i32` cannot be used with this register class
-  --> $DIR/bad-reg.rs:82:29
+  --> $DIR/bad-reg.rs:125:29
    |
 LL |         asm!("", out("xer") x);
    |                             ^
@@ -229,36 +265,12 @@ LL |         asm!("", out("xer") x);
    = note: register class `xer` supports these types: 
 
 error: type `i32` cannot be used with this register class
-  --> $DIR/bad-reg.rs:85:34
+  --> $DIR/bad-reg.rs:128:34
    |
 LL |         asm!("/* {} */", in(xer) x);
    |                                  ^
    |
    = note: register class `xer` supports these types: 
 
-error: type `i32` cannot be used with this register class
-  --> $DIR/bad-reg.rs:93:27
-   |
-LL |         asm!("", in("v0") x);
-   |                           ^
-   |
-   = note: register class `vreg` supports these types: 
-
-error: type `i32` cannot be used with this register class
-  --> $DIR/bad-reg.rs:96:28
-   |
-LL |         asm!("", out("v0") x);
-   |                            ^
-   |
-   = note: register class `vreg` supports these types: 
-
-error: type `i32` cannot be used with this register class
-  --> $DIR/bad-reg.rs:99:35
-   |
-LL |         asm!("/* {} */", in(vreg) x);
-   |                                   ^
-   |
-   = note: register class `vreg` supports these types: 
-
-error: aborting due to 38 previous errors
+error: aborting due to 41 previous errors
 
diff --git a/tests/ui/asm/powerpc/bad-reg.powerpc64.stderr b/tests/ui/asm/powerpc/bad-reg.powerpc64.stderr
index 34105ceac049b..9e0dd80b3dca1 100644
--- a/tests/ui/asm/powerpc/bad-reg.powerpc64.stderr
+++ b/tests/ui/asm/powerpc/bad-reg.powerpc64.stderr
@@ -1,125 +1,101 @@
 error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:32:18
+  --> $DIR/bad-reg.rs:45:18
    |
 LL |         asm!("", out("sp") _);
    |                  ^^^^^^^^^^^
 
 error: invalid register `r2`: r2 is a system reserved register and cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:34:18
+  --> $DIR/bad-reg.rs:47:18
    |
 LL |         asm!("", out("r2") _);
    |                  ^^^^^^^^^^^
 
 error: invalid register `r29`: r29 is used internally by LLVM and cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:38:18
+  --> $DIR/bad-reg.rs:51:18
    |
 LL |         asm!("", out("r29") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `r30`: r30 is used internally by LLVM and cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:40:18
+  --> $DIR/bad-reg.rs:53:18
    |
 LL |         asm!("", out("r30") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:42:18
+  --> $DIR/bad-reg.rs:55:18
    |
 LL |         asm!("", out("fp") _);
    |                  ^^^^^^^^^^^
 
 error: invalid register `lr`: the link register cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:44:18
+  --> $DIR/bad-reg.rs:57:18
    |
 LL |         asm!("", out("lr") _);
    |                  ^^^^^^^^^^^
 
 error: invalid register `ctr`: the counter register cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:46:18
+  --> $DIR/bad-reg.rs:59:18
    |
 LL |         asm!("", out("ctr") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:48:18
+  --> $DIR/bad-reg.rs:61:18
    |
 LL |         asm!("", out("vrsave") _);
    |                  ^^^^^^^^^^^^^^^
 
 error: register class `cr` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:66:18
+  --> $DIR/bad-reg.rs:109:18
    |
 LL |         asm!("", in("cr") x);
    |                  ^^^^^^^^^^
 
 error: register class `cr` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:69:18
+  --> $DIR/bad-reg.rs:112:18
    |
 LL |         asm!("", out("cr") x);
    |                  ^^^^^^^^^^^
 
 error: register class `cr` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:72:26
+  --> $DIR/bad-reg.rs:115:26
    |
 LL |         asm!("/* {} */", in(cr) x);
    |                          ^^^^^^^^
 
 error: register class `cr` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:75:26
+  --> $DIR/bad-reg.rs:118:26
    |
 LL |         asm!("/* {} */", out(cr) _);
    |                          ^^^^^^^^^
 
 error: register class `xer` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:79:18
+  --> $DIR/bad-reg.rs:122:18
    |
 LL |         asm!("", in("xer") x);
    |                  ^^^^^^^^^^^
 
 error: register class `xer` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:82:18
+  --> $DIR/bad-reg.rs:125:18
    |
 LL |         asm!("", out("xer") x);
    |                  ^^^^^^^^^^^^
 
 error: register class `xer` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:85:26
+  --> $DIR/bad-reg.rs:128:26
    |
 LL |         asm!("/* {} */", in(xer) x);
    |                          ^^^^^^^^^
 
 error: register class `xer` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:88:26
+  --> $DIR/bad-reg.rs:131:26
    |
 LL |         asm!("/* {} */", out(xer) _);
    |                          ^^^^^^^^^^
 
-error: register class `vreg` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:93:18
-   |
-LL |         asm!("", in("v0") x);
-   |                  ^^^^^^^^^^
-
-error: register class `vreg` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:96:18
-   |
-LL |         asm!("", out("v0") x);
-   |                  ^^^^^^^^^^^
-
-error: register class `vreg` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:99:26
-   |
-LL |         asm!("/* {} */", in(vreg) x);
-   |                          ^^^^^^^^^^
-
-error: register class `vreg` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:102:26
-   |
-LL |         asm!("/* {} */", out(vreg) _);
-   |                          ^^^^^^^^^^^
-
 error: register `cr0` conflicts with register `cr`
-  --> $DIR/bad-reg.rs:106:31
+  --> $DIR/bad-reg.rs:135:31
    |
 LL |         asm!("", out("cr") _, out("cr0") _);
    |                  -----------  ^^^^^^^^^^^^ register `cr0`
@@ -127,7 +103,7 @@ LL |         asm!("", out("cr") _, out("cr0") _);
    |                  register `cr`
 
 error: register `cr1` conflicts with register `cr`
-  --> $DIR/bad-reg.rs:108:31
+  --> $DIR/bad-reg.rs:137:31
    |
 LL |         asm!("", out("cr") _, out("cr1") _);
    |                  -----------  ^^^^^^^^^^^^ register `cr1`
@@ -135,7 +111,7 @@ LL |         asm!("", out("cr") _, out("cr1") _);
    |                  register `cr`
 
 error: register `cr2` conflicts with register `cr`
-  --> $DIR/bad-reg.rs:110:31
+  --> $DIR/bad-reg.rs:139:31
    |
 LL |         asm!("", out("cr") _, out("cr2") _);
    |                  -----------  ^^^^^^^^^^^^ register `cr2`
@@ -143,7 +119,7 @@ LL |         asm!("", out("cr") _, out("cr2") _);
    |                  register `cr`
 
 error: register `cr3` conflicts with register `cr`
-  --> $DIR/bad-reg.rs:112:31
+  --> $DIR/bad-reg.rs:141:31
    |
 LL |         asm!("", out("cr") _, out("cr3") _);
    |                  -----------  ^^^^^^^^^^^^ register `cr3`
@@ -151,7 +127,7 @@ LL |         asm!("", out("cr") _, out("cr3") _);
    |                  register `cr`
 
 error: register `cr4` conflicts with register `cr`
-  --> $DIR/bad-reg.rs:114:31
+  --> $DIR/bad-reg.rs:143:31
    |
 LL |         asm!("", out("cr") _, out("cr4") _);
    |                  -----------  ^^^^^^^^^^^^ register `cr4`
@@ -159,7 +135,7 @@ LL |         asm!("", out("cr") _, out("cr4") _);
    |                  register `cr`
 
 error: register `cr5` conflicts with register `cr`
-  --> $DIR/bad-reg.rs:116:31
+  --> $DIR/bad-reg.rs:145:31
    |
 LL |         asm!("", out("cr") _, out("cr5") _);
    |                  -----------  ^^^^^^^^^^^^ register `cr5`
@@ -167,7 +143,7 @@ LL |         asm!("", out("cr") _, out("cr5") _);
    |                  register `cr`
 
 error: register `cr6` conflicts with register `cr`
-  --> $DIR/bad-reg.rs:118:31
+  --> $DIR/bad-reg.rs:147:31
    |
 LL |         asm!("", out("cr") _, out("cr6") _);
    |                  -----------  ^^^^^^^^^^^^ register `cr6`
@@ -175,7 +151,7 @@ LL |         asm!("", out("cr") _, out("cr6") _);
    |                  register `cr`
 
 error: register `cr7` conflicts with register `cr`
-  --> $DIR/bad-reg.rs:120:31
+  --> $DIR/bad-reg.rs:149:31
    |
 LL |         asm!("", out("cr") _, out("cr7") _);
    |                  -----------  ^^^^^^^^^^^^ register `cr7`
@@ -183,13 +159,61 @@ LL |         asm!("", out("cr") _, out("cr7") _);
    |                  register `cr`
 
 error: cannot use register `r13`: r13 is a reserved register on this target
-  --> $DIR/bad-reg.rs:36:18
+  --> $DIR/bad-reg.rs:49:18
    |
 LL |         asm!("", out("r13") _);
    |                  ^^^^^^^^^^^^
 
+error: `vsx` target feature is not enabled
+  --> $DIR/bad-reg.rs:70:27
+   |
+LL |         asm!("", in("v0") v64x2); // requires vsx
+   |                           ^^^^^
+   |
+   = note: this is required to use type `i64x2` with register class `vreg`
+
+error: `vsx` target feature is not enabled
+  --> $DIR/bad-reg.rs:73:28
+   |
+LL |         asm!("", out("v0") v64x2); // requires vsx
+   |                            ^^^^^
+   |
+   = note: this is required to use type `i64x2` with register class `vreg`
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:76:27
+   |
+LL |         asm!("", in("v0") x); // FIXME: should be ok if vsx is available
+   |                           ^
+   |
+   = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:79:28
+   |
+LL |         asm!("", out("v0") x); // FIXME: should be ok if vsx is available
+   |                            ^
+   |
+   = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2
+
+error: `vsx` target feature is not enabled
+  --> $DIR/bad-reg.rs:84:35
+   |
+LL |         asm!("/* {} */", in(vreg) v64x2); // requires vsx
+   |                                   ^^^^^
+   |
+   = note: this is required to use type `i64x2` with register class `vreg`
+
 error: type `i32` cannot be used with this register class
-  --> $DIR/bad-reg.rs:66:27
+  --> $DIR/bad-reg.rs:87:35
+   |
+LL |         asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is available
+   |                                   ^
+   |
+   = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:109:27
    |
 LL |         asm!("", in("cr") x);
    |                           ^
@@ -197,7 +221,7 @@ LL |         asm!("", in("cr") x);
    = note: register class `cr` supports these types: 
 
 error: type `i32` cannot be used with this register class
-  --> $DIR/bad-reg.rs:69:28
+  --> $DIR/bad-reg.rs:112:28
    |
 LL |         asm!("", out("cr") x);
    |                            ^
@@ -205,7 +229,7 @@ LL |         asm!("", out("cr") x);
    = note: register class `cr` supports these types: 
 
 error: type `i32` cannot be used with this register class
-  --> $DIR/bad-reg.rs:72:33
+  --> $DIR/bad-reg.rs:115:33
    |
 LL |         asm!("/* {} */", in(cr) x);
    |                                 ^
@@ -213,7 +237,7 @@ LL |         asm!("/* {} */", in(cr) x);
    = note: register class `cr` supports these types: 
 
 error: type `i32` cannot be used with this register class
-  --> $DIR/bad-reg.rs:79:28
+  --> $DIR/bad-reg.rs:122:28
    |
 LL |         asm!("", in("xer") x);
    |                            ^
@@ -221,7 +245,7 @@ LL |         asm!("", in("xer") x);
    = note: register class `xer` supports these types: 
 
 error: type `i32` cannot be used with this register class
-  --> $DIR/bad-reg.rs:82:29
+  --> $DIR/bad-reg.rs:125:29
    |
 LL |         asm!("", out("xer") x);
    |                             ^
@@ -229,36 +253,12 @@ LL |         asm!("", out("xer") x);
    = note: register class `xer` supports these types: 
 
 error: type `i32` cannot be used with this register class
-  --> $DIR/bad-reg.rs:85:34
+  --> $DIR/bad-reg.rs:128:34
    |
 LL |         asm!("/* {} */", in(xer) x);
    |                                  ^
    |
    = note: register class `xer` supports these types: 
 
-error: type `i32` cannot be used with this register class
-  --> $DIR/bad-reg.rs:93:27
-   |
-LL |         asm!("", in("v0") x);
-   |                           ^
-   |
-   = note: register class `vreg` supports these types: 
-
-error: type `i32` cannot be used with this register class
-  --> $DIR/bad-reg.rs:96:28
-   |
-LL |         asm!("", out("v0") x);
-   |                            ^
-   |
-   = note: register class `vreg` supports these types: 
-
-error: type `i32` cannot be used with this register class
-  --> $DIR/bad-reg.rs:99:35
-   |
-LL |         asm!("/* {} */", in(vreg) x);
-   |                                   ^
-   |
-   = note: register class `vreg` supports these types: 
-
-error: aborting due to 38 previous errors
+error: aborting due to 37 previous errors
 
diff --git a/tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr b/tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr
index 34105ceac049b..332bdf0ff5469 100644
--- a/tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr
+++ b/tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr
@@ -1,125 +1,101 @@
 error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:32:18
+  --> $DIR/bad-reg.rs:45:18
    |
 LL |         asm!("", out("sp") _);
    |                  ^^^^^^^^^^^
 
 error: invalid register `r2`: r2 is a system reserved register and cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:34:18
+  --> $DIR/bad-reg.rs:47:18
    |
 LL |         asm!("", out("r2") _);
    |                  ^^^^^^^^^^^
 
 error: invalid register `r29`: r29 is used internally by LLVM and cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:38:18
+  --> $DIR/bad-reg.rs:51:18
    |
 LL |         asm!("", out("r29") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `r30`: r30 is used internally by LLVM and cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:40:18
+  --> $DIR/bad-reg.rs:53:18
    |
 LL |         asm!("", out("r30") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:42:18
+  --> $DIR/bad-reg.rs:55:18
    |
 LL |         asm!("", out("fp") _);
    |                  ^^^^^^^^^^^
 
 error: invalid register `lr`: the link register cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:44:18
+  --> $DIR/bad-reg.rs:57:18
    |
 LL |         asm!("", out("lr") _);
    |                  ^^^^^^^^^^^
 
 error: invalid register `ctr`: the counter register cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:46:18
+  --> $DIR/bad-reg.rs:59:18
    |
 LL |         asm!("", out("ctr") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:48:18
+  --> $DIR/bad-reg.rs:61:18
    |
 LL |         asm!("", out("vrsave") _);
    |                  ^^^^^^^^^^^^^^^
 
 error: register class `cr` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:66:18
+  --> $DIR/bad-reg.rs:109:18
    |
 LL |         asm!("", in("cr") x);
    |                  ^^^^^^^^^^
 
 error: register class `cr` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:69:18
+  --> $DIR/bad-reg.rs:112:18
    |
 LL |         asm!("", out("cr") x);
    |                  ^^^^^^^^^^^
 
 error: register class `cr` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:72:26
+  --> $DIR/bad-reg.rs:115:26
    |
 LL |         asm!("/* {} */", in(cr) x);
    |                          ^^^^^^^^
 
 error: register class `cr` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:75:26
+  --> $DIR/bad-reg.rs:118:26
    |
 LL |         asm!("/* {} */", out(cr) _);
    |                          ^^^^^^^^^
 
 error: register class `xer` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:79:18
+  --> $DIR/bad-reg.rs:122:18
    |
 LL |         asm!("", in("xer") x);
    |                  ^^^^^^^^^^^
 
 error: register class `xer` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:82:18
+  --> $DIR/bad-reg.rs:125:18
    |
 LL |         asm!("", out("xer") x);
    |                  ^^^^^^^^^^^^
 
 error: register class `xer` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:85:26
+  --> $DIR/bad-reg.rs:128:26
    |
 LL |         asm!("/* {} */", in(xer) x);
    |                          ^^^^^^^^^
 
 error: register class `xer` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:88:26
+  --> $DIR/bad-reg.rs:131:26
    |
 LL |         asm!("/* {} */", out(xer) _);
    |                          ^^^^^^^^^^
 
-error: register class `vreg` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:93:18
-   |
-LL |         asm!("", in("v0") x);
-   |                  ^^^^^^^^^^
-
-error: register class `vreg` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:96:18
-   |
-LL |         asm!("", out("v0") x);
-   |                  ^^^^^^^^^^^
-
-error: register class `vreg` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:99:26
-   |
-LL |         asm!("/* {} */", in(vreg) x);
-   |                          ^^^^^^^^^^
-
-error: register class `vreg` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:102:26
-   |
-LL |         asm!("/* {} */", out(vreg) _);
-   |                          ^^^^^^^^^^^
-
 error: register `cr0` conflicts with register `cr`
-  --> $DIR/bad-reg.rs:106:31
+  --> $DIR/bad-reg.rs:135:31
    |
 LL |         asm!("", out("cr") _, out("cr0") _);
    |                  -----------  ^^^^^^^^^^^^ register `cr0`
@@ -127,7 +103,7 @@ LL |         asm!("", out("cr") _, out("cr0") _);
    |                  register `cr`
 
 error: register `cr1` conflicts with register `cr`
-  --> $DIR/bad-reg.rs:108:31
+  --> $DIR/bad-reg.rs:137:31
    |
 LL |         asm!("", out("cr") _, out("cr1") _);
    |                  -----------  ^^^^^^^^^^^^ register `cr1`
@@ -135,7 +111,7 @@ LL |         asm!("", out("cr") _, out("cr1") _);
    |                  register `cr`
 
 error: register `cr2` conflicts with register `cr`
-  --> $DIR/bad-reg.rs:110:31
+  --> $DIR/bad-reg.rs:139:31
    |
 LL |         asm!("", out("cr") _, out("cr2") _);
    |                  -----------  ^^^^^^^^^^^^ register `cr2`
@@ -143,7 +119,7 @@ LL |         asm!("", out("cr") _, out("cr2") _);
    |                  register `cr`
 
 error: register `cr3` conflicts with register `cr`
-  --> $DIR/bad-reg.rs:112:31
+  --> $DIR/bad-reg.rs:141:31
    |
 LL |         asm!("", out("cr") _, out("cr3") _);
    |                  -----------  ^^^^^^^^^^^^ register `cr3`
@@ -151,7 +127,7 @@ LL |         asm!("", out("cr") _, out("cr3") _);
    |                  register `cr`
 
 error: register `cr4` conflicts with register `cr`
-  --> $DIR/bad-reg.rs:114:31
+  --> $DIR/bad-reg.rs:143:31
    |
 LL |         asm!("", out("cr") _, out("cr4") _);
    |                  -----------  ^^^^^^^^^^^^ register `cr4`
@@ -159,7 +135,7 @@ LL |         asm!("", out("cr") _, out("cr4") _);
    |                  register `cr`
 
 error: register `cr5` conflicts with register `cr`
-  --> $DIR/bad-reg.rs:116:31
+  --> $DIR/bad-reg.rs:145:31
    |
 LL |         asm!("", out("cr") _, out("cr5") _);
    |                  -----------  ^^^^^^^^^^^^ register `cr5`
@@ -167,7 +143,7 @@ LL |         asm!("", out("cr") _, out("cr5") _);
    |                  register `cr`
 
 error: register `cr6` conflicts with register `cr`
-  --> $DIR/bad-reg.rs:118:31
+  --> $DIR/bad-reg.rs:147:31
    |
 LL |         asm!("", out("cr") _, out("cr6") _);
    |                  -----------  ^^^^^^^^^^^^ register `cr6`
@@ -175,7 +151,7 @@ LL |         asm!("", out("cr") _, out("cr6") _);
    |                  register `cr`
 
 error: register `cr7` conflicts with register `cr`
-  --> $DIR/bad-reg.rs:120:31
+  --> $DIR/bad-reg.rs:149:31
    |
 LL |         asm!("", out("cr") _, out("cr7") _);
    |                  -----------  ^^^^^^^^^^^^ register `cr7`
@@ -183,13 +159,37 @@ LL |         asm!("", out("cr") _, out("cr7") _);
    |                  register `cr`
 
 error: cannot use register `r13`: r13 is a reserved register on this target
-  --> $DIR/bad-reg.rs:36:18
+  --> $DIR/bad-reg.rs:49:18
    |
 LL |         asm!("", out("r13") _);
    |                  ^^^^^^^^^^^^
 
 error: type `i32` cannot be used with this register class
-  --> $DIR/bad-reg.rs:66:27
+  --> $DIR/bad-reg.rs:76:27
+   |
+LL |         asm!("", in("v0") x); // FIXME: should be ok if vsx is available
+   |                           ^
+   |
+   = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:79:28
+   |
+LL |         asm!("", out("v0") x); // FIXME: should be ok if vsx is available
+   |                            ^
+   |
+   = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:87:35
+   |
+LL |         asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is available
+   |                                   ^
+   |
+   = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:109:27
    |
 LL |         asm!("", in("cr") x);
    |                           ^
@@ -197,7 +197,7 @@ LL |         asm!("", in("cr") x);
    = note: register class `cr` supports these types: 
 
 error: type `i32` cannot be used with this register class
-  --> $DIR/bad-reg.rs:69:28
+  --> $DIR/bad-reg.rs:112:28
    |
 LL |         asm!("", out("cr") x);
    |                            ^
@@ -205,7 +205,7 @@ LL |         asm!("", out("cr") x);
    = note: register class `cr` supports these types: 
 
 error: type `i32` cannot be used with this register class
-  --> $DIR/bad-reg.rs:72:33
+  --> $DIR/bad-reg.rs:115:33
    |
 LL |         asm!("/* {} */", in(cr) x);
    |                                 ^
@@ -213,7 +213,7 @@ LL |         asm!("/* {} */", in(cr) x);
    = note: register class `cr` supports these types: 
 
 error: type `i32` cannot be used with this register class
-  --> $DIR/bad-reg.rs:79:28
+  --> $DIR/bad-reg.rs:122:28
    |
 LL |         asm!("", in("xer") x);
    |                            ^
@@ -221,7 +221,7 @@ LL |         asm!("", in("xer") x);
    = note: register class `xer` supports these types: 
 
 error: type `i32` cannot be used with this register class
-  --> $DIR/bad-reg.rs:82:29
+  --> $DIR/bad-reg.rs:125:29
    |
 LL |         asm!("", out("xer") x);
    |                             ^
@@ -229,36 +229,12 @@ LL |         asm!("", out("xer") x);
    = note: register class `xer` supports these types: 
 
 error: type `i32` cannot be used with this register class
-  --> $DIR/bad-reg.rs:85:34
+  --> $DIR/bad-reg.rs:128:34
    |
 LL |         asm!("/* {} */", in(xer) x);
    |                                  ^
    |
    = note: register class `xer` supports these types: 
 
-error: type `i32` cannot be used with this register class
-  --> $DIR/bad-reg.rs:93:27
-   |
-LL |         asm!("", in("v0") x);
-   |                           ^
-   |
-   = note: register class `vreg` supports these types: 
-
-error: type `i32` cannot be used with this register class
-  --> $DIR/bad-reg.rs:96:28
-   |
-LL |         asm!("", out("v0") x);
-   |                            ^
-   |
-   = note: register class `vreg` supports these types: 
-
-error: type `i32` cannot be used with this register class
-  --> $DIR/bad-reg.rs:99:35
-   |
-LL |         asm!("/* {} */", in(vreg) x);
-   |                                   ^
-   |
-   = note: register class `vreg` supports these types: 
-
-error: aborting due to 38 previous errors
+error: aborting due to 34 previous errors
 
diff --git a/tests/ui/asm/powerpc/bad-reg.rs b/tests/ui/asm/powerpc/bad-reg.rs
index 5023ad51838a9..f34c45663a02a 100644
--- a/tests/ui/asm/powerpc/bad-reg.rs
+++ b/tests/ui/asm/powerpc/bad-reg.rs
@@ -8,17 +8,28 @@
 //@[aix64] compile-flags: --target powerpc64-ibm-aix
 //@[aix64] needs-llvm-components: powerpc
 //@ needs-asm-support
+// ignore-tidy-linelength
 
 #![crate_type = "rlib"]
-#![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)]
+#![feature(no_core, rustc_attrs, lang_items, repr_simd, asm_experimental_arch)]
 #![no_core]
+#![allow(non_camel_case_types)]
 
 #[lang = "sized"]
 trait Sized {}
 #[lang = "copy"]
 trait Copy {}
 
+#[repr(simd)]
+pub struct i32x4([i32; 4]);
+#[repr(simd)]
+pub struct i64x2([i64; 2]);
+
+impl<T: Copy, const N: usize> Copy for [T; N] {}
 impl Copy for i32 {}
+impl Copy for i64 {}
+impl Copy for i32x4 {}
+impl Copy for i64x2 {}
 
 #[rustc_builtin_macro]
 macro_rules! asm {
@@ -27,6 +38,8 @@ macro_rules! asm {
 
 fn f() {
     let mut x = 0;
+    let mut v32x4 = i32x4([0; 4]);
+    let mut v64x2 = i64x2([0; 2]);
     unsafe {
         // Unsupported registers
         asm!("", out("sp") _);
@@ -47,6 +60,36 @@ fn f() {
         //~^ ERROR invalid register `ctr`: the counter register cannot be used as an operand for inline asm
         asm!("", out("vrsave") _);
         //~^ ERROR invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm
+
+        // vreg
+        asm!("", out("v0") _); // always ok
+        asm!("", in("v0") v32x4); // requires altivec
+        //[powerpc]~^ ERROR register class `vreg` requires at least one of the following target features: altivec, vsx
+        asm!("", out("v0") v32x4); // requires altivec
+        //[powerpc]~^ ERROR register class `vreg` requires at least one of the following target features: altivec, vsx
+        asm!("", in("v0") v64x2); // requires vsx
+        //[powerpc]~^ ERROR register class `vreg` requires at least one of the following target features: altivec, vsx
+        //[powerpc64]~^^ ERROR `vsx` target feature is not enabled
+        asm!("", out("v0") v64x2); // requires vsx
+        //[powerpc]~^ ERROR register class `vreg` requires at least one of the following target features: altivec, vsx
+        //[powerpc64]~^^ ERROR `vsx` target feature is not enabled
+        asm!("", in("v0") x); // FIXME: should be ok if vsx is available
+        //[powerpc]~^ ERROR register class `vreg` requires at least one of the following target features: altivec, vsx
+        //[powerpc64,powerpc64le,aix64]~^^ ERROR type `i32` cannot be used with this register class
+        asm!("", out("v0") x); // FIXME: should be ok if vsx is available
+        //[powerpc]~^ ERROR register class `vreg` requires at least one of the following target features: altivec, vsx
+        //[powerpc64,powerpc64le,aix64]~^^ ERROR type `i32` cannot be used with this register class
+        asm!("/* {} */", in(vreg) v32x4); // requires altivec
+        //[powerpc]~^ ERROR register class `vreg` requires at least one of the following target features: altivec, vsx
+        asm!("/* {} */", in(vreg) v64x2); // requires vsx
+        //[powerpc]~^ ERROR register class `vreg` requires at least one of the following target features: altivec, vsx
+        //[powerpc64]~^^ ERROR `vsx` target feature is not enabled
+        asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is available
+        //[powerpc]~^ ERROR register class `vreg` requires at least one of the following target features: altivec, vsx
+        //[powerpc64,powerpc64le,aix64]~^^ ERROR type `i32` cannot be used with this register class
+        asm!("/* {} */", out(vreg) _); // requires altivec
+        //[powerpc]~^ ERROR register class `vreg` requires at least one of the following target features: altivec, vsx
+        // v20-v31 are reserved on AIX with vec-default ABI (this ABI is not currently used in Rust's builtin AIX targets).
         asm!("", out("v20") _);
         asm!("", out("v21") _);
         asm!("", out("v22") _);
@@ -87,20 +130,6 @@ fn f() {
         //~| ERROR type `i32` cannot be used with this register class
         asm!("/* {} */", out(xer) _);
         //~^ ERROR can only be used as a clobber
-        // vreg
-        asm!("", out("v0") _); // ok
-        // FIXME: will be supported in the subsequent patch: https://github.com/rust-lang/rust/pull/131551
-        asm!("", in("v0") x);
-        //~^ ERROR can only be used as a clobber
-        //~| ERROR type `i32` cannot be used with this register class
-        asm!("", out("v0") x);
-        //~^ ERROR can only be used as a clobber
-        //~| ERROR type `i32` cannot be used with this register class
-        asm!("/* {} */", in(vreg) x);
-        //~^ ERROR can only be used as a clobber
-        //~| ERROR type `i32` cannot be used with this register class
-        asm!("/* {} */", out(vreg) _);
-        //~^ ERROR can only be used as a clobber
 
         // Overlapping-only registers
         asm!("", out("cr") _, out("cr0") _);

From df8feb5067f99e20059c7ee8021d9ba5273bfe68 Mon Sep 17 00:00:00 2001
From: Taiki Endo <te316e89@gmail.com>
Date: Fri, 29 Nov 2024 03:10:07 +0900
Subject: [PATCH 2/2] Support floats in input/output in vector registers of
 PowerPC inline assembly

---
 compiler/rustc_codegen_llvm/src/asm.rs        | 42 ++++++++++++
 compiler/rustc_target/src/asm/powerpc.rs      |  4 +-
 .../asm-experimental-arch.md                  |  2 +-
 tests/assembly/asm/powerpc-types.rs           | 66 +++++++++++++++++++
 tests/ui/asm/powerpc/bad-reg.aix64.stderr     |  6 +-
 tests/ui/asm/powerpc/bad-reg.powerpc64.stderr |  6 +-
 .../ui/asm/powerpc/bad-reg.powerpc64le.stderr |  6 +-
 7 files changed, 120 insertions(+), 12 deletions(-)

diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs
index 1483d576362b2..d1804cb49ad19 100644
--- a/compiler/rustc_codegen_llvm/src/asm.rs
+++ b/compiler/rustc_codegen_llvm/src/asm.rs
@@ -1040,6 +1040,26 @@ fn llvm_fixup_input<'ll, 'tcx>(
             let value = bx.or(value, bx.const_u32(0xFFFF_0000));
             bx.bitcast(value, bx.type_f32())
         }
+        (PowerPC(PowerPCInlineAsmRegClass::vreg), BackendRepr::Scalar(s))
+            if s.primitive() == Primitive::Float(Float::F32) =>
+        {
+            let value = bx.insert_element(
+                bx.const_undef(bx.type_vector(bx.type_f32(), 4)),
+                value,
+                bx.const_usize(0),
+            );
+            bx.bitcast(value, bx.type_vector(bx.type_f32(), 4))
+        }
+        (PowerPC(PowerPCInlineAsmRegClass::vreg), BackendRepr::Scalar(s))
+            if s.primitive() == Primitive::Float(Float::F64) =>
+        {
+            let value = bx.insert_element(
+                bx.const_undef(bx.type_vector(bx.type_f64(), 2)),
+                value,
+                bx.const_usize(0),
+            );
+            bx.bitcast(value, bx.type_vector(bx.type_f64(), 2))
+        }
         _ => value,
     }
 }
@@ -1175,6 +1195,18 @@ fn llvm_fixup_output<'ll, 'tcx>(
             let value = bx.trunc(value, bx.type_i16());
             bx.bitcast(value, bx.type_f16())
         }
+        (PowerPC(PowerPCInlineAsmRegClass::vreg), BackendRepr::Scalar(s))
+            if s.primitive() == Primitive::Float(Float::F32) =>
+        {
+            let value = bx.bitcast(value, bx.type_vector(bx.type_f32(), 4));
+            bx.extract_element(value, bx.const_usize(0))
+        }
+        (PowerPC(PowerPCInlineAsmRegClass::vreg), BackendRepr::Scalar(s))
+            if s.primitive() == Primitive::Float(Float::F64) =>
+        {
+            let value = bx.bitcast(value, bx.type_vector(bx.type_f64(), 2));
+            bx.extract_element(value, bx.const_usize(0))
+        }
         _ => value,
     }
 }
@@ -1299,6 +1331,16 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
         {
             cx.type_f32()
         }
+        (PowerPC(PowerPCInlineAsmRegClass::vreg), BackendRepr::Scalar(s))
+            if s.primitive() == Primitive::Float(Float::F32) =>
+        {
+            cx.type_vector(cx.type_f32(), 4)
+        }
+        (PowerPC(PowerPCInlineAsmRegClass::vreg), BackendRepr::Scalar(s))
+            if s.primitive() == Primitive::Float(Float::F64) =>
+        {
+            cx.type_vector(cx.type_f64(), 2)
+        }
         _ => layout.llvm_type(cx),
     }
 }
diff --git a/compiler/rustc_target/src/asm/powerpc.rs b/compiler/rustc_target/src/asm/powerpc.rs
index a5a96b87e367a..f3934afa6d94f 100644
--- a/compiler/rustc_target/src/asm/powerpc.rs
+++ b/compiler/rustc_target/src/asm/powerpc.rs
@@ -51,10 +51,10 @@ impl PowerPCInlineAsmRegClass {
                 }
             }
             Self::freg => types! { _: F32, F64; },
-            // FIXME: vsx also supports integers and floats: https://github.com/rust-lang/rust/pull/131551#discussion_r1797651773
+            // FIXME: vsx also supports integers?: https://github.com/rust-lang/rust/pull/131551#discussion_r1862535963
             Self::vreg => types! {
                 altivec: VecI8(16), VecI16(8), VecI32(4), VecF32(4);
-                vsx: VecI64(2), VecF64(2);
+                vsx: F32, F64, VecI64(2), VecF64(2);
             },
             Self::cr | Self::xer => &[],
         }
diff --git a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md
index f2d0caa5e37cc..c2f4170d7d295 100644
--- a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md
+++ b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md
@@ -76,7 +76,7 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
 | PowerPC      | `reg_nonzero`                   | None           | `i8`, `i16`, `i32`, `i64` (powerpc64 only) |
 | PowerPC      | `freg`                          | None           | `f32`, `f64`                            |
 | PowerPC      | `vreg`                          | `altivec`      | `i8x16`, `i16x8`, `i32x4`, `f32x4`      |
-| PowerPC      | `vreg`                          | `vsx`          | `i64x2`, `f64x2`                        |
+| PowerPC      | `vreg`                          | `vsx`          | `f32`, `f64`, `i64x2`, `f64x2`          |
 | PowerPC      | `cr`                            | N/A            | Only clobbers                           |
 | PowerPC      | `xer`                           | N/A            | Only clobbers                           |
 | wasm32       | `local`                         | None           | `i8` `i16` `i32` `i64` `f32` `f64`      |
diff --git a/tests/assembly/asm/powerpc-types.rs b/tests/assembly/asm/powerpc-types.rs
index d67e0f66f66f5..aa35c4d886581 100644
--- a/tests/assembly/asm/powerpc-types.rs
+++ b/tests/assembly/asm/powerpc-types.rs
@@ -225,6 +225,28 @@ check!(vreg_f32x4, f32x4, vreg, "vmr");
 #[cfg(vsx)]
 check!(vreg_f64x2, f64x2, vreg, "vmr");
 
+// powerpc_vsx-LABEL: vreg_f32:
+// powerpc_vsx: #APP
+// powerpc_vsx: vmr {{[0-9]+}}, {{[0-9]+}}
+// powerpc_vsx: #NO_APP
+// powerpc64_vsx-LABEL: vreg_f32:
+// powerpc64_vsx: #APP
+// powerpc64_vsx: vmr {{[0-9]+}}, {{[0-9]+}}
+// powerpc64_vsx: #NO_APP
+#[cfg(vsx)]
+check!(vreg_f32, f32, vreg, "vmr");
+
+// powerpc_vsx-LABEL: vreg_f64:
+// powerpc_vsx: #APP
+// powerpc_vsx: vmr {{[0-9]+}}, {{[0-9]+}}
+// powerpc_vsx: #NO_APP
+// powerpc64_vsx-LABEL: vreg_f64:
+// powerpc64_vsx: #APP
+// powerpc64_vsx: vmr {{[0-9]+}}, {{[0-9]+}}
+// powerpc64_vsx: #NO_APP
+#[cfg(vsx)]
+check!(vreg_f64, f64, vreg, "vmr");
+
 // CHECK-LABEL: reg_i8_r0:
 // CHECK: #APP
 // CHECK: mr 0, 0
@@ -365,6 +387,28 @@ check_reg!(vreg_f32x4_v0, f32x4, "0", "v0", "vmr");
 #[cfg(vsx)]
 check_reg!(vreg_f64x2_v0, f64x2, "0", "v0", "vmr");
 
+// powerpc_vsx-LABEL: vreg_f32_v0:
+// powerpc_vsx: #APP
+// powerpc_vsx: vmr 0, 0
+// powerpc_vsx: #NO_APP
+// powerpc64_vsx-LABEL: vreg_f32_v0:
+// powerpc64_vsx: #APP
+// powerpc64_vsx: vmr 0, 0
+// powerpc64_vsx: #NO_APP
+#[cfg(vsx)]
+check_reg!(vreg_f32_v0, f32, "0", "v0", "vmr");
+
+// powerpc_vsx-LABEL: vreg_f64_v0:
+// powerpc_vsx: #APP
+// powerpc_vsx: vmr 0, 0
+// powerpc_vsx: #NO_APP
+// powerpc64_vsx-LABEL: vreg_f64_v0:
+// powerpc64_vsx: #APP
+// powerpc64_vsx: vmr 0, 0
+// powerpc64_vsx: #NO_APP
+#[cfg(vsx)]
+check_reg!(vreg_f64_v0, f64, "0", "v0", "vmr");
+
 // powerpc_altivec-LABEL: vreg_i8x16_v18:
 // powerpc_altivec: #APP
 // powerpc_altivec: vmr 18, 18
@@ -430,3 +474,25 @@ check_reg!(vreg_f32x4_v18, f32x4, "18", "v18", "vmr");
 // powerpc64_vsx: #NO_APP
 #[cfg(vsx)]
 check_reg!(vreg_f64x2_v18, f64x2, "18", "v18", "vmr");
+
+// powerpc_vsx-LABEL: vreg_f32_v18:
+// powerpc_vsx: #APP
+// powerpc_vsx: vmr 18, 18
+// powerpc_vsx: #NO_APP
+// powerpc64_vsx-LABEL: vreg_f32_v18:
+// powerpc64_vsx: #APP
+// powerpc64_vsx: vmr 18, 18
+// powerpc64_vsx: #NO_APP
+#[cfg(vsx)]
+check_reg!(vreg_f32_v18, f32, "18", "v18", "vmr");
+
+// powerpc_vsx-LABEL: vreg_f64_v18:
+// powerpc_vsx: #APP
+// powerpc_vsx: vmr 18, 18
+// powerpc_vsx: #NO_APP
+// powerpc64_vsx-LABEL: vreg_f64_v18:
+// powerpc64_vsx: #APP
+// powerpc64_vsx: vmr 18, 18
+// powerpc64_vsx: #NO_APP
+#[cfg(vsx)]
+check_reg!(vreg_f64_v18, f64, "18", "v18", "vmr");
diff --git a/tests/ui/asm/powerpc/bad-reg.aix64.stderr b/tests/ui/asm/powerpc/bad-reg.aix64.stderr
index 332bdf0ff5469..036641951cc93 100644
--- a/tests/ui/asm/powerpc/bad-reg.aix64.stderr
+++ b/tests/ui/asm/powerpc/bad-reg.aix64.stderr
@@ -170,7 +170,7 @@ error: type `i32` cannot be used with this register class
 LL |         asm!("", in("v0") x); // FIXME: should be ok if vsx is available
    |                           ^
    |
-   = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2
+   = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2
 
 error: type `i32` cannot be used with this register class
   --> $DIR/bad-reg.rs:79:28
@@ -178,7 +178,7 @@ error: type `i32` cannot be used with this register class
 LL |         asm!("", out("v0") x); // FIXME: should be ok if vsx is available
    |                            ^
    |
-   = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2
+   = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2
 
 error: type `i32` cannot be used with this register class
   --> $DIR/bad-reg.rs:87:35
@@ -186,7 +186,7 @@ error: type `i32` cannot be used with this register class
 LL |         asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is available
    |                                   ^
    |
-   = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2
+   = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2
 
 error: type `i32` cannot be used with this register class
   --> $DIR/bad-reg.rs:109:27
diff --git a/tests/ui/asm/powerpc/bad-reg.powerpc64.stderr b/tests/ui/asm/powerpc/bad-reg.powerpc64.stderr
index 9e0dd80b3dca1..6a9d552bfe29a 100644
--- a/tests/ui/asm/powerpc/bad-reg.powerpc64.stderr
+++ b/tests/ui/asm/powerpc/bad-reg.powerpc64.stderr
@@ -186,7 +186,7 @@ error: type `i32` cannot be used with this register class
 LL |         asm!("", in("v0") x); // FIXME: should be ok if vsx is available
    |                           ^
    |
-   = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2
+   = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2
 
 error: type `i32` cannot be used with this register class
   --> $DIR/bad-reg.rs:79:28
@@ -194,7 +194,7 @@ error: type `i32` cannot be used with this register class
 LL |         asm!("", out("v0") x); // FIXME: should be ok if vsx is available
    |                            ^
    |
-   = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2
+   = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2
 
 error: `vsx` target feature is not enabled
   --> $DIR/bad-reg.rs:84:35
@@ -210,7 +210,7 @@ error: type `i32` cannot be used with this register class
 LL |         asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is available
    |                                   ^
    |
-   = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2
+   = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2
 
 error: type `i32` cannot be used with this register class
   --> $DIR/bad-reg.rs:109:27
diff --git a/tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr b/tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr
index 332bdf0ff5469..036641951cc93 100644
--- a/tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr
+++ b/tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr
@@ -170,7 +170,7 @@ error: type `i32` cannot be used with this register class
 LL |         asm!("", in("v0") x); // FIXME: should be ok if vsx is available
    |                           ^
    |
-   = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2
+   = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2
 
 error: type `i32` cannot be used with this register class
   --> $DIR/bad-reg.rs:79:28
@@ -178,7 +178,7 @@ error: type `i32` cannot be used with this register class
 LL |         asm!("", out("v0") x); // FIXME: should be ok if vsx is available
    |                            ^
    |
-   = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2
+   = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2
 
 error: type `i32` cannot be used with this register class
   --> $DIR/bad-reg.rs:87:35
@@ -186,7 +186,7 @@ error: type `i32` cannot be used with this register class
 LL |         asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is available
    |                                   ^
    |
-   = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2
+   = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2
 
 error: type `i32` cannot be used with this register class
   --> $DIR/bad-reg.rs:109:27