about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_codegen_gcc/src/asm.rs10
-rw-r--r--compiler/rustc_codegen_llvm/src/asm.rs52
-rw-r--r--compiler/rustc_span/src/symbol.rs2
-rw-r--r--compiler/rustc_target/src/asm/powerpc.rs6
-rw-r--r--library/alloc/src/collections/btree/map.rs29
-rw-r--r--library/alloc/src/collections/btree/map/entry.rs5
-rw-r--r--library/alloc/src/collections/btree/set.rs110
-rw-r--r--library/alloc/src/collections/btree/set/entry.rs388
-rw-r--r--library/core/src/intrinsics/mod.rs1544
-rw-r--r--library/std/src/env.rs16
-rw-r--r--library/std/src/sys/pal/wasi/thread.rs16
-rw-r--r--library/std/src/sys/pal/windows/os.rs4
-rw-r--r--library/std/tests/env.rs12
-rw-r--r--src/bootstrap/mk/Makefile.in8
-rw-r--r--src/ci/github-actions/jobs.yml16
-rw-r--r--src/ci/shared.sh3
-rw-r--r--src/doc/unstable-book/src/language-features/asm-experimental-arch.md6
-rw-r--r--tests/assembly/asm/powerpc-types.rs303
-rw-r--r--tests/codegen/asm/powerpc-clobbers.rs13
-rw-r--r--tests/ui/asm/powerpc/bad-reg.aix64.stderr136
-rw-r--r--tests/ui/asm/powerpc/bad-reg.powerpc.stderr172
-rw-r--r--tests/ui/asm/powerpc/bad-reg.powerpc64.stderr160
-rw-r--r--tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr136
-rw-r--r--tests/ui/asm/powerpc/bad-reg.rs59
-rw-r--r--tests/ui/intrinsics/reify-intrinsic.stderr2
25 files changed, 2230 insertions, 978 deletions
diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs
index 341d1b9c179..a1f9eab10e7 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 9aa01bd1b95..d1804cb49ad 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(),
@@ -1042,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,
     }
 }
@@ -1177,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,
     }
 }
@@ -1301,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_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 3a07c283e0e..6cd754a47e9 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 aa8b26170be..f3934afa6d9 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?: https://github.com/rust-lang/rust/pull/131551#discussion_r1862535963
+            Self::vreg => types! {
+                altivec: VecI8(16), VecI16(8), VecI32(4), VecF32(4);
+                vsx: F32, F64, VecI64(2), VecF64(2);
+            },
             Self::cr | Self::xer => &[],
         }
     }
diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs
index 213924d1d02..d1ce4e215ed 100644
--- a/library/alloc/src/collections/btree/map.rs
+++ b/library/alloc/src/collections/btree/map.rs
@@ -308,11 +308,38 @@ impl<K, A: Allocator + Clone> BTreeMap<K, SetValZST, A> {
                     alloc: (*map.alloc).clone(),
                     _marker: PhantomData,
                 }
-                .insert(SetValZST::default());
+                .insert(SetValZST);
                 None
             }
         }
     }
+
+    pub(super) fn get_or_insert_with<Q: ?Sized, F>(&mut self, q: &Q, f: F) -> &K
+    where
+        K: Borrow<Q> + Ord,
+        Q: Ord,
+        F: FnOnce(&Q) -> K,
+    {
+        let (map, dormant_map) = DormantMutRef::new(self);
+        let root_node =
+            map.root.get_or_insert_with(|| Root::new((*map.alloc).clone())).borrow_mut();
+        match root_node.search_tree(q) {
+            Found(handle) => handle.into_kv_mut().0,
+            GoDown(handle) => {
+                let key = f(q);
+                assert!(*key.borrow() == *q, "new value is not equal");
+                VacantEntry {
+                    key,
+                    handle: Some(handle),
+                    dormant_map,
+                    alloc: (*map.alloc).clone(),
+                    _marker: PhantomData,
+                }
+                .insert_entry(SetValZST)
+                .into_key()
+            }
+        }
+    }
 }
 
 /// An iterator over the entries of a `BTreeMap`.
diff --git a/library/alloc/src/collections/btree/map/entry.rs b/library/alloc/src/collections/btree/map/entry.rs
index 0da6af54bc2..ea8fa363c38 100644
--- a/library/alloc/src/collections/btree/map/entry.rs
+++ b/library/alloc/src/collections/btree/map/entry.rs
@@ -449,6 +449,11 @@ impl<'a, K: Ord, V, A: Allocator + Clone> OccupiedEntry<'a, K, V, A> {
         self.handle.reborrow().into_kv().0
     }
 
+    /// Converts the entry into a reference to its key.
+    pub(crate) fn into_key(self) -> &'a K {
+        self.handle.into_kv_mut().0
+    }
+
     /// Take ownership of the key and value from the map.
     ///
     /// # Examples
diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs
index 8daee6030c2..6f8c3b2d152 100644
--- a/library/alloc/src/collections/btree/set.rs
+++ b/library/alloc/src/collections/btree/set.rs
@@ -7,12 +7,17 @@ use core::iter::{FusedIterator, Peekable};
 use core::mem::ManuallyDrop;
 use core::ops::{BitAnd, BitOr, BitXor, Bound, RangeBounds, Sub};
 
-use super::map::{BTreeMap, Keys};
+use super::map::{self, BTreeMap, Keys};
 use super::merge_iter::MergeIterInner;
 use super::set_val::SetValZST;
 use crate::alloc::{Allocator, Global};
 use crate::vec::Vec;
 
+mod entry;
+
+#[unstable(feature = "btree_set_entry", issue = "133549")]
+pub use self::entry::{Entry, OccupiedEntry, VacantEntry};
+
 /// An ordered set based on a B-Tree.
 ///
 /// See [`BTreeMap`]'s documentation for a detailed discussion of this collection's performance
@@ -928,6 +933,109 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> {
         self.map.replace(value)
     }
 
+    /// Inserts the given `value` into the set if it is not present, then
+    /// returns a reference to the value in the set.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(btree_set_entry)]
+    ///
+    /// use std::collections::BTreeSet;
+    ///
+    /// let mut set = BTreeSet::from([1, 2, 3]);
+    /// assert_eq!(set.len(), 3);
+    /// assert_eq!(set.get_or_insert(2), &2);
+    /// assert_eq!(set.get_or_insert(100), &100);
+    /// assert_eq!(set.len(), 4); // 100 was inserted
+    /// ```
+    #[inline]
+    #[unstable(feature = "btree_set_entry", issue = "133549")]
+    pub fn get_or_insert(&mut self, value: T) -> &T
+    where
+        T: Ord,
+    {
+        self.map.entry(value).insert_entry(SetValZST).into_key()
+    }
+
+    /// Inserts a value computed from `f` into the set if the given `value` is
+    /// not present, then returns a reference to the value in the set.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(btree_set_entry)]
+    ///
+    /// use std::collections::BTreeSet;
+    ///
+    /// let mut set: BTreeSet<String> = ["cat", "dog", "horse"]
+    ///     .iter().map(|&pet| pet.to_owned()).collect();
+    ///
+    /// assert_eq!(set.len(), 3);
+    /// for &pet in &["cat", "dog", "fish"] {
+    ///     let value = set.get_or_insert_with(pet, str::to_owned);
+    ///     assert_eq!(value, pet);
+    /// }
+    /// assert_eq!(set.len(), 4); // a new "fish" was inserted
+    /// ```
+    #[inline]
+    #[unstable(feature = "btree_set_entry", issue = "133549")]
+    pub fn get_or_insert_with<Q: ?Sized, F>(&mut self, value: &Q, f: F) -> &T
+    where
+        T: Borrow<Q> + Ord,
+        Q: Ord,
+        F: FnOnce(&Q) -> T,
+    {
+        self.map.get_or_insert_with(value, f)
+    }
+
+    /// Gets the given value's corresponding entry in the set for in-place manipulation.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(btree_set_entry)]
+    ///
+    /// use std::collections::BTreeSet;
+    /// use std::collections::btree_set::Entry::*;
+    ///
+    /// let mut singles = BTreeSet::new();
+    /// let mut dupes = BTreeSet::new();
+    ///
+    /// for ch in "a short treatise on fungi".chars() {
+    ///     if let Vacant(dupe_entry) = dupes.entry(ch) {
+    ///         // We haven't already seen a duplicate, so
+    ///         // check if we've at least seen it once.
+    ///         match singles.entry(ch) {
+    ///             Vacant(single_entry) => {
+    ///                 // We found a new character for the first time.
+    ///                 single_entry.insert()
+    ///             }
+    ///             Occupied(single_entry) => {
+    ///                 // We've already seen this once, "move" it to dupes.
+    ///                 single_entry.remove();
+    ///                 dupe_entry.insert();
+    ///             }
+    ///         }
+    ///     }
+    /// }
+    ///
+    /// assert!(!singles.contains(&'t') && dupes.contains(&'t'));
+    /// assert!(singles.contains(&'u') && !dupes.contains(&'u'));
+    /// assert!(!singles.contains(&'v') && !dupes.contains(&'v'));
+    /// ```
+    #[inline]
+    #[unstable(feature = "btree_set_entry", issue = "133549")]
+    pub fn entry(&mut self, value: T) -> Entry<'_, T, A>
+    where
+        T: Ord,
+    {
+        match self.map.entry(value) {
+            map::Entry::Occupied(entry) => Entry::Occupied(OccupiedEntry { inner: entry }),
+            map::Entry::Vacant(entry) => Entry::Vacant(VacantEntry { inner: entry }),
+        }
+    }
+
     /// If the set contains an element equal to the value, removes it from the
     /// set and drops it. Returns whether such an element was present.
     ///
diff --git a/library/alloc/src/collections/btree/set/entry.rs b/library/alloc/src/collections/btree/set/entry.rs
new file mode 100644
index 00000000000..a60d22f9ece
--- /dev/null
+++ b/library/alloc/src/collections/btree/set/entry.rs
@@ -0,0 +1,388 @@
+use core::fmt::{self, Debug};
+
+use Entry::*;
+
+use super::{SetValZST, map};
+use crate::alloc::{Allocator, Global};
+
+/// A view into a single entry in a set, which may either be vacant or occupied.
+///
+/// This `enum` is constructed from the [`entry`] method on [`BTreeSet`].
+///
+/// [`BTreeSet`]: super::BTreeSet
+/// [`entry`]: super::BTreeSet::entry
+///
+/// # Examples
+///
+/// ```
+/// #![feature(btree_set_entry)]
+///
+/// use std::collections::btree_set::BTreeSet;
+///
+/// let mut set = BTreeSet::new();
+/// set.extend(["a", "b", "c"]);
+/// assert_eq!(set.len(), 3);
+///
+/// // Existing value (insert)
+/// let entry = set.entry("a");
+/// let _raw_o = entry.insert();
+/// assert_eq!(set.len(), 3);
+/// // Nonexistent value (insert)
+/// set.entry("d").insert();
+///
+/// // Existing value (or_insert)
+/// set.entry("b").or_insert();
+/// // Nonexistent value (or_insert)
+/// set.entry("e").or_insert();
+///
+/// println!("Our BTreeSet: {:?}", set);
+/// assert!(set.iter().eq(&["a", "b", "c", "d", "e"]));
+/// ```
+#[unstable(feature = "btree_set_entry", issue = "133549")]
+pub enum Entry<
+    'a,
+    T,
+    #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global,
+> {
+    /// An occupied entry.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(btree_set_entry)]
+    ///
+    /// use std::collections::btree_set::{Entry, BTreeSet};
+    ///
+    /// let mut set = BTreeSet::from(["a", "b"]);
+    ///
+    /// match set.entry("a") {
+    ///     Entry::Vacant(_) => unreachable!(),
+    ///     Entry::Occupied(_) => { }
+    /// }
+    /// ```
+    #[unstable(feature = "btree_set_entry", issue = "133549")]
+    Occupied(OccupiedEntry<'a, T, A>),
+
+    /// A vacant entry.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(btree_set_entry)]
+    ///
+    /// use std::collections::btree_set::{Entry, BTreeSet};
+    ///
+    /// let mut set = BTreeSet::new();
+    ///
+    /// match set.entry("a") {
+    ///     Entry::Occupied(_) => unreachable!(),
+    ///     Entry::Vacant(_) => { }
+    /// }
+    /// ```
+    #[unstable(feature = "btree_set_entry", issue = "133549")]
+    Vacant(VacantEntry<'a, T, A>),
+}
+
+#[unstable(feature = "btree_set_entry", issue = "133549")]
+impl<T: Debug + Ord, A: Allocator + Clone> Debug for Entry<'_, T, A> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match *self {
+            Vacant(ref v) => f.debug_tuple("Entry").field(v).finish(),
+            Occupied(ref o) => f.debug_tuple("Entry").field(o).finish(),
+        }
+    }
+}
+
+/// A view into an occupied entry in a `BTreeSet`.
+/// It is part of the [`Entry`] enum.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(btree_set_entry)]
+///
+/// use std::collections::btree_set::{Entry, BTreeSet};
+///
+/// let mut set = BTreeSet::new();
+/// set.extend(["a", "b", "c"]);
+///
+/// let _entry_o = set.entry("a").insert();
+/// assert_eq!(set.len(), 3);
+///
+/// // Existing key
+/// match set.entry("a") {
+///     Entry::Vacant(_) => unreachable!(),
+///     Entry::Occupied(view) => {
+///         assert_eq!(view.get(), &"a");
+///     }
+/// }
+///
+/// assert_eq!(set.len(), 3);
+///
+/// // Existing key (take)
+/// match set.entry("c") {
+///     Entry::Vacant(_) => unreachable!(),
+///     Entry::Occupied(view) => {
+///         assert_eq!(view.remove(), "c");
+///     }
+/// }
+/// assert_eq!(set.get(&"c"), None);
+/// assert_eq!(set.len(), 2);
+/// ```
+#[unstable(feature = "btree_set_entry", issue = "133549")]
+pub struct OccupiedEntry<
+    'a,
+    T,
+    #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global,
+> {
+    pub(super) inner: map::OccupiedEntry<'a, T, SetValZST, A>,
+}
+
+#[unstable(feature = "btree_set_entry", issue = "133549")]
+impl<T: Debug + Ord, A: Allocator + Clone> Debug for OccupiedEntry<'_, T, A> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("OccupiedEntry").field("value", self.get()).finish()
+    }
+}
+
+/// A view into a vacant entry in a `BTreeSet`.
+/// It is part of the [`Entry`] enum.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(btree_set_entry)]
+///
+/// use std::collections::btree_set::{Entry, BTreeSet};
+///
+/// let mut set = BTreeSet::<&str>::new();
+///
+/// let entry_v = match set.entry("a") {
+///     Entry::Vacant(view) => view,
+///     Entry::Occupied(_) => unreachable!(),
+/// };
+/// entry_v.insert();
+/// assert!(set.contains("a") && set.len() == 1);
+///
+/// // Nonexistent key (insert)
+/// match set.entry("b") {
+///     Entry::Vacant(view) => view.insert(),
+///     Entry::Occupied(_) => unreachable!(),
+/// }
+/// assert!(set.contains("b") && set.len() == 2);
+/// ```
+#[unstable(feature = "btree_set_entry", issue = "133549")]
+pub struct VacantEntry<
+    'a,
+    T,
+    #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global,
+> {
+    pub(super) inner: map::VacantEntry<'a, T, SetValZST, A>,
+}
+
+#[unstable(feature = "btree_set_entry", issue = "133549")]
+impl<T: Debug + Ord, A: Allocator + Clone> Debug for VacantEntry<'_, T, A> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_tuple("VacantEntry").field(self.get()).finish()
+    }
+}
+
+impl<'a, T: Ord, A: Allocator + Clone> Entry<'a, T, A> {
+    /// Sets the value of the entry, and returns an `OccupiedEntry`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(btree_set_entry)]
+    ///
+    /// use std::collections::BTreeSet;
+    ///
+    /// let mut set = BTreeSet::new();
+    /// let entry = set.entry("horseyland").insert();
+    ///
+    /// assert_eq!(entry.get(), &"horseyland");
+    /// ```
+    #[inline]
+    #[unstable(feature = "btree_set_entry", issue = "133549")]
+    pub fn insert(self) -> OccupiedEntry<'a, T, A> {
+        match self {
+            Occupied(entry) => entry,
+            Vacant(entry) => entry.insert_entry(),
+        }
+    }
+
+    /// Ensures a value is in the entry by inserting if it was vacant.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(btree_set_entry)]
+    ///
+    /// use std::collections::BTreeSet;
+    ///
+    /// let mut set = BTreeSet::new();
+    ///
+    /// // nonexistent key
+    /// set.entry("poneyland").or_insert();
+    /// assert!(set.contains("poneyland"));
+    ///
+    /// // existing key
+    /// set.entry("poneyland").or_insert();
+    /// assert!(set.contains("poneyland"));
+    /// assert_eq!(set.len(), 1);
+    /// ```
+    #[inline]
+    #[unstable(feature = "btree_set_entry", issue = "133549")]
+    pub fn or_insert(self) {
+        if let Vacant(entry) = self {
+            entry.insert();
+        }
+    }
+
+    /// Returns a reference to this entry's value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(btree_set_entry)]
+    ///
+    /// use std::collections::BTreeSet;
+    ///
+    /// let mut set = BTreeSet::new();
+    /// set.entry("poneyland").or_insert();
+    ///
+    /// // existing key
+    /// assert_eq!(set.entry("poneyland").get(), &"poneyland");
+    /// // nonexistent key
+    /// assert_eq!(set.entry("horseland").get(), &"horseland");
+    /// ```
+    #[inline]
+    #[unstable(feature = "btree_set_entry", issue = "133549")]
+    pub fn get(&self) -> &T {
+        match *self {
+            Occupied(ref entry) => entry.get(),
+            Vacant(ref entry) => entry.get(),
+        }
+    }
+}
+
+impl<'a, T: Ord, A: Allocator + Clone> OccupiedEntry<'a, T, A> {
+    /// Gets a reference to the value in the entry.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(btree_set_entry)]
+    ///
+    /// use std::collections::btree_set::{Entry, BTreeSet};
+    ///
+    /// let mut set = BTreeSet::new();
+    /// set.entry("poneyland").or_insert();
+    ///
+    /// match set.entry("poneyland") {
+    ///     Entry::Vacant(_) => panic!(),
+    ///     Entry::Occupied(entry) => assert_eq!(entry.get(), &"poneyland"),
+    /// }
+    /// ```
+    #[inline]
+    #[unstable(feature = "btree_set_entry", issue = "133549")]
+    pub fn get(&self) -> &T {
+        self.inner.key()
+    }
+
+    /// Takes the value out of the entry, and returns it.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(btree_set_entry)]
+    ///
+    /// use std::collections::BTreeSet;
+    /// use std::collections::btree_set::Entry;
+    ///
+    /// let mut set = BTreeSet::new();
+    /// set.entry("poneyland").or_insert();
+    ///
+    /// if let Entry::Occupied(o) = set.entry("poneyland") {
+    ///     assert_eq!(o.remove(), "poneyland");
+    /// }
+    ///
+    /// assert_eq!(set.contains("poneyland"), false);
+    /// ```
+    #[inline]
+    #[unstable(feature = "btree_set_entry", issue = "133549")]
+    pub fn remove(self) -> T {
+        self.inner.remove_entry().0
+    }
+}
+
+impl<'a, T: Ord, A: Allocator + Clone> VacantEntry<'a, T, A> {
+    /// Gets a reference to the value that would be used when inserting
+    /// through the `VacantEntry`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(btree_set_entry)]
+    ///
+    /// use std::collections::BTreeSet;
+    ///
+    /// let mut set = BTreeSet::new();
+    /// assert_eq!(set.entry("poneyland").get(), &"poneyland");
+    /// ```
+    #[inline]
+    #[unstable(feature = "btree_set_entry", issue = "133549")]
+    pub fn get(&self) -> &T {
+        self.inner.key()
+    }
+
+    /// Take ownership of the value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(btree_set_entry)]
+    ///
+    /// use std::collections::btree_set::{Entry, BTreeSet};
+    ///
+    /// let mut set = BTreeSet::new();
+    ///
+    /// match set.entry("poneyland") {
+    ///     Entry::Occupied(_) => panic!(),
+    ///     Entry::Vacant(v) => assert_eq!(v.into_value(), "poneyland"),
+    /// }
+    /// ```
+    #[inline]
+    #[unstable(feature = "btree_set_entry", issue = "133549")]
+    pub fn into_value(self) -> T {
+        self.inner.into_key()
+    }
+
+    /// Sets the value of the entry with the VacantEntry's value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(btree_set_entry)]
+    ///
+    /// use std::collections::BTreeSet;
+    /// use std::collections::btree_set::Entry;
+    ///
+    /// let mut set = BTreeSet::new();
+    ///
+    /// if let Entry::Vacant(o) = set.entry("poneyland") {
+    ///     o.insert();
+    /// }
+    /// assert!(set.contains("poneyland"));
+    /// ```
+    #[inline]
+    #[unstable(feature = "btree_set_entry", issue = "133549")]
+    pub fn insert(self) {
+        self.inner.insert(SetValZST);
+    }
+
+    #[inline]
+    fn insert_entry(self) -> OccupiedEntry<'a, T, A> {
+        OccupiedEntry { inner: self.inner.insert_entry(SetValZST) }
+    }
+}
diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs
index 6b9011adf3d..46873fdc047 100644
--- a/library/core/src/intrinsics/mod.rs
+++ b/library/core/src/intrinsics/mod.rs
@@ -2006,628 +2006,982 @@ pub fn ptr_mask<T>(_ptr: *const T, _mask: usize) -> *const T {
     unreachable!()
 }
 
-extern "rust-intrinsic" {
-    /// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with
-    /// a size of `count` * `size_of::<T>()` and an alignment of
-    /// `min_align_of::<T>()`
-    ///
-    /// The volatile parameter is set to `true`, so it will not be optimized out
-    /// unless size is equal to zero.
-    ///
-    /// This intrinsic does not have a stable counterpart.
-    #[rustc_nounwind]
-    pub fn volatile_copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: usize);
-    /// Equivalent to the appropriate `llvm.memmove.p0i8.0i8.*` intrinsic, with
-    /// a size of `count * size_of::<T>()` and an alignment of
-    /// `min_align_of::<T>()`
-    ///
-    /// The volatile parameter is set to `true`, so it will not be optimized out
-    /// unless size is equal to zero.
-    ///
-    /// This intrinsic does not have a stable counterpart.
-    #[rustc_nounwind]
-    pub fn volatile_copy_memory<T>(dst: *mut T, src: *const T, count: usize);
-    /// Equivalent to the appropriate `llvm.memset.p0i8.*` intrinsic, with a
-    /// size of `count * size_of::<T>()` and an alignment of
-    /// `min_align_of::<T>()`.
-    ///
-    /// The volatile parameter is set to `true`, so it will not be optimized out
-    /// unless size is equal to zero.
-    ///
-    /// This intrinsic does not have a stable counterpart.
-    #[rustc_nounwind]
-    pub fn volatile_set_memory<T>(dst: *mut T, val: u8, count: usize);
+/// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with
+/// a size of `count` * `size_of::<T>()` and an alignment of
+/// `min_align_of::<T>()`
+///
+/// The volatile parameter is set to `true`, so it will not be optimized out
+/// unless size is equal to zero.
+///
+/// This intrinsic does not have a stable counterpart.
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn volatile_copy_nonoverlapping_memory<T>(_dst: *mut T, _src: *const T, _count: usize) {
+    unreachable!()
+}
+/// Equivalent to the appropriate `llvm.memmove.p0i8.0i8.*` intrinsic, with
+/// a size of `count * size_of::<T>()` and an alignment of
+/// `min_align_of::<T>()`
+///
+/// The volatile parameter is set to `true`, so it will not be optimized out
+/// unless size is equal to zero.
+///
+/// This intrinsic does not have a stable counterpart.
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn volatile_copy_memory<T>(_dst: *mut T, _src: *const T, _count: usize) {
+    unreachable!()
+}
+/// Equivalent to the appropriate `llvm.memset.p0i8.*` intrinsic, with a
+/// size of `count * size_of::<T>()` and an alignment of
+/// `min_align_of::<T>()`.
+///
+/// The volatile parameter is set to `true`, so it will not be optimized out
+/// unless size is equal to zero.
+///
+/// This intrinsic does not have a stable counterpart.
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn volatile_set_memory<T>(_dst: *mut T, _val: u8, _count: usize) {
+    unreachable!()
+}
 
-    /// Performs a volatile load from the `src` pointer.
-    ///
-    /// The stabilized version of this intrinsic is [`core::ptr::read_volatile`].
-    #[rustc_nounwind]
-    pub fn volatile_load<T>(src: *const T) -> T;
-    /// Performs a volatile store to the `dst` pointer.
-    ///
-    /// The stabilized version of this intrinsic is [`core::ptr::write_volatile`].
-    #[rustc_nounwind]
-    pub fn volatile_store<T>(dst: *mut T, val: T);
+/// Performs a volatile load from the `src` pointer.
+///
+/// The stabilized version of this intrinsic is [`core::ptr::read_volatile`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn volatile_load<T>(_src: *const T) -> T {
+    unreachable!()
+}
+/// Performs a volatile store to the `dst` pointer.
+///
+/// The stabilized version of this intrinsic is [`core::ptr::write_volatile`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn volatile_store<T>(_dst: *mut T, _val: T) {
+    unreachable!()
+}
 
-    /// Performs a volatile load from the `src` pointer
-    /// The pointer is not required to be aligned.
-    ///
-    /// This intrinsic does not have a stable counterpart.
-    #[rustc_nounwind]
-    #[rustc_diagnostic_item = "intrinsics_unaligned_volatile_load"]
-    pub fn unaligned_volatile_load<T>(src: *const T) -> T;
-    /// Performs a volatile store to the `dst` pointer.
-    /// The pointer is not required to be aligned.
-    ///
-    /// This intrinsic does not have a stable counterpart.
-    #[rustc_nounwind]
-    #[rustc_diagnostic_item = "intrinsics_unaligned_volatile_store"]
-    pub fn unaligned_volatile_store<T>(dst: *mut T, val: T);
+/// Performs a volatile load from the `src` pointer
+/// The pointer is not required to be aligned.
+///
+/// This intrinsic does not have a stable counterpart.
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+#[rustc_diagnostic_item = "intrinsics_unaligned_volatile_load"]
+pub unsafe fn unaligned_volatile_load<T>(_src: *const T) -> T {
+    unreachable!()
+}
+/// Performs a volatile store to the `dst` pointer.
+/// The pointer is not required to be aligned.
+///
+/// This intrinsic does not have a stable counterpart.
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+#[rustc_diagnostic_item = "intrinsics_unaligned_volatile_store"]
+pub unsafe fn unaligned_volatile_store<T>(_dst: *mut T, _val: T) {
+    unreachable!()
+}
 
-    /// Returns the square root of an `f16`
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f16::sqrt`](../../std/primitive.f16.html#method.sqrt)
-    #[rustc_nounwind]
-    pub fn sqrtf16(x: f16) -> f16;
-    /// Returns the square root of an `f32`
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f32::sqrt`](../../std/primitive.f32.html#method.sqrt)
-    #[rustc_nounwind]
-    pub fn sqrtf32(x: f32) -> f32;
-    /// Returns the square root of an `f64`
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f64::sqrt`](../../std/primitive.f64.html#method.sqrt)
-    #[rustc_nounwind]
-    pub fn sqrtf64(x: f64) -> f64;
-    /// Returns the square root of an `f128`
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f128::sqrt`](../../std/primitive.f128.html#method.sqrt)
-    #[rustc_nounwind]
-    pub fn sqrtf128(x: f128) -> f128;
+/// Returns the square root of an `f16`
+///
+/// The stabilized version of this intrinsic is
+/// [`f16::sqrt`](../../std/primitive.f16.html#method.sqrt)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn sqrtf16(_x: f16) -> f16 {
+    unreachable!()
+}
+/// Returns the square root of an `f32`
+///
+/// The stabilized version of this intrinsic is
+/// [`f32::sqrt`](../../std/primitive.f32.html#method.sqrt)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn sqrtf32(_x: f32) -> f32 {
+    unreachable!()
+}
+/// Returns the square root of an `f64`
+///
+/// The stabilized version of this intrinsic is
+/// [`f64::sqrt`](../../std/primitive.f64.html#method.sqrt)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn sqrtf64(_x: f64) -> f64 {
+    unreachable!()
+}
+/// Returns the square root of an `f128`
+///
+/// The stabilized version of this intrinsic is
+/// [`f128::sqrt`](../../std/primitive.f128.html#method.sqrt)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn sqrtf128(_x: f128) -> f128 {
+    unreachable!()
+}
 
-    /// Raises an `f16` to an integer power.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f16::powi`](../../std/primitive.f16.html#method.powi)
-    #[rustc_nounwind]
-    pub fn powif16(a: f16, x: i32) -> f16;
-    /// Raises an `f32` to an integer power.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f32::powi`](../../std/primitive.f32.html#method.powi)
-    #[rustc_nounwind]
-    pub fn powif32(a: f32, x: i32) -> f32;
-    /// Raises an `f64` to an integer power.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f64::powi`](../../std/primitive.f64.html#method.powi)
-    #[rustc_nounwind]
-    pub fn powif64(a: f64, x: i32) -> f64;
-    /// Raises an `f128` to an integer power.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f128::powi`](../../std/primitive.f128.html#method.powi)
-    #[rustc_nounwind]
-    pub fn powif128(a: f128, x: i32) -> f128;
+/// Raises an `f16` to an integer power.
+///
+/// The stabilized version of this intrinsic is
+/// [`f16::powi`](../../std/primitive.f16.html#method.powi)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn powif16(_a: f16, _x: i32) -> f16 {
+    unreachable!()
+}
+/// Raises an `f32` to an integer power.
+///
+/// The stabilized version of this intrinsic is
+/// [`f32::powi`](../../std/primitive.f32.html#method.powi)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn powif32(_a: f32, _x: i32) -> f32 {
+    unreachable!()
+}
+/// Raises an `f64` to an integer power.
+///
+/// The stabilized version of this intrinsic is
+/// [`f64::powi`](../../std/primitive.f64.html#method.powi)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn powif64(_a: f64, _x: i32) -> f64 {
+    unreachable!()
+}
+/// Raises an `f128` to an integer power.
+///
+/// The stabilized version of this intrinsic is
+/// [`f128::powi`](../../std/primitive.f128.html#method.powi)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn powif128(_a: f128, _x: i32) -> f128 {
+    unreachable!()
+}
 
-    /// Returns the sine of an `f16`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f16::sin`](../../std/primitive.f16.html#method.sin)
-    #[rustc_nounwind]
-    pub fn sinf16(x: f16) -> f16;
-    /// Returns the sine of an `f32`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f32::sin`](../../std/primitive.f32.html#method.sin)
-    #[rustc_nounwind]
-    pub fn sinf32(x: f32) -> f32;
-    /// Returns the sine of an `f64`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f64::sin`](../../std/primitive.f64.html#method.sin)
-    #[rustc_nounwind]
-    pub fn sinf64(x: f64) -> f64;
-    /// Returns the sine of an `f128`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f128::sin`](../../std/primitive.f128.html#method.sin)
-    #[rustc_nounwind]
-    pub fn sinf128(x: f128) -> f128;
+/// Returns the sine of an `f16`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f16::sin`](../../std/primitive.f16.html#method.sin)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn sinf16(_x: f16) -> f16 {
+    unreachable!()
+}
+/// Returns the sine of an `f32`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f32::sin`](../../std/primitive.f32.html#method.sin)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn sinf32(_x: f32) -> f32 {
+    unreachable!()
+}
+/// Returns the sine of an `f64`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f64::sin`](../../std/primitive.f64.html#method.sin)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn sinf64(_x: f64) -> f64 {
+    unreachable!()
+}
+/// Returns the sine of an `f128`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f128::sin`](../../std/primitive.f128.html#method.sin)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn sinf128(_x: f128) -> f128 {
+    unreachable!()
+}
 
-    /// Returns the cosine of an `f16`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f16::cos`](../../std/primitive.f16.html#method.cos)
-    #[rustc_nounwind]
-    pub fn cosf16(x: f16) -> f16;
-    /// Returns the cosine of an `f32`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f32::cos`](../../std/primitive.f32.html#method.cos)
-    #[rustc_nounwind]
-    pub fn cosf32(x: f32) -> f32;
-    /// Returns the cosine of an `f64`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f64::cos`](../../std/primitive.f64.html#method.cos)
-    #[rustc_nounwind]
-    pub fn cosf64(x: f64) -> f64;
-    /// Returns the cosine of an `f128`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f128::cos`](../../std/primitive.f128.html#method.cos)
-    #[rustc_nounwind]
-    pub fn cosf128(x: f128) -> f128;
+/// Returns the cosine of an `f16`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f16::cos`](../../std/primitive.f16.html#method.cos)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn cosf16(_x: f16) -> f16 {
+    unreachable!()
+}
+/// Returns the cosine of an `f32`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f32::cos`](../../std/primitive.f32.html#method.cos)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn cosf32(_x: f32) -> f32 {
+    unreachable!()
+}
+/// Returns the cosine of an `f64`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f64::cos`](../../std/primitive.f64.html#method.cos)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn cosf64(_x: f64) -> f64 {
+    unreachable!()
+}
+/// Returns the cosine of an `f128`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f128::cos`](../../std/primitive.f128.html#method.cos)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn cosf128(_x: f128) -> f128 {
+    unreachable!()
+}
 
-    /// Raises an `f16` to an `f16` power.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f16::powf`](../../std/primitive.f16.html#method.powf)
-    #[rustc_nounwind]
-    pub fn powf16(a: f16, x: f16) -> f16;
-    /// Raises an `f32` to an `f32` power.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f32::powf`](../../std/primitive.f32.html#method.powf)
-    #[rustc_nounwind]
-    pub fn powf32(a: f32, x: f32) -> f32;
-    /// Raises an `f64` to an `f64` power.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f64::powf`](../../std/primitive.f64.html#method.powf)
-    #[rustc_nounwind]
-    pub fn powf64(a: f64, x: f64) -> f64;
-    /// Raises an `f128` to an `f128` power.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f128::powf`](../../std/primitive.f128.html#method.powf)
-    #[rustc_nounwind]
-    pub fn powf128(a: f128, x: f128) -> f128;
+/// Raises an `f16` to an `f16` power.
+///
+/// The stabilized version of this intrinsic is
+/// [`f16::powf`](../../std/primitive.f16.html#method.powf)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn powf16(_a: f16, _x: f16) -> f16 {
+    unreachable!()
+}
+/// Raises an `f32` to an `f32` power.
+///
+/// The stabilized version of this intrinsic is
+/// [`f32::powf`](../../std/primitive.f32.html#method.powf)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn powf32(_a: f32, _x: f32) -> f32 {
+    unreachable!()
+}
+/// Raises an `f64` to an `f64` power.
+///
+/// The stabilized version of this intrinsic is
+/// [`f64::powf`](../../std/primitive.f64.html#method.powf)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn powf64(_a: f64, _x: f64) -> f64 {
+    unreachable!()
+}
+/// Raises an `f128` to an `f128` power.
+///
+/// The stabilized version of this intrinsic is
+/// [`f128::powf`](../../std/primitive.f128.html#method.powf)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn powf128(_a: f128, _x: f128) -> f128 {
+    unreachable!()
+}
 
-    /// Returns the exponential of an `f16`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f16::exp`](../../std/primitive.f16.html#method.exp)
-    #[rustc_nounwind]
-    pub fn expf16(x: f16) -> f16;
-    /// Returns the exponential of an `f32`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f32::exp`](../../std/primitive.f32.html#method.exp)
-    #[rustc_nounwind]
-    pub fn expf32(x: f32) -> f32;
-    /// Returns the exponential of an `f64`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f64::exp`](../../std/primitive.f64.html#method.exp)
-    #[rustc_nounwind]
-    pub fn expf64(x: f64) -> f64;
-    /// Returns the exponential of an `f128`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f128::exp`](../../std/primitive.f128.html#method.exp)
-    #[rustc_nounwind]
-    pub fn expf128(x: f128) -> f128;
+/// Returns the exponential of an `f16`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f16::exp`](../../std/primitive.f16.html#method.exp)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn expf16(_x: f16) -> f16 {
+    unreachable!()
+}
+/// Returns the exponential of an `f32`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f32::exp`](../../std/primitive.f32.html#method.exp)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn expf32(_x: f32) -> f32 {
+    unreachable!()
+}
+/// Returns the exponential of an `f64`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f64::exp`](../../std/primitive.f64.html#method.exp)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn expf64(_x: f64) -> f64 {
+    unreachable!()
+}
+/// Returns the exponential of an `f128`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f128::exp`](../../std/primitive.f128.html#method.exp)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn expf128(_x: f128) -> f128 {
+    unreachable!()
+}
 
-    /// Returns 2 raised to the power of an `f16`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f16::exp2`](../../std/primitive.f16.html#method.exp2)
-    #[rustc_nounwind]
-    pub fn exp2f16(x: f16) -> f16;
-    /// Returns 2 raised to the power of an `f32`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f32::exp2`](../../std/primitive.f32.html#method.exp2)
-    #[rustc_nounwind]
-    pub fn exp2f32(x: f32) -> f32;
-    /// Returns 2 raised to the power of an `f64`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f64::exp2`](../../std/primitive.f64.html#method.exp2)
-    #[rustc_nounwind]
-    pub fn exp2f64(x: f64) -> f64;
-    /// Returns 2 raised to the power of an `f128`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f128::exp2`](../../std/primitive.f128.html#method.exp2)
-    #[rustc_nounwind]
-    pub fn exp2f128(x: f128) -> f128;
+/// Returns 2 raised to the power of an `f16`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f16::exp2`](../../std/primitive.f16.html#method.exp2)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn exp2f16(_x: f16) -> f16 {
+    unreachable!()
+}
+/// Returns 2 raised to the power of an `f32`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f32::exp2`](../../std/primitive.f32.html#method.exp2)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn exp2f32(_x: f32) -> f32 {
+    unreachable!()
+}
+/// Returns 2 raised to the power of an `f64`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f64::exp2`](../../std/primitive.f64.html#method.exp2)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn exp2f64(_x: f64) -> f64 {
+    unreachable!()
+}
+/// Returns 2 raised to the power of an `f128`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f128::exp2`](../../std/primitive.f128.html#method.exp2)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn exp2f128(_x: f128) -> f128 {
+    unreachable!()
+}
 
-    /// Returns the natural logarithm of an `f16`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f16::ln`](../../std/primitive.f16.html#method.ln)
-    #[rustc_nounwind]
-    pub fn logf16(x: f16) -> f16;
-    /// Returns the natural logarithm of an `f32`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f32::ln`](../../std/primitive.f32.html#method.ln)
-    #[rustc_nounwind]
-    pub fn logf32(x: f32) -> f32;
-    /// Returns the natural logarithm of an `f64`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f64::ln`](../../std/primitive.f64.html#method.ln)
-    #[rustc_nounwind]
-    pub fn logf64(x: f64) -> f64;
-    /// Returns the natural logarithm of an `f128`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f128::ln`](../../std/primitive.f128.html#method.ln)
-    #[rustc_nounwind]
-    pub fn logf128(x: f128) -> f128;
+/// Returns the natural logarithm of an `f16`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f16::ln`](../../std/primitive.f16.html#method.ln)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn logf16(_x: f16) -> f16 {
+    unreachable!()
+}
+/// Returns the natural logarithm of an `f32`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f32::ln`](../../std/primitive.f32.html#method.ln)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn logf32(_x: f32) -> f32 {
+    unreachable!()
+}
+/// Returns the natural logarithm of an `f64`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f64::ln`](../../std/primitive.f64.html#method.ln)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn logf64(_x: f64) -> f64 {
+    unreachable!()
+}
+/// Returns the natural logarithm of an `f128`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f128::ln`](../../std/primitive.f128.html#method.ln)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn logf128(_x: f128) -> f128 {
+    unreachable!()
+}
 
-    /// Returns the base 10 logarithm of an `f16`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f16::log10`](../../std/primitive.f16.html#method.log10)
-    #[rustc_nounwind]
-    pub fn log10f16(x: f16) -> f16;
-    /// Returns the base 10 logarithm of an `f32`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f32::log10`](../../std/primitive.f32.html#method.log10)
-    #[rustc_nounwind]
-    pub fn log10f32(x: f32) -> f32;
-    /// Returns the base 10 logarithm of an `f64`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f64::log10`](../../std/primitive.f64.html#method.log10)
-    #[rustc_nounwind]
-    pub fn log10f64(x: f64) -> f64;
-    /// Returns the base 10 logarithm of an `f128`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f128::log10`](../../std/primitive.f128.html#method.log10)
-    #[rustc_nounwind]
-    pub fn log10f128(x: f128) -> f128;
+/// Returns the base 10 logarithm of an `f16`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f16::log10`](../../std/primitive.f16.html#method.log10)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn log10f16(_x: f16) -> f16 {
+    unreachable!()
+}
+/// Returns the base 10 logarithm of an `f32`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f32::log10`](../../std/primitive.f32.html#method.log10)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn log10f32(_x: f32) -> f32 {
+    unreachable!()
+}
+/// Returns the base 10 logarithm of an `f64`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f64::log10`](../../std/primitive.f64.html#method.log10)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn log10f64(_x: f64) -> f64 {
+    unreachable!()
+}
+/// Returns the base 10 logarithm of an `f128`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f128::log10`](../../std/primitive.f128.html#method.log10)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn log10f128(_x: f128) -> f128 {
+    unreachable!()
+}
 
-    /// Returns the base 2 logarithm of an `f16`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f16::log2`](../../std/primitive.f16.html#method.log2)
-    #[rustc_nounwind]
-    pub fn log2f16(x: f16) -> f16;
-    /// Returns the base 2 logarithm of an `f32`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f32::log2`](../../std/primitive.f32.html#method.log2)
-    #[rustc_nounwind]
-    pub fn log2f32(x: f32) -> f32;
-    /// Returns the base 2 logarithm of an `f64`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f64::log2`](../../std/primitive.f64.html#method.log2)
-    #[rustc_nounwind]
-    pub fn log2f64(x: f64) -> f64;
-    /// Returns the base 2 logarithm of an `f128`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f128::log2`](../../std/primitive.f128.html#method.log2)
-    #[rustc_nounwind]
-    pub fn log2f128(x: f128) -> f128;
+/// Returns the base 2 logarithm of an `f16`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f16::log2`](../../std/primitive.f16.html#method.log2)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn log2f16(_x: f16) -> f16 {
+    unreachable!()
+}
+/// Returns the base 2 logarithm of an `f32`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f32::log2`](../../std/primitive.f32.html#method.log2)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn log2f32(_x: f32) -> f32 {
+    unreachable!()
+}
+/// Returns the base 2 logarithm of an `f64`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f64::log2`](../../std/primitive.f64.html#method.log2)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn log2f64(_x: f64) -> f64 {
+    unreachable!()
+}
+/// Returns the base 2 logarithm of an `f128`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f128::log2`](../../std/primitive.f128.html#method.log2)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn log2f128(_x: f128) -> f128 {
+    unreachable!()
+}
 
-    /// Returns `a * b + c` for `f16` values.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f16::mul_add`](../../std/primitive.f16.html#method.mul_add)
-    #[rustc_nounwind]
-    pub fn fmaf16(a: f16, b: f16, c: f16) -> f16;
-    /// Returns `a * b + c` for `f32` values.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f32::mul_add`](../../std/primitive.f32.html#method.mul_add)
-    #[rustc_nounwind]
-    pub fn fmaf32(a: f32, b: f32, c: f32) -> f32;
-    /// Returns `a * b + c` for `f64` values.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f64::mul_add`](../../std/primitive.f64.html#method.mul_add)
-    #[rustc_nounwind]
-    pub fn fmaf64(a: f64, b: f64, c: f64) -> f64;
-    /// Returns `a * b + c` for `f128` values.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f128::mul_add`](../../std/primitive.f128.html#method.mul_add)
-    #[rustc_nounwind]
-    pub fn fmaf128(a: f128, b: f128, c: f128) -> f128;
+/// Returns `a * b + c` for `f16` values.
+///
+/// The stabilized version of this intrinsic is
+/// [`f16::mul_add`](../../std/primitive.f16.html#method.mul_add)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn fmaf16(_a: f16, _b: f16, _c: f16) -> f16 {
+    unreachable!()
+}
+/// Returns `a * b + c` for `f32` values.
+///
+/// The stabilized version of this intrinsic is
+/// [`f32::mul_add`](../../std/primitive.f32.html#method.mul_add)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn fmaf32(_a: f32, _b: f32, _c: f32) -> f32 {
+    unreachable!()
+}
+/// Returns `a * b + c` for `f64` values.
+///
+/// The stabilized version of this intrinsic is
+/// [`f64::mul_add`](../../std/primitive.f64.html#method.mul_add)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn fmaf64(_a: f64, _b: f64, _c: f64) -> f64 {
+    unreachable!()
+}
+/// Returns `a * b + c` for `f128` values.
+///
+/// The stabilized version of this intrinsic is
+/// [`f128::mul_add`](../../std/primitive.f128.html#method.mul_add)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn fmaf128(_a: f128, _b: f128, _c: f128) -> f128 {
+    unreachable!()
+}
 
-    /// Returns `a * b + c` for `f16` values, non-deterministically executing
-    /// either a fused multiply-add or two operations with rounding of the
-    /// intermediate result.
-    ///
-    /// The operation is fused if the code generator determines that target
-    /// instruction set has support for a fused operation, and that the fused
-    /// operation is more efficient than the equivalent, separate pair of mul
-    /// and add instructions. It is unspecified whether or not a fused operation
-    /// is selected, and that may depend on optimization level and context, for
-    /// example.
-    #[rustc_nounwind]
-    pub fn fmuladdf16(a: f16, b: f16, c: f16) -> f16;
-    /// Returns `a * b + c` for `f32` values, non-deterministically executing
-    /// either a fused multiply-add or two operations with rounding of the
-    /// intermediate result.
-    ///
-    /// The operation is fused if the code generator determines that target
-    /// instruction set has support for a fused operation, and that the fused
-    /// operation is more efficient than the equivalent, separate pair of mul
-    /// and add instructions. It is unspecified whether or not a fused operation
-    /// is selected, and that may depend on optimization level and context, for
-    /// example.
-    #[rustc_nounwind]
-    pub fn fmuladdf32(a: f32, b: f32, c: f32) -> f32;
-    /// Returns `a * b + c` for `f64` values, non-deterministically executing
-    /// either a fused multiply-add or two operations with rounding of the
-    /// intermediate result.
-    ///
-    /// The operation is fused if the code generator determines that target
-    /// instruction set has support for a fused operation, and that the fused
-    /// operation is more efficient than the equivalent, separate pair of mul
-    /// and add instructions. It is unspecified whether or not a fused operation
-    /// is selected, and that may depend on optimization level and context, for
-    /// example.
-    #[rustc_nounwind]
-    pub fn fmuladdf64(a: f64, b: f64, c: f64) -> f64;
-    /// Returns `a * b + c` for `f128` values, non-deterministically executing
-    /// either a fused multiply-add or two operations with rounding of the
-    /// intermediate result.
-    ///
-    /// The operation is fused if the code generator determines that target
-    /// instruction set has support for a fused operation, and that the fused
-    /// operation is more efficient than the equivalent, separate pair of mul
-    /// and add instructions. It is unspecified whether or not a fused operation
-    /// is selected, and that may depend on optimization level and context, for
-    /// example.
-    #[rustc_nounwind]
-    pub fn fmuladdf128(a: f128, b: f128, c: f128) -> f128;
+/// Returns `a * b + c` for `f16` values, non-deterministically executing
+/// either a fused multiply-add or two operations with rounding of the
+/// intermediate result.
+///
+/// The operation is fused if the code generator determines that target
+/// instruction set has support for a fused operation, and that the fused
+/// operation is more efficient than the equivalent, separate pair of mul
+/// and add instructions. It is unspecified whether or not a fused operation
+/// is selected, and that may depend on optimization level and context, for
+/// example.
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn fmuladdf16(_a: f16, _b: f16, _c: f16) -> f16 {
+    unreachable!()
+}
+/// Returns `a * b + c` for `f32` values, non-deterministically executing
+/// either a fused multiply-add or two operations with rounding of the
+/// intermediate result.
+///
+/// The operation is fused if the code generator determines that target
+/// instruction set has support for a fused operation, and that the fused
+/// operation is more efficient than the equivalent, separate pair of mul
+/// and add instructions. It is unspecified whether or not a fused operation
+/// is selected, and that may depend on optimization level and context, for
+/// example.
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn fmuladdf32(_a: f32, _b: f32, _c: f32) -> f32 {
+    unreachable!()
+}
+/// Returns `a * b + c` for `f64` values, non-deterministically executing
+/// either a fused multiply-add or two operations with rounding of the
+/// intermediate result.
+///
+/// The operation is fused if the code generator determines that target
+/// instruction set has support for a fused operation, and that the fused
+/// operation is more efficient than the equivalent, separate pair of mul
+/// and add instructions. It is unspecified whether or not a fused operation
+/// is selected, and that may depend on optimization level and context, for
+/// example.
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn fmuladdf64(_a: f64, _b: f64, _c: f64) -> f64 {
+    unreachable!()
+}
+/// Returns `a * b + c` for `f128` values, non-deterministically executing
+/// either a fused multiply-add or two operations with rounding of the
+/// intermediate result.
+///
+/// The operation is fused if the code generator determines that target
+/// instruction set has support for a fused operation, and that the fused
+/// operation is more efficient than the equivalent, separate pair of mul
+/// and add instructions. It is unspecified whether or not a fused operation
+/// is selected, and that may depend on optimization level and context, for
+/// example.
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn fmuladdf128(_a: f128, _b: f128, _c: f128) -> f128 {
+    unreachable!()
+}
 
-    /// Returns the largest integer less than or equal to an `f16`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f16::floor`](../../std/primitive.f16.html#method.floor)
-    #[rustc_nounwind]
-    pub fn floorf16(x: f16) -> f16;
-    /// Returns the largest integer less than or equal to an `f32`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f32::floor`](../../std/primitive.f32.html#method.floor)
-    #[rustc_nounwind]
-    pub fn floorf32(x: f32) -> f32;
-    /// Returns the largest integer less than or equal to an `f64`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f64::floor`](../../std/primitive.f64.html#method.floor)
-    #[rustc_nounwind]
-    pub fn floorf64(x: f64) -> f64;
-    /// Returns the largest integer less than or equal to an `f128`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f128::floor`](../../std/primitive.f128.html#method.floor)
-    #[rustc_nounwind]
-    pub fn floorf128(x: f128) -> f128;
+/// Returns the largest integer less than or equal to an `f16`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f16::floor`](../../std/primitive.f16.html#method.floor)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn floorf16(_x: f16) -> f16 {
+    unreachable!()
+}
+/// Returns the largest integer less than or equal to an `f32`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f32::floor`](../../std/primitive.f32.html#method.floor)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn floorf32(_x: f32) -> f32 {
+    unreachable!()
+}
+/// Returns the largest integer less than or equal to an `f64`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f64::floor`](../../std/primitive.f64.html#method.floor)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn floorf64(_x: f64) -> f64 {
+    unreachable!()
+}
+/// Returns the largest integer less than or equal to an `f128`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f128::floor`](../../std/primitive.f128.html#method.floor)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn floorf128(_x: f128) -> f128 {
+    unreachable!()
+}
 
-    /// Returns the smallest integer greater than or equal to an `f16`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f16::ceil`](../../std/primitive.f16.html#method.ceil)
-    #[rustc_nounwind]
-    pub fn ceilf16(x: f16) -> f16;
-    /// Returns the smallest integer greater than or equal to an `f32`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f32::ceil`](../../std/primitive.f32.html#method.ceil)
-    #[rustc_nounwind]
-    pub fn ceilf32(x: f32) -> f32;
-    /// Returns the smallest integer greater than or equal to an `f64`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f64::ceil`](../../std/primitive.f64.html#method.ceil)
-    #[rustc_nounwind]
-    pub fn ceilf64(x: f64) -> f64;
-    /// Returns the smallest integer greater than or equal to an `f128`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f128::ceil`](../../std/primitive.f128.html#method.ceil)
-    #[rustc_nounwind]
-    pub fn ceilf128(x: f128) -> f128;
+/// Returns the smallest integer greater than or equal to an `f16`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f16::ceil`](../../std/primitive.f16.html#method.ceil)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn ceilf16(_x: f16) -> f16 {
+    unreachable!()
+}
+/// Returns the smallest integer greater than or equal to an `f32`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f32::ceil`](../../std/primitive.f32.html#method.ceil)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn ceilf32(_x: f32) -> f32 {
+    unreachable!()
+}
+/// Returns the smallest integer greater than or equal to an `f64`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f64::ceil`](../../std/primitive.f64.html#method.ceil)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn ceilf64(_x: f64) -> f64 {
+    unreachable!()
+}
+/// Returns the smallest integer greater than or equal to an `f128`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f128::ceil`](../../std/primitive.f128.html#method.ceil)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn ceilf128(_x: f128) -> f128 {
+    unreachable!()
+}
 
-    /// Returns the integer part of an `f16`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f16::trunc`](../../std/primitive.f16.html#method.trunc)
-    #[rustc_nounwind]
-    pub fn truncf16(x: f16) -> f16;
-    /// Returns the integer part of an `f32`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f32::trunc`](../../std/primitive.f32.html#method.trunc)
-    #[rustc_nounwind]
-    pub fn truncf32(x: f32) -> f32;
-    /// Returns the integer part of an `f64`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f64::trunc`](../../std/primitive.f64.html#method.trunc)
-    #[rustc_nounwind]
-    pub fn truncf64(x: f64) -> f64;
-    /// Returns the integer part of an `f128`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f128::trunc`](../../std/primitive.f128.html#method.trunc)
-    #[rustc_nounwind]
-    pub fn truncf128(x: f128) -> f128;
+/// Returns the integer part of an `f16`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f16::trunc`](../../std/primitive.f16.html#method.trunc)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn truncf16(_x: f16) -> f16 {
+    unreachable!()
+}
+/// Returns the integer part of an `f32`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f32::trunc`](../../std/primitive.f32.html#method.trunc)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn truncf32(_x: f32) -> f32 {
+    unreachable!()
+}
+/// Returns the integer part of an `f64`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f64::trunc`](../../std/primitive.f64.html#method.trunc)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn truncf64(_x: f64) -> f64 {
+    unreachable!()
+}
+/// Returns the integer part of an `f128`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f128::trunc`](../../std/primitive.f128.html#method.trunc)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn truncf128(_x: f128) -> f128 {
+    unreachable!()
+}
 
-    /// Returns the nearest integer to an `f16`. Changing the rounding mode is not possible in Rust,
-    /// so this rounds half-way cases to the number with an even least significant digit.
-    ///
-    /// May raise an inexact floating-point exception if the argument is not an integer.
-    /// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions
-    /// cannot actually be utilized from Rust code.
-    /// In other words, this intrinsic is equivalent in behavior to `nearbyintf16` and `roundevenf16`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f16::round_ties_even`](../../std/primitive.f16.html#method.round_ties_even)
-    #[rustc_nounwind]
-    pub fn rintf16(x: f16) -> f16;
-    /// Returns the nearest integer to an `f32`. Changing the rounding mode is not possible in Rust,
-    /// so this rounds half-way cases to the number with an even least significant digit.
-    ///
-    /// May raise an inexact floating-point exception if the argument is not an integer.
-    /// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions
-    /// cannot actually be utilized from Rust code.
-    /// In other words, this intrinsic is equivalent in behavior to `nearbyintf32` and `roundevenf32`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f32::round_ties_even`](../../std/primitive.f32.html#method.round_ties_even)
-    #[rustc_nounwind]
-    pub fn rintf32(x: f32) -> f32;
-    /// Returns the nearest integer to an `f64`. Changing the rounding mode is not possible in Rust,
-    /// so this rounds half-way cases to the number with an even least significant digit.
-    ///
-    /// May raise an inexact floating-point exception if the argument is not an integer.
-    /// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions
-    /// cannot actually be utilized from Rust code.
-    /// In other words, this intrinsic is equivalent in behavior to `nearbyintf64` and `roundevenf64`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f64::round_ties_even`](../../std/primitive.f64.html#method.round_ties_even)
-    #[rustc_nounwind]
-    pub fn rintf64(x: f64) -> f64;
-    /// Returns the nearest integer to an `f128`. Changing the rounding mode is not possible in Rust,
-    /// so this rounds half-way cases to the number with an even least significant digit.
-    ///
-    /// May raise an inexact floating-point exception if the argument is not an integer.
-    /// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions
-    /// cannot actually be utilized from Rust code.
-    /// In other words, this intrinsic is equivalent in behavior to `nearbyintf128` and `roundevenf128`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f128::round_ties_even`](../../std/primitive.f128.html#method.round_ties_even)
-    #[rustc_nounwind]
-    pub fn rintf128(x: f128) -> f128;
+/// Returns the nearest integer to an `f16`. Changing the rounding mode is not possible in Rust,
+/// so this rounds half-way cases to the number with an even least significant digit.
+///
+/// May raise an inexact floating-point exception if the argument is not an integer.
+/// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions
+/// cannot actually be utilized from Rust code.
+/// In other words, this intrinsic is equivalent in behavior to `nearbyintf16` and `roundevenf16`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f16::round_ties_even`](../../std/primitive.f16.html#method.round_ties_even)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn rintf16(_x: f16) -> f16 {
+    unreachable!()
+}
+/// Returns the nearest integer to an `f32`. Changing the rounding mode is not possible in Rust,
+/// so this rounds half-way cases to the number with an even least significant digit.
+///
+/// May raise an inexact floating-point exception if the argument is not an integer.
+/// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions
+/// cannot actually be utilized from Rust code.
+/// In other words, this intrinsic is equivalent in behavior to `nearbyintf32` and `roundevenf32`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f32::round_ties_even`](../../std/primitive.f32.html#method.round_ties_even)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn rintf32(_x: f32) -> f32 {
+    unreachable!()
+}
+/// Returns the nearest integer to an `f64`. Changing the rounding mode is not possible in Rust,
+/// so this rounds half-way cases to the number with an even least significant digit.
+///
+/// May raise an inexact floating-point exception if the argument is not an integer.
+/// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions
+/// cannot actually be utilized from Rust code.
+/// In other words, this intrinsic is equivalent in behavior to `nearbyintf64` and `roundevenf64`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f64::round_ties_even`](../../std/primitive.f64.html#method.round_ties_even)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn rintf64(_x: f64) -> f64 {
+    unreachable!()
+}
+/// Returns the nearest integer to an `f128`. Changing the rounding mode is not possible in Rust,
+/// so this rounds half-way cases to the number with an even least significant digit.
+///
+/// May raise an inexact floating-point exception if the argument is not an integer.
+/// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions
+/// cannot actually be utilized from Rust code.
+/// In other words, this intrinsic is equivalent in behavior to `nearbyintf128` and `roundevenf128`.
+///
+/// The stabilized version of this intrinsic is
+/// [`f128::round_ties_even`](../../std/primitive.f128.html#method.round_ties_even)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn rintf128(_x: f128) -> f128 {
+    unreachable!()
+}
 
-    /// Returns the nearest integer to an `f16`. Changing the rounding mode is not possible in Rust,
-    /// so this rounds half-way cases to the number with an even least significant digit.
-    ///
-    /// This intrinsic does not have a stable counterpart.
-    #[rustc_nounwind]
-    pub fn nearbyintf16(x: f16) -> f16;
-    /// Returns the nearest integer to an `f32`. Changing the rounding mode is not possible in Rust,
-    /// so this rounds half-way cases to the number with an even least significant digit.
-    ///
-    /// This intrinsic does not have a stable counterpart.
-    #[rustc_nounwind]
-    pub fn nearbyintf32(x: f32) -> f32;
-    /// Returns the nearest integer to an `f64`. Changing the rounding mode is not possible in Rust,
-    /// so this rounds half-way cases to the number with an even least significant digit.
-    ///
-    /// This intrinsic does not have a stable counterpart.
-    #[rustc_nounwind]
-    pub fn nearbyintf64(x: f64) -> f64;
-    /// Returns the nearest integer to an `f128`. Changing the rounding mode is not possible in Rust,
-    /// so this rounds half-way cases to the number with an even least significant digit.
-    ///
-    /// This intrinsic does not have a stable counterpart.
-    #[rustc_nounwind]
-    pub fn nearbyintf128(x: f128) -> f128;
+/// Returns the nearest integer to an `f16`. Changing the rounding mode is not possible in Rust,
+/// so this rounds half-way cases to the number with an even least significant digit.
+///
+/// This intrinsic does not have a stable counterpart.
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn nearbyintf16(_x: f16) -> f16 {
+    unreachable!()
+}
+/// Returns the nearest integer to an `f32`. Changing the rounding mode is not possible in Rust,
+/// so this rounds half-way cases to the number with an even least significant digit.
+///
+/// This intrinsic does not have a stable counterpart.
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn nearbyintf32(_x: f32) -> f32 {
+    unreachable!()
+}
+/// Returns the nearest integer to an `f64`. Changing the rounding mode is not possible in Rust,
+/// so this rounds half-way cases to the number with an even least significant digit.
+///
+/// This intrinsic does not have a stable counterpart.
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn nearbyintf64(_x: f64) -> f64 {
+    unreachable!()
+}
+/// Returns the nearest integer to an `f128`. Changing the rounding mode is not possible in Rust,
+/// so this rounds half-way cases to the number with an even least significant digit.
+///
+/// This intrinsic does not have a stable counterpart.
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn nearbyintf128(_x: f128) -> f128 {
+    unreachable!()
+}
 
-    /// Returns the nearest integer to an `f16`. Rounds half-way cases away from zero.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f16::round`](../../std/primitive.f16.html#method.round)
-    #[rustc_nounwind]
-    pub fn roundf16(x: f16) -> f16;
-    /// Returns the nearest integer to an `f32`. Rounds half-way cases away from zero.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f32::round`](../../std/primitive.f32.html#method.round)
-    #[rustc_nounwind]
-    pub fn roundf32(x: f32) -> f32;
-    /// Returns the nearest integer to an `f64`. Rounds half-way cases away from zero.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f64::round`](../../std/primitive.f64.html#method.round)
-    #[rustc_nounwind]
-    pub fn roundf64(x: f64) -> f64;
-    /// Returns the nearest integer to an `f128`. Rounds half-way cases away from zero.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`f128::round`](../../std/primitive.f128.html#method.round)
-    #[rustc_nounwind]
-    pub fn roundf128(x: f128) -> f128;
+/// Returns the nearest integer to an `f16`. Rounds half-way cases away from zero.
+///
+/// The stabilized version of this intrinsic is
+/// [`f16::round`](../../std/primitive.f16.html#method.round)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn roundf16(_x: f16) -> f16 {
+    unreachable!()
+}
+/// Returns the nearest integer to an `f32`. Rounds half-way cases away from zero.
+///
+/// The stabilized version of this intrinsic is
+/// [`f32::round`](../../std/primitive.f32.html#method.round)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn roundf32(_x: f32) -> f32 {
+    unreachable!()
+}
+/// Returns the nearest integer to an `f64`. Rounds half-way cases away from zero.
+///
+/// The stabilized version of this intrinsic is
+/// [`f64::round`](../../std/primitive.f64.html#method.round)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn roundf64(_x: f64) -> f64 {
+    unreachable!()
+}
+/// Returns the nearest integer to an `f128`. Rounds half-way cases away from zero.
+///
+/// The stabilized version of this intrinsic is
+/// [`f128::round`](../../std/primitive.f128.html#method.round)
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn roundf128(_x: f128) -> f128 {
+    unreachable!()
+}
 
-    /// Returns the nearest integer to an `f16`. Rounds half-way cases to the number
-    /// with an even least significant digit.
-    ///
-    /// This intrinsic does not have a stable counterpart.
-    #[rustc_nounwind]
-    pub fn roundevenf16(x: f16) -> f16;
-    /// Returns the nearest integer to an `f32`. Rounds half-way cases to the number
-    /// with an even least significant digit.
-    ///
-    /// This intrinsic does not have a stable counterpart.
-    #[rustc_nounwind]
-    pub fn roundevenf32(x: f32) -> f32;
-    /// Returns the nearest integer to an `f64`. Rounds half-way cases to the number
-    /// with an even least significant digit.
-    ///
-    /// This intrinsic does not have a stable counterpart.
-    #[rustc_nounwind]
-    pub fn roundevenf64(x: f64) -> f64;
-    /// Returns the nearest integer to an `f128`. Rounds half-way cases to the number
-    /// with an even least significant digit.
-    ///
-    /// This intrinsic does not have a stable counterpart.
-    #[rustc_nounwind]
-    pub fn roundevenf128(x: f128) -> f128;
+/// Returns the nearest integer to an `f16`. Rounds half-way cases to the number
+/// with an even least significant digit.
+///
+/// This intrinsic does not have a stable counterpart.
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn roundevenf16(_x: f16) -> f16 {
+    unreachable!()
+}
+/// Returns the nearest integer to an `f32`. Rounds half-way cases to the number
+/// with an even least significant digit.
+///
+/// This intrinsic does not have a stable counterpart.
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn roundevenf32(_x: f32) -> f32 {
+    unreachable!()
+}
+/// Returns the nearest integer to an `f64`. Rounds half-way cases to the number
+/// with an even least significant digit.
+///
+/// This intrinsic does not have a stable counterpart.
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn roundevenf64(_x: f64) -> f64 {
+    unreachable!()
+}
+/// Returns the nearest integer to an `f128`. Rounds half-way cases to the number
+/// with an even least significant digit.
+///
+/// This intrinsic does not have a stable counterpart.
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn roundevenf128(_x: f128) -> f128 {
+    unreachable!()
+}
 
-    /// Float addition that allows optimizations based on algebraic rules.
-    /// May assume inputs are finite.
-    ///
-    /// This intrinsic does not have a stable counterpart.
-    #[rustc_nounwind]
-    pub fn fadd_fast<T: Copy>(a: T, b: T) -> T;
+/// Float addition that allows optimizations based on algebraic rules.
+/// May assume inputs are finite.
+///
+/// This intrinsic does not have a stable counterpart.
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn fadd_fast<T: Copy>(_a: T, _b: T) -> T {
+    unreachable!()
+}
 
-    /// Float subtraction that allows optimizations based on algebraic rules.
-    /// May assume inputs are finite.
-    ///
-    /// This intrinsic does not have a stable counterpart.
-    #[rustc_nounwind]
-    pub fn fsub_fast<T: Copy>(a: T, b: T) -> T;
+/// Float subtraction that allows optimizations based on algebraic rules.
+/// May assume inputs are finite.
+///
+/// This intrinsic does not have a stable counterpart.
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn fsub_fast<T: Copy>(_a: T, _b: T) -> T {
+    unreachable!()
+}
 
-    /// Float multiplication that allows optimizations based on algebraic rules.
-    /// May assume inputs are finite.
-    ///
-    /// This intrinsic does not have a stable counterpart.
-    #[rustc_nounwind]
-    pub fn fmul_fast<T: Copy>(a: T, b: T) -> T;
+/// Float multiplication that allows optimizations based on algebraic rules.
+/// May assume inputs are finite.
+///
+/// This intrinsic does not have a stable counterpart.
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn fmul_fast<T: Copy>(_a: T, _b: T) -> T {
+    unreachable!()
+}
 
-    /// Float division that allows optimizations based on algebraic rules.
-    /// May assume inputs are finite.
-    ///
-    /// This intrinsic does not have a stable counterpart.
-    #[rustc_nounwind]
-    pub fn fdiv_fast<T: Copy>(a: T, b: T) -> T;
+/// Float division that allows optimizations based on algebraic rules.
+/// May assume inputs are finite.
+///
+/// This intrinsic does not have a stable counterpart.
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn fdiv_fast<T: Copy>(_a: T, _b: T) -> T {
+    unreachable!()
+}
 
-    /// Float remainder that allows optimizations based on algebraic rules.
-    /// May assume inputs are finite.
-    ///
-    /// This intrinsic does not have a stable counterpart.
-    #[rustc_nounwind]
-    pub fn frem_fast<T: Copy>(a: T, b: T) -> T;
+/// Float remainder that allows optimizations based on algebraic rules.
+/// May assume inputs are finite.
+///
+/// This intrinsic does not have a stable counterpart.
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn frem_fast<T: Copy>(_a: T, _b: T) -> T {
+    unreachable!()
+}
 
-    /// Converts with LLVM’s fptoui/fptosi, which may return undef for values out of range
-    /// (<https://github.com/rust-lang/rust/issues/10184>)
-    ///
-    /// Stabilized as [`f32::to_int_unchecked`] and [`f64::to_int_unchecked`].
-    #[rustc_nounwind]
-    pub fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
+/// Converts with LLVM’s fptoui/fptosi, which may return undef for values out of range
+/// (<https://github.com/rust-lang/rust/issues/10184>)
+///
+/// Stabilized as [`f32::to_int_unchecked`] and [`f64::to_int_unchecked`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int {
+    unreachable!()
 }
 
 /// Float addition that allows optimizations based on algebraic rules.
diff --git a/library/std/src/env.rs b/library/std/src/env.rs
index 27f4daba44b..043747d0bc5 100644
--- a/library/std/src/env.rs
+++ b/library/std/src/env.rs
@@ -608,20 +608,16 @@ impl Error for JoinPathsError {
 ///
 /// # Windows
 ///
-/// - Returns the value of the 'HOME' environment variable if it is set
-///   (including to an empty string).
-/// - Otherwise, returns the value of the 'USERPROFILE' environment variable if it is set
-///   (including to an empty string).
-/// - If both do not exist, [`GetUserProfileDirectory`][msdn] is used to return the path.
+/// - Returns the value of the 'USERPROFILE' environment variable if it is set, and is not an empty string.
+/// - Otherwise, [`GetUserProfileDirectory`][msdn] is used to return the path. This may change in the future.
 ///
 /// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-getuserprofiledirectorya
 ///
-/// # Deprecation
+/// In UWP (Universal Windows Platform) targets this function is unimplemented and always returns `None`.
 ///
-/// This function is deprecated because the behavior on Windows is not correct.
-/// The 'HOME' environment variable is not standard on Windows, and may not produce
-/// desired results; for instance, under Cygwin or Mingw it will return `/home/you`
-/// when it should return `C:\Users\you`.
+/// Before Rust CURRENT_RUSTC_VERSION, this function used to return the value of the 'HOME' environment variable
+/// on Windows, which in Cygwin or Mingw environments could return non-standard paths like `/home/you`
+/// instead of `C:\Users\you`.
 ///
 /// # Examples
 ///
diff --git a/library/std/src/sys/pal/wasi/thread.rs b/library/std/src/sys/pal/wasi/thread.rs
index 4b83870fdea..f5e19f26bfe 100644
--- a/library/std/src/sys/pal/wasi/thread.rs
+++ b/library/std/src/sys/pal/wasi/thread.rs
@@ -2,7 +2,6 @@
 
 use crate::ffi::CStr;
 use crate::num::NonZero;
-use crate::sys::unsupported;
 use crate::time::Duration;
 use crate::{io, mem};
 
@@ -34,6 +33,8 @@ cfg_if::cfg_if! {
             #[allow(non_camel_case_types)]
             pub type pthread_t = *mut ffi::c_void;
 
+            pub const _SC_NPROCESSORS_ONLN: ffi::c_int = 84;
+
             extern "C" {
                 pub fn pthread_create(
                     native: *mut pthread_t,
@@ -121,7 +122,7 @@ impl Thread {
             }
         } else {
             pub unsafe fn new(_stack: usize, _p: Box<dyn FnOnce()>) -> io::Result<Thread> {
-                unsupported()
+                crate::sys::unsupported()
             }
         }
     }
@@ -187,5 +188,14 @@ impl Thread {
 }
 
 pub fn available_parallelism() -> io::Result<NonZero<usize>> {
-    unsupported()
+    cfg_if::cfg_if! {
+        if #[cfg(target_feature = "atomics")] {
+            match unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) } {
+                -1 => Err(io::Error::last_os_error()),
+                cpus => NonZero::new(cpus as usize).ok_or(io::Error::UNKNOWN_THREAD_COUNT),
+            }
+        } else {
+            crate::sys::unsupported()
+        }
+    }
 }
diff --git a/library/std/src/sys/pal/windows/os.rs b/library/std/src/sys/pal/windows/os.rs
index 5242bc9da31..5231a34469a 100644
--- a/library/std/src/sys/pal/windows/os.rs
+++ b/library/std/src/sys/pal/windows/os.rs
@@ -377,8 +377,8 @@ fn home_dir_crt() -> Option<PathBuf> {
 }
 
 pub fn home_dir() -> Option<PathBuf> {
-    crate::env::var_os("HOME")
-        .or_else(|| crate::env::var_os("USERPROFILE"))
+    crate::env::var_os("USERPROFILE")
+        .filter(|s| !s.is_empty())
         .map(PathBuf::from)
         .or_else(home_dir_crt)
 }
diff --git a/library/std/tests/env.rs b/library/std/tests/env.rs
index 4e472b4ce99..44fe84c989f 100644
--- a/library/std/tests/env.rs
+++ b/library/std/tests/env.rs
@@ -122,19 +122,19 @@ fn env_home_dir() {
 
             assert!(home_dir().is_some());
 
-            set_var("HOME", "/home/MountainView");
+            set_var("HOME", "/home/PaloAlto");
+            assert_ne!(home_dir(), Some(PathBuf::from("/home/PaloAlto")), "HOME must not be used");
+
+            set_var("USERPROFILE", "/home/MountainView");
             assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));
 
             remove_var("HOME");
 
-            set_var("USERPROFILE", "/home/MountainView");
             assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));
 
-            set_var("HOME", "/home/MountainView");
-            set_var("USERPROFILE", "/home/PaloAlto");
-            assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));
+            set_var("USERPROFILE", "");
+            assert_ne!(home_dir(), Some(PathBuf::from("")), "Empty USERPROFILE must be ignored");
 
-            remove_var("HOME");
             remove_var("USERPROFILE");
 
             if let Some(oldhome) = oldhome { set_var("HOME", oldhome); }
diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in
index 92c8f5dc452..a1f38b9ac14 100644
--- a/src/bootstrap/mk/Makefile.in
+++ b/src/bootstrap/mk/Makefile.in
@@ -108,11 +108,13 @@ ci-msvc: ci-msvc-py ci-msvc-ps1
 
 ## MingW native builders
 
-# test both x and bootstrap entrypoints
+# Set of tests that should represent half of the time of the test suite.
+# Used to split tests across multiple CI runners.
+# Test both x and bootstrap entrypoints.
 ci-mingw-x:
-	$(Q)$(CFG_SRC_DIR)/x test --stage 2 tidy
+	$(Q)$(CFG_SRC_DIR)/x test --stage 2 --skip=compiler --skip=src
 ci-mingw-bootstrap:
-	$(Q)$(BOOTSTRAP) test --stage 2 --skip tidy
+	$(Q)$(BOOTSTRAP) test --stage 2 --skip=tests --skip=coverage-map --skip=coverage-run --skip=library --skip=tidyselftest
 ci-mingw: ci-mingw-x ci-mingw-bootstrap
 
 .PHONY: dist
diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml
index 2f59892acf6..454c855c75d 100644
--- a/src/ci/github-actions/jobs.yml
+++ b/src/ci/github-actions/jobs.yml
@@ -439,14 +439,24 @@ auto:
       NO_DOWNLOAD_CI_LLVM: 1
     <<: *job-windows-8c
 
-  - image: x86_64-mingw
+  # x86_64-mingw is split into two jobs to run tests in parallel.
+  - image: x86_64-mingw-1
     env:
-      SCRIPT: make ci-mingw
+      SCRIPT: make ci-mingw-x
       RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu
       # We are intentionally allowing an old toolchain on this builder (and that's
       # incompatible with LLVM downloads today).
       NO_DOWNLOAD_CI_LLVM: 1
-    <<: *job-windows-8c
+    <<: *job-windows
+
+  - image: x86_64-mingw-2
+    env:
+      SCRIPT: make ci-mingw-bootstrap
+      RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu
+      # We are intentionally allowing an old toolchain on this builder (and that's
+      # incompatible with LLVM downloads today).
+      NO_DOWNLOAD_CI_LLVM: 1
+    <<: *job-windows
 
   - image: dist-x86_64-msvc
     env:
diff --git a/src/ci/shared.sh b/src/ci/shared.sh
index 1e6a008a5de..9fce68947f4 100644
--- a/src/ci/shared.sh
+++ b/src/ci/shared.sh
@@ -53,7 +53,8 @@ function isLinux {
 }
 
 function isKnownToBeMingwBuild {
-    isGitHubActions && [[ "${CI_JOB_NAME}" == *mingw ]]
+    # CI_JOB_NAME must end with "mingw" and optionally `-N` to be considered a MinGW build.
+    isGitHubActions && [[ "${CI_JOB_NAME}" =~ mingw(-[0-9]+)?$ ]]
 }
 
 function isCiBranch {
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 12a73f0508b..c2f4170d7d2 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`          | `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`      |
@@ -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 85321e5f345..aa35c4d8865 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,94 @@ 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");
+
+// 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
@@ -197,3 +320,179 @@ 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_vsx-LABEL: vreg_f32_v0:
+// powerpc_vsx: #APP
+// powerpc_vsx: vmr 0, 0
+// powerpc_vsx: #NO_APP
+// powerpc64_vsx-LABEL: vreg_f32_v0:
+// powerpc64_vsx: #APP
+// powerpc64_vsx: vmr 0, 0
+// powerpc64_vsx: #NO_APP
+#[cfg(vsx)]
+check_reg!(vreg_f32_v0, f32, "0", "v0", "vmr");
+
+// powerpc_vsx-LABEL: vreg_f64_v0:
+// powerpc_vsx: #APP
+// powerpc_vsx: vmr 0, 0
+// powerpc_vsx: #NO_APP
+// powerpc64_vsx-LABEL: vreg_f64_v0:
+// powerpc64_vsx: #APP
+// powerpc64_vsx: vmr 0, 0
+// powerpc64_vsx: #NO_APP
+#[cfg(vsx)]
+check_reg!(vreg_f64_v0, f64, "0", "v0", "vmr");
+
+// powerpc_altivec-LABEL: vreg_i8x16_v18:
+// powerpc_altivec: #APP
+// powerpc_altivec: vmr 18, 18
+// powerpc_altivec: #NO_APP
+// powerpc64-LABEL: vreg_i8x16_v18:
+// powerpc64: #APP
+// powerpc64: vmr 18, 18
+// powerpc64: #NO_APP
+#[cfg(altivec)]
+check_reg!(vreg_i8x16_v18, i8x16, "18", "v18", "vmr");
+
+// powerpc_altivec-LABEL: vreg_i16x8_v18:
+// powerpc_altivec: #APP
+// powerpc_altivec: vmr 18, 18
+// powerpc_altivec: #NO_APP
+// powerpc64-LABEL: vreg_i16x8_v18:
+// powerpc64: #APP
+// powerpc64: vmr 18, 18
+// powerpc64: #NO_APP
+#[cfg(altivec)]
+check_reg!(vreg_i16x8_v18, i16x8, "18", "v18", "vmr");
+
+// powerpc_altivec-LABEL: vreg_i32x4_v18:
+// powerpc_altivec: #APP
+// powerpc_altivec: vmr 18, 18
+// powerpc_altivec: #NO_APP
+// powerpc64-LABEL: vreg_i32x4_v18:
+// powerpc64: #APP
+// powerpc64: vmr 18, 18
+// powerpc64: #NO_APP
+#[cfg(altivec)]
+check_reg!(vreg_i32x4_v18, i32x4, "18", "v18", "vmr");
+
+// powerpc_vsx-LABEL: vreg_i64x2_v18:
+// powerpc_vsx: #APP
+// powerpc_vsx: vmr 18, 18
+// powerpc_vsx: #NO_APP
+// powerpc64_vsx-LABEL: vreg_i64x2_v18:
+// powerpc64_vsx: #APP
+// powerpc64_vsx: vmr 18, 18
+// powerpc64_vsx: #NO_APP
+#[cfg(vsx)]
+check_reg!(vreg_i64x2_v18, i64x2, "18", "v18", "vmr");
+
+// powerpc_altivec-LABEL: vreg_f32x4_v18:
+// powerpc_altivec: #APP
+// powerpc_altivec: vmr 18, 18
+// powerpc_altivec: #NO_APP
+// powerpc64-LABEL: vreg_f32x4_v18:
+// powerpc64: #APP
+// powerpc64: vmr 18, 18
+// powerpc64: #NO_APP
+#[cfg(altivec)]
+check_reg!(vreg_f32x4_v18, f32x4, "18", "v18", "vmr");
+
+// powerpc_vsx-LABEL: vreg_f64x2_v18:
+// powerpc_vsx: #APP
+// powerpc_vsx: vmr 18, 18
+// powerpc_vsx: #NO_APP
+// powerpc64_vsx-LABEL: vreg_f64x2_v18:
+// powerpc64_vsx: #APP
+// powerpc64_vsx: vmr 18, 18
+// powerpc64_vsx: #NO_APP
+#[cfg(vsx)]
+check_reg!(vreg_f64x2_v18, f64x2, "18", "v18", "vmr");
+
+// powerpc_vsx-LABEL: vreg_f32_v18:
+// powerpc_vsx: #APP
+// powerpc_vsx: vmr 18, 18
+// powerpc_vsx: #NO_APP
+// powerpc64_vsx-LABEL: vreg_f32_v18:
+// powerpc64_vsx: #APP
+// powerpc64_vsx: vmr 18, 18
+// powerpc64_vsx: #NO_APP
+#[cfg(vsx)]
+check_reg!(vreg_f32_v18, f32, "18", "v18", "vmr");
+
+// powerpc_vsx-LABEL: vreg_f64_v18:
+// powerpc_vsx: #APP
+// powerpc_vsx: vmr 18, 18
+// powerpc_vsx: #NO_APP
+// powerpc64_vsx-LABEL: vreg_f64_v18:
+// powerpc64_vsx: #APP
+// powerpc64_vsx: vmr 18, 18
+// powerpc64_vsx: #NO_APP
+#[cfg(vsx)]
+check_reg!(vreg_f64_v18, f64, "18", "v18", "vmr");
diff --git a/tests/codegen/asm/powerpc-clobbers.rs b/tests/codegen/asm/powerpc-clobbers.rs
index e97e8300ca7..2832377cef0 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 34105ceac04..036641951cc 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, f32, f64, 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, f32, f64, 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, f32, f64, 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 34105ceac04..13fc5a048d8 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 34105ceac04..6a9d552bfe2 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, f32, f64, 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, f32, f64, 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, f32, f64, 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 34105ceac04..036641951cc 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, f32, f64, 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, f32, f64, 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, f32, f64, 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 5023ad51838..f34c45663a0 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") _);
diff --git a/tests/ui/intrinsics/reify-intrinsic.stderr b/tests/ui/intrinsics/reify-intrinsic.stderr
index a456e81e762..aea6d263a72 100644
--- a/tests/ui/intrinsics/reify-intrinsic.stderr
+++ b/tests/ui/intrinsics/reify-intrinsic.stderr
@@ -22,7 +22,7 @@ LL |         std::intrinsics::floorf32,
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot coerce intrinsics to function pointers
    |
    = note: expected fn pointer `unsafe extern "rust-intrinsic" fn(_) -> _`
-                 found fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {floorf32}`
+                 found fn item `unsafe fn(_) -> _ {floorf32}`
 
 error: aborting due to 3 previous errors