about summary refs log tree commit diff
path: root/tests/codegen
diff options
context:
space:
mode:
Diffstat (limited to 'tests/codegen')
-rw-r--r--tests/codegen/aarch64-struct-align-128.rs150
-rw-r--r--tests/codegen/abi-main-signature-16bit-c-int.rs19
-rw-r--r--tests/codegen/abi-main-signature-32bit-c-int.rs3
-rw-r--r--tests/codegen/addr-of-mutate.rs33
-rw-r--r--tests/codegen/adjustments.rs6
-rw-r--r--tests/codegen/align-byval-vector.rs58
-rw-r--r--tests/codegen/align-byval.rs342
-rw-r--r--tests/codegen/align-enum.rs2
-rw-r--r--tests/codegen/align-offset.rs77
-rw-r--r--tests/codegen/align-struct.rs4
-rw-r--r--tests/codegen/alloc-optimisation.rs3
-rw-r--r--tests/codegen/array-codegen.rs34
-rw-r--r--tests/codegen/array-equality.rs8
-rw-r--r--tests/codegen/array-map.rs12
-rw-r--r--tests/codegen/ascii-char.rs37
-rw-r--r--tests/codegen/atomic-operations.rs60
-rw-r--r--tests/codegen/autovectorize-f32x4.rs7
-rw-r--r--tests/codegen/avr/avr-func-addrspace.rs6
-rw-r--r--tests/codegen/binary-search-index-no-bound-check.rs4
-rw-r--r--tests/codegen/box-maybe-uninit-llvm14.rs2
-rw-r--r--tests/codegen/box-maybe-uninit.rs5
-rw-r--r--tests/codegen/call-llvm-intrinsics.rs1
-rw-r--r--tests/codegen/call-metadata.rs2
-rw-r--r--tests/codegen/catch-unwind.rs2
-rw-r--r--tests/codegen/comparison-operators-2-tuple.rs1
-rw-r--r--tests/codegen/comparison-operators-newtype.rs1
-rw-r--r--tests/codegen/const_scalar_pair.rs10
-rw-r--r--tests/codegen/consts.rs4
-rw-r--r--tests/codegen/debug-column.rs4
-rw-r--r--tests/codegen/debug-vtable.rs2
-rw-r--r--tests/codegen/debuginfo-constant-locals.rs28
-rw-r--r--tests/codegen/drop-in-place-noalias.rs38
-rw-r--r--tests/codegen/drop.rs1
-rw-r--r--tests/codegen/enable-lto-unit-splitting.rs10
-rw-r--r--tests/codegen/enum-debug-niche-2.rs4
-rw-r--r--tests/codegen/enum-match.rs2
-rw-r--r--tests/codegen/enum-u128.rs27
-rw-r--r--tests/codegen/external-no-mangle-statics.rs32
-rw-r--r--tests/codegen/fastcall-inreg.rs2
-rw-r--r--tests/codegen/fewer-names.rs14
-rw-r--r--tests/codegen/function-arguments-noopt.rs10
-rw-r--r--tests/codegen/function-arguments.rs64
-rw-r--r--tests/codegen/global_asm.rs23
-rw-r--r--tests/codegen/global_asm_include.rs23
-rw-r--r--tests/codegen/global_asm_x2.rs23
-rw-r--r--tests/codegen/intrinsics/mask.rs2
-rw-r--r--tests/codegen/intrinsics/nontemporal.rs2
-rw-r--r--tests/codegen/intrinsics/offset.rs33
-rw-r--r--tests/codegen/intrinsics/transmute-niched.rs183
-rw-r--r--tests/codegen/intrinsics/transmute-x64.rs13
-rw-r--r--tests/codegen/intrinsics/transmute.rs190
-rw-r--r--tests/codegen/issues/issue-103840.rs1
-rw-r--r--tests/codegen/issues/issue-105386-ub-in-debuginfo.rs7
-rw-r--r--tests/codegen/issues/issue-111603.rs40
-rw-r--r--tests/codegen/issues/issue-37945.rs8
-rw-r--r--tests/codegen/issues/issue-56267-2.rs2
-rw-r--r--tests/codegen/issues/issue-56267.rs2
-rw-r--r--tests/codegen/issues/issue-56927.rs14
-rw-r--r--tests/codegen/issues/issue-58881.rs2
-rw-r--r--tests/codegen/issues/issue-73396-bounds-check-after-position.rs30
-rw-r--r--tests/codegen/issues/issue-85872-multiple-reverse.rs1
-rw-r--r--tests/codegen/issues/issue-86106.rs34
-rw-r--r--tests/codegen/issues/issue-96274.rs1
-rw-r--r--tests/codegen/issues/issue-96497-slice-size-nowrap.rs1
-rw-r--r--tests/codegen/issues/issue-98294-get-mut-copy-from-slice-opt.rs1
-rw-r--r--tests/codegen/iter-repeat-n-trivial-drop.rs3
-rw-r--r--tests/codegen/lifetime_start_end.rs8
-rw-r--r--tests/codegen/link_section.rs8
-rw-r--r--tests/codegen/llvm-ident.rs15
-rw-r--r--tests/codegen/loads.rs34
-rw-r--r--tests/codegen/loongarch-abi/call-llvm-intrinsics.rs31
-rw-r--r--tests/codegen/loongarch-abi/loongarch64-lp64d-abi.rs293
-rw-r--r--tests/codegen/match-optimized.rs6
-rw-r--r--tests/codegen/mem-replace-big-type.rs19
-rw-r--r--tests/codegen/mem-replace-direct-memcpy.rs33
-rw-r--r--tests/codegen/mem-replace-simple-type.rs44
-rw-r--r--tests/codegen/mir-inlined-line-numbers.rs2
-rw-r--r--tests/codegen/move-operands.rs7
-rw-r--r--tests/codegen/naked-nocoverage.rs2
-rw-r--r--tests/codegen/naked-noinline.rs4
-rw-r--r--tests/codegen/no_builtins-at-crate.rs24
-rw-r--r--tests/codegen/noalias-box-off.rs5
-rw-r--r--tests/codegen/nrvo.rs2
-rw-r--r--tests/codegen/option-nonzero-eq.rs14
-rw-r--r--tests/codegen/packed.rs40
-rw-r--r--tests/codegen/personality_lifetimes.rs3
-rw-r--r--tests/codegen/ptr-read-metadata.rs16
-rw-r--r--tests/codegen/refs.rs6
-rw-r--r--tests/codegen/repeat-trusted-len.rs4
-rw-r--r--tests/codegen/repr-transparent-aggregates-1.rs87
-rw-r--r--tests/codegen/repr-transparent-aggregates-2.rs89
-rw-r--r--tests/codegen/repr/transparent-imm-array.rs86
-rw-r--r--tests/codegen/repr/transparent-mips64.rs (renamed from tests/codegen/repr-transparent-aggregates-3.rs)2
-rw-r--r--tests/codegen/repr/transparent-struct-ptr.rs87
-rw-r--r--tests/codegen/repr/transparent-sysv64.rs (renamed from tests/codegen/repr-transparent-sysv64.rs)0
-rw-r--r--tests/codegen/repr/transparent.rs (renamed from tests/codegen/repr-transparent.rs)16
-rw-r--r--tests/codegen/riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs10
-rw-r--r--tests/codegen/sanitizer-cfi-add-canonical-jump-tables-flag.rs2
-rw-r--r--tests/codegen/sanitizer-cfi-add-enable-split-lto-unit-flag.rs11
-rw-r--r--tests/codegen/sanitizer-cfi-emit-type-checks-attr-no-sanitize.rs18
-rw-r--r--tests/codegen/sanitizer-cfi-emit-type-checks.rs5
-rw-r--r--tests/codegen/sanitizer-cfi-emit-type-metadata-attr-cfi-encoding.rs48
-rw-r--r--tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs365
-rw-r--r--tests/codegen/sanitizer-cfi-emit-type-metadata-itanium-cxx-abi-generalized.rs31
-rw-r--r--tests/codegen/sanitizer-cfi-emit-type-metadata-itanium-cxx-abi-normalized-generalized.rs31
-rw-r--r--tests/codegen/sanitizer-cfi-emit-type-metadata-itanium-cxx-abi-normalized.rs31
-rw-r--r--tests/codegen/sanitizer-cfi-emit-type-metadata-itanium-cxx-abi.rs12
-rw-r--r--tests/codegen/sanitizer-cfi-emit-type-metadata-trait-objects.rs149
-rw-r--r--tests/codegen/sanitizer-cfi-generalize-pointers.rs46
-rw-r--r--tests/codegen/sanitizer-cfi-normalize-integers.rs83
-rw-r--r--tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-attr-no-sanitize.rs30
-rw-r--r--tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi-generalized.rs44
-rw-r--r--tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi-normalized-generalized.rs44
-rw-r--r--tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi-normalized.rs44
-rw-r--r--tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi.rs12
-rw-r--r--tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle.rs27
-rw-r--r--tests/codegen/sanitizer-kcfi-emit-type-metadata-trait-objects.rs174
-rw-r--r--tests/codegen/sanitizer-safestack-attr-check.rs11
-rw-r--r--tests/codegen/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs166
-rw-r--r--tests/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs4
-rw-r--r--tests/codegen/simd-intrinsic/simd-intrinsic-generic-gather.rs4
-rw-r--r--tests/codegen/simd-intrinsic/simd-intrinsic-generic-scatter.rs4
-rw-r--r--tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs13
-rw-r--r--tests/codegen/simd-wide-sum.rs12
-rw-r--r--tests/codegen/simd_arith_offset.rs2
-rw-r--r--tests/codegen/slice-init.rs22
-rw-r--r--tests/codegen/slice-iter-fold.rs14
-rw-r--r--tests/codegen/slice-iter-len-eq-zero.rs8
-rw-r--r--tests/codegen/slice-iter-nonnull.rs116
-rw-r--r--tests/codegen/slice-ref-equality.rs44
-rw-r--r--tests/codegen/slice_as_from_ptr_range.rs1
-rw-r--r--tests/codegen/split-lto-unit.rs11
-rw-r--r--tests/codegen/stack-protector.rs36
-rw-r--r--tests/codegen/stores.rs8
-rw-r--r--tests/codegen/swap-large-types.rs6
-rw-r--r--tests/codegen/swap-simd-types.rs9
-rw-r--r--tests/codegen/swap-small-types.rs25
-rw-r--r--tests/codegen/target-feature-inline-closure.rs33
-rw-r--r--tests/codegen/tied-features-strength.rs29
-rw-r--r--tests/codegen/transmute-optimized.rs108
-rw-r--r--tests/codegen/transmute-scalar.rs35
-rw-r--r--tests/codegen/try_question_mark_nop.rs1
-rw-r--r--tests/codegen/tuple-layout-opt.rs12
-rw-r--r--tests/codegen/unchecked_shifts.rs5
-rw-r--r--tests/codegen/uninit-consts.rs10
-rw-r--r--tests/codegen/union-abi.rs22
-rw-r--r--tests/codegen/unwind-abis/c-unwind-abi.rs1
-rw-r--r--tests/codegen/unwind-abis/cdecl-unwind-abi.rs1
-rw-r--r--tests/codegen/unwind-abis/nounwind-on-stable-panic-unwind.rs1
-rw-r--r--tests/codegen/unwind-abis/system-unwind-abi.rs1
-rw-r--r--tests/codegen/unwind-extern-exports.rs1
-rw-r--r--tests/codegen/unwind-extern-imports.rs1
-rw-r--r--tests/codegen/var-names.rs4
-rw-r--r--tests/codegen/vec-as-ptr.rs4
-rw-r--r--tests/codegen/vec-calloc.rs1
-rw-r--r--tests/codegen/vec-optimizes-away.rs3
-rw-r--r--tests/codegen/vec-shrink-panik.rs11
-rw-r--r--tests/codegen/wasm_exceptions.rs51
158 files changed, 3746 insertions, 1079 deletions
diff --git a/tests/codegen/aarch64-struct-align-128.rs b/tests/codegen/aarch64-struct-align-128.rs
new file mode 100644
index 00000000000..bf34717786d
--- /dev/null
+++ b/tests/codegen/aarch64-struct-align-128.rs
@@ -0,0 +1,150 @@
+// Test that structs aligned to 128 bits are passed with the correct ABI on aarch64.
+
+// revisions:linux darwin windows
+//[linux] compile-flags: --target aarch64-unknown-linux-gnu
+//[darwin] compile-flags: --target aarch64-apple-darwin
+//[windows] compile-flags: --target aarch64-pc-windows-msvc
+//[linux] needs-llvm-components: aarch64
+//[darwin] needs-llvm-components: aarch64
+//[windows] needs-llvm-components: aarch64
+
+#![feature(no_core, lang_items)]
+#![crate_type = "lib"]
+#![no_core]
+
+#[lang="sized"]
+trait Sized { }
+#[lang="freeze"]
+trait Freeze { }
+#[lang="copy"]
+trait Copy { }
+
+
+
+// Passed as `[i64 x 2]`, since it's an aggregate with size <= 128 bits, align < 128 bits.
+#[repr(C)]
+pub struct Align8 {
+    pub a: u64,
+    pub b: u64,
+}
+
+// repr(transparent), so same as above.
+#[repr(transparent)]
+pub struct Transparent8 {
+    a: Align8
+}
+
+// Passed as `[i64 x 2]`, since it's an aggregate with size <= 128 bits, align < 128 bits.
+#[repr(C)]
+pub struct Wrapped8 {
+    a: Align8,
+}
+
+extern "C" {
+    // linux:   declare void @test_8([2 x i64], [2 x i64], [2 x i64])
+    // darwin:  declare void @test_8([2 x i64], [2 x i64], [2 x i64])
+    // windows: declare void @test_8([2 x i64], [2 x i64], [2 x i64])
+    fn test_8(a: Align8, b: Transparent8, c: Wrapped8);
+}
+
+
+
+// Passed as `i128`, since it's an aggregate with size <= 128 bits, align = 128 bits.
+// EXCEPT on Linux, where there's a special case to use its unadjusted alignment,
+// making it the same as `Align8`, so it's be passed as `[i64 x 2]`.
+#[repr(C)]
+#[repr(align(16))]
+pub struct Align16 {
+    pub a: u64,
+    pub b: u64,
+}
+
+// repr(transparent), so same as above.
+#[repr(transparent)]
+pub struct Transparent16 {
+    a: Align16
+}
+
+// Passed as `i128`, since it's an aggregate with size <= 128 bits, align = 128 bits.
+// On Linux, the "unadjustedness" doesn't recurse into fields, so this is passed as `i128`.
+#[repr(C)]
+pub struct Wrapped16 {
+    pub a: Align16,
+}
+
+extern "C" {
+    // linux:   declare void @test_16([2 x i64], [2 x i64], i128)
+    // darwin:  declare void @test_16(i128, i128, i128)
+    // windows: declare void @test_16(i128, i128, i128)
+    fn test_16(a: Align16, b: Transparent16, c: Wrapped16);
+}
+
+
+
+// Passed as `i128`, since it's an aggregate with size <= 128 bits, align = 128 bits.
+#[repr(C)]
+pub struct I128 {
+    pub a: i128,
+}
+
+// repr(transparent), so same as above.
+#[repr(transparent)]
+pub struct TransparentI128 {
+    a: I128
+}
+
+// Passed as `i128`, since it's an aggregate with size <= 128 bits, align = 128 bits.
+#[repr(C)]
+pub struct WrappedI128 {
+    pub a: I128
+}
+
+extern "C" {
+    // linux:   declare void @test_i128(i128, i128, i128)
+    // darwin:  declare void @test_i128(i128, i128, i128)
+    // windows: declare void @test_i128(i128, i128, i128)
+    fn test_i128(a: I128, b: TransparentI128, c: WrappedI128);
+}
+
+
+
+// Passed as `[2 x i64]`, since it's an aggregate with size <= 128 bits, align < 128 bits.
+// Note that the Linux special case does not apply, because packing is not considered "adjustment".
+#[repr(C)]
+#[repr(packed)]
+pub struct Packed {
+    pub a: i128,
+}
+
+// repr(transparent), so same as above.
+#[repr(transparent)]
+pub struct TransparentPacked {
+    a: Packed
+}
+
+// Passed as `[2 x i64]`, since it's an aggregate with size <= 128 bits, align < 128 bits.
+#[repr(C)]
+pub struct WrappedPacked {
+    pub a: Packed
+}
+
+extern "C" {
+    // linux:   declare void @test_packed([2 x i64], [2 x i64], [2 x i64])
+    // darwin:  declare void @test_packed([2 x i64], [2 x i64], [2 x i64])
+    // windows: declare void @test_packed([2 x i64], [2 x i64], [2 x i64])
+    fn test_packed(a: Packed, b: TransparentPacked, c: WrappedPacked);
+}
+
+
+
+pub unsafe fn main(
+    a1: Align8, a2: Transparent8, a3: Wrapped8,
+    b1: Align16, b2: Transparent16, b3: Wrapped16,
+    c1: I128, c2: TransparentI128, c3: WrappedI128,
+    d1: Packed, d2: TransparentPacked, d3: WrappedPacked,
+) {
+    test_8(a1, a2, a3);
+    test_16(b1, b2, b3);
+    test_i128(c1, c2, c3);
+    test_packed(d1, d2, d3);
+}
diff --git a/tests/codegen/abi-main-signature-16bit-c-int.rs b/tests/codegen/abi-main-signature-16bit-c-int.rs
index 3548cc06a5b..ce4d35dea0c 100644
--- a/tests/codegen/abi-main-signature-16bit-c-int.rs
+++ b/tests/codegen/abi-main-signature-16bit-c-int.rs
@@ -2,21 +2,10 @@
 // entry point. It must match C's `int main(int, char **)`.
 
 // This test is for targets with 16bit c_int only.
-// ignore-aarch64
-// ignore-arm
-// ignore-asmjs
-// ignore-hexagon
-// ignore-mips
-// ignore-mips64
-// ignore-powerpc
-// ignore-powerpc64
-// ignore-riscv64
-// ignore-s390x
-// ignore-sparc
-// ignore-sparc64
-// ignore-wasm32
-// ignore-x86
-// ignore-x86_64
+// revisions: avr msp
+//[avr] only-avr
+//[msp] only-msp430
+
 
 fn main() {
 }
diff --git a/tests/codegen/abi-main-signature-32bit-c-int.rs b/tests/codegen/abi-main-signature-32bit-c-int.rs
index 7f22ddcfc12..34571823f13 100644
--- a/tests/codegen/abi-main-signature-32bit-c-int.rs
+++ b/tests/codegen/abi-main-signature-32bit-c-int.rs
@@ -3,8 +3,9 @@
 
 // This test is for targets with 32bit c_int only.
 // ignore-msp430
+// ignore-avr
 
 fn main() {
 }
 
-// CHECK: define{{( hidden)?}} i32 @main(i32{{( %0)?}}, {{i8\*\*|ptr}}{{( %1)?}})
+// CHECK: define{{( hidden)?}} i32 @main(i32{{( %0)?}}, ptr{{( %1)?}})
diff --git a/tests/codegen/addr-of-mutate.rs b/tests/codegen/addr-of-mutate.rs
new file mode 100644
index 00000000000..97af6181524
--- /dev/null
+++ b/tests/codegen/addr-of-mutate.rs
@@ -0,0 +1,33 @@
+// compile-flags: -C opt-level=3 -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+// Test for the absence of `readonly` on the argument when it is mutated via `&raw const`.
+// See <https://github.com/rust-lang/rust/issues/111502>.
+
+// CHECK: i8 @foo(ptr noalias nocapture noundef align 1 dereferenceable(128) %x)
+#[no_mangle]
+pub fn foo(x: [u8; 128]) -> u8 {
+    let ptr = core::ptr::addr_of!(x).cast_mut();
+    unsafe {
+        (*ptr)[0] = 1;
+    }
+    x[0]
+}
+
+// CHECK: i1 @second(ptr noalias nocapture noundef align {{[0-9]+}} dereferenceable({{[0-9]+}}) %a_ptr_and_b)
+#[no_mangle]
+pub unsafe fn second(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool {
+    let b_bool_ptr = core::ptr::addr_of!(a_ptr_and_b.1.1).cast_mut();
+    (*b_bool_ptr) = true;
+    a_ptr_and_b.1.1
+}
+
+// If going through a deref (and there are no other mutating accesses), then `readonly` is fine.
+// CHECK: i1 @third(ptr noalias nocapture noundef readonly align {{[0-9]+}} dereferenceable({{[0-9]+}}) %a_ptr_and_b)
+#[no_mangle]
+pub unsafe fn third(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool {
+    let b_bool_ptr = core::ptr::addr_of!((*a_ptr_and_b.0).1).cast_mut();
+    (*b_bool_ptr) = true;
+    a_ptr_and_b.1.1
+}
diff --git a/tests/codegen/adjustments.rs b/tests/codegen/adjustments.rs
index b53a68a5588..0739c79ba8d 100644
--- a/tests/codegen/adjustments.rs
+++ b/tests/codegen/adjustments.rs
@@ -13,9 +13,9 @@ pub fn helper(_: usize) {
 pub fn no_op_slice_adjustment(x: &[u8]) -> &[u8] {
     // We used to generate an extra alloca and memcpy for the block's trailing expression value, so
     // check that we copy directly to the return value slot
-// CHECK: %0 = insertvalue { {{\[0 x i8\]\*|ptr}}, [[USIZE]] } poison, {{\[0 x i8\]\*|ptr}} %x.0, 0
-// CHECK: %1 = insertvalue { {{\[0 x i8\]\*|ptr}}, [[USIZE]] } %0, [[USIZE]] %x.1, 1
-// CHECK: ret { {{\[0 x i8\]\*|ptr}}, [[USIZE]] } %1
+// CHECK: %0 = insertvalue { ptr, [[USIZE]] } poison, ptr %x.0, 0
+// CHECK: %1 = insertvalue { ptr, [[USIZE]] } %0, [[USIZE]] %x.1, 1
+// CHECK: ret { ptr, [[USIZE]] } %1
     { x }
 }
 
diff --git a/tests/codegen/align-byval-vector.rs b/tests/codegen/align-byval-vector.rs
new file mode 100644
index 00000000000..3c8be659671
--- /dev/null
+++ b/tests/codegen/align-byval-vector.rs
@@ -0,0 +1,58 @@
+// revisions:x86-linux x86-darwin
+
+//[x86-linux] compile-flags: --target i686-unknown-linux-gnu
+//[x86-linux] needs-llvm-components: x86
+//[x86-darwin] compile-flags: --target i686-apple-darwin
+//[x86-darwin] needs-llvm-components: x86
+
+// Tests that aggregates containing vector types get their alignment increased to 16 on Darwin.
+
+#![feature(no_core, lang_items, repr_simd, simd_ffi)]
+#![crate_type = "lib"]
+#![no_std]
+#![no_core]
+#![allow(non_camel_case_types)]
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "freeze"]
+trait Freeze {}
+#[lang = "copy"]
+trait Copy {}
+
+#[repr(simd)]
+pub struct i32x4(i32, i32, i32, i32);
+
+#[repr(C)]
+pub struct Foo {
+    a: i32x4,
+    b: i8,
+}
+
+// This tests that we recursively check for vector types, not just at the top level.
+#[repr(C)]
+pub struct DoubleFoo {
+    one: Foo,
+    two: Foo,
+}
+
+extern "C" {
+    // x86-linux: declare void @f({{.*}}byval(%Foo) align 4{{.*}})
+    // x86-darwin: declare void @f({{.*}}byval(%Foo) align 16{{.*}})
+    fn f(foo: Foo);
+
+    // x86-linux: declare void @g({{.*}}byval(%DoubleFoo) align 4{{.*}})
+    // x86-darwin: declare void @g({{.*}}byval(%DoubleFoo) align 16{{.*}})
+    fn g(foo: DoubleFoo);
+}
+
+pub fn main() {
+    unsafe { f(Foo { a: i32x4(1, 2, 3, 4), b: 0 }) }
+
+    unsafe {
+        g(DoubleFoo {
+            one: Foo { a: i32x4(1, 2, 3, 4), b: 0 },
+            two: Foo { a: i32x4(1, 2, 3, 4), b: 0 },
+        })
+    }
+}
diff --git a/tests/codegen/align-byval.rs b/tests/codegen/align-byval.rs
new file mode 100644
index 00000000000..e2446e02ef4
--- /dev/null
+++ b/tests/codegen/align-byval.rs
@@ -0,0 +1,342 @@
+// ignore-tidy-linelength
+// revisions:m68k wasm x86_64-linux x86_64-windows i686-linux i686-windows
+
+//[m68k] compile-flags: --target m68k-unknown-linux-gnu
+//[m68k] needs-llvm-components: m68k
+//[wasm] compile-flags: --target wasm32-unknown-emscripten
+//[wasm] needs-llvm-components: webassembly
+//[x86_64-linux] compile-flags: --target x86_64-unknown-linux-gnu
+//[x86_64-linux] needs-llvm-components: x86
+//[x86_64-windows] compile-flags: --target x86_64-pc-windows-msvc
+//[x86_64-windows] needs-llvm-components: x86
+//[i686-linux] compile-flags: --target i686-unknown-linux-gnu
+//[i686-linux] needs-llvm-components: x86
+//[i686-windows] compile-flags: --target i686-pc-windows-msvc
+//[i686-windows] needs-llvm-components: x86
+
+// Tests that `byval` alignment is properly specified (#80127).
+// The only targets that use `byval` are m68k, wasm, x86-64, and x86.
+// Note also that Windows mandates a by-ref ABI here, so it does not use byval.
+
+#![feature(no_core, lang_items)]
+#![crate_type = "lib"]
+#![no_std]
+#![no_core]
+
+#[lang="sized"] trait Sized { }
+#[lang="freeze"] trait Freeze { }
+#[lang="copy"] trait Copy { }
+
+impl Copy for i32 {}
+impl Copy for i64 {}
+
+// This struct can be represented as a pair, so it exercises the OperandValue::Pair
+// codepath in `codegen_argument`.
+#[repr(C)]
+pub struct NaturalAlign1 {
+    a: i8,
+    b: i8,
+}
+
+// This struct cannot be represented as an immediate, so it exercises the OperandValue::Ref
+// codepath in `codegen_argument`.
+#[repr(C)]
+pub struct NaturalAlign2 {
+    a: [i16; 16],
+    b: i16,
+}
+
+#[repr(C)]
+#[repr(align(4))]
+pub struct ForceAlign4 {
+    a: [i8; 16],
+    b: i8,
+}
+
+// On i686-windows, this is passed on stack using `byval`
+#[repr(C)]
+pub struct NaturalAlign8 {
+    a: i64,
+    b: i64,
+    c: i64
+}
+
+// On i686-windows, this is passed by reference (because alignment is >4 and requested/forced),
+// even though it has the exact same layout as `NaturalAlign8`!
+#[repr(C)]
+#[repr(align(8))]
+pub struct ForceAlign8 {
+    a: i64,
+    b: i64,
+    c: i64
+}
+
+// On i686-windows, this is passed on stack, because requested alignment is <=4.
+#[repr(C)]
+#[repr(align(4))]
+pub struct LowerFA8 {
+    a: i64,
+    b: i64,
+    c: i64
+}
+
+// On i686-windows, this is passed by reference, because it contains a field with
+// requested/forced alignment.
+#[repr(C)]
+pub struct WrappedFA8 {
+    a: ForceAlign8
+}
+
+// On i686-windows, this has the same ABI as ForceAlign8, i.e. passed by reference.
+#[repr(transparent)]
+pub struct TransparentFA8 {
+    _0: (),
+    a: ForceAlign8
+}
+
+#[repr(C)]
+#[repr(align(16))]
+pub struct ForceAlign16 {
+    a: [i32; 16],
+    b: i8
+}
+
+// CHECK-LABEL: @call_na1
+#[no_mangle]
+pub unsafe fn call_na1(x: NaturalAlign1) {
+    // CHECK: start:
+
+    // m68k: [[ALLOCA:%[a-z0-9+]]] = alloca { i8, i8 }, align 1
+    // m68k: call void @natural_align_1({{.*}}byval({ i8, i8 }) align 1{{.*}} [[ALLOCA]])
+
+    // wasm: [[ALLOCA:%[a-z0-9+]]] = alloca { i8, i8 }, align 1
+    // wasm: call void @natural_align_1({{.*}}byval({ i8, i8 }) align 1{{.*}} [[ALLOCA]])
+
+    // x86_64-linux: call void @natural_align_1(i16
+
+    // x86_64-windows: call void @natural_align_1(i16
+
+    // i686-linux: [[ALLOCA:%[a-z0-9+]]] = alloca { i8, i8 }, align 4
+    // i686-linux: call void @natural_align_1({{.*}}byval({ i8, i8 }) align 4{{.*}} [[ALLOCA]])
+
+    // i686-windows: [[ALLOCA:%[a-z0-9+]]] = alloca { i8, i8 }, align 4
+    // i686-windows: call void @natural_align_1({{.*}}byval({ i8, i8 }) align 4{{.*}} [[ALLOCA]])
+    natural_align_1(x);
+}
+
+// CHECK-LABEL: @call_na2
+#[no_mangle]
+pub unsafe fn call_na2(x: NaturalAlign2) {
+    // CHECK: start:
+
+    // m68k-NEXT: call void @natural_align_2
+    // wasm-NEXT: call void @natural_align_2
+    // x86_64-linux-NEXT: call void @natural_align_2
+    // x86_64-windows-NEXT: call void @natural_align_2
+
+    // i686-linux: [[ALLOCA:%[0-9]+]] = alloca %NaturalAlign2, align 4
+    // i686-linux: call void @natural_align_2({{.*}}byval(%NaturalAlign2) align 4{{.*}} [[ALLOCA]])
+
+    // i686-windows: [[ALLOCA:%[0-9]+]] = alloca %NaturalAlign2, align 4
+    // i686-windows: call void @natural_align_2({{.*}}byval(%NaturalAlign2) align 4{{.*}} [[ALLOCA]])
+    natural_align_2(x);
+}
+
+// CHECK-LABEL: @call_fa4
+#[no_mangle]
+pub unsafe fn call_fa4(x: ForceAlign4) {
+    // CHECK: start:
+    // CHECK-NEXT: call void @force_align_4
+    force_align_4(x);
+}
+
+// CHECK-LABEL: @call_na8
+#[no_mangle]
+pub unsafe fn call_na8(x: NaturalAlign8) {
+    // CHECK: start:
+    // CHECK-NEXT: call void @natural_align_8
+    natural_align_8(x);
+}
+
+// CHECK-LABEL: @call_fa8
+#[no_mangle]
+pub unsafe fn call_fa8(x: ForceAlign8) {
+    // CHECK: start:
+    // CHECK-NEXT: call void @force_align_8
+    force_align_8(x);
+}
+
+// CHECK-LABEL: @call_lfa8
+#[no_mangle]
+pub unsafe fn call_lfa8(x: LowerFA8) {
+    // CHECK: start:
+    // CHECK-NEXT: call void @lower_fa8
+    lower_fa8(x);
+}
+
+// CHECK-LABEL: @call_wfa8
+#[no_mangle]
+pub unsafe fn call_wfa8(x: WrappedFA8) {
+    // CHECK: start:
+    // CHECK-NEXT: call void @wrapped_fa8
+    wrapped_fa8(x);
+}
+
+// CHECK-LABEL: @call_tfa8
+#[no_mangle]
+pub unsafe fn call_tfa8(x: TransparentFA8) {
+    // CHECK: start:
+    // CHECK-NEXT: call void @transparent_fa8
+    transparent_fa8(x);
+}
+
+// CHECK-LABEL: @call_fa16
+#[no_mangle]
+pub unsafe fn call_fa16(x: ForceAlign16) {
+    // CHECK: start:
+    // CHECK-NEXT: call void @force_align_16
+    force_align_16(x);
+}
+
+extern "C" {
+    // m68k: declare void @natural_align_1({{.*}}byval({ i8, i8 }) align 1{{.*}})
+
+    // wasm: declare void @natural_align_1({{.*}}byval({ i8, i8 }) align 1{{.*}})
+
+    // x86_64-linux: declare void @natural_align_1(i16)
+
+    // x86_64-windows: declare void @natural_align_1(i16)
+
+    // i686-linux: declare void @natural_align_1({{.*}}byval({ i8, i8 }) align 4{{.*}})
+
+    // i686-windows: declare void @natural_align_1({{.*}}byval({ i8, i8 }) align 4{{.*}})
+    fn natural_align_1(x: NaturalAlign1);
+
+    // m68k: declare void @natural_align_2({{.*}}byval(%NaturalAlign2) align 2{{.*}})
+
+    // wasm: declare void @natural_align_2({{.*}}byval(%NaturalAlign2) align 2{{.*}})
+
+    // x86_64-linux: declare void @natural_align_2({{.*}}byval(%NaturalAlign2) align 2{{.*}})
+
+    // x86_64-windows: declare void @natural_align_2(
+    // x86_64-windows-NOT: byval
+    // x86_64-windows-SAME: align 2{{.*}})
+
+    // i686-linux: declare void @natural_align_2({{.*}}byval(%NaturalAlign2) align 4{{.*}})
+
+    // i686-windows: declare void @natural_align_2({{.*}}byval(%NaturalAlign2) align 4{{.*}})
+    fn natural_align_2(x: NaturalAlign2);
+
+    // m68k: declare void @force_align_4({{.*}}byval(%ForceAlign4) align 4{{.*}})
+
+    // wasm: declare void @force_align_4({{.*}}byval(%ForceAlign4) align 4{{.*}})
+
+    // x86_64-linux: declare void @force_align_4({{.*}}byval(%ForceAlign4) align 4{{.*}})
+
+    // x86_64-windows: declare void @force_align_4(
+    // x86_64-windows-NOT: byval
+    // x86_64-windows-SAME: align 4{{.*}})
+
+    // i686-linux: declare void @force_align_4({{.*}}byval(%ForceAlign4) align 4{{.*}})
+
+    // i686-windows: declare void @force_align_4({{.*}}byval(%ForceAlign4) align 4{{.*}})
+    fn force_align_4(x: ForceAlign4);
+
+    // m68k: declare void @natural_align_8({{.*}}byval(%NaturalAlign8) align 4{{.*}})
+
+    // wasm: declare void @natural_align_8({{.*}}byval(%NaturalAlign8) align 8{{.*}})
+
+    // x86_64-linux: declare void @natural_align_8({{.*}}byval(%NaturalAlign8) align 8{{.*}})
+
+    // x86_64-windows: declare void @natural_align_8(
+    // x86_64-windows-NOT: byval
+    // x86_64-windows-SAME: align 8{{.*}})
+
+    // i686-linux: declare void @natural_align_8({{.*}}byval(%NaturalAlign8) align 4{{.*}})
+
+    // i686-windows: declare void @natural_align_8({{.*}}byval(%NaturalAlign8) align 4{{.*}})
+    fn natural_align_8(x: NaturalAlign8);
+
+    // m68k: declare void @force_align_8({{.*}}byval(%ForceAlign8) align 8{{.*}})
+
+    // wasm: declare void @force_align_8({{.*}}byval(%ForceAlign8) align 8{{.*}})
+
+    // x86_64-linux: declare void @force_align_8({{.*}}byval(%ForceAlign8) align 8{{.*}})
+
+    // x86_64-windows: declare void @force_align_8(
+    // x86_64-windows-NOT: byval
+    // x86_64-windows-SAME: align 8{{.*}})
+
+    // i686-linux: declare void @force_align_8({{.*}}byval(%ForceAlign8) align 4{{.*}})
+
+    // i686-windows: declare void @force_align_8(
+    // i686-windows-NOT: byval
+    // i686-windows-SAME: align 8{{.*}})
+    fn force_align_8(x: ForceAlign8);
+
+    // m68k: declare void @lower_fa8({{.*}}byval(%LowerFA8) align 4{{.*}})
+
+    // wasm: declare void @lower_fa8({{.*}}byval(%LowerFA8) align 8{{.*}})
+
+    // x86_64-linux: declare void @lower_fa8({{.*}}byval(%LowerFA8) align 8{{.*}})
+
+    // x86_64-windows: declare void @lower_fa8(
+    // x86_64-windows-NOT: byval
+    // x86_64-windows-SAME: align 8{{.*}})
+
+    // i686-linux: declare void @lower_fa8({{.*}}byval(%LowerFA8) align 4{{.*}})
+
+    // i686-windows: declare void @lower_fa8({{.*}}byval(%LowerFA8) align 4{{.*}})
+    fn lower_fa8(x: LowerFA8);
+
+    // m68k: declare void @wrapped_fa8({{.*}}byval(%WrappedFA8) align 8{{.*}})
+
+    // wasm: declare void @wrapped_fa8({{.*}}byval(%WrappedFA8) align 8{{.*}})
+
+    // x86_64-linux: declare void @wrapped_fa8({{.*}}byval(%WrappedFA8) align 8{{.*}})
+
+    // x86_64-windows: declare void @wrapped_fa8(
+    // x86_64-windows-NOT: byval
+    // x86_64-windows-SAME: align 8{{.*}})
+
+    // i686-linux: declare void @wrapped_fa8({{.*}}byval(%WrappedFA8) align 4{{.*}})
+
+    // i686-windows: declare void @wrapped_fa8(
+    // i686-windows-NOT: byval
+    // i686-windows-SAME: align 8{{.*}})
+    fn wrapped_fa8(x: WrappedFA8);
+
+    // m68k: declare void @transparent_fa8({{.*}}byval(%TransparentFA8) align 8{{.*}})
+
+    // wasm: declare void @transparent_fa8({{.*}}byval(%TransparentFA8) align 8{{.*}})
+
+    // x86_64-linux: declare void @transparent_fa8({{.*}}byval(%TransparentFA8) align 8{{.*}})
+
+    // x86_64-windows: declare void @transparent_fa8(
+    // x86_64-windows-NOT: byval
+    // x86_64-windows-SAME: align 8{{.*}})
+
+    // i686-linux: declare void @transparent_fa8({{.*}}byval(%TransparentFA8) align 4{{.*}})
+
+    // i686-windows: declare void @transparent_fa8(
+    // i686-windows-NOT: byval
+    // i686-windows-SAME: align 8{{.*}})
+    fn transparent_fa8(x: TransparentFA8);
+
+    // m68k: declare void @force_align_16({{.*}}byval(%ForceAlign16) align 16{{.*}})
+
+    // wasm: declare void @force_align_16({{.*}}byval(%ForceAlign16) align 16{{.*}})
+
+    // x86_64-linux: declare void @force_align_16({{.*}}byval(%ForceAlign16) align 16{{.*}})
+
+    // x86_64-windows: declare void @force_align_16(
+    // x86_64-windows-NOT: byval
+    // x86_64-windows-SAME: align 16{{.*}})
+
+    // i686-linux: declare void @force_align_16({{.*}}byval(%ForceAlign16) align 4{{.*}})
+
+    // i686-windows: declare void @force_align_16(
+    // i686-windows-NOT: byval
+    // i686-windows-SAME: align 16{{.*}})
+    fn force_align_16(x: ForceAlign16);
+}
diff --git a/tests/codegen/align-enum.rs b/tests/codegen/align-enum.rs
index 70f09ace006..5901f0113c3 100644
--- a/tests/codegen/align-enum.rs
+++ b/tests/codegen/align-enum.rs
@@ -20,7 +20,7 @@ pub struct Nested64 {
 #[no_mangle]
 pub fn align64(a: u32) -> Align64 {
 // CHECK: %a64 = alloca %Align64, align 64
-// CHECK: call void @llvm.memcpy.{{.*}}({{i8\*|ptr}} align 64 %{{.*}}, {{i8\*|ptr}} align 64 %{{.*}}, i{{[0-9]+}} 64, i1 false)
+// CHECK: call void @llvm.memcpy.{{.*}}(ptr align 64 %{{.*}}, ptr align 64 %{{.*}}, i{{[0-9]+}} 64, i1 false)
     let a64 = Align64::A(a);
     a64
 }
diff --git a/tests/codegen/align-offset.rs b/tests/codegen/align-offset.rs
new file mode 100644
index 00000000000..d4d8b18d35b
--- /dev/null
+++ b/tests/codegen/align-offset.rs
@@ -0,0 +1,77 @@
+// compile-flags: -O
+// ignore-debug (debug assertions in `slice::from_raw_parts` block optimizations)
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @align8
+#[no_mangle]
+pub fn align8(p: *const u8) -> bool {
+    // CHECK: ret i1 true
+    p.align_offset(8) < 8
+}
+
+#[repr(align(4))]
+pub struct Align4([u8; 4]);
+
+// CHECK-LABEL: @align_to4
+#[no_mangle]
+pub fn align_to4(x: &[u8]) -> bool {
+    // CHECK: ret i1 true
+    let (prefix, _middle, suffix) = unsafe { x.align_to::<Align4>() };
+    prefix.len() < 4 && suffix.len() < 4
+}
+
+// CHECK-LABEL: @align_offset_byte_ptr(ptr{{.+}}%ptr)
+#[no_mangle]
+pub fn align_offset_byte_ptr(ptr: *const u8) -> usize {
+    // CHECK: %[[ADDR:.+]] = ptrtoint ptr %ptr to [[USIZE:i[0-9]+]]
+    // CHECK: %[[UP:.+]] = add [[USIZE]] %[[ADDR]], 31
+    // CHECK: %[[ALIGNED:.+]] = and [[USIZE]] %[[UP]], -32
+    // CHECK: %[[OFFSET:.+]] = sub [[USIZE]] %[[ALIGNED]], %[[ADDR]]
+
+    // Since we're offsetting a byte pointer, there's no further fixups
+    // CHECK-NOT: shr
+    // CHECK-NOT: div
+    // CHECK-NOT: select
+
+    // CHECK: ret [[USIZE]] %[[OFFSET]]
+    ptr.align_offset(32)
+}
+
+// CHECK-LABEL: @align_offset_word_slice(ptr{{.+}}align 4{{.+}}%slice.0
+#[no_mangle]
+pub fn align_offset_word_slice(slice: &[Align4]) -> usize {
+    // CHECK: %[[ADDR:.+]] = ptrtoint ptr %slice.0 to [[USIZE]]
+    // CHECK: %[[UP:.+]] = add [[USIZE]] %[[ADDR]], 31
+    // CHECK: %[[ALIGNED:.+]] = and [[USIZE]] %[[UP]], -32
+    // CHECK: %[[BOFFSET:.+]] = sub [[USIZE]] %[[ALIGNED]], %[[ADDR]]
+    // CHECK: %[[OFFSET:.+]] = lshr exact [[USIZE]] %[[BOFFSET]], 2
+
+    // Slices are known to be aligned, so we don't need the "maybe -1" path
+    // CHECK-NOT: select
+
+    // CHECK: ret [[USIZE]] %[[OFFSET]]
+    slice.as_ptr().align_offset(32)
+}
+
+
+// CHECK-LABEL: @align_offset_word_ptr(ptr{{.+}}%ptr
+#[no_mangle]
+pub fn align_offset_word_ptr(ptr: *const Align4) -> usize {
+    // CHECK: %[[ADDR:.+]] = ptrtoint ptr %ptr to [[USIZE]]
+    // CHECK: %[[UP:.+]] = add [[USIZE]] %[[ADDR]], 31
+    // CHECK: %[[ALIGNED:.+]] = and [[USIZE]] %[[UP]], -32
+    // CHECK: %[[BOFFSET:.+]] = sub [[USIZE]] %[[ALIGNED]], %[[ADDR]]
+
+    // While we can always get a *byte* offset that will work, if the original
+    // pointer is unaligned it might be impossible to return an *element* offset
+    // that will make it aligned. We want it to be a `select`, not a `br`, so
+    // that the assembly will be branchless.
+    // CHECK: %[[LOW:.+]] = and [[USIZE]] %[[ADDR]], 3
+    // CHECK: %[[ORIGINAL_ALIGNED:.+]] = icmp eq [[USIZE]] %[[LOW]], 0
+    // CHECK: %[[OFFSET:.+]] = lshr exact [[USIZE]] %[[BOFFSET]], 2
+    // CHECK: %[[R:.+]] = select i1 %[[ORIGINAL_ALIGNED]], [[USIZE]] %[[OFFSET]], [[USIZE]] -1
+
+    // CHECK: ret [[USIZE]] %[[R]]
+    ptr.align_offset(32)
+}
diff --git a/tests/codegen/align-struct.rs b/tests/codegen/align-struct.rs
index a2f47354b2b..40bba6d5254 100644
--- a/tests/codegen/align-struct.rs
+++ b/tests/codegen/align-struct.rs
@@ -32,7 +32,7 @@ pub enum Enum64 {
 #[no_mangle]
 pub fn align64(i : i32) -> Align64 {
 // CHECK: %a64 = alloca %Align64, align 64
-// CHECK: call void @llvm.memcpy.{{.*}}({{i8\*|ptr}} align 64 %{{.*}}, {{i8\*|ptr}} align 64 %{{.*}}, i{{[0-9]+}} 64, i1 false)
+// CHECK: call void @llvm.memcpy.{{.*}}(ptr align 64 %{{.*}}, ptr align 64 %{{.*}}, i{{[0-9]+}} 64, i1 false)
     let a64 = Align64(i);
     a64
 }
@@ -42,7 +42,7 @@ pub fn align64(i : i32) -> Align64 {
 // CHECK-LABEL: @align64_load
 #[no_mangle]
 pub fn align64_load(a: Align64) -> i32 {
-// CHECK: {{%.*}} = load i32, {{i32\*|ptr}} {{%.*}}, align 64
+// CHECK: {{%.*}} = load i32, ptr {{%.*}}, align 64
     a.0
 }
 
diff --git a/tests/codegen/alloc-optimisation.rs b/tests/codegen/alloc-optimisation.rs
index c3ffaeb9547..f88d695d87e 100644
--- a/tests/codegen/alloc-optimisation.rs
+++ b/tests/codegen/alloc-optimisation.rs
@@ -1,12 +1,13 @@
 //
 // no-system-llvm
 // compile-flags: -O
-#![crate_type="lib"]
+#![crate_type = "lib"]
 
 #[no_mangle]
 pub fn alloc_test(data: u32) {
     // CHECK-LABEL: @alloc_test
     // CHECK-NEXT: start:
+    // CHECK-NEXT: {{.*}} load volatile i8, ptr @__rust_no_alloc_shim_is_unstable, align 1
     // CHECK-NEXT: ret void
     let x = Box::new(data);
     drop(x);
diff --git a/tests/codegen/array-codegen.rs b/tests/codegen/array-codegen.rs
new file mode 100644
index 00000000000..ba0d444f97e
--- /dev/null
+++ b/tests/codegen/array-codegen.rs
@@ -0,0 +1,34 @@
+// compile-flags: -O -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @array_load
+#[no_mangle]
+pub fn array_load(a: &[u8; 4]) -> [u8; 4] {
+    // CHECK: %_0 = alloca [4 x i8], align 1
+    // CHECK: %[[TEMP1:.+]] = load <4 x i8>, ptr %a, align 1
+    // CHECK: store <4 x i8> %[[TEMP1]], ptr %_0, align 1
+    // CHECK: %[[TEMP2:.+]] = load i32, ptr %_0, align 1
+    // CHECK: ret i32 %[[TEMP2]]
+    *a
+}
+
+// CHECK-LABEL: @array_store
+#[no_mangle]
+pub fn array_store(a: [u8; 4], p: &mut [u8; 4]) {
+    // CHECK: %a = alloca [4 x i8]
+    // CHECK: %[[TEMP:.+]] = load <4 x i8>, ptr %a, align 1
+    // CHECK-NEXT: store <4 x i8> %[[TEMP]], ptr %p, align 1
+    *p = a;
+}
+
+// CHECK-LABEL: @array_copy
+#[no_mangle]
+pub fn array_copy(a: &[u8; 4], p: &mut [u8; 4]) {
+    // CHECK: %[[LOCAL:.+]] = alloca [4 x i8], align 1
+    // CHECK: %[[TEMP1:.+]] = load <4 x i8>, ptr %a, align 1
+    // CHECK: store <4 x i8> %[[TEMP1]], ptr %[[LOCAL]], align 1
+    // CHECK: %[[TEMP2:.+]] = load <4 x i8>, ptr %[[LOCAL]], align 1
+    // CHECK: store <4 x i8> %[[TEMP2]], ptr %p, align 1
+    *p = *a;
+}
diff --git a/tests/codegen/array-equality.rs b/tests/codegen/array-equality.rs
index abfe295f8b6..1941452ea61 100644
--- a/tests/codegen/array-equality.rs
+++ b/tests/codegen/array-equality.rs
@@ -16,8 +16,8 @@ pub fn array_eq_value(a: [u16; 3], b: [u16; 3]) -> bool {
 #[no_mangle]
 pub fn array_eq_ref(a: &[u16; 3], b: &[u16; 3]) -> bool {
     // CHECK: start:
-    // CHECK: load i48, {{i48\*|ptr}} %{{.+}}, align 2
-    // CHECK: load i48, {{i48\*|ptr}} %{{.+}}, align 2
+    // CHECK: load i48, ptr %{{.+}}, align 2
+    // CHECK: load i48, ptr %{{.+}}, align 2
     // CHECK: icmp eq i48
     // CHECK-NEXT: ret
     a == b
@@ -27,7 +27,7 @@ pub fn array_eq_ref(a: &[u16; 3], b: &[u16; 3]) -> bool {
 #[no_mangle]
 pub fn array_eq_value_still_passed_by_pointer(a: [u16; 9], b: [u16; 9]) -> bool {
     // CHECK-NEXT: start:
-    // CHECK: %[[CMP:.+]] = tail call i32 @{{bcmp|memcmp}}({{i8\*|ptr}} {{.*}} dereferenceable(18) %{{.+}}, {{i8\*|ptr}} {{.*}} dereferenceable(18) %{{.+}}, i64 18)
+    // CHECK: %[[CMP:.+]] = tail call i32 @{{bcmp|memcmp}}(ptr {{.*}} dereferenceable(18) %{{.+}}, ptr {{.*}} dereferenceable(18) %{{.+}}, i64 18)
     // CHECK-NEXT: %[[EQ:.+]] = icmp eq i32 %[[CMP]], 0
     // CHECK-NEXT: ret i1 %[[EQ]]
     a == b
@@ -37,7 +37,7 @@ pub fn array_eq_value_still_passed_by_pointer(a: [u16; 9], b: [u16; 9]) -> bool
 #[no_mangle]
 pub fn array_eq_long(a: &[u16; 1234], b: &[u16; 1234]) -> bool {
     // CHECK-NEXT: start:
-    // CHECK: %[[CMP:.+]] = tail call i32 @{{bcmp|memcmp}}({{i8\*|ptr}} {{.*}} dereferenceable(2468) %{{.+}}, {{i8\*|ptr}} {{.*}} dereferenceable(2468) %{{.+}}, i64 2468)
+    // CHECK: %[[CMP:.+]] = tail call i32 @{{bcmp|memcmp}}(ptr {{.*}} dereferenceable(2468) %{{.+}}, ptr {{.*}} dereferenceable(2468) %{{.+}}, i64 2468)
     // CHECK-NEXT: %[[EQ:.+]] = icmp eq i32 %[[CMP]], 0
     // CHECK-NEXT: ret i1 %[[EQ]]
     a == b
diff --git a/tests/codegen/array-map.rs b/tests/codegen/array-map.rs
index 3706ddf99fd..4d218e6a951 100644
--- a/tests/codegen/array-map.rs
+++ b/tests/codegen/array-map.rs
@@ -4,7 +4,6 @@
 // ignore-debug (the extra assertions get in the way)
 
 #![crate_type = "lib"]
-#![feature(array_zip)]
 
 // CHECK-LABEL: @short_integer_map
 #[no_mangle]
@@ -16,16 +15,6 @@ pub fn short_integer_map(x: [u32; 8]) -> [u32; 8] {
     x.map(|x| 2 * x + 1)
 }
 
-// CHECK-LABEL: @short_integer_zip_map
-#[no_mangle]
-pub fn short_integer_zip_map(x: [u32; 8], y: [u32; 8]) -> [u32; 8] {
-    // CHECK: %[[A:.+]] = load <8 x i32>
-    // CHECK: %[[B:.+]] = load <8 x i32>
-    // CHECK: sub <8 x i32> %[[B]], %[[A]]
-    // CHECK: store <8 x i32>
-    x.zip(y).map(|(x, y)| x - y)
-}
-
 // This test is checking that LLVM can SRoA away a bunch of the overhead,
 // like fully moving the iterators to registers.  Notably, previous implementations
 // of `map` ended up `alloca`ing the whole `array::IntoIterator`, meaning both a
@@ -41,7 +30,6 @@ pub fn short_integer_zip_map(x: [u32; 8], y: [u32; 8]) -> [u32; 8] {
 pub fn long_integer_map(x: [u32; 512]) -> [u32; 512] {
     // CHECK: start:
     // CHECK-NEXT: alloca [512 x i32]
-    // CHECK-NEXT: alloca %"core::mem::manually_drop::ManuallyDrop<[u32; 512]>"
     // CHECK-NOT: alloca
     // CHECK: mul <{{[0-9]+}} x i32>
     // CHECK: add <{{[0-9]+}} x i32>
diff --git a/tests/codegen/ascii-char.rs b/tests/codegen/ascii-char.rs
new file mode 100644
index 00000000000..4167becf5e9
--- /dev/null
+++ b/tests/codegen/ascii-char.rs
@@ -0,0 +1,37 @@
+// compile-flags: -C opt-level=1
+// ignore-debug (the extra assertions get in the way)
+
+#![crate_type = "lib"]
+#![feature(ascii_char)]
+
+use std::ascii::Char as AsciiChar;
+
+// CHECK-LABEL: i8 @unwrap_digit_from_remainder(i32
+#[no_mangle]
+pub fn unwrap_digit_from_remainder(v: u32) -> AsciiChar {
+    // CHECK-NOT: icmp
+    // CHECK-NOT: panic
+
+    // CHECK: %[[R:.+]] = urem i32 %v, 10
+    // CHECK-NEXT: %[[T:.+]] = trunc i32 %[[R]] to i8
+    // CHECK-NEXT: %[[D:.+]] = or i8 %[[T]], 48
+    // CHECK-NEXT: ret i8 %[[D]]
+
+    // CHECK-NOT: icmp
+    // CHECK-NOT: panic
+    AsciiChar::digit((v % 10) as u8).unwrap()
+}
+
+// CHECK-LABEL: i8 @unwrap_from_masked(i8
+#[no_mangle]
+pub fn unwrap_from_masked(b: u8) -> AsciiChar {
+    // CHECK-NOT: icmp
+    // CHECK-NOT: panic
+
+    // CHECK: %[[M:.+]] = and i8 %b, 127
+    // CHECK-NEXT: ret i8 %[[M]]
+
+    // CHECK-NOT: icmp
+    // CHECK-NOT: panic
+    AsciiChar::from_u8(b & 0x7f).unwrap()
+}
diff --git a/tests/codegen/atomic-operations.rs b/tests/codegen/atomic-operations.rs
index d2bc618dfc5..20980c48960 100644
--- a/tests/codegen/atomic-operations.rs
+++ b/tests/codegen/atomic-operations.rs
@@ -7,37 +7,37 @@ use std::sync::atomic::{AtomicI32, Ordering::*};
 // CHECK-LABEL: @compare_exchange
 #[no_mangle]
 pub fn compare_exchange(a: &AtomicI32) {
-    // CHECK: cmpxchg {{i32\*|ptr}} %{{.*}}, i32 0, i32 10 monotonic monotonic
-    // CHECK: cmpxchg {{i32\*|ptr}} %{{.*}}, i32 0, i32 11 monotonic acquire
-    // CHECK: cmpxchg {{i32\*|ptr}} %{{.*}}, i32 0, i32 12 monotonic seq_cst
+    // CHECK: cmpxchg ptr %{{.*}}, i32 0, i32 10 monotonic monotonic
+    // CHECK: cmpxchg ptr %{{.*}}, i32 0, i32 11 monotonic acquire
+    // CHECK: cmpxchg ptr %{{.*}}, i32 0, i32 12 monotonic seq_cst
     let _ = a.compare_exchange(0, 10, Relaxed, Relaxed);
     let _ = a.compare_exchange(0, 11, Relaxed, Acquire);
     let _ = a.compare_exchange(0, 12, Relaxed, SeqCst);
 
-    // CHECK: cmpxchg {{i32\*|ptr}} %{{.*}}, i32 0, i32 20 release monotonic
-    // CHECK: cmpxchg {{i32\*|ptr}} %{{.*}}, i32 0, i32 21 release acquire
-    // CHECK: cmpxchg {{i32\*|ptr}} %{{.*}}, i32 0, i32 22 release seq_cst
+    // CHECK: cmpxchg ptr %{{.*}}, i32 0, i32 20 release monotonic
+    // CHECK: cmpxchg ptr %{{.*}}, i32 0, i32 21 release acquire
+    // CHECK: cmpxchg ptr %{{.*}}, i32 0, i32 22 release seq_cst
     let _ = a.compare_exchange(0, 20, Release, Relaxed);
     let _ = a.compare_exchange(0, 21, Release, Acquire);
     let _ = a.compare_exchange(0, 22, Release, SeqCst);
 
-    // CHECK: cmpxchg {{i32\*|ptr}} %{{.*}}, i32 0, i32 30 acquire monotonic
-    // CHECK: cmpxchg {{i32\*|ptr}} %{{.*}}, i32 0, i32 31 acquire acquire
-    // CHECK: cmpxchg {{i32\*|ptr}} %{{.*}}, i32 0, i32 32 acquire seq_cst
+    // CHECK: cmpxchg ptr %{{.*}}, i32 0, i32 30 acquire monotonic
+    // CHECK: cmpxchg ptr %{{.*}}, i32 0, i32 31 acquire acquire
+    // CHECK: cmpxchg ptr %{{.*}}, i32 0, i32 32 acquire seq_cst
     let _ = a.compare_exchange(0, 30, Acquire, Relaxed);
     let _ = a.compare_exchange(0, 31, Acquire, Acquire);
     let _ = a.compare_exchange(0, 32, Acquire, SeqCst);
 
-    // CHECK: cmpxchg {{i32\*|ptr}} %{{.*}}, i32 0, i32 40 acq_rel monotonic
-    // CHECK: cmpxchg {{i32\*|ptr}} %{{.*}}, i32 0, i32 41 acq_rel acquire
-    // CHECK: cmpxchg {{i32\*|ptr}} %{{.*}}, i32 0, i32 42 acq_rel seq_cst
+    // CHECK: cmpxchg ptr %{{.*}}, i32 0, i32 40 acq_rel monotonic
+    // CHECK: cmpxchg ptr %{{.*}}, i32 0, i32 41 acq_rel acquire
+    // CHECK: cmpxchg ptr %{{.*}}, i32 0, i32 42 acq_rel seq_cst
     let _ = a.compare_exchange(0, 40, AcqRel, Relaxed);
     let _ = a.compare_exchange(0, 41, AcqRel, Acquire);
     let _ = a.compare_exchange(0, 42, AcqRel, SeqCst);
 
-    // CHECK: cmpxchg {{i32\*|ptr}} %{{.*}}, i32 0, i32 50 seq_cst monotonic
-    // CHECK: cmpxchg {{i32\*|ptr}} %{{.*}}, i32 0, i32 51 seq_cst acquire
-    // CHECK: cmpxchg {{i32\*|ptr}} %{{.*}}, i32 0, i32 52 seq_cst seq_cst
+    // CHECK: cmpxchg ptr %{{.*}}, i32 0, i32 50 seq_cst monotonic
+    // CHECK: cmpxchg ptr %{{.*}}, i32 0, i32 51 seq_cst acquire
+    // CHECK: cmpxchg ptr %{{.*}}, i32 0, i32 52 seq_cst seq_cst
     let _ = a.compare_exchange(0, 50, SeqCst, Relaxed);
     let _ = a.compare_exchange(0, 51, SeqCst, Acquire);
     let _ = a.compare_exchange(0, 52, SeqCst, SeqCst);
@@ -46,37 +46,37 @@ pub fn compare_exchange(a: &AtomicI32) {
 // CHECK-LABEL: @compare_exchange_weak
 #[no_mangle]
 pub fn compare_exchange_weak(w: &AtomicI32) {
-    // CHECK: cmpxchg weak {{i32\*|ptr}} %{{.*}}, i32 1, i32 10 monotonic monotonic
-    // CHECK: cmpxchg weak {{i32\*|ptr}} %{{.*}}, i32 1, i32 11 monotonic acquire
-    // CHECK: cmpxchg weak {{i32\*|ptr}} %{{.*}}, i32 1, i32 12 monotonic seq_cst
+    // CHECK: cmpxchg weak ptr %{{.*}}, i32 1, i32 10 monotonic monotonic
+    // CHECK: cmpxchg weak ptr %{{.*}}, i32 1, i32 11 monotonic acquire
+    // CHECK: cmpxchg weak ptr %{{.*}}, i32 1, i32 12 monotonic seq_cst
     let _ = w.compare_exchange_weak(1, 10, Relaxed, Relaxed);
     let _ = w.compare_exchange_weak(1, 11, Relaxed, Acquire);
     let _ = w.compare_exchange_weak(1, 12, Relaxed, SeqCst);
 
-    // CHECK: cmpxchg weak {{i32\*|ptr}} %{{.*}}, i32 1, i32 20 release monotonic
-    // CHECK: cmpxchg weak {{i32\*|ptr}} %{{.*}}, i32 1, i32 21 release acquire
-    // CHECK: cmpxchg weak {{i32\*|ptr}} %{{.*}}, i32 1, i32 22 release seq_cst
+    // CHECK: cmpxchg weak ptr %{{.*}}, i32 1, i32 20 release monotonic
+    // CHECK: cmpxchg weak ptr %{{.*}}, i32 1, i32 21 release acquire
+    // CHECK: cmpxchg weak ptr %{{.*}}, i32 1, i32 22 release seq_cst
     let _ = w.compare_exchange_weak(1, 20, Release, Relaxed);
     let _ = w.compare_exchange_weak(1, 21, Release, Acquire);
     let _ = w.compare_exchange_weak(1, 22, Release, SeqCst);
 
-    // CHECK: cmpxchg weak {{i32\*|ptr}} %{{.*}}, i32 1, i32 30 acquire monotonic
-    // CHECK: cmpxchg weak {{i32\*|ptr}} %{{.*}}, i32 1, i32 31 acquire acquire
-    // CHECK: cmpxchg weak {{i32\*|ptr}} %{{.*}}, i32 1, i32 32 acquire seq_cst
+    // CHECK: cmpxchg weak ptr %{{.*}}, i32 1, i32 30 acquire monotonic
+    // CHECK: cmpxchg weak ptr %{{.*}}, i32 1, i32 31 acquire acquire
+    // CHECK: cmpxchg weak ptr %{{.*}}, i32 1, i32 32 acquire seq_cst
     let _ = w.compare_exchange_weak(1, 30, Acquire, Relaxed);
     let _ = w.compare_exchange_weak(1, 31, Acquire, Acquire);
     let _ = w.compare_exchange_weak(1, 32, Acquire, SeqCst);
 
-    // CHECK: cmpxchg weak {{i32\*|ptr}} %{{.*}}, i32 1, i32 40 acq_rel monotonic
-    // CHECK: cmpxchg weak {{i32\*|ptr}} %{{.*}}, i32 1, i32 41 acq_rel acquire
-    // CHECK: cmpxchg weak {{i32\*|ptr}} %{{.*}}, i32 1, i32 42 acq_rel seq_cst
+    // CHECK: cmpxchg weak ptr %{{.*}}, i32 1, i32 40 acq_rel monotonic
+    // CHECK: cmpxchg weak ptr %{{.*}}, i32 1, i32 41 acq_rel acquire
+    // CHECK: cmpxchg weak ptr %{{.*}}, i32 1, i32 42 acq_rel seq_cst
     let _ = w.compare_exchange_weak(1, 40, AcqRel, Relaxed);
     let _ = w.compare_exchange_weak(1, 41, AcqRel, Acquire);
     let _ = w.compare_exchange_weak(1, 42, AcqRel, SeqCst);
 
-    // CHECK: cmpxchg weak {{i32\*|ptr}} %{{.*}}, i32 1, i32 50 seq_cst monotonic
-    // CHECK: cmpxchg weak {{i32\*|ptr}} %{{.*}}, i32 1, i32 51 seq_cst acquire
-    // CHECK: cmpxchg weak {{i32\*|ptr}} %{{.*}}, i32 1, i32 52 seq_cst seq_cst
+    // CHECK: cmpxchg weak ptr %{{.*}}, i32 1, i32 50 seq_cst monotonic
+    // CHECK: cmpxchg weak ptr %{{.*}}, i32 1, i32 51 seq_cst acquire
+    // CHECK: cmpxchg weak ptr %{{.*}}, i32 1, i32 52 seq_cst seq_cst
     let _ = w.compare_exchange_weak(1, 50, SeqCst, Relaxed);
     let _ = w.compare_exchange_weak(1, 51, SeqCst, Acquire);
     let _ = w.compare_exchange_weak(1, 52, SeqCst, SeqCst);
diff --git a/tests/codegen/autovectorize-f32x4.rs b/tests/codegen/autovectorize-f32x4.rs
index 9ecea53f1c0..54392be707f 100644
--- a/tests/codegen/autovectorize-f32x4.rs
+++ b/tests/codegen/autovectorize-f32x4.rs
@@ -1,7 +1,6 @@
 // compile-flags: -C opt-level=3 -Z merge-functions=disabled
 // only-x86_64
 #![crate_type = "lib"]
-#![feature(array_zip)]
 
 // CHECK-LABEL: @auto_vectorize_direct
 #[no_mangle]
@@ -32,12 +31,12 @@ pub fn auto_vectorize_loop(a: [f32; 4], b: [f32; 4]) -> [f32; 4] {
     c
 }
 
-// CHECK-LABEL: @auto_vectorize_array_zip_map
+// CHECK-LABEL: @auto_vectorize_array_from_fn
 #[no_mangle]
-pub fn auto_vectorize_array_zip_map(a: [f32; 4], b: [f32; 4]) -> [f32; 4] {
+pub fn auto_vectorize_array_from_fn(a: [f32; 4], b: [f32; 4]) -> [f32; 4] {
 // CHECK: load <4 x float>
 // CHECK: load <4 x float>
 // CHECK: fadd <4 x float>
 // CHECK: store <4 x float>
-    a.zip(b).map(|(a, b)| a + b)
+    std::array::from_fn(|i| a[i] + b[i])
 }
diff --git a/tests/codegen/avr/avr-func-addrspace.rs b/tests/codegen/avr/avr-func-addrspace.rs
index bc11e108124..dc36a9fac8c 100644
--- a/tests/codegen/avr/avr-func-addrspace.rs
+++ b/tests/codegen/avr/avr-func-addrspace.rs
@@ -94,7 +94,7 @@ pub extern "C" fn test() {
 
 // Validate that we can codegen transmutes between data ptrs and fn ptrs.
 
-// CHECK: define{{.+}}{{void \(\) addrspace\(1\)\*|ptr addrspace\(1\)}} @transmute_data_ptr_to_fn({{\{\}\*|ptr}}{{.*}} %x)
+// CHECK: define{{.+}}ptr addrspace(1) @transmute_data_ptr_to_fn(ptr{{.*}} %x)
 #[no_mangle]
 pub unsafe fn transmute_data_ptr_to_fn(x: *const ()) -> fn() {
     // It doesn't matter precisely how this is codegenned (through memory or an addrspacecast),
@@ -102,7 +102,7 @@ pub unsafe fn transmute_data_ptr_to_fn(x: *const ()) -> fn() {
     transmute(x)
 }
 
-// CHECK: define{{.+}}{{\{\}\*|ptr}} @transmute_fn_ptr_to_data({{void \(\) addrspace\(1\)\*|ptr addrspace\(1\)}}{{.*}} %x)
+// CHECK: define{{.+}}ptr @transmute_fn_ptr_to_data(ptr addrspace(1){{.*}} %x)
 #[no_mangle]
 pub unsafe fn transmute_fn_ptr_to_data(x: fn()) -> *const () {
     // It doesn't matter precisely how this is codegenned (through memory or an addrspacecast),
@@ -116,7 +116,7 @@ pub enum Either<T, U> { A(T), B(U) }
 // with the `ptr` field representing both `&i32` and `fn()` depending on the variant.
 // This is incorrect, because `fn()` should be `ptr addrspace(1)`, not `ptr`.
 
-// CHECK: define{{.+}}void @should_not_combine_addrspace({{.+\*|ptr}}{{.+}}sret{{.+}}%0, {{.+\*|ptr}}{{.+}}%x)
+// CHECK: define{{.+}}void @should_not_combine_addrspace(ptr{{.+}}sret{{.+}}%_0, ptr{{.+}}%x)
 #[no_mangle]
 #[inline(never)]
 pub fn should_not_combine_addrspace(x: Either<&i32, fn()>) -> Either<&i32, fn()> {
diff --git a/tests/codegen/binary-search-index-no-bound-check.rs b/tests/codegen/binary-search-index-no-bound-check.rs
index c1766a4a44a..595969a8979 100644
--- a/tests/codegen/binary-search-index-no-bound-check.rs
+++ b/tests/codegen/binary-search-index-no-bound-check.rs
@@ -9,7 +9,9 @@
 #[no_mangle]
 pub fn binary_search_index_no_bounds_check(s: &[u8]) -> u8 {
     // CHECK-NOT: panic
-    // CHECK-NOT: slice_index_len_fail
+    // CHECK-NOT: slice_start_index_len_fail
+    // CHECK-NOT: slice_end_index_len_fail
+    // CHECK-NOT: panic_bounds_check
     if let Ok(idx) = s.binary_search(&b'\\') {
         s[idx]
     } else {
diff --git a/tests/codegen/box-maybe-uninit-llvm14.rs b/tests/codegen/box-maybe-uninit-llvm14.rs
index b0c88f76c43..c9f88fb3fe4 100644
--- a/tests/codegen/box-maybe-uninit-llvm14.rs
+++ b/tests/codegen/box-maybe-uninit-llvm14.rs
@@ -31,4 +31,4 @@ pub fn box_uninitialized2() -> Box<MaybeUninit<[usize; 1024 * 1024]>> {
 // Hide the LLVM 15+ `allocalign` attribute in the declaration of __rust_alloc
 // from the CHECK-NOT above. We don't check the attributes here because we can't rely
 // on all of them being set until LLVM 15.
-// CHECK: declare noalias{{.*}} @__rust_alloc(i{{[0-9]+}} noundef, i{{[0-9]+.*}} noundef)
+// CHECK: declare {{(dso_local )?}}noalias{{.*}} @__rust_alloc(i{{[0-9]+}} noundef, i{{[0-9]+.*}} noundef)
diff --git a/tests/codegen/box-maybe-uninit.rs b/tests/codegen/box-maybe-uninit.rs
index 2f88966996a..282af99b067 100644
--- a/tests/codegen/box-maybe-uninit.rs
+++ b/tests/codegen/box-maybe-uninit.rs
@@ -1,5 +1,4 @@
 // compile-flags: -O
-// min-llvm-version: 15.0
 #![crate_type = "lib"]
 
 use std::mem::MaybeUninit;
@@ -28,6 +27,6 @@ pub fn box_uninitialized2() -> Box<MaybeUninit<[usize; 1024 * 1024]>> {
 
 // Hide the `allocalign` attribute in the declaration of __rust_alloc
 // from the CHECK-NOT above, and also verify the attributes got set reasonably.
-// CHECK: declare noalias noundef ptr @__rust_alloc(i{{[0-9]+}} noundef, i{{[0-9]+}} allocalign noundef) unnamed_addr [[RUST_ALLOC_ATTRS:#[0-9]+]]
+// CHECK: declare {{(dso_local )?}}noalias noundef ptr @__rust_alloc(i{{[0-9]+}} noundef, i{{[0-9]+}} allocalign noundef) unnamed_addr [[RUST_ALLOC_ATTRS:#[0-9]+]]
 
-// CHECK-DAG: attributes [[RUST_ALLOC_ATTRS]] = { {{.*}} allockind("alloc,uninitialized,aligned") allocsize(0) uwtable "alloc-family"="__rust_alloc" {{.*}} }
+// CHECK-DAG: attributes [[RUST_ALLOC_ATTRS]] = { {{.*}} allockind("alloc,uninitialized,aligned") allocsize(0) {{(uwtable )?}}"alloc-family"="__rust_alloc" {{.*}} }
diff --git a/tests/codegen/call-llvm-intrinsics.rs b/tests/codegen/call-llvm-intrinsics.rs
index cb8abae198e..11f2917717c 100644
--- a/tests/codegen/call-llvm-intrinsics.rs
+++ b/tests/codegen/call-llvm-intrinsics.rs
@@ -1,6 +1,7 @@
 // compile-flags: -C no-prepopulate-passes -Copt-level=0
 
 // ignore-riscv64
+// ignore-loongarch64
 
 #![feature(link_llvm_intrinsics)]
 #![crate_type = "lib"]
diff --git a/tests/codegen/call-metadata.rs b/tests/codegen/call-metadata.rs
index 1c30c08d3b2..07cc0c96371 100644
--- a/tests/codegen/call-metadata.rs
+++ b/tests/codegen/call-metadata.rs
@@ -6,7 +6,7 @@
 #![crate_type = "lib"]
 
 pub fn test() {
-    // CHECK: call noundef i8 @some_true(), !range [[R0:![0-9]+]]
+    // CHECK: call noundef i8 @some_true(){{( #[0-9]+)?}}, !range [[R0:![0-9]+]]
     // CHECK: [[R0]] = !{i8 0, i8 3}
     some_true();
 }
diff --git a/tests/codegen/catch-unwind.rs b/tests/codegen/catch-unwind.rs
index b90ef104ce7..6b63b83ef45 100644
--- a/tests/codegen/catch-unwind.rs
+++ b/tests/codegen/catch-unwind.rs
@@ -10,6 +10,8 @@
 // ignore-riscv64 FIXME
 // On s390x the closure is also in another function
 // ignore-s390x FIXME
+// On loongarch64 the closure is also in another function
+// ignore-loongarch64 FIXME
 
 #![crate_type = "lib"]
 #![feature(c_unwind)]
diff --git a/tests/codegen/comparison-operators-2-tuple.rs b/tests/codegen/comparison-operators-2-tuple.rs
index a9d25e3b53c..7a2a3fc93f8 100644
--- a/tests/codegen/comparison-operators-2-tuple.rs
+++ b/tests/codegen/comparison-operators-2-tuple.rs
@@ -1,5 +1,4 @@
 // compile-flags: -C opt-level=1 -Z merge-functions=disabled
-// min-llvm-version: 15.0
 // only-x86_64
 
 #![crate_type = "lib"]
diff --git a/tests/codegen/comparison-operators-newtype.rs b/tests/codegen/comparison-operators-newtype.rs
index 683a2bd4fbb..8fd8a81dfeb 100644
--- a/tests/codegen/comparison-operators-newtype.rs
+++ b/tests/codegen/comparison-operators-newtype.rs
@@ -3,7 +3,6 @@
 // in the operators for such a type all optimize away.
 
 // compile-flags: -C opt-level=1
-// min-llvm-version: 15.0
 
 #![crate_type = "lib"]
 
diff --git a/tests/codegen/const_scalar_pair.rs b/tests/codegen/const_scalar_pair.rs
new file mode 100644
index 00000000000..aa4cf7a64d5
--- /dev/null
+++ b/tests/codegen/const_scalar_pair.rs
@@ -0,0 +1,10 @@
+// compile-flags: --crate-type=lib -Copt-level=0 -Zmir-opt-level=0 -C debuginfo=2
+
+#![feature(inline_const)]
+
+// Test that we don't generate a memory allocation for the constant
+// and read the fields from that, but instead just create the value pair directly.
+pub fn foo() -> (i32, i32) {
+    // CHECK: ret { i32, i32 } { i32 1, i32 2 }
+    const { (1, 2) }
+}
diff --git a/tests/codegen/consts.rs b/tests/codegen/consts.rs
index fc2badc417c..3797e1a99da 100644
--- a/tests/codegen/consts.rs
+++ b/tests/codegen/consts.rs
@@ -42,7 +42,7 @@ pub fn inline_enum_const() -> E<i8, i16> {
 #[no_mangle]
 pub fn low_align_const() -> E<i16, [i16; 3]> {
     // Check that low_align_const and high_align_const use the same constant
-    // CHECK: memcpy.{{.+}}({{i8\*|ptr}} align 2 %{{[0-9]+}}, {{i8\*|ptr}} align 2 {{.*}}[[LOW_HIGH]]{{.*}}, i{{(32|64)}} 8, i1 false)
+    // CHECK: memcpy.{{.+}}(ptr align 2 %_0, ptr align 2 {{.*}}[[LOW_HIGH]]{{.*}}, i{{(32|64)}} 8, i1 false)
     *&E::A(0)
 }
 
@@ -50,6 +50,6 @@ pub fn low_align_const() -> E<i16, [i16; 3]> {
 #[no_mangle]
 pub fn high_align_const() -> E<i16, i32> {
     // Check that low_align_const and high_align_const use the same constant
-    // CHECK: memcpy.{{.+}}({{i8\*|ptr}} align 4 %{{[0-9]+}}, {{i8\*|ptr}} align 4 {{.*}}[[LOW_HIGH]]{{.*}}, i{{(32|64)}} 8, i1 false)
+    // CHECK: memcpy.{{.+}}(ptr align 4 %_0, ptr align 4 {{.*}}[[LOW_HIGH]]{{.*}}, i{{(32|64)}} 8, i1 false)
     *&E::A(0)
 }
diff --git a/tests/codegen/debug-column.rs b/tests/codegen/debug-column.rs
index e61642b8e1b..f3b19a2eb2f 100644
--- a/tests/codegen/debug-column.rs
+++ b/tests/codegen/debug-column.rs
@@ -6,11 +6,11 @@
 fn main() {
     unsafe {
         // Column numbers are 1-based. Regression test for #65437.
-        // CHECK: call void @giraffe(), !dbg [[A:!.*]]
+        // CHECK: call void @giraffe(){{( #[0-9]+)?}}, !dbg [[A:!.*]]
         giraffe();
 
         // Column numbers use byte offests. Regression test for #67360
-        // CHECK: call void @turtle(), !dbg [[B:!.*]]
+        // CHECK: call void @turtle(){{( #[0-9]+)?}}, !dbg [[B:!.*]]
 /* ż */ turtle();
 
         // CHECK: [[A]] = !DILocation(line: 10, column: 9,
diff --git a/tests/codegen/debug-vtable.rs b/tests/codegen/debug-vtable.rs
index d82b737de0b..e52392b260b 100644
--- a/tests/codegen/debug-vtable.rs
+++ b/tests/codegen/debug-vtable.rs
@@ -11,8 +11,6 @@
 
 // Make sure that vtables don't have the unnamed_addr attribute when debuginfo is enabled.
 // This helps debuggers more reliably map from dyn pointer to concrete type.
-// CHECK: @vtable.0 = private constant <{
-// CHECK: @vtable.1 = private constant <{
 // CHECK: @vtable.2 = private constant <{
 // CHECK: @vtable.3 = private constant <{
 // CHECK: @vtable.4 = private constant <{
diff --git a/tests/codegen/debuginfo-constant-locals.rs b/tests/codegen/debuginfo-constant-locals.rs
new file mode 100644
index 00000000000..95a1b8c9d21
--- /dev/null
+++ b/tests/codegen/debuginfo-constant-locals.rs
@@ -0,0 +1,28 @@
+// compile-flags: -g -O
+
+// Check that simple constant values are preserved in debuginfo across both MIR opts and LLVM opts
+
+#![crate_type = "lib"]
+
+#[no_mangle]
+pub fn check_it() {
+    let a = 1;
+    let b = 42;
+
+    foo(a + b);
+}
+
+#[inline(never)]
+fn foo(x: i32) {
+    std::process::exit(x);
+}
+
+// CHECK-LABEL: @check_it
+// CHECK: call void @llvm.dbg.value(metadata i32 1, metadata ![[a_metadata:[0-9]+]], metadata !DIExpression())
+// CHECK: call void @llvm.dbg.value(metadata i32 42, metadata ![[b_metadata:[0-9]+]], metadata !DIExpression())
+
+// CHECK: ![[a_metadata]] = !DILocalVariable(name: "a"
+// CHECK-SAME: line: 9
+
+// CHECK: ![[b_metadata]] = !DILocalVariable(name: "b"
+// CHECK-SAME: line: 10
diff --git a/tests/codegen/drop-in-place-noalias.rs b/tests/codegen/drop-in-place-noalias.rs
new file mode 100644
index 00000000000..ece1e426c08
--- /dev/null
+++ b/tests/codegen/drop-in-place-noalias.rs
@@ -0,0 +1,38 @@
+// compile-flags: -O -C no-prepopulate-passes
+
+// Tests that the compiler can apply `noalias` and other &mut attributes to `drop_in_place`.
+// Note that non-Unpin types should not get `noalias`, matching &mut behavior.
+
+#![crate_type="lib"]
+
+use std::marker::PhantomPinned;
+
+// CHECK: define internal void @{{.*}}core{{.*}}ptr{{.*}}drop_in_place{{.*}}StructUnpin{{.*}}(ptr noalias noundef align 4 dereferenceable(12) %{{.+}})
+
+// CHECK: define internal void @{{.*}}core{{.*}}ptr{{.*}}drop_in_place{{.*}}StructNotUnpin{{.*}}(ptr noundef nonnull align 4 %{{.+}})
+
+pub struct StructUnpin {
+    a: i32,
+    b: i32,
+    c: i32,
+}
+
+impl Drop for StructUnpin {
+    fn drop(&mut self) {}
+}
+
+pub struct StructNotUnpin {
+    a: i32,
+    b: i32,
+    c: i32,
+    p: PhantomPinned,
+}
+
+impl Drop for StructNotUnpin {
+    fn drop(&mut self) {}
+}
+
+pub unsafe fn main(x: StructUnpin, y: StructNotUnpin) {
+    drop(x);
+    drop(y);
+}
diff --git a/tests/codegen/drop.rs b/tests/codegen/drop.rs
index 99402827158..3615ef47b53 100644
--- a/tests/codegen/drop.rs
+++ b/tests/codegen/drop.rs
@@ -1,4 +1,5 @@
 // ignore-wasm32-bare compiled with panic=abort by default
+// needs-unwind - this test verifies the amount of drop calls when unwinding is used
 // compile-flags: -C no-prepopulate-passes
 
 #![crate_type = "lib"]
diff --git a/tests/codegen/enable-lto-unit-splitting.rs b/tests/codegen/enable-lto-unit-splitting.rs
new file mode 100644
index 00000000000..7daa05f69d1
--- /dev/null
+++ b/tests/codegen/enable-lto-unit-splitting.rs
@@ -0,0 +1,10 @@
+// Verifies that "EnableSplitLTOUnit" module flag is added.
+//
+// compile-flags: -Clto -Ctarget-feature=-crt-static -Zsplit-lto-unit
+
+#![crate_type="lib"]
+
+pub fn foo() {
+}
+
+// CHECK: !{{[0-9]+}} = !{i32 4, !"EnableSplitLTOUnit", i32 1}
diff --git a/tests/codegen/enum-debug-niche-2.rs b/tests/codegen/enum-debug-niche-2.rs
index 9c72ad9d248..4b607d50574 100644
--- a/tests/codegen/enum-debug-niche-2.rs
+++ b/tests/codegen/enum-debug-niche-2.rs
@@ -7,8 +7,8 @@
 // compile-flags: -g -C no-prepopulate-passes
 
 // CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_variant_part,{{.*}}size: 32,{{.*}}
-// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "Placeholder",{{.*}}extraData: i64 4294967295{{[,)].*}}
-// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "Error",{{.*}}extraData: i64 0{{[,)].*}}
+// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "Placeholder",{{.*}}extraData: i128 4294967295{{[,)].*}}
+// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "Error",{{.*}}extraData: i128 0{{[,)].*}}
 
 #![feature(never_type)]
 
diff --git a/tests/codegen/enum-match.rs b/tests/codegen/enum-match.rs
index 36c6be19012..5548cd25147 100644
--- a/tests/codegen/enum-match.rs
+++ b/tests/codegen/enum-match.rs
@@ -15,7 +15,7 @@ pub enum Enum0 {
 // CHECK-NEXT: start:
 // CHECK-NEXT: %1 = icmp eq i8 %0, 2
 // CHECK-NEXT: %2 = and i8 %0, 1
-// CHECK-NEXT: %.0 = select i1 %1, i8 13, i8 %2
+// CHECK-NEXT: %_0.0 = select i1 %1, i8 13, i8 %2
 #[no_mangle]
 pub fn match0(e: Enum0) -> u8 {
     use Enum0::*;
diff --git a/tests/codegen/enum-u128.rs b/tests/codegen/enum-u128.rs
new file mode 100644
index 00000000000..f50d360ac9f
--- /dev/null
+++ b/tests/codegen/enum-u128.rs
@@ -0,0 +1,27 @@
+// This tests that debug info for "c-like" 128bit enums is properly emitted.
+// This is ignored for the fallback mode on MSVC due to problems with PDB.
+
+//
+// ignore-msvc
+
+// compile-flags: -g -C no-prepopulate-passes
+
+// CHECK-LABEL: @main
+// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_enumeration_type,{{.*}}name: "Foo",{{.*}}flags: DIFlagEnumClass,{{.*}}
+// CHECK: {{.*}}DIEnumerator{{.*}}name: "Lo",{{.*}}value: 0,{{.*}}
+// CHECK: {{.*}}DIEnumerator{{.*}}name: "Hi",{{.*}}value: 18446744073709551616,{{.*}}
+// CHECK: {{.*}}DIEnumerator{{.*}}name: "Bar",{{.*}}value: 18446745000000000123,{{.*}}
+
+#![allow(incomplete_features)]
+#![feature(repr128)]
+
+#[repr(u128)]
+pub enum Foo {
+    Lo,
+    Hi = 1 << 64,
+    Bar = 18_446_745_000_000_000_123,
+}
+
+pub fn main() {
+    let foo = Foo::Bar;
+}
diff --git a/tests/codegen/external-no-mangle-statics.rs b/tests/codegen/external-no-mangle-statics.rs
index c6ecb7aa96a..48023a2a901 100644
--- a/tests/codegen/external-no-mangle-statics.rs
+++ b/tests/codegen/external-no-mangle-statics.rs
@@ -6,72 +6,72 @@
 // `#[no_mangle]`d static variables always have external linkage, i.e., no `internal` in their
 // definitions
 
-// CHECK: @A = local_unnamed_addr constant
+// CHECK: @A = {{(dso_local )?}}local_unnamed_addr constant
 #[no_mangle]
 static A: u8 = 0;
 
-// CHECK: @B = local_unnamed_addr global
+// CHECK: @B = {{(dso_local )?}}local_unnamed_addr global
 #[no_mangle]
 static mut B: u8 = 0;
 
-// CHECK: @C = local_unnamed_addr constant
+// CHECK: @C = {{(dso_local )?}}local_unnamed_addr constant
 #[no_mangle]
 pub static C: u8 = 0;
 
-// CHECK: @D = local_unnamed_addr global
+// CHECK: @D = {{(dso_local )?}}local_unnamed_addr global
 #[no_mangle]
 pub static mut D: u8 = 0;
 
 mod private {
-    // CHECK: @E = local_unnamed_addr constant
+    // CHECK: @E = {{(dso_local )?}}local_unnamed_addr constant
     #[no_mangle]
     static E: u8 = 0;
 
-    // CHECK: @F = local_unnamed_addr global
+    // CHECK: @F = {{(dso_local )?}}local_unnamed_addr global
     #[no_mangle]
     static mut F: u8 = 0;
 
-    // CHECK: @G = local_unnamed_addr constant
+    // CHECK: @G = {{(dso_local )?}}local_unnamed_addr constant
     #[no_mangle]
     pub static G: u8 = 0;
 
-    // CHECK: @H = local_unnamed_addr global
+    // CHECK: @H = {{(dso_local )?}}local_unnamed_addr global
     #[no_mangle]
     pub static mut H: u8 = 0;
 }
 
 const HIDDEN: () = {
-    // CHECK: @I = local_unnamed_addr constant
+    // CHECK: @I = {{(dso_local )?}}local_unnamed_addr constant
     #[no_mangle]
     static I: u8 = 0;
 
-    // CHECK: @J = local_unnamed_addr global
+    // CHECK: @J = {{(dso_local )?}}local_unnamed_addr global
     #[no_mangle]
     static mut J: u8 = 0;
 
-    // CHECK: @K = local_unnamed_addr constant
+    // CHECK: @K = {{(dso_local )?}}local_unnamed_addr constant
     #[no_mangle]
     pub static K: u8 = 0;
 
-    // CHECK: @L = local_unnamed_addr global
+    // CHECK: @L = {{(dso_local )?}}local_unnamed_addr global
     #[no_mangle]
     pub static mut L: u8 = 0;
 };
 
 fn x() {
-    // CHECK: @M = local_unnamed_addr constant
+    // CHECK: @M = {{(dso_local )?}}local_unnamed_addr constant
     #[no_mangle]
     static M: fn() = x;
 
-    // CHECK: @N = local_unnamed_addr global
+    // CHECK: @N = {{(dso_local )?}}local_unnamed_addr global
     #[no_mangle]
     static mut N: u8 = 0;
 
-    // CHECK: @O = local_unnamed_addr constant
+    // CHECK: @O = {{(dso_local )?}}local_unnamed_addr constant
     #[no_mangle]
     pub static O: u8 = 0;
 
-    // CHECK: @P = local_unnamed_addr global
+    // CHECK: @P = {{(dso_local )?}}local_unnamed_addr global
     #[no_mangle]
     pub static mut P: u8 = 0;
 }
diff --git a/tests/codegen/fastcall-inreg.rs b/tests/codegen/fastcall-inreg.rs
index 02f5d545910..ab19efa45bf 100644
--- a/tests/codegen/fastcall-inreg.rs
+++ b/tests/codegen/fastcall-inreg.rs
@@ -19,7 +19,7 @@ pub mod tests {
     #[no_mangle]
     pub extern "fastcall" fn f1(_: i32, _: i32, _: i32) {}
 
-    // CHECK: @f2({{i32\*|ptr}} inreg noundef %_1, {{i32\*|ptr}} inreg noundef %_2, {{i32\*|ptr}} noundef %_3)
+    // CHECK: @f2(ptr inreg noundef %_1, ptr inreg noundef %_2, ptr noundef %_3)
     #[no_mangle]
     pub extern "fastcall" fn f2(_: *const i32, _: *const i32, _: *const i32) {}
 
diff --git a/tests/codegen/fewer-names.rs b/tests/codegen/fewer-names.rs
index 7f383a5c149..df1080bff2b 100644
--- a/tests/codegen/fewer-names.rs
+++ b/tests/codegen/fewer-names.rs
@@ -7,14 +7,14 @@
 
 #[no_mangle]
 pub fn sum(x: u32, y: u32) -> u32 {
-// YES-LABEL: define{{.*}}i32 @sum(i32 noundef %0, i32 noundef %1)
-// YES-NEXT:    %3 = add i32 %1, %0
-// YES-NEXT:    ret i32 %3
+    // YES-LABEL: define{{.*}}i32 @sum(i32 noundef %0, i32 noundef %1)
+    // YES-NEXT:    %3 = add i32 %1, %0
+    // YES-NEXT:    ret i32 %3
 
-// NO-LABEL: define{{.*}}i32 @sum(i32 noundef %x, i32 noundef %y)
-// NO-NEXT:  start:
-// NO-NEXT:    %0 = add i32 %y, %x
-// NO-NEXT:    ret i32 %0
+    // NO-LABEL: define{{.*}}i32 @sum(i32 noundef %x, i32 noundef %y)
+    // NO-NEXT:  start:
+    // NO-NEXT:    %z = add i32 %y, %x
+    // NO-NEXT:    ret i32 %z
     let z = x + y;
     z
 }
diff --git a/tests/codegen/function-arguments-noopt.rs b/tests/codegen/function-arguments-noopt.rs
index 0c62e0d35e3..8fe6c790dda 100644
--- a/tests/codegen/function-arguments-noopt.rs
+++ b/tests/codegen/function-arguments-noopt.rs
@@ -23,13 +23,13 @@ pub fn boolean_call(x: bool, f: fn(bool) -> bool) -> bool {
   f(x)
 }
 
-// CHECK: align 4 {{i32\*|ptr}} @borrow({{i32\*|ptr}} align 4 %x)
+// CHECK: align 4 ptr @borrow(ptr align 4 %x)
 #[no_mangle]
 pub fn borrow(x: &i32) -> &i32 {
   x
 }
 
-// CHECK: align 4 {{i32\*|ptr}} @borrow_mut({{i32\*|ptr}} align 4 %x)
+// CHECK: align 4 ptr @borrow_mut(ptr align 4 %x)
 #[no_mangle]
 pub fn borrow_mut(x: &mut i32) -> &mut i32 {
   x
@@ -38,11 +38,11 @@ pub fn borrow_mut(x: &mut i32) -> &mut i32 {
 // CHECK-LABEL: @borrow_call
 #[no_mangle]
 pub fn borrow_call(x: &i32, f: fn(&i32) -> &i32) -> &i32 {
-  // CHECK: call align 4 {{i32\*|ptr}} %f({{i32\*|ptr}} align 4 %x)
+  // CHECK: call align 4 ptr %f(ptr align 4 %x)
   f(x)
 }
 
-// CHECK: void @struct_({{%S\*|ptr}} sret(%S){{( %0)?}}, {{%S\*|ptr}} %x)
+// CHECK: void @struct_(ptr sret(%S) align 4{{( %_0)?}}, ptr align 4 %x)
 #[no_mangle]
 pub fn struct_(x: S) -> S {
   x
@@ -51,7 +51,7 @@ pub fn struct_(x: S) -> S {
 // CHECK-LABEL: @struct_call
 #[no_mangle]
 pub fn struct_call(x: S, f: fn(S) -> S) -> S {
-  // CHECK: call void %f({{%S\*|ptr}} sret(%S){{( %0)?}}, {{%S\*|ptr}} %{{.+}})
+  // CHECK: call void %f(ptr sret(%S) align 4{{( %_0)?}}, ptr align 4 %{{.+}})
   f(x)
 }
 
diff --git a/tests/codegen/function-arguments.rs b/tests/codegen/function-arguments.rs
index d6f019016a5..a218596da1d 100644
--- a/tests/codegen/function-arguments.rs
+++ b/tests/codegen/function-arguments.rs
@@ -80,95 +80,95 @@ pub fn option_nonzero_int(x: Option<NonZeroU64>) -> Option<NonZeroU64> {
   x
 }
 
-// CHECK: @readonly_borrow({{i32\*|ptr}} noalias noundef readonly align 4 dereferenceable(4) %_1)
+// CHECK: @readonly_borrow(ptr noalias noundef readonly align 4 dereferenceable(4) %_1)
 // FIXME #25759 This should also have `nocapture`
 #[no_mangle]
 pub fn readonly_borrow(_: &i32) {
 }
 
-// CHECK: noundef align 4 dereferenceable(4) {{i32\*|ptr}} @readonly_borrow_ret()
+// CHECK: noundef align 4 dereferenceable(4) ptr @readonly_borrow_ret()
 #[no_mangle]
 pub fn readonly_borrow_ret() -> &'static i32 {
   loop {}
 }
 
-// CHECK: @static_borrow({{i32\*|ptr}} noalias noundef readonly align 4 dereferenceable(4) %_1)
+// CHECK: @static_borrow(ptr noalias noundef readonly align 4 dereferenceable(4) %_1)
 // static borrow may be captured
 #[no_mangle]
 pub fn static_borrow(_: &'static i32) {
 }
 
-// CHECK: @named_borrow({{i32\*|ptr}} noalias noundef readonly align 4 dereferenceable(4) %_1)
+// CHECK: @named_borrow(ptr noalias noundef readonly align 4 dereferenceable(4) %_1)
 // borrow with named lifetime may be captured
 #[no_mangle]
 pub fn named_borrow<'r>(_: &'r i32) {
 }
 
-// CHECK: @unsafe_borrow({{i16\*|ptr}} noundef nonnull align 2 %_1)
+// CHECK: @unsafe_borrow(ptr noundef nonnull align 2 %_1)
 // unsafe interior means this isn't actually readonly and there may be aliases ...
 #[no_mangle]
 pub fn unsafe_borrow(_: &UnsafeInner) {
 }
 
-// CHECK: @mutable_unsafe_borrow({{i16\*|ptr}} noalias noundef align 2 dereferenceable(2) %_1)
+// CHECK: @mutable_unsafe_borrow(ptr noalias noundef align 2 dereferenceable(2) %_1)
 // ... unless this is a mutable borrow, those never alias
 #[no_mangle]
 pub fn mutable_unsafe_borrow(_: &mut UnsafeInner) {
 }
 
-// CHECK: @mutable_borrow({{i32\*|ptr}} noalias noundef align 4 dereferenceable(4) %_1)
+// CHECK: @mutable_borrow(ptr noalias noundef align 4 dereferenceable(4) %_1)
 // FIXME #25759 This should also have `nocapture`
 #[no_mangle]
 pub fn mutable_borrow(_: &mut i32) {
 }
 
-// CHECK: noundef align 4 dereferenceable(4) {{i32\*|ptr}} @mutable_borrow_ret()
+// CHECK: noundef align 4 dereferenceable(4) ptr @mutable_borrow_ret()
 #[no_mangle]
 pub fn mutable_borrow_ret() -> &'static mut i32 {
   loop {}
 }
 
 #[no_mangle]
-// CHECK: @mutable_notunpin_borrow({{i32\*|ptr}} noundef nonnull align 4 %_1)
+// CHECK: @mutable_notunpin_borrow(ptr noundef nonnull align 4 %_1)
 // This one is *not* `noalias` because it might be self-referential.
 // It is also not `dereferenceable` due to
 // <https://github.com/rust-lang/unsafe-code-guidelines/issues/381>.
 pub fn mutable_notunpin_borrow(_: &mut NotUnpin) {
 }
 
-// CHECK: @notunpin_borrow({{i32\*|ptr}} noalias noundef readonly align 4 dereferenceable(4) %_1)
+// CHECK: @notunpin_borrow(ptr noalias noundef readonly align 4 dereferenceable(4) %_1)
 // But `&NotUnpin` behaves perfectly normal.
 #[no_mangle]
 pub fn notunpin_borrow(_: &NotUnpin) {
 }
 
-// CHECK: @indirect_struct({{%S\*|ptr}} noalias nocapture noundef readonly dereferenceable(32) %_1)
+// CHECK: @indirect_struct(ptr noalias nocapture noundef readonly align 4 dereferenceable(32) %_1)
 #[no_mangle]
 pub fn indirect_struct(_: S) {
 }
 
-// CHECK: @borrowed_struct({{%S\*|ptr}} noalias noundef readonly align 4 dereferenceable(32) %_1)
+// CHECK: @borrowed_struct(ptr noalias noundef readonly align 4 dereferenceable(32) %_1)
 // FIXME #25759 This should also have `nocapture`
 #[no_mangle]
 pub fn borrowed_struct(_: &S) {
 }
 
-// CHECK: @option_borrow({{i32\*|ptr}} noalias noundef readonly align 4 dereferenceable_or_null(4) %x)
+// CHECK: @option_borrow(ptr noalias noundef readonly align 4 dereferenceable_or_null(4) %x)
 #[no_mangle]
 pub fn option_borrow(x: Option<&i32>) {
 }
 
-// CHECK: @option_borrow_mut({{i32\*|ptr}} noalias noundef align 4 dereferenceable_or_null(4) %x)
+// CHECK: @option_borrow_mut(ptr noalias noundef align 4 dereferenceable_or_null(4) %x)
 #[no_mangle]
 pub fn option_borrow_mut(x: Option<&mut i32>) {
 }
 
-// CHECK: @raw_struct({{%S\*|ptr}} noundef %_1)
+// CHECK: @raw_struct(ptr noundef %_1)
 #[no_mangle]
 pub fn raw_struct(_: *const S) {
 }
 
-// CHECK: @raw_option_nonnull_struct({{i32\*|ptr}} noundef %_1)
+// CHECK: @raw_option_nonnull_struct(ptr noundef %_1)
 #[no_mangle]
 pub fn raw_option_nonnull_struct(_: Option<NonNull<S>>) {
 }
@@ -176,19 +176,19 @@ pub fn raw_option_nonnull_struct(_: Option<NonNull<S>>) {
 
 // `Box` can get deallocated during execution of the function, so it should
 // not get `dereferenceable`.
-// CHECK: noundef nonnull align 4 {{i32\*|ptr}} @_box({{i32\*|ptr}} noalias noundef nonnull align 4 %x)
+// CHECK: noundef nonnull align 4 ptr @_box(ptr noalias noundef nonnull align 4 %x)
 #[no_mangle]
 pub fn _box(x: Box<i32>) -> Box<i32> {
   x
 }
 
-// CHECK: noundef nonnull align 4 {{i32\*|ptr}} @notunpin_box({{i32\*|ptr}} noundef nonnull align 4 %x)
+// CHECK: noundef nonnull align 4 ptr @notunpin_box(ptr noundef nonnull align 4 %x)
 #[no_mangle]
 pub fn notunpin_box(x: Box<NotUnpin>) -> Box<NotUnpin> {
   x
 }
 
-// CHECK: @struct_return({{%S\*|ptr}} noalias nocapture noundef sret(%S) dereferenceable(32){{( %0)?}})
+// CHECK: @struct_return(ptr noalias nocapture noundef sret(%S) align 4 dereferenceable(32){{( %_0)?}})
 #[no_mangle]
 pub fn struct_return() -> S {
   S {
@@ -202,68 +202,68 @@ pub fn struct_return() -> S {
 pub fn helper(_: usize) {
 }
 
-// CHECK: @slice({{\[0 x i8\]\*|ptr}} noalias noundef nonnull readonly align 1 %_1.0, [[USIZE]] noundef %_1.1)
+// CHECK: @slice(ptr noalias noundef nonnull readonly align 1 %_1.0, [[USIZE]] noundef %_1.1)
 // FIXME #25759 This should also have `nocapture`
 #[no_mangle]
 pub fn slice(_: &[u8]) {
 }
 
-// CHECK: @mutable_slice({{\[0 x i8\]\*|ptr}} noalias noundef nonnull align 1 %_1.0, [[USIZE]] noundef %_1.1)
+// CHECK: @mutable_slice(ptr noalias noundef nonnull align 1 %_1.0, [[USIZE]] noundef %_1.1)
 // FIXME #25759 This should also have `nocapture`
 #[no_mangle]
 pub fn mutable_slice(_: &mut [u8]) {
 }
 
-// CHECK: @unsafe_slice({{\[0 x i16\]\*|ptr}} noundef nonnull align 2 %_1.0, [[USIZE]] noundef %_1.1)
+// CHECK: @unsafe_slice(ptr noundef nonnull align 2 %_1.0, [[USIZE]] noundef %_1.1)
 // unsafe interior means this isn't actually readonly and there may be aliases ...
 #[no_mangle]
 pub fn unsafe_slice(_: &[UnsafeInner]) {
 }
 
-// CHECK: @raw_slice({{\[0 x i8\]\*|ptr}} noundef %_1.0, [[USIZE]] noundef %_1.1)
+// CHECK: @raw_slice(ptr noundef %_1.0, [[USIZE]] noundef %_1.1)
 #[no_mangle]
 pub fn raw_slice(_: *const [u8]) {
 }
 
-// CHECK: @str({{\[0 x i8\]\*|ptr}} noalias noundef nonnull readonly align 1 %_1.0, [[USIZE]] noundef %_1.1)
+// CHECK: @str(ptr noalias noundef nonnull readonly align 1 %_1.0, [[USIZE]] noundef %_1.1)
 // FIXME #25759 This should also have `nocapture`
 #[no_mangle]
 pub fn str(_: &[u8]) {
 }
 
-// CHECK: @trait_borrow({{\{\}\*|ptr}} noundef nonnull align 1 %_1.0, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}) %_1.1)
+// CHECK: @trait_borrow(ptr noundef nonnull align 1 %_1.0, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}) %_1.1)
 // FIXME #25759 This should also have `nocapture`
 #[no_mangle]
 pub fn trait_borrow(_: &dyn Drop) {
 }
 
-// CHECK: @option_trait_borrow({{i8\*|ptr}} noundef align 1 %x.0, {{i8\*|ptr}} %x.1)
+// CHECK: @option_trait_borrow(ptr noundef align 1 %x.0, ptr %x.1)
 #[no_mangle]
 pub fn option_trait_borrow(x: Option<&dyn Drop>) {
 }
 
-// CHECK: @option_trait_borrow_mut({{i8\*|ptr}} noundef align 1 %x.0, {{i8\*|ptr}} %x.1)
+// CHECK: @option_trait_borrow_mut(ptr noundef align 1 %x.0, ptr %x.1)
 #[no_mangle]
 pub fn option_trait_borrow_mut(x: Option<&mut dyn Drop>) {
 }
 
-// CHECK: @trait_raw({{\{\}\*|ptr}} noundef %_1.0, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}) %_1.1)
+// CHECK: @trait_raw(ptr noundef %_1.0, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}) %_1.1)
 #[no_mangle]
 pub fn trait_raw(_: *const dyn Drop) {
 }
 
-// CHECK: @trait_box({{\{\}\*|ptr}} noalias noundef nonnull align 1{{( %0)?}}, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}){{( %1)?}})
+// CHECK: @trait_box(ptr noalias noundef nonnull align 1{{( %0)?}}, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}){{( %1)?}})
 #[no_mangle]
 pub fn trait_box(_: Box<dyn Drop + Unpin>) {
 }
 
-// CHECK: { {{i8\*|ptr}}, {{i8\*|ptr}} } @trait_option({{i8\*|ptr}} noalias noundef align 1 %x.0, {{i8\*|ptr}} %x.1)
+// CHECK: { ptr, ptr } @trait_option(ptr noalias noundef align 1 %x.0, ptr %x.1)
 #[no_mangle]
 pub fn trait_option(x: Option<Box<dyn Drop + Unpin>>) -> Option<Box<dyn Drop + Unpin>> {
   x
 }
 
-// CHECK: { {{\[0 x i16\]\*|ptr}}, [[USIZE]] } @return_slice({{\[0 x i16\]\*|ptr}} noalias noundef nonnull readonly align 2 %x.0, [[USIZE]] noundef %x.1)
+// CHECK: { ptr, [[USIZE]] } @return_slice(ptr noalias noundef nonnull readonly align 2 %x.0, [[USIZE]] noundef %x.1)
 #[no_mangle]
 pub fn return_slice(x: &[u16]) -> &[u16] {
   x
@@ -281,7 +281,7 @@ pub fn enum_id_2(x: Option<u8>) -> Option<u8> {
   x
 }
 
-// CHECK: { {{\{\}\*|ptr}}, {{.+}} } @dyn_star({{\{\}\*|ptr}} noundef %x.0, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}) %x.1)
+// CHECK: { ptr, {{.+}} } @dyn_star(ptr noundef %x.0, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}) %x.1)
 // Expect an ABI something like `{ {}*, [3 x i64]* }`, but that's hard to match on generically,
 // so do like the `trait_box` test and just match on `{{.+}}` for the vtable.
 #[no_mangle]
diff --git a/tests/codegen/global_asm.rs b/tests/codegen/global_asm.rs
index 9912b1e75bf..4c2ccf4e0e9 100644
--- a/tests/codegen/global_asm.rs
+++ b/tests/codegen/global_asm.rs
@@ -1,23 +1,6 @@
-// ignore-aarch64
-// ignore-arm
-// ignore-avr
-// ignore-bpf
-// ignore-bpf
-// ignore-hexagon
-// ignore-mips
-// ignore-mips64
-// ignore-msp430
-// ignore-powerpc64
-// ignore-powerpc
-// ignore-sparc
-// ignore-sparc64
-// ignore-s390x
-// ignore-thumb
-// ignore-nvptx64
-// ignore-spirv
-// ignore-wasm32
-// ignore-wasm64
-// ignore-emscripten
+// revisions: x32 x64
+//[x32] only-x86
+//[x64] only-x86_64
 // compile-flags: -C no-prepopulate-passes
 
 #![crate_type = "lib"]
diff --git a/tests/codegen/global_asm_include.rs b/tests/codegen/global_asm_include.rs
index b68c5ad3b9d..0fede8c71e4 100644
--- a/tests/codegen/global_asm_include.rs
+++ b/tests/codegen/global_asm_include.rs
@@ -1,23 +1,6 @@
-// ignore-aarch64
-// ignore-arm
-// ignore-avr
-// ignore-bpf
-// ignore-bpf
-// ignore-hexagon
-// ignore-mips
-// ignore-mips64
-// ignore-msp430
-// ignore-powerpc64
-// ignore-powerpc
-// ignore-sparc
-// ignore-sparc64
-// ignore-s390x
-// ignore-thumb
-// ignore-nvptx64
-// ignore-spirv
-// ignore-wasm32
-// ignore-wasm64
-// ignore-emscripten
+// revisions: x32 x64
+//[x32] only-x86
+//[x64] only-x86_64
 // compile-flags: -C no-prepopulate-passes
 
 #![crate_type = "lib"]
diff --git a/tests/codegen/global_asm_x2.rs b/tests/codegen/global_asm_x2.rs
index d87e02befb9..1fc2825b2bd 100644
--- a/tests/codegen/global_asm_x2.rs
+++ b/tests/codegen/global_asm_x2.rs
@@ -1,23 +1,6 @@
-// ignore-aarch64
-// ignore-arm
-// ignore-avr
-// ignore-bpf
-// ignore-bpf
-// ignore-hexagon
-// ignore-mips
-// ignore-mips64
-// ignore-msp430
-// ignore-powerpc64
-// ignore-powerpc
-// ignore-sparc
-// ignore-sparc64
-// ignore-s390x
-// ignore-thumb
-// ignore-nvptx64
-// ignore-spirv
-// ignore-wasm32
-// ignore-wasm64
-// ignore-emscripten
+// revisions: x32 x64
+//[x32] only-x86
+//[x64] only-x86_64
 // compile-flags: -C no-prepopulate-passes
 
 #![crate_type = "lib"]
diff --git a/tests/codegen/intrinsics/mask.rs b/tests/codegen/intrinsics/mask.rs
index 8f93da2e5da..82131c55847 100644
--- a/tests/codegen/intrinsics/mask.rs
+++ b/tests/codegen/intrinsics/mask.rs
@@ -7,6 +7,6 @@
 #[no_mangle]
 pub fn mask_ptr(ptr: *const u16, mask: usize) -> *const u16 {
     // CHECK: call
-    // CHECK-SAME: @llvm.ptrmask.{{p0|p0i8}}.[[WORD]]({{ptr|i8\*}} {{%ptr|%1}}, [[WORD]] %mask)
+    // CHECK-SAME: @llvm.ptrmask.{{p0|p0i8}}.[[WORD]](ptr {{%ptr|%1}}, [[WORD]] %mask)
     core::intrinsics::ptr_mask(ptr, mask)
 }
diff --git a/tests/codegen/intrinsics/nontemporal.rs b/tests/codegen/intrinsics/nontemporal.rs
index d8ee2945266..dc020c12119 100644
--- a/tests/codegen/intrinsics/nontemporal.rs
+++ b/tests/codegen/intrinsics/nontemporal.rs
@@ -6,7 +6,7 @@
 #[no_mangle]
 pub fn a(a: &mut u32, b: u32) {
     // CHECK-LABEL: define{{.*}}void @a
-    // CHECK: store i32 %b, {{i32\*|ptr}} %a, align 4, !nontemporal
+    // CHECK: store i32 %b, ptr %a, align 4, !nontemporal
     unsafe {
         std::intrinsics::nontemporal_store(a, b);
     }
diff --git a/tests/codegen/intrinsics/offset.rs b/tests/codegen/intrinsics/offset.rs
new file mode 100644
index 00000000000..542bacf99a8
--- /dev/null
+++ b/tests/codegen/intrinsics/offset.rs
@@ -0,0 +1,33 @@
+// compile-flags: -O -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+#![feature(core_intrinsics)]
+
+use std::intrinsics::offset;
+
+// CHECK-LABEL: ptr @offset_zst
+// CHECK-SAME: (ptr noundef %p, [[SIZE:i[0-9]+]] noundef %d)
+#[no_mangle]
+pub unsafe fn offset_zst(p: *const (), d: usize) -> *const () {
+    // CHECK-NOT: getelementptr
+    // CHECK: ret ptr %p
+    offset(p, d)
+}
+
+// CHECK-LABEL: ptr @offset_isize
+// CHECK-SAME: (ptr noundef %p, [[SIZE]] noundef %d)
+#[no_mangle]
+pub unsafe fn offset_isize(p: *const u32, d: isize) -> *const u32 {
+    // CHECK: %[[R:.*]] = getelementptr inbounds i32, ptr %p, [[SIZE]] %d
+    // CHECK-NEXT: ret ptr %[[R]]
+    offset(p, d)
+}
+
+// CHECK-LABEL: ptr @offset_usize
+// CHECK-SAME: (ptr noundef %p, [[SIZE]] noundef %d)
+#[no_mangle]
+pub unsafe fn offset_usize(p: *const u64, d: usize) -> *const u64 {
+    // CHECK: %[[R:.*]] = getelementptr inbounds i64, ptr %p, [[SIZE]] %d
+    // CHECK-NEXT: ret ptr %[[R]]
+    offset(p, d)
+}
diff --git a/tests/codegen/intrinsics/transmute-niched.rs b/tests/codegen/intrinsics/transmute-niched.rs
new file mode 100644
index 00000000000..e9c8d803cb9
--- /dev/null
+++ b/tests/codegen/intrinsics/transmute-niched.rs
@@ -0,0 +1,183 @@
+// revisions: OPT DBG
+// [OPT] compile-flags: -C opt-level=3 -C no-prepopulate-passes
+// [DBG] compile-flags: -C opt-level=0 -C no-prepopulate-passes
+// only-64bit (so I don't need to worry about usize)
+
+#![crate_type = "lib"]
+
+use std::mem::transmute;
+use std::num::NonZeroU32;
+
+#[repr(u8)]
+pub enum SmallEnum {
+    A = 10,
+    B = 11,
+    C = 12,
+}
+
+// CHECK-LABEL: @check_to_enum(
+#[no_mangle]
+pub unsafe fn check_to_enum(x: i8) -> SmallEnum {
+    // OPT: %0 = icmp uge i8 %x, 10
+    // OPT: call void @llvm.assume(i1 %0)
+    // OPT: %1 = icmp ule i8 %x, 12
+    // OPT: call void @llvm.assume(i1 %1)
+    // DBG-NOT: icmp
+    // DBG-NOT: assume
+    // CHECK: ret i8 %x
+
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_from_enum(
+#[no_mangle]
+pub unsafe fn check_from_enum(x: SmallEnum) -> i8 {
+    // OPT: %0 = icmp uge i8 %x, 10
+    // OPT: call void @llvm.assume(i1 %0)
+    // OPT: %1 = icmp ule i8 %x, 12
+    // OPT: call void @llvm.assume(i1 %1)
+    // DBG-NOT: icmp
+    // DBG-NOT: assume
+    // CHECK: ret i8 %x
+
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_to_ordering(
+#[no_mangle]
+pub unsafe fn check_to_ordering(x: u8) -> std::cmp::Ordering {
+    // OPT: %0 = icmp uge i8 %x, -1
+    // OPT: %1 = icmp ule i8 %x, 1
+    // OPT: %2 = or i1 %0, %1
+    // OPT: call void @llvm.assume(i1 %2)
+    // DBG-NOT: icmp
+    // DBG-NOT: assume
+    // CHECK: ret i8 %x
+
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_from_ordering(
+#[no_mangle]
+pub unsafe fn check_from_ordering(x: std::cmp::Ordering) -> u8 {
+    // OPT: %0 = icmp uge i8 %x, -1
+    // OPT: %1 = icmp ule i8 %x, 1
+    // OPT: %2 = or i1 %0, %1
+    // OPT: call void @llvm.assume(i1 %2)
+    // DBG-NOT: icmp
+    // DBG-NOT: assume
+    // CHECK: ret i8 %x
+
+    transmute(x)
+}
+
+#[repr(i32)]
+pub enum Minus100ToPlus100 {
+    A = -100,
+    B = -90,
+    C = -80,
+    D = -70,
+    E = -60,
+    F = -50,
+    G = -40,
+    H = -30,
+    I = -20,
+    J = -10,
+    K = 0,
+    L = 10,
+    M = 20,
+    N = 30,
+    O = 40,
+    P = 50,
+    Q = 60,
+    R = 70,
+    S = 80,
+    T = 90,
+    U = 100,
+}
+
+// CHECK-LABEL: @check_enum_from_char(
+#[no_mangle]
+pub unsafe fn check_enum_from_char(x: char) -> Minus100ToPlus100 {
+    // OPT: %0 = icmp ule i32 %x, 1114111
+    // OPT: call void @llvm.assume(i1 %0)
+    // OPT: %1 = icmp uge i32 %x, -100
+    // OPT: %2 = icmp ule i32 %x, 100
+    // OPT: %3 = or i1 %1, %2
+    // OPT: call void @llvm.assume(i1 %3)
+    // DBG-NOT: icmp
+    // DBG-NOT: assume
+    // CHECK: ret i32 %x
+
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_enum_to_char(
+#[no_mangle]
+pub unsafe fn check_enum_to_char(x: Minus100ToPlus100) -> char {
+    // OPT: %0 = icmp uge i32 %x, -100
+    // OPT: %1 = icmp ule i32 %x, 100
+    // OPT: %2 = or i1 %0, %1
+    // OPT: call void @llvm.assume(i1 %2)
+    // OPT: %3 = icmp ule i32 %x, 1114111
+    // OPT: call void @llvm.assume(i1 %3)
+    // DBG-NOT: icmp
+    // DBG-NOT: assume
+    // CHECK: ret i32 %x
+
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_swap_pair(
+#[no_mangle]
+pub unsafe fn check_swap_pair(x: (char, NonZeroU32)) -> (NonZeroU32, char) {
+    // OPT: %0 = icmp ule i32 %x.0, 1114111
+    // OPT: call void @llvm.assume(i1 %0)
+    // OPT: %1 = icmp uge i32 %x.0, 1
+    // OPT: call void @llvm.assume(i1 %1)
+    // OPT: %2 = icmp uge i32 %x.1, 1
+    // OPT: call void @llvm.assume(i1 %2)
+    // OPT: %3 = icmp ule i32 %x.1, 1114111
+    // OPT: call void @llvm.assume(i1 %3)
+    // DBG-NOT: icmp
+    // DBG-NOT: assume
+    // CHECK: %[[P1:.+]] = insertvalue { i32, i32 } poison, i32 %x.0, 0
+    // CHECK: %[[P2:.+]] = insertvalue { i32, i32 } %[[P1]], i32 %x.1, 1
+    // CHECK: ret { i32, i32 } %[[P2]]
+
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_bool_from_ordering(
+#[no_mangle]
+pub unsafe fn check_bool_from_ordering(x: std::cmp::Ordering) -> bool {
+    // OPT: %0 = icmp uge i8 %x, -1
+    // OPT: %1 = icmp ule i8 %x, 1
+    // OPT: %2 = or i1 %0, %1
+    // OPT: call void @llvm.assume(i1 %2)
+    // OPT: %3 = icmp ule i8 %x, 1
+    // OPT: call void @llvm.assume(i1 %3)
+    // DBG-NOT: icmp
+    // DBG-NOT: assume
+    // CHECK: %[[R:.+]] = trunc i8 %x to i1
+    // CHECK: ret i1 %[[R]]
+
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_bool_to_ordering(
+#[no_mangle]
+pub unsafe fn check_bool_to_ordering(x: bool) -> std::cmp::Ordering {
+    // CHECK: %_0 = zext i1 %x to i8
+    // OPT: %0 = icmp ule i8 %_0, 1
+    // OPT: call void @llvm.assume(i1 %0)
+    // OPT: %1 = icmp uge i8 %_0, -1
+    // OPT: %2 = icmp ule i8 %_0, 1
+    // OPT: %3 = or i1 %1, %2
+    // OPT: call void @llvm.assume(i1 %3)
+    // DBG-NOT: icmp
+    // DBG-NOT: assume
+    // CHECK: ret i8 %_0
+
+    transmute(x)
+}
diff --git a/tests/codegen/intrinsics/transmute-x64.rs b/tests/codegen/intrinsics/transmute-x64.rs
index 99d258c6204..19020f6280a 100644
--- a/tests/codegen/intrinsics/transmute-x64.rs
+++ b/tests/codegen/intrinsics/transmute-x64.rs
@@ -1,6 +1,5 @@
 // compile-flags: -O -C no-prepopulate-passes
 // only-x86_64 (it's using arch-specific types)
-// min-llvm-version: 15.0 # this test assumes `ptr`s
 
 #![crate_type = "lib"]
 
@@ -11,8 +10,8 @@ use std::mem::transmute;
 #[no_mangle]
 pub unsafe fn check_sse_float_to_int(x: __m128) -> __m128i {
     // CHECK-NOT: alloca
-    // CHECK: %1 = load <4 x float>, ptr %x, align 16
-    // CHECK: store <4 x float> %1, ptr %0, align 16
+    // CHECK: %0 = load <4 x float>, ptr %x, align 16
+    // CHECK: store <4 x float> %0, ptr %_0, align 16
     transmute(x)
 }
 
@@ -20,8 +19,8 @@ pub unsafe fn check_sse_float_to_int(x: __m128) -> __m128i {
 #[no_mangle]
 pub unsafe fn check_sse_pair_to_avx(x: (__m128i, __m128i)) -> __m256i {
     // CHECK-NOT: alloca
-    // CHECK: %1 = load <4 x i64>, ptr %x, align 16
-    // CHECK: store <4 x i64> %1, ptr %0, align 32
+    // CHECK: %0 = load <4 x i64>, ptr %x, align 16
+    // CHECK: store <4 x i64> %0, ptr %_0, align 32
     transmute(x)
 }
 
@@ -29,7 +28,7 @@ pub unsafe fn check_sse_pair_to_avx(x: (__m128i, __m128i)) -> __m256i {
 #[no_mangle]
 pub unsafe fn check_sse_pair_from_avx(x: __m256i) -> (__m128i, __m128i) {
     // CHECK-NOT: alloca
-    // CHECK: %1 = load <4 x i64>, ptr %x, align 32
-    // CHECK: store <4 x i64> %1, ptr %0, align 16
+    // CHECK: %0 = load <4 x i64>, ptr %x, align 32
+    // CHECK: store <4 x i64> %0, ptr %_0, align 16
     transmute(x)
 }
diff --git a/tests/codegen/intrinsics/transmute.rs b/tests/codegen/intrinsics/transmute.rs
index 57f901c6719..e64af33ab6c 100644
--- a/tests/codegen/intrinsics/transmute.rs
+++ b/tests/codegen/intrinsics/transmute.rs
@@ -1,6 +1,5 @@
 // compile-flags: -O -C no-prepopulate-passes
 // only-64bit (so I don't need to worry about usize)
-// min-llvm-version: 15.0 # this test assumes `ptr`s
 
 #![crate_type = "lib"]
 #![feature(core_intrinsics)]
@@ -8,16 +7,16 @@
 #![feature(inline_const)]
 #![allow(unreachable_code)]
 
-use std::mem::{transmute, MaybeUninit};
+use std::intrinsics::{transmute, transmute_unchecked};
+use std::mem::MaybeUninit;
 
-// Some of the cases here are statically rejected by `mem::transmute`, so
-// we need to generate custom MIR for those cases to get to codegen.
+// Some of these need custom MIR to not get removed by MIR optimizations.
 use std::intrinsics::mir::*;
 
-enum Never {}
+pub enum ZstNever {}
 
 #[repr(align(2))]
-pub struct BigNever(Never, u16, Never);
+pub struct BigNever(ZstNever, u16, ZstNever);
 
 #[repr(align(8))]
 pub struct Scalar64(i64);
@@ -30,36 +29,40 @@ pub struct Aggregate8(u8);
 
 // CHECK-LABEL: @check_bigger_size(
 #[no_mangle]
-#[custom_mir(dialect = "runtime", phase = "initial")]
 pub unsafe fn check_bigger_size(x: u16) -> u32 {
     // CHECK: call void @llvm.trap
-    mir!{
-        {
-            RET = CastTransmute(x);
-            Return()
-        }
-    }
+    transmute_unchecked(x)
 }
 
 // CHECK-LABEL: @check_smaller_size(
 #[no_mangle]
-#[custom_mir(dialect = "runtime", phase = "initial")]
 pub unsafe fn check_smaller_size(x: u32) -> u16 {
     // CHECK: call void @llvm.trap
-    mir!{
-        {
-            RET = CastTransmute(x);
-            Return()
-        }
-    }
+    transmute_unchecked(x)
 }
 
 // CHECK-LABEL: @check_smaller_array(
 #[no_mangle]
-#[custom_mir(dialect = "runtime", phase = "initial")]
 pub unsafe fn check_smaller_array(x: [u32; 7]) -> [u32; 3] {
     // CHECK: call void @llvm.trap
-    mir!{
+    transmute_unchecked(x)
+}
+
+// CHECK-LABEL: @check_bigger_array(
+#[no_mangle]
+pub unsafe fn check_bigger_array(x: [u32; 3]) -> [u32; 7] {
+    // CHECK: call void @llvm.trap
+    transmute_unchecked(x)
+}
+
+// CHECK-LABEL: @check_to_empty_array(
+#[no_mangle]
+#[custom_mir(dialect = "runtime", phase = "optimized")]
+pub unsafe fn check_to_empty_array(x: [u32; 5]) -> [u32; 0] {
+    // CHECK-NOT: trap
+    // CHECK: call void @llvm.trap
+    // CHECK-NOT: trap
+    mir! {
         {
             RET = CastTransmute(x);
             Return()
@@ -67,12 +70,14 @@ pub unsafe fn check_smaller_array(x: [u32; 7]) -> [u32; 3] {
     }
 }
 
-// CHECK-LABEL: @check_bigger_array(
+// CHECK-LABEL: @check_from_empty_array(
 #[no_mangle]
-#[custom_mir(dialect = "runtime", phase = "initial")]
-pub unsafe fn check_bigger_array(x: [u32; 3]) -> [u32; 7] {
+#[custom_mir(dialect = "runtime", phase = "optimized")]
+pub unsafe fn check_from_empty_array(x: [u32; 0]) -> [u32; 5] {
+    // CHECK-NOT: trap
     // CHECK: call void @llvm.trap
-    mir!{
+    // CHECK-NOT: trap
+    mir! {
         {
             RET = CastTransmute(x);
             Return()
@@ -82,12 +87,15 @@ pub unsafe fn check_bigger_array(x: [u32; 3]) -> [u32; 7] {
 
 // CHECK-LABEL: @check_to_uninhabited(
 #[no_mangle]
-#[custom_mir(dialect = "runtime", phase = "initial")]
-pub unsafe fn check_to_uninhabited(x: u16) -> BigNever {
+#[custom_mir(dialect = "runtime", phase = "optimized")]
+pub unsafe fn check_to_uninhabited(x: u16) {
+    // CHECK-NOT: trap
     // CHECK: call void @llvm.trap
-    mir!{
+    // CHECK-NOT: trap
+    mir! {
+        let temp: BigNever;
         {
-            RET = CastTransmute(x);
+            temp = CastTransmute(x);
             Return()
         }
     }
@@ -95,10 +103,10 @@ pub unsafe fn check_to_uninhabited(x: u16) -> BigNever {
 
 // CHECK-LABEL: @check_from_uninhabited(
 #[no_mangle]
-#[custom_mir(dialect = "runtime", phase = "initial")]
+#[custom_mir(dialect = "runtime", phase = "optimized")]
 pub unsafe fn check_from_uninhabited(x: BigNever) -> u16 {
     // CHECK: ret i16 poison
-    mir!{
+    mir! {
         {
             RET = CastTransmute(x);
             Return()
@@ -113,9 +121,7 @@ pub unsafe fn check_intermediate_passthrough(x: u32) -> i32 {
     // CHECK: %[[TMP:.+]] = add i32 1, %x
     // CHECK: %[[RET:.+]] = add i32 %[[TMP]], 1
     // CHECK: ret i32 %[[RET]]
-    unsafe {
-        transmute::<u32, i32>(1 + x) + 1
-    }
+    unsafe { transmute::<u32, i32>(1 + x) + 1 }
 }
 
 // CHECK-LABEL: @check_nop_pair(
@@ -125,9 +131,7 @@ pub unsafe fn check_nop_pair(x: (u8, i8)) -> (i8, u8) {
     // CHECK: %0 = insertvalue { i8, i8 } poison, i8 %x.0, 0
     // CHECK: %1 = insertvalue { i8, i8 } %0, i8 %x.1, 1
     // CHECK: ret { i8, i8 } %1
-    unsafe {
-        transmute(x)
-    }
+    unsafe { transmute(x) }
 }
 
 // CHECK-LABEL: @check_to_newtype(
@@ -159,9 +163,9 @@ pub unsafe fn check_aggregate_to_bool(x: Aggregate8) -> bool {
 // CHECK-LABEL: @check_aggregate_from_bool(
 #[no_mangle]
 pub unsafe fn check_aggregate_from_bool(x: bool) -> Aggregate8 {
-    // CHECK: %0 = alloca %Aggregate8, align 1
+    // CHECK: %_0 = alloca %Aggregate8, align 1
     // CHECK: %[[BYTE:.+]] = zext i1 %x to i8
-    // CHECK: store i8 %[[BYTE]], ptr %0, align 1
+    // CHECK: store i8 %[[BYTE]], ptr %_0, align 1
     transmute(x)
 }
 
@@ -169,8 +173,8 @@ pub unsafe fn check_aggregate_from_bool(x: bool) -> Aggregate8 {
 #[no_mangle]
 pub unsafe fn check_byte_to_bool(x: u8) -> bool {
     // CHECK-NOT: alloca
-    // CHECK: %0 = trunc i8 %x to i1
-    // CHECK: ret i1 %0
+    // CHECK: %[[R:.+]] = trunc i8 %x to i1
+    // CHECK: ret i1 %[[R]]
     transmute(x)
 }
 
@@ -178,16 +182,16 @@ pub unsafe fn check_byte_to_bool(x: u8) -> bool {
 #[no_mangle]
 pub unsafe fn check_byte_from_bool(x: bool) -> u8 {
     // CHECK-NOT: alloca
-    // CHECK: %0 = zext i1 %x to i8
-    // CHECK: ret i8 %0
+    // CHECK: %[[R:.+]] = zext i1 %x to i8
+    // CHECK: ret i8 %[[R:.+]]
     transmute(x)
 }
 
 // CHECK-LABEL: @check_to_pair(
 #[no_mangle]
 pub unsafe fn check_to_pair(x: u64) -> Option<i32> {
-    // CHECK: %0 = alloca { i32, i32 }, align 4
-    // CHECK: store i64 %x, ptr %0, align 4
+    // CHECK: %_0 = alloca { i32, i32 }, align 4
+    // CHECK: store i64 %x, ptr %_0, align 4
     transmute(x)
 }
 
@@ -198,11 +202,11 @@ pub unsafe fn check_from_pair(x: Option<i32>) -> u64 {
     // immediates so we can write using the destination alloca's alignment.
     const { assert!(std::mem::align_of::<Option<i32>>() == 4) };
 
-    // CHECK: %0 = alloca i64, align 8
-    // CHECK: store i32 %x.0, ptr %1, align 8
-    // CHECK: store i32 %x.1, ptr %2, align 4
-    // CHECK: %3 = load i64, ptr %0, align 8
-    // CHECK: ret i64 %3
+    // CHECK: %_0 = alloca i64, align 8
+    // CHECK: store i32 %x.0, ptr %0, align 8
+    // CHECK: store i32 %x.1, ptr %1, align 4
+    // CHECK: %2 = load i64, ptr %_0, align 8
+    // CHECK: ret i64 %2
     transmute(x)
 }
 
@@ -210,8 +214,8 @@ pub unsafe fn check_from_pair(x: Option<i32>) -> u64 {
 #[no_mangle]
 pub unsafe fn check_to_float(x: u32) -> f32 {
     // CHECK-NOT: alloca
-    // CHECK: %0 = bitcast i32 %x to float
-    // CHECK: ret float %0
+    // CHECK: %_0 = bitcast i32 %x to float
+    // CHECK: ret float %_0
     transmute(x)
 }
 
@@ -219,16 +223,16 @@ pub unsafe fn check_to_float(x: u32) -> f32 {
 #[no_mangle]
 pub unsafe fn check_from_float(x: f32) -> u32 {
     // CHECK-NOT: alloca
-    // CHECK: %0 = bitcast float %x to i32
-    // CHECK: ret i32 %0
+    // CHECK: %_0 = bitcast float %x to i32
+    // CHECK: ret i32 %_0
     transmute(x)
 }
 
 // CHECK-LABEL: @check_to_bytes(
 #[no_mangle]
 pub unsafe fn check_to_bytes(x: u32) -> [u8; 4] {
-    // CHECK: %0 = alloca [4 x i8], align 1
-    // CHECK: store i32 %x, ptr %0, align 1
+    // CHECK: %_0 = alloca [4 x i8], align 1
+    // CHECK: store i32 %x, ptr %_0, align 1
     transmute(x)
 }
 
@@ -244,10 +248,10 @@ pub unsafe fn check_from_bytes(x: [u8; 4]) -> u32 {
 // CHECK-LABEL: @check_to_aggregate(
 #[no_mangle]
 pub unsafe fn check_to_aggregate(x: u64) -> Aggregate64 {
-    // CHECK: %0 = alloca %Aggregate64, align 4
-    // CHECK: store i64 %x, ptr %0, align 4
-    // CHECK: %1 = load i64, ptr %0, align 4
-    // CHECK: ret i64 %1
+    // CHECK: %_0 = alloca %Aggregate64, align 4
+    // CHECK: store i64 %x, ptr %_0, align 4
+    // CHECK: %0 = load i64, ptr %_0, align 4
+    // CHECK: ret i64 %0
     transmute(x)
 }
 
@@ -264,7 +268,7 @@ pub unsafe fn check_from_aggregate(x: Aggregate64) -> u64 {
 #[no_mangle]
 pub unsafe fn check_long_array_less_aligned(x: [u64; 100]) -> [u16; 400] {
     // CHECK-NEXT: start
-    // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 2 %0, ptr align 8 %x, i64 800, i1 false)
+    // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 2 %_0, ptr align 8 %x, i64 800, i1 false)
     // CHECK-NEXT: ret void
     transmute(x)
 }
@@ -273,7 +277,7 @@ pub unsafe fn check_long_array_less_aligned(x: [u64; 100]) -> [u16; 400] {
 #[no_mangle]
 pub unsafe fn check_long_array_more_aligned(x: [u8; 100]) -> [u32; 25] {
     // CHECK-NEXT: start
-    // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %0, ptr align 1 %x, i64 100, i1 false)
+    // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %_0, ptr align 1 %x, i64 100, i1 false)
     // CHECK-NEXT: ret void
     transmute(x)
 }
@@ -292,8 +296,8 @@ pub unsafe fn check_pair_with_bool(x: (u8, bool)) -> (bool, i8) {
 pub unsafe fn check_float_to_pointer(x: f64) -> *const () {
     // CHECK-NOT: alloca
     // CHECK: %0 = bitcast double %x to i64
-    // CHECK: %1 = inttoptr i64 %0 to ptr
-    // CHECK: ret ptr %1
+    // CHECK: %_0 = inttoptr i64 %0 to ptr
+    // CHECK: ret ptr %_0
     transmute(x)
 }
 
@@ -302,8 +306,8 @@ pub unsafe fn check_float_to_pointer(x: f64) -> *const () {
 pub unsafe fn check_float_from_pointer(x: *const ()) -> f64 {
     // CHECK-NOT: alloca
     // CHECK: %0 = ptrtoint ptr %x to i64
-    // CHECK: %1 = bitcast i64 %0 to double
-    // CHECK: ret double %1
+    // CHECK: %_0 = bitcast i64 %0 to double
+    // CHECK: ret double %_0
     transmute(x)
 }
 
@@ -367,10 +371,10 @@ pub unsafe fn check_issue_110005(x: (usize, bool)) -> Option<Box<[u8]>> {
 // CHECK-LABEL: @check_pair_to_dst_ref(
 #[no_mangle]
 pub unsafe fn check_pair_to_dst_ref<'a>(x: (usize, usize)) -> &'a [u8] {
-    // CHECK: %0 = inttoptr i64 %x.0 to ptr
-    // CHECK: %1 = insertvalue { ptr, i64 } poison, ptr %0, 0
-    // CHECK: %2 = insertvalue { ptr, i64 } %1, i64 %x.1, 1
-    // CHECK: ret { ptr, i64 } %2
+    // CHECK: %_0.0 = inttoptr i64 %x.0 to ptr
+    // CHECK: %0 = insertvalue { ptr, i64 } poison, ptr %_0.0, 0
+    // CHECK: %1 = insertvalue { ptr, i64 } %0, i64 %x.1, 1
+    // CHECK: ret { ptr, i64 } %1
     transmute(x)
 }
 
@@ -382,7 +386,41 @@ pub unsafe fn check_issue_109992(x: ()) -> [(); 1] {
 
     // CHECK: start
     // CHECK-NEXT: ret void
-    mir!{
+    mir! {
+        {
+            RET = CastTransmute(x);
+            Return()
+        }
+    }
+}
+
+// CHECK-LABEL: @check_unit_to_never(
+#[no_mangle]
+#[custom_mir(dialect = "runtime", phase = "optimized")]
+pub unsafe fn check_unit_to_never(x: ()) {
+    // This uses custom MIR to avoid MIR optimizations having removed ZST ops.
+
+    // CHECK-NOT: trap
+    // CHECK: call void @llvm.trap
+    // CHECK-NOT: trap
+    mir! {
+        let temp: ZstNever;
+        {
+            temp = CastTransmute(x);
+            Return()
+        }
+    }
+}
+
+// CHECK-LABEL: @check_unit_from_never(
+#[no_mangle]
+#[custom_mir(dialect = "runtime", phase = "optimized")]
+pub unsafe fn check_unit_from_never(x: ZstNever) -> () {
+    // This uses custom MIR to avoid MIR optimizations having removed ZST ops.
+
+    // CHECK: start
+    // CHECK-NEXT: ret void
+    mir! {
         {
             RET = CastTransmute(x);
             Return()
@@ -414,10 +452,10 @@ pub struct HighAlignScalar(u8);
 // CHECK-LABEL: @check_to_overalign(
 #[no_mangle]
 pub unsafe fn check_to_overalign(x: u64) -> HighAlignScalar {
-    // CHECK: %0 = alloca %HighAlignScalar, align 8
-    // CHECK: store i64 %x, ptr %0, align 8
-    // CHECK: %1 = load i64, ptr %0, align 8
-    // CHECK: ret i64 %1
+    // CHECK: %_0 = alloca %HighAlignScalar, align 8
+    // CHECK: store i64 %x, ptr %_0, align 8
+    // CHECK: %0 = load i64, ptr %_0, align 8
+    // CHECK: ret i64 %0
     transmute(x)
 }
 
diff --git a/tests/codegen/issues/issue-103840.rs b/tests/codegen/issues/issue-103840.rs
index f19d7031bb3..da64692d27d 100644
--- a/tests/codegen/issues/issue-103840.rs
+++ b/tests/codegen/issues/issue-103840.rs
@@ -1,4 +1,5 @@
 // compile-flags: -O
+// min-llvm-version: 16.0
 #![crate_type = "lib"]
 
 pub fn foo(t: &mut Vec<usize>) {
diff --git a/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs b/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs
index d54ac9e33bc..f345c96e6f7 100644
--- a/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs
+++ b/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs
@@ -1,5 +1,5 @@
-// compile-flags: --crate-type=lib -O -Cdebuginfo=2 -Cno-prepopulate-passes
-// min-llvm-version: 15.0 # this test uses opaque pointer notation
+// compile-flags: --crate-type=lib -O -Cdebuginfo=2 -Cno-prepopulate-passes -Zmir-enable-passes=-ScalarReplacementOfAggregates
+// MIR SROA will decompose the closure
 #![feature(stmt_expr_attributes)]
 
 pub struct S([usize; 8]);
@@ -19,4 +19,5 @@ pub fn outer_function(x: S, y: S) -> usize {
 // CHECK-NOT: [[ptr_tmp:%.*]] = getelementptr inbounds %"[closure@{{.*.rs}}:9:23: 9:25]", ptr [[spill]]
 // CHECK-NOT: [[load:%.*]] = load ptr, ptr
 // CHECK: call void @llvm.lifetime.start{{.*}}({{.*}}, ptr [[spill]])
-// CHECK: call void @llvm.memcpy{{.*}}(ptr {{align .*}} [[spill]], ptr {{align .*}} %x
+// CHECK: [[inner:%.*]] = getelementptr inbounds %"{{.*}}", ptr [[spill]]
+// CHECK: call void @llvm.memcpy{{.*}}(ptr {{align .*}} [[inner]], ptr {{align .*}} %x
diff --git a/tests/codegen/issues/issue-111603.rs b/tests/codegen/issues/issue-111603.rs
new file mode 100644
index 00000000000..06429ed3fa9
--- /dev/null
+++ b/tests/codegen/issues/issue-111603.rs
@@ -0,0 +1,40 @@
+// compile-flags: -O
+
+#![crate_type = "lib"]
+#![feature(get_mut_unchecked, new_uninit)]
+
+use std::sync::Arc;
+
+// CHECK-LABEL: @new_from_array
+#[no_mangle]
+pub fn new_from_array(x: u64) -> Arc<[u64]> {
+    // Ensure that we only generate one alloca for the array.
+
+    // CHECK: alloca
+    // CHECK-SAME: [1000 x i64]
+    // CHECK-NOT: alloca
+    let array = [x; 1000];
+    Arc::new(array)
+}
+
+// CHECK-LABEL: @new_uninit
+#[no_mangle]
+pub fn new_uninit(x: u64) -> Arc<[u64; 1000]> {
+    // CHECK: call alloc::sync::arcinner_layout_for_value_layout
+    // CHECK-NOT: call alloc::sync::arcinner_layout_for_value_layout
+    let mut arc = Arc::new_uninit();
+    unsafe { Arc::get_mut_unchecked(&mut arc) }.write([x; 1000]);
+    unsafe { arc.assume_init() }
+}
+
+// CHECK-LABEL: @new_uninit_slice
+#[no_mangle]
+pub fn new_uninit_slice(x: u64) -> Arc<[u64]> {
+    // CHECK: call alloc::sync::arcinner_layout_for_value_layout
+    // CHECK-NOT: call alloc::sync::arcinner_layout_for_value_layout
+    let mut arc = Arc::new_uninit_slice(1000);
+    for elem in unsafe { Arc::get_mut_unchecked(&mut arc) } {
+        elem.write(x);
+    }
+    unsafe { arc.assume_init() }
+}
diff --git a/tests/codegen/issues/issue-37945.rs b/tests/codegen/issues/issue-37945.rs
index 4f386d335c7..329769940f9 100644
--- a/tests/codegen/issues/issue-37945.rs
+++ b/tests/codegen/issues/issue-37945.rs
@@ -12,11 +12,11 @@ use std::slice::Iter;
 pub fn is_empty_1(xs: Iter<f32>) -> bool {
 // CHECK-LABEL: @is_empty_1(
 // CHECK-NEXT:  start:
-// CHECK-NEXT:    [[A:%.*]] = icmp ne {{i32\*|ptr}} {{%xs.0|%xs.1}}, null
+// CHECK-NEXT:    [[A:%.*]] = icmp ne ptr {{%xs.0|%xs.1}}, null
 // CHECK-NEXT:    tail call void @llvm.assume(i1 [[A]])
 // The order between %xs.0 and %xs.1 on the next line doesn't matter
 // and different LLVM versions produce different order.
-// CHECK-NEXT:    [[B:%.*]] = icmp eq {{i32\*|ptr}} {{%xs.0, %xs.1|%xs.1, %xs.0}}
+// CHECK-NEXT:    [[B:%.*]] = icmp eq ptr {{%xs.0, %xs.1|%xs.1, %xs.0}}
 // CHECK-NEXT:    ret i1 [[B:%.*]]
     {xs}.next().is_none()
 }
@@ -25,11 +25,11 @@ pub fn is_empty_1(xs: Iter<f32>) -> bool {
 pub fn is_empty_2(xs: Iter<f32>) -> bool {
 // CHECK-LABEL: @is_empty_2
 // CHECK-NEXT:  start:
-// CHECK-NEXT:    [[C:%.*]] = icmp ne {{i32\*|ptr}} {{%xs.0|%xs.1}}, null
+// CHECK-NEXT:    [[C:%.*]] = icmp ne ptr {{%xs.0|%xs.1}}, null
 // CHECK-NEXT:    tail call void @llvm.assume(i1 [[C]])
 // The order between %xs.0 and %xs.1 on the next line doesn't matter
 // and different LLVM versions produce different order.
-// CHECK-NEXT:    [[D:%.*]] = icmp eq {{i32\*|ptr}} {{%xs.0, %xs.1|%xs.1, %xs.0}}
+// CHECK-NEXT:    [[D:%.*]] = icmp eq ptr {{%xs.0, %xs.1|%xs.1, %xs.0}}
 // CHECK-NEXT:    ret i1 [[D:%.*]]
     xs.map(|&x| x).next().is_none()
 }
diff --git a/tests/codegen/issues/issue-56267-2.rs b/tests/codegen/issues/issue-56267-2.rs
index 4dc9ebfebbc..1715e9f05ab 100644
--- a/tests/codegen/issues/issue-56267-2.rs
+++ b/tests/codegen/issues/issue-56267-2.rs
@@ -11,7 +11,7 @@ pub struct Foo<T> {
 // The load from bar.1 should have alignment 4. Not checking
 // other loads here, as the alignment will be platform-dependent.
 
-// CHECK: %{{.+}} = load i32, {{i32\*|ptr}} %{{.+}}, align 4
+// CHECK: %{{.+}} = load i32, ptr %{{.+}}, align 4
 #[no_mangle]
 pub fn test(x: Foo<(i32, i32)>) -> (i32, i32) {
     x.bar
diff --git a/tests/codegen/issues/issue-56267.rs b/tests/codegen/issues/issue-56267.rs
index 7bdd2577998..90aa9f7ae89 100644
--- a/tests/codegen/issues/issue-56267.rs
+++ b/tests/codegen/issues/issue-56267.rs
@@ -11,7 +11,7 @@ pub struct Foo<T> {
 // The store writing to bar.1 should have alignment 4. Not checking
 // other stores here, as the alignment will be platform-dependent.
 
-// CHECK: store i32 [[TMP1:%.+]], {{i32\*|ptr}} [[TMP2:%.+]], align 4
+// CHECK: store i32 [[TMP1:%.+]], ptr [[TMP2:%.+]], align 4
 #[no_mangle]
 pub fn test(x: (i32, i32)) -> Foo<(i32, i32)> {
     Foo { foo: 0, bar: x }
diff --git a/tests/codegen/issues/issue-56927.rs b/tests/codegen/issues/issue-56927.rs
index 044d721814b..1b09ce565b3 100644
--- a/tests/codegen/issues/issue-56927.rs
+++ b/tests/codegen/issues/issue-56927.rs
@@ -8,10 +8,10 @@ pub struct S {
 }
 
 // CHECK-LABEL: @test1
-// CHECK: store i32 0, {{i32\*|ptr}} %{{.+}}, align 16
-// CHECK: store i32 1, {{i32\*|ptr}} %{{.+}}, align 4
-// CHECK: store i32 2, {{i32\*|ptr}} %{{.+}}, align 8
-// CHECK: store i32 3, {{i32\*|ptr}} %{{.+}}, align 4
+// CHECK: store i32 0, ptr %{{.+}}, align 16
+// CHECK: store i32 1, ptr %{{.+}}, align 4
+// CHECK: store i32 2, ptr %{{.+}}, align 8
+// CHECK: store i32 3, ptr %{{.+}}, align 4
 #[no_mangle]
 pub fn test1(s: &mut S) {
     s.arr[0] = 0;
@@ -21,7 +21,7 @@ pub fn test1(s: &mut S) {
 }
 
 // CHECK-LABEL: @test2
-// CHECK: store i32 4, {{i32\*|ptr}} %{{.+}}, align 4
+// CHECK: store i32 4, ptr %{{.+}}, align 4
 #[allow(unconditional_panic)]
 #[no_mangle]
 pub fn test2(s: &mut S) {
@@ -29,14 +29,14 @@ pub fn test2(s: &mut S) {
 }
 
 // CHECK-LABEL: @test3
-// CHECK: store i32 5, {{i32\*|ptr}} %{{.+}}, align 4
+// CHECK: store i32 5, ptr %{{.+}}, align 4
 #[no_mangle]
 pub fn test3(s: &mut S, i: usize) {
     s.arr[i] = 5;
 }
 
 // CHECK-LABEL: @test4
-// CHECK: store i32 6, {{i32\*|ptr}} %{{.+}}, align 4
+// CHECK: store i32 6, ptr %{{.+}}, align 4
 #[no_mangle]
 pub fn test4(s: &mut S) {
     s.arr = [6; 4];
diff --git a/tests/codegen/issues/issue-58881.rs b/tests/codegen/issues/issue-58881.rs
index 00f8953d949..a1d0e8eb7e0 100644
--- a/tests/codegen/issues/issue-58881.rs
+++ b/tests/codegen/issues/issue-58881.rs
@@ -16,6 +16,6 @@ struct Bar(u64, u64, u64);
 
 // Ensure that emit arguments of the correct type.
 pub unsafe fn test_call_variadic() {
-    // CHECK: call void (i32, ...) @variadic_fn(i32 0, i8 {{.*}}, {{%Bar\*|ptr}} {{.*}})
+    // CHECK: call void (i32, ...) @variadic_fn(i32 0, i8 {{.*}}, ptr {{.*}})
     variadic_fn(0, Foo(0), Bar(0, 0, 0))
 }
diff --git a/tests/codegen/issues/issue-73396-bounds-check-after-position.rs b/tests/codegen/issues/issue-73396-bounds-check-after-position.rs
index 8d07a67a1b4..2d779788791 100644
--- a/tests/codegen/issues/issue-73396-bounds-check-after-position.rs
+++ b/tests/codegen/issues/issue-73396-bounds-check-after-position.rs
@@ -9,7 +9,10 @@
 #[no_mangle]
 pub fn position_slice_to_no_bounds_check(s: &[u8]) -> &[u8] {
     // CHECK-NOT: panic
-    // CHECK-NOT: slice_index_len_fail
+    // CHECK-NOT: slice_start_index_len_fail
+    // CHECK-NOT: slice_end_index_len_fail
+    // CHECK-NOT: panic_bounds_check
+    // CHECK-NOT: unreachable
     if let Some(idx) = s.iter().position(|b| *b == b'\\') {
         &s[..idx]
     } else {
@@ -21,7 +24,10 @@ pub fn position_slice_to_no_bounds_check(s: &[u8]) -> &[u8] {
 #[no_mangle]
 pub fn position_slice_from_no_bounds_check(s: &[u8]) -> &[u8] {
     // CHECK-NOT: panic
-    // CHECK-NOT: slice_index_len_fail
+    // CHECK-NOT: slice_start_index_len_fail
+    // CHECK-NOT: slice_end_index_len_fail
+    // CHECK-NOT: panic_bounds_check
+    // CHECK-NOT: unreachable
     if let Some(idx) = s.iter().position(|b| *b == b'\\') {
         &s[idx..]
     } else {
@@ -33,7 +39,10 @@ pub fn position_slice_from_no_bounds_check(s: &[u8]) -> &[u8] {
 #[no_mangle]
 pub fn position_index_no_bounds_check(s: &[u8]) -> u8 {
     // CHECK-NOT: panic
-    // CHECK-NOT: slice_index_len_fail
+    // CHECK-NOT: slice_start_index_len_fail
+    // CHECK-NOT: slice_end_index_len_fail
+    // CHECK-NOT: panic_bounds_check
+    // CHECK-NOT: unreachable
     if let Some(idx) = s.iter().position(|b| *b == b'\\') {
         s[idx]
     } else {
@@ -44,7 +53,10 @@ pub fn position_index_no_bounds_check(s: &[u8]) -> u8 {
 #[no_mangle]
 pub fn rposition_slice_to_no_bounds_check(s: &[u8]) -> &[u8] {
     // CHECK-NOT: panic
-    // CHECK-NOT: slice_index_len_fail
+    // CHECK-NOT: slice_start_index_len_fail
+    // CHECK-NOT: slice_end_index_len_fail
+    // CHECK-NOT: panic_bounds_check
+    // CHECK-NOT: unreachable
     if let Some(idx) = s.iter().rposition(|b| *b == b'\\') {
         &s[..idx]
     } else {
@@ -56,7 +68,10 @@ pub fn rposition_slice_to_no_bounds_check(s: &[u8]) -> &[u8] {
 #[no_mangle]
 pub fn rposition_slice_from_no_bounds_check(s: &[u8]) -> &[u8] {
     // CHECK-NOT: panic
-    // CHECK-NOT: slice_index_len_fail
+    // CHECK-NOT: slice_start_index_len_fail
+    // CHECK-NOT: slice_end_index_len_fail
+    // CHECK-NOT: panic_bounds_check
+    // CHECK-NOT: unreachable
     if let Some(idx) = s.iter().rposition(|b| *b == b'\\') {
         &s[idx..]
     } else {
@@ -68,7 +83,10 @@ pub fn rposition_slice_from_no_bounds_check(s: &[u8]) -> &[u8] {
 #[no_mangle]
 pub fn rposition_index_no_bounds_check(s: &[u8]) -> u8 {
     // CHECK-NOT: panic
-    // CHECK-NOT: slice_index_len_fail
+    // CHECK-NOT: slice_start_index_len_fail
+    // CHECK-NOT: slice_end_index_len_fail
+    // CHECK-NOT: panic_bounds_check
+    // CHECK-NOT: unreachable
     if let Some(idx) = s.iter().rposition(|b| *b == b'\\') {
         s[idx]
     } else {
diff --git a/tests/codegen/issues/issue-85872-multiple-reverse.rs b/tests/codegen/issues/issue-85872-multiple-reverse.rs
index 591a1aca747..a4723a0e946 100644
--- a/tests/codegen/issues/issue-85872-multiple-reverse.rs
+++ b/tests/codegen/issues/issue-85872-multiple-reverse.rs
@@ -1,4 +1,3 @@
-// min-llvm-version: 15.0.0
 // compile-flags: -O
 
 #![crate_type = "lib"]
diff --git a/tests/codegen/issues/issue-86106.rs b/tests/codegen/issues/issue-86106.rs
index 9ccbcb24f56..15aef344ac0 100644
--- a/tests/codegen/issues/issue-86106.rs
+++ b/tests/codegen/issues/issue-86106.rs
@@ -1,4 +1,4 @@
-// min-llvm-version: 15.0
+// only-64bit llvm appears to use stores instead of memset on 32bit
 // compile-flags: -C opt-level=3 -Z merge-functions=disabled
 
 // The below two functions ensure that both `String::new()` and `"".to_string()`
@@ -6,28 +6,22 @@
 
 #![crate_type = "lib"]
 
-// CHECK-LABEL: define void @string_new
+// CHECK-LABEL: define {{(dso_local )?}}void @string_new
 #[no_mangle]
 pub fn string_new() -> String {
-    // CHECK-NOT: load i8
-    // CHECK: store i{{32|64}}
+    // CHECK: store ptr inttoptr
     // CHECK-NEXT: getelementptr
-    // CHECK-NEXT: store ptr
-    // CHECK-NEXT: getelementptr
-    // CHECK-NEXT: store i{{32|64}}
+    // CHECK-NEXT: call void @llvm.memset
     // CHECK-NEXT: ret void
     String::new()
 }
 
-// CHECK-LABEL: define void @empty_to_string
+// CHECK-LABEL: define {{(dso_local )?}}void @empty_to_string
 #[no_mangle]
 pub fn empty_to_string() -> String {
-    // CHECK-NOT: load i8
-    // CHECK: store i{{32|64}}
-    // CHECK-NEXT: getelementptr
-    // CHECK-NEXT: store ptr
+    // CHECK: store ptr inttoptr
     // CHECK-NEXT: getelementptr
-    // CHECK-NEXT: store i{{32|64}}
+    // CHECK-NEXT: call void @llvm.memset
     // CHECK-NEXT: ret void
     "".to_string()
 }
@@ -38,12 +32,9 @@ pub fn empty_to_string() -> String {
 // CHECK-LABEL: @empty_vec
 #[no_mangle]
 pub fn empty_vec() -> Vec<u8> {
-    // CHECK: store i{{32|64}}
-    // CHECK-NOT: load i8
+    // CHECK: store ptr inttoptr
     // CHECK-NEXT: getelementptr
-    // CHECK-NEXT: store ptr
-    // CHECK-NEXT: getelementptr
-    // CHECK-NEXT: store i{{32|64}}
+    // CHECK-NEXT: call void @llvm.memset
     // CHECK-NEXT: ret void
     vec![]
 }
@@ -51,12 +42,9 @@ pub fn empty_vec() -> Vec<u8> {
 // CHECK-LABEL: @empty_vec_clone
 #[no_mangle]
 pub fn empty_vec_clone() -> Vec<u8> {
-    // CHECK: store i{{32|64}}
-    // CHECK-NOT: load i8
-    // CHECK-NEXT: getelementptr
-    // CHECK-NEXT: store ptr
+    // CHECK: store ptr inttoptr
     // CHECK-NEXT: getelementptr
-    // CHECK-NEXT: store i{{32|64}}
+    // CHECK-NEXT: call void @llvm.memset
     // CHECK-NEXT: ret void
     vec![].clone()
 }
diff --git a/tests/codegen/issues/issue-96274.rs b/tests/codegen/issues/issue-96274.rs
index 28bfcce0d7b..a44789ce350 100644
--- a/tests/codegen/issues/issue-96274.rs
+++ b/tests/codegen/issues/issue-96274.rs
@@ -1,4 +1,3 @@
-// min-llvm-version: 15.0
 // compile-flags: -O
 
 #![crate_type = "lib"]
diff --git a/tests/codegen/issues/issue-96497-slice-size-nowrap.rs b/tests/codegen/issues/issue-96497-slice-size-nowrap.rs
index 0413ed6b26f..3ea6a5405e5 100644
--- a/tests/codegen/issues/issue-96497-slice-size-nowrap.rs
+++ b/tests/codegen/issues/issue-96497-slice-size-nowrap.rs
@@ -3,7 +3,6 @@
 // in some situations, see https://github.com/rust-lang/rust/issues/96497#issuecomment-1112865218
 
 // compile-flags: -O
-// min-llvm-version: 15.0
 
 #![crate_type="lib"]
 
diff --git a/tests/codegen/issues/issue-98294-get-mut-copy-from-slice-opt.rs b/tests/codegen/issues/issue-98294-get-mut-copy-from-slice-opt.rs
index 7da29cd7952..b87e43c13b6 100644
--- a/tests/codegen/issues/issue-98294-get-mut-copy-from-slice-opt.rs
+++ b/tests/codegen/issues/issue-98294-get-mut-copy-from-slice-opt.rs
@@ -1,4 +1,3 @@
-// min-llvm-version: 15.0.0
 // ignore-debug: The debug assertions get in the way
 // compile-flags: -O
 
diff --git a/tests/codegen/iter-repeat-n-trivial-drop.rs b/tests/codegen/iter-repeat-n-trivial-drop.rs
index 24059f190ac..0b08e578151 100644
--- a/tests/codegen/iter-repeat-n-trivial-drop.rs
+++ b/tests/codegen/iter-repeat-n-trivial-drop.rs
@@ -33,7 +33,8 @@ pub fn iter_repeat_n_next(it: &mut std::iter::RepeatN<NotCopy>) -> Option<NotCop
 
     // CHECK: [[EMPTY]]:
     // CHECK-NOT: br
-    // CHECK: phi i16 [ undef, %start ], [ %[[VAL]], %[[NOT_EMPTY]] ]
+    // CHECK: phi i16
+    // CHECK-SAME: [ %[[VAL]], %[[NOT_EMPTY]] ]
     // CHECK-NOT: br
     // CHECK: ret
 
diff --git a/tests/codegen/lifetime_start_end.rs b/tests/codegen/lifetime_start_end.rs
index 471a0b8cedd..16175dc18c2 100644
--- a/tests/codegen/lifetime_start_end.rs
+++ b/tests/codegen/lifetime_start_end.rs
@@ -8,7 +8,7 @@ pub fn test() {
     let a = 0u8;
     &a; // keep variable in an alloca
 
-// CHECK: call void @llvm.lifetime.start{{.*}}(i{{[0-9 ]+}}, {{i8\*|ptr}} %a)
+// CHECK: call void @llvm.lifetime.start{{.*}}(i{{[0-9 ]+}}, ptr %a)
 
     {
         let b = &Some(a);
@@ -26,9 +26,9 @@ pub fn test() {
     let c = 1u8;
     &c; // keep variable in an alloca
 
-// CHECK: call void @llvm.lifetime.start{{.*}}(i{{[0-9 ]+}}, {{i8\*|ptr}} %c)
+// CHECK: call void @llvm.lifetime.start{{.*}}(i{{[0-9 ]+}}, ptr %c)
 
-// CHECK: call void @llvm.lifetime.end{{.*}}(i{{[0-9 ]+}}, {{i8\*|ptr}} %c)
+// CHECK: call void @llvm.lifetime.end{{.*}}(i{{[0-9 ]+}}, ptr %c)
 
-// CHECK: call void @llvm.lifetime.end{{.*}}(i{{[0-9 ]+}}, {{i8\*|ptr}} %a)
+// CHECK: call void @llvm.lifetime.end{{.*}}(i{{[0-9 ]+}}, ptr %a)
 }
diff --git a/tests/codegen/link_section.rs b/tests/codegen/link_section.rs
index 88b8692b0ac..2b26b604ad3 100644
--- a/tests/codegen/link_section.rs
+++ b/tests/codegen/link_section.rs
@@ -3,7 +3,7 @@
 
 #![crate_type = "lib"]
 
-// CHECK: @VAR1 = constant <{ [4 x i8] }> <{ [4 x i8] c"\01\00\00\00" }>, section ".test_one"
+// CHECK: @VAR1 = {{(dso_local )?}}constant <{ [4 x i8] }> <{ [4 x i8] c"\01\00\00\00" }>, section ".test_one"
 #[no_mangle]
 #[link_section = ".test_one"]
 #[cfg(target_endian = "little")]
@@ -19,17 +19,17 @@ pub enum E {
     B(f32)
 }
 
-// CHECK: @VAR2 = constant {{.*}}, section ".test_two"
+// CHECK: @VAR2 = {{(dso_local )?}}constant {{.*}}, section ".test_two"
 #[no_mangle]
 #[link_section = ".test_two"]
 pub static VAR2: E = E::A(666);
 
-// CHECK: @VAR3 = constant {{.*}}, section ".test_three"
+// CHECK: @VAR3 = {{(dso_local )?}}constant {{.*}}, section ".test_three"
 #[no_mangle]
 #[link_section = ".test_three"]
 pub static VAR3: E = E::B(1.);
 
-// CHECK: define void @fn1() {{.*}} section ".test_four" {
+// CHECK: define {{(dso_local )?}}void @fn1() {{.*}} section ".test_four" {
 #[no_mangle]
 #[link_section = ".test_four"]
 pub fn fn1() {}
diff --git a/tests/codegen/llvm-ident.rs b/tests/codegen/llvm-ident.rs
new file mode 100644
index 00000000000..927f0d602ad
--- /dev/null
+++ b/tests/codegen/llvm-ident.rs
@@ -0,0 +1,15 @@
+// Verifies that the `!llvm.ident` named metadata is emitted.
+//
+// revisions: NONE OPT DEBUG
+//
+// [OPT] compile-flags: -Copt-level=2
+// [DEBUG] compile-flags: -Cdebuginfo=2
+
+// The named metadata should contain a single metadata node (see
+// `LLVMRustPrepareThinLTOImport` for details).
+// CHECK: !llvm.ident = !{![[ID:[0-9]+]]}
+
+// In addition, check that the metadata node has the expected content.
+// CHECK: ![[ID]] = !{!"rustc version 1.{{.*}}"}
+
+fn main() {}
diff --git a/tests/codegen/loads.rs b/tests/codegen/loads.rs
index f29a26596bf..4a09a1dc033 100644
--- a/tests/codegen/loads.rs
+++ b/tests/codegen/loads.rs
@@ -28,22 +28,22 @@ pub fn ptr_alignment_helper(x: &&()) {}
 // CHECK-LABEL: @load_ref
 #[no_mangle]
 pub fn load_ref<'a>(x: &&'a i32) -> &'a i32 {
-    // CHECK: load {{i32\*|ptr}}, {{i32\*\*|ptr}} %x, align [[PTR_ALIGNMENT]], !nonnull !{{[0-9]+}}, !align ![[ALIGN_4_META:[0-9]+]], !noundef !{{[0-9]+}}
+    // CHECK: load ptr, ptr %x, align [[PTR_ALIGNMENT]], !nonnull !{{[0-9]+}}, !align ![[ALIGN_4_META:[0-9]+]], !noundef !{{[0-9]+}}
     *x
 }
 
 // CHECK-LABEL: @load_ref_higher_alignment
 #[no_mangle]
 pub fn load_ref_higher_alignment<'a>(x: &&'a Align16) -> &'a Align16 {
-    // CHECK: load {{%Align16\*|i128\*|ptr}}, {{%Align16\*\*|i128\*\*|ptr}} %x, align [[PTR_ALIGNMENT]], !nonnull !{{[0-9]+}}, !align ![[ALIGN_16_META:[0-9]+]], !noundef !{{[0-9]+}}
+    // CHECK: load ptr, ptr %x, align [[PTR_ALIGNMENT]], !nonnull !{{[0-9]+}}, !align ![[ALIGN_16_META:[0-9]+]], !noundef !{{[0-9]+}}
     *x
 }
 
 // CHECK-LABEL: @load_scalar_pair
 #[no_mangle]
 pub fn load_scalar_pair<'a>(x: &(&'a i32, &'a Align16)) -> (&'a i32, &'a Align16) {
-    // CHECK: load {{i32\*|ptr}}, {{i32\*\*|ptr}} %{{.+}}, align [[PTR_ALIGNMENT]], !nonnull !{{[0-9]+}}, !align ![[ALIGN_4_META]], !noundef !{{[0-9]+}}
-    // CHECK: load {{i64\*|ptr}}, {{i64\*\*|ptr}} %{{.+}}, align [[PTR_ALIGNMENT]], !nonnull !{{[0-9]+}}, !align ![[ALIGN_16_META]], !noundef !{{[0-9]+}}
+    // CHECK: load ptr, ptr %{{.+}}, align [[PTR_ALIGNMENT]], !nonnull !{{[0-9]+}}, !align ![[ALIGN_4_META]], !noundef !{{[0-9]+}}
+    // CHECK: load ptr, ptr %{{.+}}, align [[PTR_ALIGNMENT]], !nonnull !{{[0-9]+}}, !align ![[ALIGN_16_META]], !noundef !{{[0-9]+}}
     *x
 }
 
@@ -51,70 +51,70 @@ pub fn load_scalar_pair<'a>(x: &(&'a i32, &'a Align16)) -> (&'a i32, &'a Align16
 #[no_mangle]
 pub fn load_raw_pointer<'a>(x: &*const i32) -> *const i32 {
     // loaded raw pointer should not have !nonnull or !align metadata
-    // CHECK: load {{i32\*|ptr}}, {{i32\*\*|ptr}} %x, align [[PTR_ALIGNMENT]], !noundef ![[NOUNDEF:[0-9]+]]{{$}}
+    // CHECK: load ptr, ptr %x, align [[PTR_ALIGNMENT]], !noundef ![[NOUNDEF:[0-9]+]]{{$}}
     *x
 }
 
 // CHECK-LABEL: @load_box
 #[no_mangle]
 pub fn load_box<'a>(x: Box<Box<i32>>) -> Box<i32> {
-    // CHECK: load {{i32\*|ptr}}, {{i32\*\*|ptr}} %{{.*}}, align [[PTR_ALIGNMENT]], !nonnull !{{[0-9]+}}, !align ![[ALIGN_4_META]], !noundef !{{[0-9]+}}
+    // CHECK: load ptr, ptr %{{.*}}, align [[PTR_ALIGNMENT]], !nonnull !{{[0-9]+}}, !align ![[ALIGN_4_META]], !noundef !{{[0-9]+}}
     *x
 }
 
 // CHECK-LABEL: @load_bool
 #[no_mangle]
 pub fn load_bool(x: &bool) -> bool {
-    // CHECK: load i8, {{i8\*|ptr}} %x, align 1, !range ![[BOOL_RANGE:[0-9]+]], !noundef !{{[0-9]+}}
+    // CHECK: load i8, ptr %x, align 1, !range ![[BOOL_RANGE:[0-9]+]], !noundef !{{[0-9]+}}
     *x
 }
 
 // CHECK-LABEL: @load_maybeuninit_bool
 #[no_mangle]
 pub fn load_maybeuninit_bool(x: &MaybeUninit<bool>) -> MaybeUninit<bool> {
-    // CHECK: load i8, {{i8\*|ptr}} %x, align 1{{$}}
+    // CHECK: load i8, ptr %x, align 1{{$}}
     *x
 }
 
 // CHECK-LABEL: @load_enum_bool
 #[no_mangle]
 pub fn load_enum_bool(x: &MyBool) -> MyBool {
-    // CHECK: load i8, {{i8\*|ptr}} %x, align 1, !range ![[BOOL_RANGE]], !noundef !{{[0-9]+}}
+    // CHECK: load i8, ptr %x, align 1, !range ![[BOOL_RANGE]], !noundef !{{[0-9]+}}
     *x
 }
 
 // CHECK-LABEL: @load_maybeuninit_enum_bool
 #[no_mangle]
 pub fn load_maybeuninit_enum_bool(x: &MaybeUninit<MyBool>) -> MaybeUninit<MyBool> {
-    // CHECK: load i8, {{i8\*|ptr}} %x, align 1{{$}}
+    // CHECK: load i8, ptr %x, align 1{{$}}
     *x
 }
 
 // CHECK-LABEL: @load_int
 #[no_mangle]
 pub fn load_int(x: &u16) -> u16 {
-    // CHECK: load i16, {{i16\*|ptr}} %x, align 2, !noundef ![[NOUNDEF]]{{$}}
+    // CHECK: load i16, ptr %x, align 2, !noundef ![[NOUNDEF]]{{$}}
     *x
 }
 
 // CHECK-LABEL: @load_nonzero_int
 #[no_mangle]
 pub fn load_nonzero_int(x: &NonZeroU16) -> NonZeroU16 {
-    // CHECK: load i16, {{i16\*|ptr}} %x, align 2, !range ![[NONZEROU16_RANGE:[0-9]+]], !noundef !{{[0-9]+}}
+    // CHECK: load i16, ptr %x, align 2, !range ![[NONZEROU16_RANGE:[0-9]+]], !noundef !{{[0-9]+}}
     *x
 }
 
 // CHECK-LABEL: @load_option_nonzero_int
 #[no_mangle]
 pub fn load_option_nonzero_int(x: &Option<NonZeroU16>) -> Option<NonZeroU16> {
-    // CHECK: load i16, {{i16\*|ptr}} %x, align 2, !noundef ![[NOUNDEF]]{{$}}
+    // CHECK: load i16, ptr %x, align 2, !noundef ![[NOUNDEF]]{{$}}
     *x
 }
 
 // CHECK-LABEL: @borrow
 #[no_mangle]
 pub fn borrow(x: &i32) -> &i32 {
-    // CHECK: load {{i32\*|ptr}}, {{i32\*\*|ptr}} %x{{.*}}, !nonnull
+    // CHECK: load ptr, ptr %x{{.*}}, !nonnull
     &x; // keep variable in an alloca
     x
 }
@@ -122,7 +122,7 @@ pub fn borrow(x: &i32) -> &i32 {
 // CHECK-LABEL: @_box
 #[no_mangle]
 pub fn _box(x: Box<i32>) -> i32 {
-    // CHECK: load {{i32\*|ptr}}, {{i32\*\*|ptr}} %x{{.*}}, align [[PTR_ALIGNMENT]]
+    // CHECK: load ptr, ptr %x{{.*}}, align [[PTR_ALIGNMENT]]
     *x
 }
 
@@ -131,7 +131,7 @@ pub fn _box(x: Box<i32>) -> i32 {
 // dependent alignment
 #[no_mangle]
 pub fn small_array_alignment(x: [i8; 4]) -> [i8; 4] {
-    // CHECK: [[VAR:%[0-9]+]] = load i32, {{i32\*|ptr}} %{{.*}}, align 1
+    // CHECK: [[VAR:%[0-9]+]] = load i32, ptr %{{.*}}, align 1
     // CHECK: ret i32 [[VAR]]
     x
 }
@@ -141,7 +141,7 @@ pub fn small_array_alignment(x: [i8; 4]) -> [i8; 4] {
 // dependent alignment
 #[no_mangle]
 pub fn small_struct_alignment(x: Bytes) -> Bytes {
-    // CHECK: [[VAR:%[0-9]+]] = load i32, {{i32\*|ptr}} %{{.*}}, align 1
+    // CHECK: [[VAR:%[0-9]+]] = load i32, ptr %{{.*}}, align 1
     // CHECK: ret i32 [[VAR]]
     x
 }
diff --git a/tests/codegen/loongarch-abi/call-llvm-intrinsics.rs b/tests/codegen/loongarch-abi/call-llvm-intrinsics.rs
new file mode 100644
index 00000000000..4b78f6e24f7
--- /dev/null
+++ b/tests/codegen/loongarch-abi/call-llvm-intrinsics.rs
@@ -0,0 +1,31 @@
+// compile-flags: -C no-prepopulate-passes
+
+// only-loongarch64
+
+#![feature(link_llvm_intrinsics)]
+#![crate_type = "lib"]
+
+struct A;
+
+impl Drop for A {
+    fn drop(&mut self) {
+        println!("A");
+    }
+}
+
+extern "C" {
+    #[link_name = "llvm.sqrt.f32"]
+    fn sqrt(x: f32) -> f32;
+}
+
+pub fn do_call() {
+    let _a = A;
+
+    unsafe {
+        // Ensure that we `call` LLVM intrinsics instead of trying to `invoke` them
+        // CHECK: store float 4.000000e+00, ptr %{{.}}, align 4
+        // CHECK: load float, ptr %{{.}}, align 4
+        // CHECK: call float @llvm.sqrt.f32(float %{{.}}
+        sqrt(4.0);
+    }
+}
diff --git a/tests/codegen/loongarch-abi/loongarch64-lp64d-abi.rs b/tests/codegen/loongarch-abi/loongarch64-lp64d-abi.rs
new file mode 100644
index 00000000000..7555553c2c5
--- /dev/null
+++ b/tests/codegen/loongarch-abi/loongarch64-lp64d-abi.rs
@@ -0,0 +1,293 @@
+// compile-flags: -C no-prepopulate-passes
+// only-loongarch64
+// only-linux
+
+#![crate_type = "lib"]
+
+// CHECK: define void @f_fpr_tracking(double %0, double %1, double %2, double %3, double %4, double %5, double %6, double %7, i8 noundef zeroext %i)
+#[no_mangle]
+pub extern "C" fn f_fpr_tracking(
+    a: f64,
+    b: f64,
+    c: f64,
+    d: f64,
+    e: f64,
+    f: f64,
+    g: f64,
+    h: f64,
+    i: u8,
+) {
+}
+
+#[repr(C)]
+pub struct Double {
+    f: f64,
+}
+
+#[repr(C)]
+pub struct DoubleDouble {
+    f: f64,
+    g: f64,
+}
+
+#[repr(C)]
+pub struct DoubleFloat {
+    f: f64,
+    g: f32,
+}
+
+// CHECK: define void @f_double_s_arg(double %0)
+#[no_mangle]
+pub extern "C" fn f_double_s_arg(a: Double) {}
+
+// CHECK: define double @f_ret_double_s()
+#[no_mangle]
+pub extern "C" fn f_ret_double_s() -> Double {
+    Double { f: 1. }
+}
+
+// CHECK: define void @f_double_double_s_arg({ double, double } %0)
+#[no_mangle]
+pub extern "C" fn f_double_double_s_arg(a: DoubleDouble) {}
+
+// CHECK: define { double, double } @f_ret_double_double_s()
+#[no_mangle]
+pub extern "C" fn f_ret_double_double_s() -> DoubleDouble {
+    DoubleDouble { f: 1., g: 2. }
+}
+
+// CHECK: define void @f_double_float_s_arg({ double, float } %0)
+#[no_mangle]
+pub extern "C" fn f_double_float_s_arg(a: DoubleFloat) {}
+
+// CHECK: define { double, float } @f_ret_double_float_s()
+#[no_mangle]
+pub extern "C" fn f_ret_double_float_s() -> DoubleFloat {
+    DoubleFloat { f: 1., g: 2. }
+}
+
+// CHECK: define void @f_double_double_s_arg_insufficient_fprs(double %0, double %1, double %2, double %3, double %4, double %5, double %6, [2 x i64] %7)
+#[no_mangle]
+pub extern "C" fn f_double_double_s_arg_insufficient_fprs(
+    a: f64,
+    b: f64,
+    c: f64,
+    d: f64,
+    e: f64,
+    f: f64,
+    g: f64,
+    h: DoubleDouble,
+) {
+}
+
+#[repr(C)]
+pub struct DoubleInt8 {
+    f: f64,
+    i: i8,
+}
+
+#[repr(C)]
+pub struct DoubleUInt8 {
+    f: f64,
+    i: u8,
+}
+
+#[repr(C)]
+pub struct DoubleInt32 {
+    f: f64,
+    i: i32,
+}
+
+#[repr(C)]
+pub struct DoubleInt64 {
+    f: f64,
+    i: i64,
+}
+
+// CHECK: define void @f_double_int8_s_arg({ double, i8 } %0)
+#[no_mangle]
+pub extern "C" fn f_double_int8_s_arg(a: DoubleInt8) {}
+
+// CHECK: define { double, i8 } @f_ret_double_int8_s()
+#[no_mangle]
+pub extern "C" fn f_ret_double_int8_s() -> DoubleInt8 {
+    DoubleInt8 { f: 1., i: 2 }
+}
+
+// CHECK: define void @f_double_int32_s_arg({ double, i32 } %0)
+#[no_mangle]
+pub extern "C" fn f_double_int32_s_arg(a: DoubleInt32) {}
+
+// CHECK: define { double, i32 } @f_ret_double_int32_s()
+#[no_mangle]
+pub extern "C" fn f_ret_double_int32_s() -> DoubleInt32 {
+    DoubleInt32 { f: 1., i: 2 }
+}
+
+// CHECK: define void @f_double_uint8_s_arg({ double, i8 } %0)
+#[no_mangle]
+pub extern "C" fn f_double_uint8_s_arg(a: DoubleUInt8) {}
+
+// CHECK: define { double, i8 } @f_ret_double_uint8_s()
+#[no_mangle]
+pub extern "C" fn f_ret_double_uint8_s() -> DoubleUInt8 {
+    DoubleUInt8 { f: 1., i: 2 }
+}
+
+// CHECK: define void @f_double_int64_s_arg({ double, i64 } %0)
+#[no_mangle]
+pub extern "C" fn f_double_int64_s_arg(a: DoubleInt64) {}
+
+// CHECK: define { double, i64 } @f_ret_double_int64_s()
+#[no_mangle]
+pub extern "C" fn f_ret_double_int64_s() -> DoubleInt64 {
+    DoubleInt64 { f: 1., i: 2 }
+}
+
+// CHECK: define void @f_double_int8_s_arg_insufficient_gprs(i32 noundef signext %a, i32 noundef signext %b, i32 noundef signext %c, i32 noundef signext %d, i32 noundef signext %e, i32 noundef signext %f, i32 noundef signext %g, i32 noundef signext %h, [2 x i64] %0)
+#[no_mangle]
+pub extern "C" fn f_double_int8_s_arg_insufficient_gprs(
+    a: i32,
+    b: i32,
+    c: i32,
+    d: i32,
+    e: i32,
+    f: i32,
+    g: i32,
+    h: i32,
+    i: DoubleInt8,
+) {
+}
+
+// CHECK: define void @f_struct_double_int8_insufficient_fprs(float %0, double %1, double %2, double %3, double %4, double %5, double %6, double %7, [2 x i64] %8)
+#[no_mangle]
+pub extern "C" fn f_struct_double_int8_insufficient_fprs(
+    a: f32,
+    b: f64,
+    c: f64,
+    d: f64,
+    e: f64,
+    f: f64,
+    g: f64,
+    h: f64,
+    i: DoubleInt8,
+) {
+}
+
+#[repr(C)]
+pub struct DoubleArr1 {
+    a: [f64; 1],
+}
+
+// CHECK: define void @f_doublearr1_s_arg(double %0)
+#[no_mangle]
+pub extern "C" fn f_doublearr1_s_arg(a: DoubleArr1) {}
+
+// CHECK: define double @f_ret_doublearr1_s()
+#[no_mangle]
+pub extern "C" fn f_ret_doublearr1_s() -> DoubleArr1 {
+    DoubleArr1 { a: [1.] }
+}
+
+#[repr(C)]
+pub struct DoubleArr2 {
+    a: [f64; 2],
+}
+
+// CHECK: define void @f_doublearr2_s_arg({ double, double } %0)
+#[no_mangle]
+pub extern "C" fn f_doublearr2_s_arg(a: DoubleArr2) {}
+
+// CHECK: define { double, double } @f_ret_doublearr2_s()
+#[no_mangle]
+pub extern "C" fn f_ret_doublearr2_s() -> DoubleArr2 {
+    DoubleArr2 { a: [1., 2.] }
+}
+
+#[repr(C)]
+pub struct Tricky1 {
+    f: [f64; 1],
+}
+
+#[repr(C)]
+pub struct DoubleArr2Tricky1 {
+    g: [Tricky1; 2],
+}
+
+// CHECK: define void @f_doublearr2_tricky1_s_arg({ double, double } %0)
+#[no_mangle]
+pub extern "C" fn f_doublearr2_tricky1_s_arg(a: DoubleArr2Tricky1) {}
+
+// CHECK: define { double, double } @f_ret_doublearr2_tricky1_s()
+#[no_mangle]
+pub extern "C" fn f_ret_doublearr2_tricky1_s() -> DoubleArr2Tricky1 {
+    DoubleArr2Tricky1 { g: [Tricky1 { f: [1.] }, Tricky1 { f: [2.] }] }
+}
+
+#[repr(C)]
+pub struct EmptyStruct {}
+
+#[repr(C)]
+pub struct DoubleArr2Tricky2 {
+    s: EmptyStruct,
+    g: [Tricky1; 2],
+}
+
+// CHECK: define void @f_doublearr2_tricky2_s_arg({ double, double } %0)
+#[no_mangle]
+pub extern "C" fn f_doublearr2_tricky2_s_arg(a: DoubleArr2Tricky2) {}
+
+// CHECK: define { double, double } @f_ret_doublearr2_tricky2_s()
+#[no_mangle]
+pub extern "C" fn f_ret_doublearr2_tricky2_s() -> DoubleArr2Tricky2 {
+    DoubleArr2Tricky2 { s: EmptyStruct {}, g: [Tricky1 { f: [1.] }, Tricky1 { f: [2.] }] }
+}
+
+#[repr(C)]
+pub struct IntDoubleInt {
+    a: i32,
+    b: f64,
+    c: i32,
+}
+
+// CHECK: define void @f_int_double_int_s_arg(ptr noalias nocapture noundef dereferenceable(24) %a)
+#[no_mangle]
+pub extern "C" fn f_int_double_int_s_arg(a: IntDoubleInt) {}
+
+// CHECK: define void @f_ret_int_double_int_s(ptr noalias nocapture noundef sret(%IntDoubleInt) dereferenceable(24) %0)
+#[no_mangle]
+pub extern "C" fn f_ret_int_double_int_s() -> IntDoubleInt {
+    IntDoubleInt { a: 1, b: 2., c: 3 }
+}
+
+#[repr(C)]
+pub struct CharCharDouble {
+    a: u8,
+    b: u8,
+    c: f64,
+}
+
+// CHECK: define void @f_char_char_double_s_arg([2 x i64] %0)
+#[no_mangle]
+pub extern "C" fn f_char_char_double_s_arg(a: CharCharDouble) {}
+
+// CHECK: define [2 x i64] @f_ret_char_char_double_s()
+#[no_mangle]
+pub extern "C" fn f_ret_char_char_double_s() -> CharCharDouble {
+    CharCharDouble { a: 1, b: 2, c: 3. }
+}
+
+#[repr(C)]
+pub union DoubleU {
+    a: f64,
+}
+
+// CHECK: define void @f_double_u_arg(i64 %0)
+#[no_mangle]
+pub extern "C" fn f_double_u_arg(a: DoubleU) {}
+
+// CHECK: define i64 @f_ret_double_u()
+#[no_mangle]
+pub extern "C" fn f_ret_double_u() -> DoubleU {
+    unsafe { DoubleU { a: 1. } }
+}
diff --git a/tests/codegen/match-optimized.rs b/tests/codegen/match-optimized.rs
index 520c46a0d57..e32a5e54504 100644
--- a/tests/codegen/match-optimized.rs
+++ b/tests/codegen/match-optimized.rs
@@ -20,13 +20,13 @@ pub fn exhaustive_match(e: E) -> u8 {
 // CHECK-NEXT: unreachable
 //
 // CHECK: [[A]]:
-// CHECK-NEXT: store i8 0, {{i8\*|ptr}} %1, align 1
+// CHECK-NEXT: store i8 0, ptr %_0, align 1
 // CHECK-NEXT: br label %[[EXIT:[a-zA-Z0-9_]+]]
 // CHECK: [[B]]:
-// CHECK-NEXT: store i8 1, {{i8\*|ptr}} %1, align 1
+// CHECK-NEXT: store i8 1, ptr %_0, align 1
 // CHECK-NEXT: br label %[[EXIT]]
 // CHECK: [[C]]:
-// CHECK-NEXT: store i8 2, {{i8\*|ptr}} %1, align 1
+// CHECK-NEXT: store i8 2, ptr %_0, align 1
 // CHECK-NEXT: br label %[[EXIT]]
     match e {
         E::A => 0,
diff --git a/tests/codegen/mem-replace-big-type.rs b/tests/codegen/mem-replace-big-type.rs
index f6898e2f758..fc3e9d22bdf 100644
--- a/tests/codegen/mem-replace-big-type.rs
+++ b/tests/codegen/mem-replace-big-type.rs
@@ -11,7 +11,9 @@
 #[repr(C, align(8))]
 pub struct Big([u64; 7]);
 pub fn replace_big(dst: &mut Big, src: Big) -> Big {
-    // Before the `read_via_copy` intrinsic, this emitted six `memcpy`s.
+    // Back in 1.68, this emitted six `memcpy`s.
+    // `read_via_copy` in 1.69 got that down to three.
+    // `write_via_move` and nvro get this down to the essential two.
     std::mem::replace(dst, src)
 }
 
@@ -22,15 +24,10 @@ pub fn replace_big(dst: &mut Big, src: Big) -> Big {
 
 // For a large type, we expect exactly three `memcpy`s
 // CHECK-LABEL: define internal void @{{.+}}mem{{.+}}replace{{.+}}sret(%Big)
-    // CHECK-NOT: alloca
-    // CHECK: alloca %Big
-    // CHECK-NOT: alloca
-    // CHECK-NOT: call void @llvm.memcpy
-    // CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 8 %{{.*}}, {{i8\*|ptr}} align 8 %{{.*}}, i{{.*}} 56, i1 false)
-    // CHECK-NOT: call void @llvm.memcpy
-    // CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 8 %{{.*}}, {{i8\*|ptr}} align 8 %{{.*}}, i{{.*}} 56, i1 false)
-    // CHECK-NOT: call void @llvm.memcpy
-    // CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 8 %{{.*}}, {{i8\*|ptr}} align 8 %{{.*}}, i{{.*}} 56, i1 false)
-    // CHECK-NOT: call void @llvm.memcpy
+// CHECK-NOT: call void @llvm.memcpy
+// CHECK: call void @llvm.memcpy.{{.+}}(ptr align 8 %result, ptr align 8 %dest, i{{.*}} 56, i1 false)
+// CHECK-NOT: call void @llvm.memcpy
+// CHECK: call void @llvm.memcpy.{{.+}}(ptr align 8 %dest, ptr align 8 %src, i{{.*}} 56, i1 false)
+// CHECK-NOT: call void @llvm.memcpy
 
 // CHECK-NOT: call void @llvm.memcpy
diff --git a/tests/codegen/mem-replace-direct-memcpy.rs b/tests/codegen/mem-replace-direct-memcpy.rs
deleted file mode 100644
index 83babab4f84..00000000000
--- a/tests/codegen/mem-replace-direct-memcpy.rs
+++ /dev/null
@@ -1,33 +0,0 @@
-// This test ensures that `mem::replace::<T>` only ever calls `@llvm.memcpy`
-// with `size_of::<T>()` as the size, and never goes through any wrapper that
-// may e.g. multiply `size_of::<T>()` with a variable "count" (which is only
-// known to be `1` after inlining).
-
-// compile-flags: -C no-prepopulate-passes -Zinline-mir=no
-// ignore-debug: the debug assertions get in the way
-
-#![crate_type = "lib"]
-
-pub fn replace_byte(dst: &mut u8, src: u8) -> u8 {
-    std::mem::replace(dst, src)
-}
-
-// NOTE(eddyb) the `CHECK-NOT`s ensure that the only calls of `@llvm.memcpy` in
-// the entire output, are the direct calls we want, from `ptr::replace`.
-
-// CHECK-NOT: call void @llvm.memcpy
-
-// For a small type, we expect one each of `load`/`store`/`memcpy` instead
-// CHECK-LABEL: define internal noundef i8 @{{.+}}mem{{.+}}replace
-    // CHECK-NOT: alloca
-    // CHECK: alloca i8
-    // CHECK-NOT: alloca
-    // CHECK-NOT: call void @llvm.memcpy
-    // CHECK: load i8
-    // CHECK-NOT: call void @llvm.memcpy
-    // CHECK: store i8
-    // CHECK-NOT: call void @llvm.memcpy
-    // CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 1 %{{.*}}, {{i8\*|ptr}} align 1 %{{.*}}, i{{.*}} 1, i1 false)
-    // CHECK-NOT: call void @llvm.memcpy
-
-// CHECK-NOT: call void @llvm.memcpy
diff --git a/tests/codegen/mem-replace-simple-type.rs b/tests/codegen/mem-replace-simple-type.rs
new file mode 100644
index 00000000000..174ac608e01
--- /dev/null
+++ b/tests/codegen/mem-replace-simple-type.rs
@@ -0,0 +1,44 @@
+// compile-flags: -O -C no-prepopulate-passes
+// only-x86_64 (to not worry about usize differing)
+// ignore-debug (the debug assertions get in the way)
+
+#![crate_type = "lib"]
+
+#[no_mangle]
+// CHECK-LABEL: @replace_usize(
+pub fn replace_usize(r: &mut usize, v: usize) -> usize {
+    // CHECK-NOT: alloca
+    // CHECK: %[[R:.+]] = load i64, ptr %r
+    // CHECK: store i64 %v, ptr %r
+    // CHECK: ret i64 %[[R]]
+    std::mem::replace(r, v)
+}
+
+#[no_mangle]
+// CHECK-LABEL: @replace_ref_str(
+pub fn replace_ref_str<'a>(r: &mut &'a str, v: &'a str) -> &'a str {
+    // CHECK-NOT: alloca
+    // CHECK: %[[A:.+]] = load ptr
+    // CHECK: %[[B:.+]] = load i64
+    // CHECK-NOT: store
+    // CHECK-NOT: load
+    // CHECK: store ptr
+    // CHECK: store i64
+    // CHECK-NOT: load
+    // CHECK-NOT: store
+    // CHECK: %[[P1:.+]] = insertvalue { ptr, i64 } poison, ptr %[[A]], 0
+    // CHECK: %[[P2:.+]] = insertvalue { ptr, i64 } %[[P1]], i64 %[[B]], 1
+    // CHECK: ret { ptr, i64 } %[[P2]]
+    std::mem::replace(r, v)
+}
+
+#[no_mangle]
+// CHECK-LABEL: @replace_short_array(
+pub fn replace_short_array(r: &mut [u32; 3], v: [u32; 3]) -> [u32; 3] {
+    // CHECK-NOT: alloca
+    // CHECK: %[[R:.+]] = load <3 x i32>, ptr %r, align 4
+    // CHECK: store <3 x i32> %[[R]], ptr %result
+    // CHECK: %[[V:.+]] = load <3 x i32>, ptr %v, align 4
+    // CHECK: store <3 x i32> %[[V]], ptr %r
+    std::mem::replace(r, v)
+}
diff --git a/tests/codegen/mir-inlined-line-numbers.rs b/tests/codegen/mir-inlined-line-numbers.rs
index 19d83f0eee7..d13527b9521 100644
--- a/tests/codegen/mir-inlined-line-numbers.rs
+++ b/tests/codegen/mir-inlined-line-numbers.rs
@@ -19,7 +19,7 @@ pub fn example() {
 }
 
 // CHECK-LABEL: @example
-// CHECK:   tail call void @bar(), !dbg [[DBG_ID:![0-9]+]]
+// CHECK:   tail call void @bar(){{( #[0-9]+)?}}, !dbg [[DBG_ID:![0-9]+]]
 // CHECK: [[DBG_ID]] = !DILocation(line: 7,
 // CHECK-SAME:                     inlinedAt: [[INLINE_ID:![0-9]+]])
 // CHECK: [[INLINE_ID]] = !DILocation(line: 18,
diff --git a/tests/codegen/move-operands.rs b/tests/codegen/move-operands.rs
index 1d8209e8ea5..cd87e6d813c 100644
--- a/tests/codegen/move-operands.rs
+++ b/tests/codegen/move-operands.rs
@@ -1,4 +1,5 @@
-// compile-flags: -C no-prepopulate-passes -Zmir-enable-passes=+DestinationPropagation,-CopyProp
+// Verify that optimized MIR only copies `a` once.
+// compile-flags: -O -C no-prepopulate-passes
 
 #![crate_type = "lib"]
 
@@ -6,7 +7,7 @@ type T = [u8; 256];
 
 #[no_mangle]
 pub fn f(a: T, b: fn(_: T, _: T)) {
-    // CHECK: call void @llvm.memcpy.{{.*}}({{i8\*|ptr}} align 1 %{{.*}}, {{i8\*|ptr}} align 1 %{{.*}}, {{.*}} 256, i1 false)
-    // CHECK-NOT: call void @llvm.memcpy.{{.*}}({{i8\*|ptr}} align 1 %{{.*}}, {{i8\*|ptr}} align 1 %{{.*}}, {{.*}} 256, i1 false)
+    // CHECK: call void @llvm.memcpy.{{.*}}(ptr align 1 %{{.*}}, ptr align 1 %{{.*}}, {{.*}} 256, i1 false)
+    // CHECK-NOT: call void @llvm.memcpy.{{.*}}(ptr align 1 %{{.*}}, ptr align 1 %{{.*}}, {{.*}} 256, i1 false)
     b(a, a)
 }
diff --git a/tests/codegen/naked-nocoverage.rs b/tests/codegen/naked-nocoverage.rs
index 91a6260bf2a..3c755e49c6d 100644
--- a/tests/codegen/naked-nocoverage.rs
+++ b/tests/codegen/naked-nocoverage.rs
@@ -11,7 +11,7 @@ use std::arch::asm;
 #[naked]
 #[no_mangle]
 pub unsafe extern "C" fn f() {
-    // CHECK:       define void @f()
+    // CHECK:       define {{(dso_local )?}}void @f()
     // CHECK-NEXT:  start:
     // CHECK-NEXT:    call void asm
     // CHECK-NEXT:    unreachable
diff --git a/tests/codegen/naked-noinline.rs b/tests/codegen/naked-noinline.rs
index c0ac69f4ed7..5cfb500c0ef 100644
--- a/tests/codegen/naked-noinline.rs
+++ b/tests/codegen/naked-noinline.rs
@@ -12,7 +12,7 @@ use std::arch::asm;
 pub unsafe extern "C" fn f() {
     // Check that f has naked and noinline attributes.
     //
-    // CHECK:       define void @f() unnamed_addr [[ATTR:#[0-9]+]]
+    // CHECK:       define {{(dso_local )?}}void @f() unnamed_addr [[ATTR:#[0-9]+]]
     // CHECK-NEXT:  start:
     // CHECK-NEXT:    call void asm
     asm!("", options(noreturn));
@@ -22,7 +22,7 @@ pub unsafe extern "C" fn f() {
 pub unsafe fn g() {
     // Check that call to f is not inlined.
     //
-    // CHECK-LABEL: define void @g()
+    // CHECK-LABEL: define {{(dso_local )?}}void @g()
     // CHECK-NEXT:  start:
     // CHECK-NEXT:    call void @f()
     f();
diff --git a/tests/codegen/no_builtins-at-crate.rs b/tests/codegen/no_builtins-at-crate.rs
new file mode 100644
index 00000000000..02ed670900e
--- /dev/null
+++ b/tests/codegen/no_builtins-at-crate.rs
@@ -0,0 +1,24 @@
+// compile-flags: -C opt-level=1
+
+#![no_builtins]
+#![crate_type = "lib"]
+
+// CHECK: define
+// CHECK-SAME: @__aeabi_memcpy
+// CHECK-SAME: #0
+#[no_mangle]
+pub unsafe extern "C" fn __aeabi_memcpy(dest: *mut u8, src: *const u8, size: usize) {
+    // CHECK: call
+    // CHECK-SAME: @memcpy(
+    memcpy(dest, src, size);
+}
+
+// CHECK: declare
+// CHECK-SAME: @memcpy
+// CHECK-SAME: #0
+extern "C" {
+    pub fn memcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut u8;
+}
+
+// CHECK: attributes #0
+// CHECK-SAME: "no-builtins"
diff --git a/tests/codegen/noalias-box-off.rs b/tests/codegen/noalias-box-off.rs
index afd17c7c160..c82c53b2a48 100644
--- a/tests/codegen/noalias-box-off.rs
+++ b/tests/codegen/noalias-box-off.rs
@@ -4,5 +4,8 @@
 
 // CHECK-LABEL: @box_should_not_have_noalias_if_disabled(
 // CHECK-NOT: noalias
+// CHECK-SAME: %foo)
 #[no_mangle]
-pub fn box_should_not_have_noalias_if_disabled(_b: Box<u8>) {}
+pub fn box_should_not_have_noalias_if_disabled(foo: Box<u8>) {
+    drop(foo);
+}
diff --git a/tests/codegen/nrvo.rs b/tests/codegen/nrvo.rs
index fddb0d1fb3c..b2ae99f3761 100644
--- a/tests/codegen/nrvo.rs
+++ b/tests/codegen/nrvo.rs
@@ -8,7 +8,7 @@
 pub fn nrvo(init: fn(&mut [u8; 4096])) -> [u8; 4096] {
     // CHECK-LABEL: nrvo
     // CHECK: @llvm.memset
-    // CHECK-NOT: @llvm.memcpy
+    // FIXME: turn on nrvo then check-not: @llvm.memcpy
     // CHECK: ret
     // CHECK-EMPTY
     let mut buf = [0; 4096];
diff --git a/tests/codegen/option-nonzero-eq.rs b/tests/codegen/option-nonzero-eq.rs
index 835decd3e5f..ce5b6328af6 100644
--- a/tests/codegen/option-nonzero-eq.rs
+++ b/tests/codegen/option-nonzero-eq.rs
@@ -7,6 +7,9 @@ use core::cmp::Ordering;
 use core::num::{NonZeroU32, NonZeroI64};
 use core::ptr::NonNull;
 
+// See also tests/assembly/option-nonzero-eq.rs, for cases with `assume`s in the
+// LLVM and thus don't optimize down clearly here, but do in assembly.
+
 // CHECK-lABEL: @non_zero_eq
 #[no_mangle]
 pub fn non_zero_eq(l: Option<NonZeroU32>, r: Option<NonZeroU32>) -> bool {
@@ -29,16 +32,7 @@ pub fn non_zero_signed_eq(l: Option<NonZeroI64>, r: Option<NonZeroI64>) -> bool
 #[no_mangle]
 pub fn non_null_eq(l: Option<NonNull<u8>>, r: Option<NonNull<u8>>) -> bool {
     // CHECK: start:
-    // CHECK-NEXT: icmp eq {{(i8\*|ptr)}}
-    // CHECK-NEXT: ret i1
-    l == r
-}
-
-// CHECK-lABEL: @ordering_eq
-#[no_mangle]
-pub fn ordering_eq(l: Option<Ordering>, r: Option<Ordering>) -> bool {
-    // CHECK: start:
-    // CHECK-NEXT: icmp eq i8
+    // CHECK-NEXT: icmp eq ptr
     // CHECK-NEXT: ret i1
     l == r
 }
diff --git a/tests/codegen/packed.rs b/tests/codegen/packed.rs
index fd63b4f0acd..96cd9a42e7d 100644
--- a/tests/codegen/packed.rs
+++ b/tests/codegen/packed.rs
@@ -18,8 +18,8 @@ pub struct Packed2 {
 // CHECK-LABEL: @write_pkd1
 #[no_mangle]
 pub fn write_pkd1(pkd: &mut Packed1) -> u32 {
-// CHECK: %{{.*}} = load i32, {{i32\*|ptr}} %{{.*}}, align 1
-// CHECK: store i32 42, {{i32\*|ptr}} %{{.*}}, align 1
+// CHECK: %{{.*}} = load i32, ptr %{{.*}}, align 1
+// CHECK: store i32 42, ptr %{{.*}}, align 1
     let result = pkd.data;
     pkd.data = 42;
     result
@@ -28,8 +28,8 @@ pub fn write_pkd1(pkd: &mut Packed1) -> u32 {
 // CHECK-LABEL: @write_pkd2
 #[no_mangle]
 pub fn write_pkd2(pkd: &mut Packed2) -> u32 {
-// CHECK: %{{.*}} = load i32, {{i32\*|ptr}} %{{.*}}, align 2
-// CHECK: store i32 42, {{i32\*|ptr}} %{{.*}}, align 2
+// CHECK: %{{.*}} = load i32, ptr %{{.*}}, align 2
+// CHECK: store i32 42, ptr %{{.*}}, align 2
     let result = pkd.data;
     pkd.data = 42;
     result
@@ -52,8 +52,8 @@ pub struct BigPacked2 {
 #[no_mangle]
 pub fn call_pkd1(f: fn() -> Array) -> BigPacked1 {
 // CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca %Array
-// CHECK: call void %{{.*}}({{%Array\*|ptr}} noalias nocapture noundef sret{{.*}} dereferenceable(32) [[ALLOCA]])
-// CHECK: call void @llvm.memcpy.{{.*}}({{i8\*|ptr}} align 1 %{{.*}}, {{i8\*|ptr}} align 4 %{{.*}}, i{{[0-9]+}} 32, i1 false)
+// CHECK: call void %{{.*}}(ptr noalias nocapture noundef sret{{.*}} dereferenceable(32) [[ALLOCA]])
+// CHECK: call void @llvm.memcpy.{{.*}}(ptr align 1 %{{.*}}, ptr align 4 %{{.*}}, i{{[0-9]+}} 32, i1 false)
     // check that calls whose destination is a field of a packed struct
     // go through an alloca rather than calling the function with an
     // unaligned destination.
@@ -64,8 +64,8 @@ pub fn call_pkd1(f: fn() -> Array) -> BigPacked1 {
 #[no_mangle]
 pub fn call_pkd2(f: fn() -> Array) -> BigPacked2 {
 // CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca %Array
-// CHECK: call void %{{.*}}({{%Array\*|ptr}} noalias nocapture noundef sret{{.*}} dereferenceable(32) [[ALLOCA]])
-// CHECK: call void @llvm.memcpy.{{.*}}({{i8\*|ptr}} align 2 %{{.*}}, {{i8\*|ptr}} align 4 %{{.*}}, i{{[0-9]+}} 32, i1 false)
+// CHECK: call void %{{.*}}(ptr noalias nocapture noundef sret{{.*}} dereferenceable(32) [[ALLOCA]])
+// CHECK: call void @llvm.memcpy.{{.*}}(ptr align 2 %{{.*}}, ptr align 4 %{{.*}}, i{{[0-9]+}} 32, i1 false)
     // check that calls whose destination is a field of a packed struct
     // go through an alloca rather than calling the function with an
     // unaligned destination.
@@ -73,9 +73,9 @@ pub fn call_pkd2(f: fn() -> Array) -> BigPacked2 {
 }
 
 // CHECK-LABEL: @write_packed_array1
-// CHECK: store i32 0, {{i32\*|ptr}} %{{.+}}, align 1
-// CHECK: store i32 1, {{i32\*|ptr}} %{{.+}}, align 1
-// CHECK: store i32 2, {{i32\*|ptr}} %{{.+}}, align 1
+// CHECK: store i32 0, ptr %{{.+}}, align 1
+// CHECK: store i32 1, ptr %{{.+}}, align 1
+// CHECK: store i32 2, ptr %{{.+}}, align 1
 #[no_mangle]
 pub fn write_packed_array1(p: &mut BigPacked1) {
     p.data.0[0] = 0;
@@ -84,9 +84,9 @@ pub fn write_packed_array1(p: &mut BigPacked1) {
 }
 
 // CHECK-LABEL: @write_packed_array2
-// CHECK: store i32 0, {{i32\*|ptr}} %{{.+}}, align 2
-// CHECK: store i32 1, {{i32\*|ptr}} %{{.+}}, align 2
-// CHECK: store i32 2, {{i32\*|ptr}} %{{.+}}, align 2
+// CHECK: store i32 0, ptr %{{.+}}, align 2
+// CHECK: store i32 1, ptr %{{.+}}, align 2
+// CHECK: store i32 2, ptr %{{.+}}, align 2
 #[no_mangle]
 pub fn write_packed_array2(p: &mut BigPacked2) {
     p.data.0[0] = 0;
@@ -95,14 +95,14 @@ pub fn write_packed_array2(p: &mut BigPacked2) {
 }
 
 // CHECK-LABEL: @repeat_packed_array1
-// CHECK: store i32 42, {{i32\*|ptr}} %{{.+}}, align 1
+// CHECK: store i32 42, ptr %{{.+}}, align 1
 #[no_mangle]
 pub fn repeat_packed_array1(p: &mut BigPacked1) {
     p.data.0 = [42; 8];
 }
 
 // CHECK-LABEL: @repeat_packed_array2
-// CHECK: store i32 42, {{i32\*|ptr}} %{{.+}}, align 2
+// CHECK: store i32 42, ptr %{{.+}}, align 2
 #[no_mangle]
 pub fn repeat_packed_array2(p: &mut BigPacked2) {
     p.data.0 = [42; 8];
@@ -119,14 +119,14 @@ pub struct Packed2Pair(u8, u32);
 // CHECK-LABEL: @pkd1_pair
 #[no_mangle]
 pub fn pkd1_pair(pair1: &mut Packed1Pair, pair2: &mut Packed1Pair) {
-// CHECK: call void @llvm.memcpy.{{.*}}({{i8\*|ptr}} align 1 %{{.*}}, {{i8\*|ptr}} align 1 %{{.*}}, i{{[0-9]+}} 5, i1 false)
+// CHECK: call void @llvm.memcpy.{{.*}}(ptr align 1 %{{.*}}, ptr align 1 %{{.*}}, i{{[0-9]+}} 5, i1 false)
     *pair2 = *pair1;
 }
 
 // CHECK-LABEL: @pkd2_pair
 #[no_mangle]
 pub fn pkd2_pair(pair1: &mut Packed2Pair, pair2: &mut Packed2Pair) {
-// CHECK: call void @llvm.memcpy.{{.*}}({{i8\*|ptr}} align 2 %{{.*}}, {{i8\*|ptr}} align 2 %{{.*}}, i{{[0-9]+}} 6, i1 false)
+// CHECK: call void @llvm.memcpy.{{.*}}(ptr align 2 %{{.*}}, ptr align 2 %{{.*}}, i{{[0-9]+}} 6, i1 false)
     *pair2 = *pair1;
 }
 
@@ -141,13 +141,13 @@ pub struct Packed2NestedPair((u32, u32));
 // CHECK-LABEL: @pkd1_nested_pair
 #[no_mangle]
 pub fn pkd1_nested_pair(pair1: &mut Packed1NestedPair, pair2: &mut Packed1NestedPair) {
-// CHECK: call void @llvm.memcpy.{{.*}}({{i8\*|ptr}} align 1 %{{.*}}, {{i8\*|ptr}} align 1 %{{.*}}, i{{[0-9]+}} 8, i1 false)
+// CHECK: call void @llvm.memcpy.{{.*}}(ptr align 1 %{{.*}}, ptr align 1 %{{.*}}, i{{[0-9]+}} 8, i1 false)
     *pair2 = *pair1;
 }
 
 // CHECK-LABEL: @pkd2_nested_pair
 #[no_mangle]
 pub fn pkd2_nested_pair(pair1: &mut Packed2NestedPair, pair2: &mut Packed2NestedPair) {
-// CHECK: call void @llvm.memcpy.{{.*}}({{i8\*|ptr}} align 2 %{{.*}}, {{i8\*|ptr}} align 2 %{{.*}}, i{{[0-9]+}} 8, i1 false)
+// CHECK: call void @llvm.memcpy.{{.*}}(ptr align 2 %{{.*}}, ptr align 2 %{{.*}}, i{{[0-9]+}} 8, i1 false)
     *pair2 = *pair1;
 }
diff --git a/tests/codegen/personality_lifetimes.rs b/tests/codegen/personality_lifetimes.rs
index 2104022f578..47243bece98 100644
--- a/tests/codegen/personality_lifetimes.rs
+++ b/tests/codegen/personality_lifetimes.rs
@@ -1,5 +1,6 @@
 // ignore-msvc
 // ignore-wasm32-bare compiled with panic=abort by default
+// needs-unwind
 
 // compile-flags: -O -C no-prepopulate-passes
 
@@ -21,7 +22,7 @@ pub fn test() {
     let _s = S;
     // Check that the personality slot alloca gets a lifetime start in each cleanup block, not just
     // in the first one.
-    // CHECK: [[SLOT:%[0-9]+]] = alloca { {{i8\*|ptr}}, i32 }
+    // CHECK: [[SLOT:%[0-9]+]] = alloca { ptr, i32 }
     // CHECK-LABEL: cleanup:
     // CHECK: call void @llvm.lifetime.start.{{.*}}({{.*}})
     // CHECK-LABEL: cleanup1:
diff --git a/tests/codegen/ptr-read-metadata.rs b/tests/codegen/ptr-read-metadata.rs
index e1e3272662c..73d1db6df27 100644
--- a/tests/codegen/ptr-read-metadata.rs
+++ b/tests/codegen/ptr-read-metadata.rs
@@ -9,7 +9,7 @@
 
 use std::mem::MaybeUninit;
 
-// CHECK-LABEL: define noundef i8 @copy_byte(
+// CHECK-LABEL: define {{(dso_local )?}}noundef i8 @copy_byte(
 #[no_mangle]
 pub unsafe fn copy_byte(p: *const u8) -> u8 {
     // CHECK-NOT: load
@@ -19,7 +19,7 @@ pub unsafe fn copy_byte(p: *const u8) -> u8 {
     *p
 }
 
-// CHECK-LABEL: define noundef i8 @read_byte(
+// CHECK-LABEL: define {{(dso_local )?}}noundef i8 @read_byte(
 #[no_mangle]
 pub unsafe fn read_byte(p: *const u8) -> u8 {
     // CHECK-NOT: load
@@ -29,7 +29,7 @@ pub unsafe fn read_byte(p: *const u8) -> u8 {
     p.read()
 }
 
-// CHECK-LABEL: define i8 @read_byte_maybe_uninit(
+// CHECK-LABEL: define {{(dso_local )?}}i8 @read_byte_maybe_uninit(
 #[no_mangle]
 pub unsafe fn read_byte_maybe_uninit(p: *const MaybeUninit<u8>) -> MaybeUninit<u8> {
     // CHECK-NOT: load
@@ -39,7 +39,7 @@ pub unsafe fn read_byte_maybe_uninit(p: *const MaybeUninit<u8>) -> MaybeUninit<u
     p.read()
 }
 
-// CHECK-LABEL: define noundef i8 @read_byte_assume_init(
+// CHECK-LABEL: define {{(dso_local )?}}noundef i8 @read_byte_assume_init(
 #[no_mangle]
 pub unsafe fn read_byte_assume_init(p: &MaybeUninit<u8>) -> u8 {
     // CHECK-NOT: load
@@ -49,7 +49,7 @@ pub unsafe fn read_byte_assume_init(p: &MaybeUninit<u8>) -> u8 {
     p.assume_init_read()
 }
 
-// CHECK-LABEL: define noundef i32 @copy_char(
+// CHECK-LABEL: define {{(dso_local )?}}noundef i32 @copy_char(
 #[no_mangle]
 pub unsafe fn copy_char(p: *const char) -> char {
     // CHECK-NOT: load
@@ -60,7 +60,7 @@ pub unsafe fn copy_char(p: *const char) -> char {
     *p
 }
 
-// CHECK-LABEL: define noundef i32 @read_char(
+// CHECK-LABEL: define {{(dso_local )?}}noundef i32 @read_char(
 #[no_mangle]
 pub unsafe fn read_char(p: *const char) -> char {
     // CHECK-NOT: load
@@ -71,7 +71,7 @@ pub unsafe fn read_char(p: *const char) -> char {
     p.read()
 }
 
-// CHECK-LABEL: define i32 @read_char_maybe_uninit(
+// CHECK-LABEL: define {{(dso_local )?}}i32 @read_char_maybe_uninit(
 #[no_mangle]
 pub unsafe fn read_char_maybe_uninit(p: *const MaybeUninit<char>) -> MaybeUninit<char> {
     // CHECK-NOT: load
@@ -82,7 +82,7 @@ pub unsafe fn read_char_maybe_uninit(p: *const MaybeUninit<char>) -> MaybeUninit
     p.read()
 }
 
-// CHECK-LABEL: define noundef i32 @read_char_assume_init(
+// CHECK-LABEL: define {{(dso_local )?}}noundef i32 @read_char_assume_init(
 #[no_mangle]
 pub unsafe fn read_char_assume_init(p: &MaybeUninit<char>) -> char {
     // CHECK-NOT: load
diff --git a/tests/codegen/refs.rs b/tests/codegen/refs.rs
index a5289766711..1c7746a3079 100644
--- a/tests/codegen/refs.rs
+++ b/tests/codegen/refs.rs
@@ -13,9 +13,9 @@ pub fn helper(_: usize) {
 pub fn ref_dst(s: &[u8]) {
     // We used to generate an extra alloca and memcpy to ref the dst, so check that we copy
     // directly to the alloca for "x"
-// CHECK: [[X0:%[0-9]+]] = getelementptr inbounds { {{\[0 x i8\]\*|ptr}}, [[USIZE]] }, {{.*}}  %x, i32 0, i32 0
-// CHECK: store {{\[0 x i8\]\*|ptr}} %s.0, {{.*}} [[X0]]
-// CHECK: [[X1:%[0-9]+]] = getelementptr inbounds { {{\[0 x i8\]\*|ptr}}, [[USIZE]] }, {{.*}} %x, i32 0, i32 1
+// CHECK: [[X0:%[0-9]+]] = getelementptr inbounds { ptr, [[USIZE]] }, {{.*}}  %x, i32 0, i32 0
+// CHECK: store ptr %s.0, {{.*}} [[X0]]
+// CHECK: [[X1:%[0-9]+]] = getelementptr inbounds { ptr, [[USIZE]] }, {{.*}} %x, i32 0, i32 1
 // CHECK: store [[USIZE]] %s.1, {{.*}} [[X1]]
 
     let x = &*s;
diff --git a/tests/codegen/repeat-trusted-len.rs b/tests/codegen/repeat-trusted-len.rs
index 87c8fe1354d..bd6ff977e1f 100644
--- a/tests/codegen/repeat-trusted-len.rs
+++ b/tests/codegen/repeat-trusted-len.rs
@@ -8,13 +8,13 @@ use std::iter;
 // CHECK-LABEL: @repeat_take_collect
 #[no_mangle]
 pub fn repeat_take_collect() -> Vec<u8> {
-// CHECK: call void @llvm.memset.{{.+}}({{i8\*|ptr}} {{.*}}align 1{{.*}} %{{[0-9]+}}, i8 42, i{{[0-9]+}} 100000, i1 false)
+    // CHECK: call void @llvm.memset.{{.+}}(ptr {{.*}}align 1{{.*}} %{{.*}}, i8 42, i{{[0-9]+}} 100000, i1 false)
     iter::repeat(42).take(100000).collect()
 }
 
 // CHECK-LABEL: @repeat_with_take_collect
 #[no_mangle]
 pub fn repeat_with_take_collect() -> Vec<u8> {
-// CHECK: call void @llvm.memset.{{.+}}({{i8\*|ptr}} {{.*}}align 1{{.*}} %{{[0-9]+}}, i8 13, i{{[0-9]+}} 12345, i1 false)
+    // CHECK: call void @llvm.memset.{{.+}}(ptr {{.*}}align 1{{.*}} %{{.*}}, i8 13, i{{[0-9]+}} 12345, i1 false)
     iter::repeat_with(|| 13).take(12345).collect()
 }
diff --git a/tests/codegen/repr-transparent-aggregates-1.rs b/tests/codegen/repr-transparent-aggregates-1.rs
deleted file mode 100644
index f733de12b35..00000000000
--- a/tests/codegen/repr-transparent-aggregates-1.rs
+++ /dev/null
@@ -1,87 +0,0 @@
-// compile-flags: -O -C no-prepopulate-passes
-//
-
-// ignore-arm
-// ignore-aarch64
-// ignore-mips
-// ignore-mips64
-// ignore-powerpc
-// ignore-powerpc64
-// ignore-riscv64 see codegen/riscv-abi
-// ignore-s390x
-// ignore-windows
-// See repr-transparent.rs
-
-#![feature(transparent_unions)]
-
-#![crate_type="lib"]
-
-
-#[derive(Clone, Copy)]
-#[repr(C)]
-pub struct BigS([u32; 16]);
-
-#[repr(transparent)]
-pub struct TsBigS(BigS);
-
-#[repr(transparent)]
-pub union TuBigS {
-    field: BigS,
-}
-
-#[repr(transparent)]
-pub enum TeBigS {
-    Variant(BigS),
-}
-
-// CHECK: define{{.*}}void @test_BigS({{%BigS\*|ptr}} [[BIGS_RET_ATTRS1:.*]] sret(%BigS) [[BIGS_RET_ATTRS2:.*]], {{%BigS\*|ptr}} [[BIGS_ARG_ATTRS1:.*]] byval(%BigS) [[BIGS_ARG_ATTRS2:.*]])
-#[no_mangle]
-pub extern "C" fn test_BigS(_: BigS) -> BigS { loop {} }
-
-// CHECK: define{{.*}}void @test_TsBigS({{%TsBigS\*|ptr}} [[BIGS_RET_ATTRS1]] sret(%TsBigS) [[BIGS_RET_ATTRS2]], {{%TsBigS\*|ptr}} [[BIGS_ARG_ATTRS1]] byval(%TsBigS) [[BIGS_ARG_ATTRS2:.*]])
-#[no_mangle]
-pub extern "C" fn test_TsBigS(_: TsBigS) -> TsBigS { loop {} }
-
-// CHECK: define{{.*}}void @test_TuBigS({{%TuBigS\*|ptr}} [[BIGS_RET_ATTRS1]] sret(%TuBigS) [[BIGS_RET_ATTRS2]], {{%TuBigS\*|ptr}} [[BIGS_ARG_ATTRS1]] byval(%TuBigS) [[BIGS_ARG_ATTRS2:.*]])
-#[no_mangle]
-pub extern "C" fn test_TuBigS(_: TuBigS) -> TuBigS { loop {} }
-
-// CHECK: define{{.*}}void @test_TeBigS({{%"TeBigS::Variant"\*|ptr}} [[BIGS_RET_ATTRS1]] sret(%"TeBigS::Variant") [[BIGS_RET_ATTRS2]], {{%"TeBigS::Variant"\*|ptr}} [[BIGS_ARG_ATTRS1]] byval(%"TeBigS::Variant") [[BIGS_ARG_ATTRS2]])
-#[no_mangle]
-pub extern "C" fn test_TeBigS(_: TeBigS) -> TeBigS { loop {} }
-
-
-#[derive(Clone, Copy)]
-#[repr(C)]
-pub union BigU {
-    foo: [u32; 16],
-}
-
-#[repr(transparent)]
-pub struct TsBigU(BigU);
-
-#[repr(transparent)]
-pub union TuBigU {
-    field: BigU,
-}
-
-#[repr(transparent)]
-pub enum TeBigU {
-    Variant(BigU),
-}
-
-// CHECK: define{{.*}}void @test_BigU({{%BigU\*|ptr}} [[BIGU_RET_ATTRS1:.*]] sret(%BigU) [[BIGU_RET_ATTRS2:.*]], {{%BigU\*|ptr}} [[BIGU_ARG_ATTRS1:.*]] byval(%BigU) [[BIGU_ARG_ATTRS2:.*]])
-#[no_mangle]
-pub extern "C" fn test_BigU(_: BigU) -> BigU { loop {} }
-
-// CHECK: define{{.*}}void @test_TsBigU({{%TsBigU\*|ptr}} [[BIGU_RET_ATTRS1:.*]] sret(%TsBigU) [[BIGU_RET_ATTRS2:.*]], {{%TsBigU\*|ptr}} [[BIGU_ARG_ATTRS1]] byval(%TsBigU) [[BIGU_ARG_ATTRS2]])
-#[no_mangle]
-pub extern "C" fn test_TsBigU(_: TsBigU) -> TsBigU { loop {} }
-
-// CHECK: define{{.*}}void @test_TuBigU({{%TuBigU\*|ptr}} [[BIGU_RET_ATTRS1]] sret(%TuBigU) [[BIGU_RET_ATTRS2:.*]], {{%TuBigU\*|ptr}} [[BIGU_ARG_ATTRS1]] byval(%TuBigU) [[BIGU_ARG_ATTRS2]])
-#[no_mangle]
-pub extern "C" fn test_TuBigU(_: TuBigU) -> TuBigU { loop {} }
-
-// CHECK: define{{.*}}void @test_TeBigU({{%"TeBigU::Variant"\*|ptr}} [[BIGU_RET_ATTRS1]] sret(%"TeBigU::Variant") [[BIGU_RET_ATTRS2:.*]], {{%"TeBigU::Variant"\*|ptr}} [[BIGU_ARG_ATTRS1]] byval(%"TeBigU::Variant") [[BIGU_ARG_ATTRS2]])
-#[no_mangle]
-pub extern "C" fn test_TeBigU(_: TeBigU) -> TeBigU { loop {} }
diff --git a/tests/codegen/repr-transparent-aggregates-2.rs b/tests/codegen/repr-transparent-aggregates-2.rs
deleted file mode 100644
index e9fa5143b18..00000000000
--- a/tests/codegen/repr-transparent-aggregates-2.rs
+++ /dev/null
@@ -1,89 +0,0 @@
-// compile-flags: -C no-prepopulate-passes
-//
-
-// ignore-aarch64
-// ignore-emscripten
-// ignore-mips64
-// ignore-powerpc
-// ignore-powerpc64
-// ignore-riscv64 see codegen/riscv-abi
-// ignore-s390x
-// ignore-sparc
-// ignore-sparc64
-// ignore-x86
-// ignore-x86_64
-// See repr-transparent.rs
-
-#![feature(transparent_unions)]
-
-#![crate_type="lib"]
-
-
-#[derive(Clone, Copy)]
-#[repr(C)]
-pub struct BigS([u32; 16]);
-
-#[repr(transparent)]
-pub struct TsBigS(BigS);
-
-#[repr(transparent)]
-pub union TuBigS {
-    field: BigS,
-}
-
-#[repr(transparent)]
-pub enum TeBigS {
-    Variant(BigS),
-}
-
-// CHECK: define void @test_BigS({{%BigS\*|ptr}} [[BIGS_RET_ATTRS1:.*]] sret(%BigS) [[BIGS_RET_ATTRS2:.*]], [16 x i32]
-#[no_mangle]
-pub extern fn test_BigS(_: BigS) -> BigS { loop {} }
-
-// CHECK: define void @test_TsBigS({{%TsBigS\*|ptr}} [[BIGS_RET_ATTRS1]] sret(%TsBigS) [[BIGS_RET_ATTRS2]], [16 x i32]
-#[no_mangle]
-pub extern fn test_TsBigS(_: TsBigS) -> TsBigS { loop {} }
-
-// CHECK: define void @test_TuBigS({{%TuBigS\*|ptr}} [[BIGS_RET_ATTRS1]] sret(%TuBigS) [[BIGS_RET_ATTRS2]], [16 x i32]
-#[no_mangle]
-pub extern fn test_TuBigS(_: TuBigS) -> TuBigS { loop {} }
-
-// CHECK: define void @test_TeBigS({{%"TeBigS::Variant"\*|ptr}} [[BIGS_RET_ATTRS1]] sret(%"TeBigS::Variant") [[BIGS_RET_ATTRS2]], [16 x i32]
-#[no_mangle]
-pub extern fn test_TeBigS(_: TeBigS) -> TeBigS { loop {} }
-
-
-#[derive(Clone, Copy)]
-#[repr(C)]
-pub union BigU {
-    foo: [u32; 16],
-}
-
-#[repr(transparent)]
-pub struct TsBigU(BigU);
-
-#[repr(transparent)]
-pub union TuBigU {
-    field: BigU,
-}
-
-#[repr(transparent)]
-pub enum TeBigU {
-    Variant(BigU),
-}
-
-// CHECK: define void @test_BigU({{%BigU\*|ptr}} [[BIGU_RET_ATTRS1:.*]] sret(%BigU) [[BIGU_RET_ATTRS2:.*]], [16 x i32]
-#[no_mangle]
-pub extern fn test_BigU(_: BigU) -> BigU { loop {} }
-
-// CHECK: define void @test_TsBigU({{%TsBigU\*|ptr}} [[BIGU_RET_ATTRS1]] sret(%TsBigU) [[BIGU_RET_ATTRS2]], [16 x i32]
-#[no_mangle]
-pub extern fn test_TsBigU(_: TsBigU) -> TsBigU { loop {} }
-
-// CHECK: define void @test_TuBigU({{%TuBigU\*|ptr}} [[BIGU_RET_ATTRS1]] sret(%TuBigU) [[BIGU_RET_ATTRS2]], [16 x i32]
-#[no_mangle]
-pub extern fn test_TuBigU(_: TuBigU) -> TuBigU { loop {} }
-
-// CHECK: define void @test_TeBigU({{%"TeBigU::Variant"\*|ptr}} [[BIGU_RET_ATTRS1]] sret(%"TeBigU::Variant") [[BIGU_RET_ATTRS2]], [16 x i32]
-#[no_mangle]
-pub extern fn test_TeBigU(_: TeBigU) -> TeBigU { loop {} }
diff --git a/tests/codegen/repr/transparent-imm-array.rs b/tests/codegen/repr/transparent-imm-array.rs
new file mode 100644
index 00000000000..6d712778509
--- /dev/null
+++ b/tests/codegen/repr/transparent-imm-array.rs
@@ -0,0 +1,86 @@
+// revisions: arm mips thumb wasm32
+// compile-flags: -C no-prepopulate-passes
+//
+//[arm] only-arm
+//[mips] only-mips
+//[thumb] only-thumb
+//[wasm32] only-wasm32
+// ignore-emscripten
+// See ./transparent.rs
+// Some platforms pass large aggregates using immediate arrays in LLVMIR
+// Other platforms pass large aggregates using struct pointer in LLVMIR
+// This covers the "immediate array" case.
+
+#![feature(transparent_unions)]
+
+#![crate_type="lib"]
+
+
+#[derive(Clone, Copy)]
+#[repr(C)]
+pub struct BigS([u32; 16]);
+
+#[repr(transparent)]
+pub struct TsBigS(BigS);
+
+#[repr(transparent)]
+pub union TuBigS {
+    field: BigS,
+}
+
+#[repr(transparent)]
+pub enum TeBigS {
+    Variant(BigS),
+}
+
+// CHECK: define void @test_BigS(ptr [[BIGS_RET_ATTRS1:.*]] sret(%BigS) [[BIGS_RET_ATTRS2:.*]], [16 x i32]
+#[no_mangle]
+pub extern fn test_BigS(_: BigS) -> BigS { loop {} }
+
+// CHECK: define void @test_TsBigS(ptr [[BIGS_RET_ATTRS1]] sret(%TsBigS) [[BIGS_RET_ATTRS2]], [16 x i32]
+#[no_mangle]
+pub extern fn test_TsBigS(_: TsBigS) -> TsBigS { loop {} }
+
+// CHECK: define void @test_TuBigS(ptr [[BIGS_RET_ATTRS1]] sret(%TuBigS) [[BIGS_RET_ATTRS2]], [16 x i32]
+#[no_mangle]
+pub extern fn test_TuBigS(_: TuBigS) -> TuBigS { loop {} }
+
+// CHECK: define void @test_TeBigS(ptr [[BIGS_RET_ATTRS1]] sret(%"TeBigS::Variant") [[BIGS_RET_ATTRS2]], [16 x i32]
+#[no_mangle]
+pub extern fn test_TeBigS(_: TeBigS) -> TeBigS { loop {} }
+
+
+#[derive(Clone, Copy)]
+#[repr(C)]
+pub union BigU {
+    foo: [u32; 16],
+}
+
+#[repr(transparent)]
+pub struct TsBigU(BigU);
+
+#[repr(transparent)]
+pub union TuBigU {
+    field: BigU,
+}
+
+#[repr(transparent)]
+pub enum TeBigU {
+    Variant(BigU),
+}
+
+// CHECK: define void @test_BigU(ptr [[BIGU_RET_ATTRS1:.*]] sret(%BigU) [[BIGU_RET_ATTRS2:.*]], [16 x i32]
+#[no_mangle]
+pub extern fn test_BigU(_: BigU) -> BigU { loop {} }
+
+// CHECK: define void @test_TsBigU(ptr [[BIGU_RET_ATTRS1]] sret(%TsBigU) [[BIGU_RET_ATTRS2]], [16 x i32]
+#[no_mangle]
+pub extern fn test_TsBigU(_: TsBigU) -> TsBigU { loop {} }
+
+// CHECK: define void @test_TuBigU(ptr [[BIGU_RET_ATTRS1]] sret(%TuBigU) [[BIGU_RET_ATTRS2]], [16 x i32]
+#[no_mangle]
+pub extern fn test_TuBigU(_: TuBigU) -> TuBigU { loop {} }
+
+// CHECK: define void @test_TeBigU(ptr [[BIGU_RET_ATTRS1]] sret(%"TeBigU::Variant") [[BIGU_RET_ATTRS2]], [16 x i32]
+#[no_mangle]
+pub extern fn test_TeBigU(_: TeBigU) -> TeBigU { loop {} }
diff --git a/tests/codegen/repr-transparent-aggregates-3.rs b/tests/codegen/repr/transparent-mips64.rs
index 0db17e6b13a..245daf13e28 100644
--- a/tests/codegen/repr-transparent-aggregates-3.rs
+++ b/tests/codegen/repr/transparent-mips64.rs
@@ -2,7 +2,7 @@
 //
 
 // only-mips64
-// See repr-transparent.rs
+// See ./transparent.rs
 
 #![feature(transparent_unions)]
 
diff --git a/tests/codegen/repr/transparent-struct-ptr.rs b/tests/codegen/repr/transparent-struct-ptr.rs
new file mode 100644
index 00000000000..d2120f7ec14
--- /dev/null
+++ b/tests/codegen/repr/transparent-struct-ptr.rs
@@ -0,0 +1,87 @@
+// revisions: x32 x64 sparc sparc64
+// compile-flags: -O -C no-prepopulate-passes
+//
+//[x32] only-x86
+//[x64] only-x86_64
+//[sparc] only-sparc
+//[sparc64] only-sparc64
+// ignore-windows
+// See ./transparent.rs
+// Some platforms pass large aggregates using immediate arrays in LLVMIR
+// Other platforms pass large aggregates using struct pointer in LLVMIR
+// This covers the "struct pointer" case.
+
+
+#![feature(transparent_unions)]
+
+#![crate_type="lib"]
+
+
+#[derive(Clone, Copy)]
+#[repr(C)]
+pub struct BigS([u32; 16]);
+
+#[repr(transparent)]
+pub struct TsBigS(BigS);
+
+#[repr(transparent)]
+pub union TuBigS {
+    field: BigS,
+}
+
+#[repr(transparent)]
+pub enum TeBigS {
+    Variant(BigS),
+}
+
+// CHECK: define{{.*}}void @test_BigS(ptr [[BIGS_RET_ATTRS1:.*]] sret(%BigS) [[BIGS_RET_ATTRS2:.*]], ptr [[BIGS_ARG_ATTRS1:.*]] byval(%BigS) [[BIGS_ARG_ATTRS2:.*]])
+#[no_mangle]
+pub extern "C" fn test_BigS(_: BigS) -> BigS { loop {} }
+
+// CHECK: define{{.*}}void @test_TsBigS(ptr [[BIGS_RET_ATTRS1]] sret(%TsBigS) [[BIGS_RET_ATTRS2]], ptr [[BIGS_ARG_ATTRS1]] byval(%TsBigS) [[BIGS_ARG_ATTRS2:.*]])
+#[no_mangle]
+pub extern "C" fn test_TsBigS(_: TsBigS) -> TsBigS { loop {} }
+
+// CHECK: define{{.*}}void @test_TuBigS(ptr [[BIGS_RET_ATTRS1]] sret(%TuBigS) [[BIGS_RET_ATTRS2]], ptr [[BIGS_ARG_ATTRS1]] byval(%TuBigS) [[BIGS_ARG_ATTRS2:.*]])
+#[no_mangle]
+pub extern "C" fn test_TuBigS(_: TuBigS) -> TuBigS { loop {} }
+
+// CHECK: define{{.*}}void @test_TeBigS(ptr [[BIGS_RET_ATTRS1]] sret(%"TeBigS::Variant") [[BIGS_RET_ATTRS2]], ptr [[BIGS_ARG_ATTRS1]] byval(%"TeBigS::Variant") [[BIGS_ARG_ATTRS2]])
+#[no_mangle]
+pub extern "C" fn test_TeBigS(_: TeBigS) -> TeBigS { loop {} }
+
+
+#[derive(Clone, Copy)]
+#[repr(C)]
+pub union BigU {
+    foo: [u32; 16],
+}
+
+#[repr(transparent)]
+pub struct TsBigU(BigU);
+
+#[repr(transparent)]
+pub union TuBigU {
+    field: BigU,
+}
+
+#[repr(transparent)]
+pub enum TeBigU {
+    Variant(BigU),
+}
+
+// CHECK: define{{.*}}void @test_BigU(ptr [[BIGU_RET_ATTRS1:.*]] sret(%BigU) [[BIGU_RET_ATTRS2:.*]], ptr [[BIGU_ARG_ATTRS1:.*]] byval(%BigU) [[BIGU_ARG_ATTRS2:.*]])
+#[no_mangle]
+pub extern "C" fn test_BigU(_: BigU) -> BigU { loop {} }
+
+// CHECK: define{{.*}}void @test_TsBigU(ptr [[BIGU_RET_ATTRS1:.*]] sret(%TsBigU) [[BIGU_RET_ATTRS2:.*]], ptr [[BIGU_ARG_ATTRS1]] byval(%TsBigU) [[BIGU_ARG_ATTRS2]])
+#[no_mangle]
+pub extern "C" fn test_TsBigU(_: TsBigU) -> TsBigU { loop {} }
+
+// CHECK: define{{.*}}void @test_TuBigU(ptr [[BIGU_RET_ATTRS1]] sret(%TuBigU) [[BIGU_RET_ATTRS2:.*]], ptr [[BIGU_ARG_ATTRS1]] byval(%TuBigU) [[BIGU_ARG_ATTRS2]])
+#[no_mangle]
+pub extern "C" fn test_TuBigU(_: TuBigU) -> TuBigU { loop {} }
+
+// CHECK: define{{.*}}void @test_TeBigU(ptr [[BIGU_RET_ATTRS1]] sret(%"TeBigU::Variant") [[BIGU_RET_ATTRS2:.*]], ptr [[BIGU_ARG_ATTRS1]] byval(%"TeBigU::Variant") [[BIGU_ARG_ATTRS2]])
+#[no_mangle]
+pub extern "C" fn test_TeBigU(_: TeBigU) -> TeBigU { loop {} }
diff --git a/tests/codegen/repr-transparent-sysv64.rs b/tests/codegen/repr/transparent-sysv64.rs
index 886b0dd9e7b..886b0dd9e7b 100644
--- a/tests/codegen/repr-transparent-sysv64.rs
+++ b/tests/codegen/repr/transparent-sysv64.rs
diff --git a/tests/codegen/repr-transparent.rs b/tests/codegen/repr/transparent.rs
index 311cbfbaa09..b140fc719da 100644
--- a/tests/codegen/repr-transparent.rs
+++ b/tests/codegen/repr/transparent.rs
@@ -1,8 +1,12 @@
 // compile-flags: -O -C no-prepopulate-passes
-
 // ignore-riscv64 riscv64 has an i128 type used with test_Vector
-// see codegen/riscv-abi for riscv functiona call tests
 // ignore-s390x s390x with default march passes vector types per reference
+// ignore-loongarch64 see codegen/loongarch-abi for loongarch function call tests
+
+// This codegen test embeds assumptions about how certain "C" psABIs are handled
+// so it doesn't apply to all architectures or even all OS
+// For RISCV: see codegen/riscv-abi
+// For LoongArch: see codegen/loongarch-abi
 
 #![crate_type="lib"]
 #![feature(repr_simd, transparent_unions)]
@@ -25,7 +29,7 @@ pub extern "C" fn test_F32(_: F32) -> F32 { loop {} }
 #[repr(transparent)]
 pub struct Ptr(*mut u8);
 
-// CHECK: define{{.*}}{{i8\*|ptr}} @test_Ptr({{i8\*|ptr}} noundef %_1)
+// CHECK: define{{.*}}ptr @test_Ptr(ptr noundef %_1)
 #[no_mangle]
 pub extern "C" fn test_Ptr(_: Ptr) -> Ptr { loop {} }
 
@@ -40,7 +44,7 @@ pub extern "C" fn test_WithZst(_: WithZst) -> WithZst { loop {} }
 pub struct WithZeroSizedArray(*const f32, [i8; 0]);
 
 // Apparently we use i32* when newtype-unwrapping f32 pointers. Whatever.
-// CHECK: define{{.*}}{{i32\*|ptr}} @test_WithZeroSizedArray({{i32\*|ptr}} noundef %_1)
+// CHECK: define{{.*}}ptr @test_WithZeroSizedArray(ptr noundef %_1)
 #[no_mangle]
 pub extern "C" fn test_WithZeroSizedArray(_: WithZeroSizedArray) -> WithZeroSizedArray { loop {} }
 
@@ -64,7 +68,7 @@ pub extern "C" fn test_Gpz(_: GenericPlusZst<Bool>) -> GenericPlusZst<Bool> { lo
 #[repr(transparent)]
 pub struct LifetimePhantom<'a, T: 'a>(*const T, PhantomData<&'a T>);
 
-// CHECK: define{{.*}}{{i16\*|ptr}} @test_LifetimePhantom({{i16\*|ptr}} noundef %_1)
+// CHECK: define{{.*}}ptr @test_LifetimePhantom(ptr noundef %_1)
 #[no_mangle]
 pub extern "C" fn test_LifetimePhantom(_: LifetimePhantom<i16>) -> LifetimePhantom<i16> { loop {} }
 
@@ -158,7 +162,7 @@ pub union UnionF32WithZsts {
 pub extern "C" fn test_UnionF32WithZsts(_: UnionF32WithZsts) -> UnionF32WithZsts { loop {} }
 
 
-// All that remains to be tested are aggregates. They are tested in separate files called repr-
+// All that remains to be tested are aggregates. They are tested in separate files called
 // transparent-*.rs  with `only-*` or `ignore-*` directives, because the expected LLVM IR
 // function signatures vary so much that it's not reasonably possible to cover all of them with a
 // single CHECK line.
diff --git a/tests/codegen/riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs b/tests/codegen/riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs
index 045f01985a5..fdb9c6217de 100644
--- a/tests/codegen/riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs
+++ b/tests/codegen/riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs
@@ -127,18 +127,18 @@ pub struct Large {
     d: i64,
 }
 
-// CHECK: define void @f_agg_large({{%Large\*|ptr}} {{.*}}%x)
+// CHECK: define void @f_agg_large(ptr {{.*}}%x)
 #[no_mangle]
 pub extern "C" fn f_agg_large(mut x: Large) {
 }
 
-// CHECK: define void @f_agg_large_ret({{%Large\*|ptr}} {{.*}}sret{{.*}}, i32 noundef signext %i, i8 noundef signext %j)
+// CHECK: define void @f_agg_large_ret(ptr {{.*}}sret{{.*}}, i32 noundef signext %i, i8 noundef signext %j)
 #[no_mangle]
 pub extern "C" fn f_agg_large_ret(i: i32, j: i8) -> Large {
     Large { a: 1, b: 2, c: 3, d: 4 }
 }
 
-// CHECK: define void @f_scalar_stack_1(i64 %0, [2 x i64] %1, i128 %2, {{%Large\*|ptr}} {{.*}}%d, i8 noundef zeroext %e, i8 noundef signext %f, i8 noundef %g, i8 noundef %h)
+// CHECK: define void @f_scalar_stack_1(i64 %0, [2 x i64] %1, i128 %2, ptr {{.*}}%d, i8 noundef zeroext %e, i8 noundef signext %f, i8 noundef %g, i8 noundef %h)
 #[no_mangle]
 pub extern "C" fn f_scalar_stack_1(
     a: Tiny,
@@ -152,7 +152,7 @@ pub extern "C" fn f_scalar_stack_1(
 ) {
 }
 
-// CHECK: define void @f_scalar_stack_2({{%Large\*|ptr}} {{.*}}sret{{.*}} %0, i64 noundef %a, i128 %1, i128 %2, i64 noundef %d, i8 noundef zeroext %e, i8 noundef %f, i8 noundef %g)
+// CHECK: define void @f_scalar_stack_2(ptr {{.*}}sret{{.*}} %_0, i64 noundef %a, i128 %0, i128 %1, i64 noundef %d, i8 noundef zeroext %e, i8 noundef %f, i8 noundef %g)
 #[no_mangle]
 pub extern "C" fn f_scalar_stack_2(
     a: u64,
@@ -172,7 +172,7 @@ extern "C" {
 
 #[no_mangle]
 pub unsafe extern "C" fn f_va_caller() {
-    // CHECK: call noundef signext i32 (i32, ...) @f_va_callee(i32 noundef signext 1, i32 noundef signext 2, i64 noundef 3, double {{.*}}, double {{.*}}, i64 {{.*}}, [2 x i64] {{.*}}, i128 {{.*}}, {{%Large\*|ptr}} {{.*}})
+    // CHECK: call noundef signext i32 (i32, ...) @f_va_callee(i32 noundef signext 1, i32 noundef signext 2, i64 noundef 3, double {{.*}}, double {{.*}}, i64 {{.*}}, [2 x i64] {{.*}}, i128 {{.*}}, ptr {{.*}})
     f_va_callee(
         1,
         2i32,
diff --git a/tests/codegen/sanitizer-cfi-add-canonical-jump-tables-flag.rs b/tests/codegen/sanitizer-cfi-add-canonical-jump-tables-flag.rs
index c42fbba7425..1ee8bdfc3ab 100644
--- a/tests/codegen/sanitizer-cfi-add-canonical-jump-tables-flag.rs
+++ b/tests/codegen/sanitizer-cfi-add-canonical-jump-tables-flag.rs
@@ -8,4 +8,4 @@
 pub fn foo() {
 }
 
-// CHECK: !{{[0-9]+}} = !{i32 2, !"CFI Canonical Jump Tables", i32 1}
+// CHECK: !{{[0-9]+}} = !{i32 4, !"CFI Canonical Jump Tables", i32 1}
diff --git a/tests/codegen/sanitizer-cfi-add-enable-split-lto-unit-flag.rs b/tests/codegen/sanitizer-cfi-add-enable-split-lto-unit-flag.rs
new file mode 100644
index 00000000000..68c91384b82
--- /dev/null
+++ b/tests/codegen/sanitizer-cfi-add-enable-split-lto-unit-flag.rs
@@ -0,0 +1,11 @@
+// Verifies that "EnableSplitLTOUnit" module flag is added.
+//
+// needs-sanitizer-cfi
+// compile-flags: -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi
+
+#![crate_type="lib"]
+
+pub fn foo() {
+}
+
+// CHECK: !{{[0-9]+}} = !{i32 4, !"EnableSplitLTOUnit", i32 1}
diff --git a/tests/codegen/sanitizer-cfi-emit-type-checks-attr-no-sanitize.rs b/tests/codegen/sanitizer-cfi-emit-type-checks-attr-no-sanitize.rs
new file mode 100644
index 00000000000..2b61c9078fd
--- /dev/null
+++ b/tests/codegen/sanitizer-cfi-emit-type-checks-attr-no-sanitize.rs
@@ -0,0 +1,18 @@
+// Verifies that pointer type membership tests for indirect calls are omitted.
+//
+// needs-sanitizer-cfi
+// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Copt-level=0
+
+#![crate_type="lib"]
+#![feature(no_sanitize)]
+
+#[no_sanitize(cfi)]
+pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
+    // CHECK-LABEL: sanitizer_cfi_emit_type_checks_attr_no_sanitize::foo
+    // CHECK:       Function Attrs: {{.*}}
+    // CHECK-LABEL: define{{.*}}foo{{.*}}!type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+    // CHECK:       start:
+    // CHECK-NEXT:  {{%.+}} = call i32 %f(i32 %arg)
+    // CHECK-NEXT:  ret i32 {{%.+}}
+    f(arg)
+}
diff --git a/tests/codegen/sanitizer-cfi-emit-type-checks.rs b/tests/codegen/sanitizer-cfi-emit-type-checks.rs
index 597b867ebad..f0fe5de9f66 100644
--- a/tests/codegen/sanitizer-cfi-emit-type-checks.rs
+++ b/tests/codegen/sanitizer-cfi-emit-type-checks.rs
@@ -6,13 +6,12 @@
 #![crate_type="lib"]
 
 pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
-    // CHECK-LABEL: define{{.*}}foo{{.*}}!type !{{[0-9]+}}
+    // CHECK-LABEL: define{{.*}}foo{{.*}}!type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
     // CHECK:       start:
-    // CHECK:       [[TT:%.+]] = call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0}}, metadata !"{{[[:print:]]+}}")
+    // CHECK:       [[TT:%.+]] = call i1 @llvm.type.test(ptr {{%f|%0}}, metadata !"{{[[:print:]]+}}")
     // CHECK-NEXT:  br i1 [[TT]], label %type_test.pass, label %type_test.fail
     // CHECK:       type_test.pass:
     // CHECK-NEXT:  {{%.+}} = call i32 %f(i32 %arg)
-    // CHECK-NEXT:  br label %bb1
     // CHECK:       type_test.fail:
     // CHECK-NEXT:  call void @llvm.trap()
     // CHECK-NEXT:  unreachable
diff --git a/tests/codegen/sanitizer-cfi-emit-type-metadata-attr-cfi-encoding.rs b/tests/codegen/sanitizer-cfi-emit-type-metadata-attr-cfi-encoding.rs
new file mode 100644
index 00000000000..084d8bf803c
--- /dev/null
+++ b/tests/codegen/sanitizer-cfi-emit-type-metadata-attr-cfi-encoding.rs
@@ -0,0 +1,48 @@
+// Verifies that user-defined CFI encoding for types are emitted.
+//
+// needs-sanitizer-cfi
+// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi
+
+#![crate_type="lib"]
+#![feature(cfi_encoding, extern_types)]
+
+#[cfi_encoding = "3Foo"]
+pub struct Type1(i32);
+
+extern {
+    #[cfi_encoding = "3Bar"]
+    type Type2;
+}
+
+#[cfi_encoding = "3Baz"]
+#[repr(transparent)]
+pub struct Type3(i32);
+
+pub fn foo0(_: Type1) { }
+// CHECK: define{{.*}}foo0{{.*}}!type ![[TYPE0:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo1(_: Type1, _: Type1) { }
+// CHECK: define{{.*}}foo1{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo2(_: Type1, _: Type1, _: Type1) { }
+// CHECK: define{{.*}}foo2{{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo3(_: *mut Type2) { }
+// CHECK: define{{.*}}foo3{{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo4(_: *mut Type2, _: *mut Type2) { }
+// CHECK: define{{.*}}foo4{{.*}}!type ![[TYPE4:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo5(_: *mut Type2, _: *mut Type2, _: *mut Type2) { }
+// CHECK: define{{.*}}foo5{{.*}}!type ![[TYPE5:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo6(_: *mut Type3) { }
+// CHECK: define{{.*}}foo6{{.*}}!type ![[TYPE6:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo7(_: *mut Type3, _: *mut Type3) { }
+// CHECK: define{{.*}}foo7{{.*}}!type ![[TYPE7:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo8(_: *mut Type3, _: *mut Type3, _: *mut Type3) { }
+// CHECK: define{{.*}}foo8{{.*}}!type ![[TYPE8:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+
+// CHECK: ![[TYPE0]] = !{i64 0, !"_ZTSFv3FooE"}
+// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFv3FooS_E"}
+// CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFv3FooS_S_E"}
+// CHECK: ![[TYPE3]] = !{i64 0, !"_ZTSFvP3BarE"}
+// CHECK: ![[TYPE4]] = !{i64 0, !"_ZTSFvP3BarS0_E"}
+// CHECK: ![[TYPE5]] = !{i64 0, !"_ZTSFvP3BarS0_S0_E"}
+// CHECK: ![[TYPE6]] = !{i64 0, !"_ZTSFvP3BazE"}
+// CHECK: ![[TYPE7]] = !{i64 0, !"_ZTSFvP3BazS0_E"}
+// CHECK: ![[TYPE8]] = !{i64 0, !"_ZTSFvP3BazS0_S0_E"}
diff --git a/tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs b/tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs
index b9c33914360..63e63c5d4aa 100644
--- a/tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs
+++ b/tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs
@@ -10,7 +10,7 @@
 #![feature(adt_const_params, extern_types, inline_const, type_alias_impl_trait)]
 
 extern crate core;
-use core::ffi::c_void;
+use core::ffi::*;
 use std::marker::PhantomData;
 
 // User-defined type (structure)
@@ -44,7 +44,7 @@ impl<T> Trait1<T> for i32 {
 }
 
 // Trait implementation
-impl<T> Trait1<T> for Struct1<T> {
+impl<T, U> Trait1<T> for Struct1<U> {
     fn foo(&self) { }
 }
 
@@ -61,7 +61,19 @@ pub type Type9 = impl Send;
 pub type Type10 = impl Send;
 pub type Type11 = impl Send;
 
-pub fn fn1<'a>() {
+pub fn fn1<'a>() where
+    Type1: 'static,
+    Type2: 'static,
+    Type3: 'static,
+    Type4: 'static,
+    Type5: 'static,
+    Type6: 'static,
+    Type7: 'static,
+    Type8: 'static,
+    Type9: 'static,
+    Type10: 'static,
+    Type11: 'static,
+{
     // Closure
     let closure1 = || { };
     let _: Type1 = closure1;
@@ -113,9 +125,10 @@ pub fn fn1<'a>() {
     let _: Type11 = Quuux;
 }
 
-// repr(transparent) user-defined type
+// Helper type to make Type12 have an unique id
 struct Foo(i32);
 
+// repr(transparent) user-defined type
 #[repr(transparent)]
 pub struct Type12 {
     member1: (),
@@ -131,313 +144,313 @@ pub struct Type13<'a> {
     member3: &'a Type13<'a>,
 }
 
-// Helper type to allow `Type14<Bar>` to be a unique ID
+// Helper type to make Type14 have an unique id
 pub struct Bar;
 
-// repr(transparent) parameterized type
+// repr(transparent) user-defined generic type
 #[repr(transparent)]
 pub struct Type14<T>(T);
 
 pub fn foo0(_: ()) { }
-// CHECK: define{{.*}}foo0{{.*}}!type ![[TYPE0:[0-9]+]]
-pub fn foo1(_: c_void, _: ()) { }
-// CHECK: define{{.*}}foo1{{.*}}!type ![[TYPE1:[0-9]+]]
+// CHECK: define{{.*}}foo0{{.*}}!type ![[TYPE0:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo1(_: (), _: c_void) { }
+// CHECK: define{{.*}}foo1{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo2(_: (), _: c_void, _: c_void) { }
-// CHECK: define{{.*}}foo2{{.*}}!type ![[TYPE2:[0-9]+]]
-pub fn foo3(_: *mut c_void) { }
-// CHECK: define{{.*}}foo3{{.*}}!type ![[TYPE3:[0-9]+]]
-pub fn foo4(_: *mut c_void, _: *mut ()) { }
-// CHECK: define{{.*}}foo4{{.*}}!type ![[TYPE4:[0-9]+]]
+// CHECK: define{{.*}}foo2{{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo3(_: *mut ()) { }
+// CHECK: define{{.*}}foo3{{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo4(_: *mut (), _: *mut c_void) { }
+// CHECK: define{{.*}}foo4{{.*}}!type ![[TYPE4:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo5(_: *mut (), _: *mut c_void, _: *mut c_void) { }
-// CHECK: define{{.*}}foo5{{.*}}!type ![[TYPE5:[0-9]+]]
-pub fn foo6(_: *const c_void) { }
-// CHECK: define{{.*}}foo6{{.*}}!type ![[TYPE6:[0-9]+]]
-pub fn foo7(_: *const c_void, _: *const ()) { }
-// CHECK: define{{.*}}foo7{{.*}}!type ![[TYPE7:[0-9]+]]
+// CHECK: define{{.*}}foo5{{.*}}!type ![[TYPE5:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo6(_: *const ()) { }
+// CHECK: define{{.*}}foo6{{.*}}!type ![[TYPE6:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo7(_: *const (), _: *const c_void) { }
+// CHECK: define{{.*}}foo7{{.*}}!type ![[TYPE7:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo8(_: *const (), _: *const c_void, _: *const c_void) { }
-// CHECK: define{{.*}}foo8{{.*}}!type ![[TYPE8:[0-9]+]]
+// CHECK: define{{.*}}foo8{{.*}}!type ![[TYPE8:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo9(_: bool) { }
-// CHECK: define{{.*}}foo9{{.*}}!type ![[TYPE9:[0-9]+]]
+// CHECK: define{{.*}}foo9{{.*}}!type ![[TYPE9:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo10(_: bool, _: bool) { }
-// CHECK: define{{.*}}foo10{{.*}}!type ![[TYPE10:[0-9]+]]
+// CHECK: define{{.*}}foo10{{.*}}!type ![[TYPE10:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo11(_: bool, _: bool, _: bool) { }
-// CHECK: define{{.*}}foo11{{.*}}!type ![[TYPE11:[0-9]+]]
+// CHECK: define{{.*}}foo11{{.*}}!type ![[TYPE11:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo12(_: i8) { }
-// CHECK: define{{.*}}foo12{{.*}}!type ![[TYPE12:[0-9]+]]
+// CHECK: define{{.*}}foo12{{.*}}!type ![[TYPE12:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo13(_: i8, _: i8) { }
-// CHECK: define{{.*}}foo13{{.*}}!type ![[TYPE13:[0-9]+]]
+// CHECK: define{{.*}}foo13{{.*}}!type ![[TYPE13:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo14(_: i8, _: i8, _: i8) { }
-// CHECK: define{{.*}}foo14{{.*}}!type ![[TYPE14:[0-9]+]]
+// CHECK: define{{.*}}foo14{{.*}}!type ![[TYPE14:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo15(_: i16) { }
-// CHECK: define{{.*}}foo15{{.*}}!type ![[TYPE15:[0-9]+]]
+// CHECK: define{{.*}}foo15{{.*}}!type ![[TYPE15:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo16(_: i16, _: i16) { }
-// CHECK: define{{.*}}foo16{{.*}}!type ![[TYPE16:[0-9]+]]
+// CHECK: define{{.*}}foo16{{.*}}!type ![[TYPE16:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo17(_: i16, _: i16, _: i16) { }
-// CHECK: define{{.*}}foo17{{.*}}!type ![[TYPE17:[0-9]+]]
+// CHECK: define{{.*}}foo17{{.*}}!type ![[TYPE17:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo18(_: i32) { }
-// CHECK: define{{.*}}foo18{{.*}}!type ![[TYPE18:[0-9]+]]
+// CHECK: define{{.*}}foo18{{.*}}!type ![[TYPE18:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo19(_: i32, _: i32) { }
-// CHECK: define{{.*}}foo19{{.*}}!type ![[TYPE19:[0-9]+]]
+// CHECK: define{{.*}}foo19{{.*}}!type ![[TYPE19:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo20(_: i32, _: i32, _: i32) { }
-// CHECK: define{{.*}}foo20{{.*}}!type ![[TYPE20:[0-9]+]]
+// CHECK: define{{.*}}foo20{{.*}}!type ![[TYPE20:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo21(_: i64) { }
-// CHECK: define{{.*}}foo21{{.*}}!type ![[TYPE21:[0-9]+]]
+// CHECK: define{{.*}}foo21{{.*}}!type ![[TYPE21:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo22(_: i64, _: i64) { }
-// CHECK: define{{.*}}foo22{{.*}}!type ![[TYPE22:[0-9]+]]
+// CHECK: define{{.*}}foo22{{.*}}!type ![[TYPE22:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo23(_: i64, _: i64, _: i64) { }
-// CHECK: define{{.*}}foo23{{.*}}!type ![[TYPE23:[0-9]+]]
+// CHECK: define{{.*}}foo23{{.*}}!type ![[TYPE23:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo24(_: i128) { }
-// CHECK: define{{.*}}foo24{{.*}}!type ![[TYPE24:[0-9]+]]
+// CHECK: define{{.*}}foo24{{.*}}!type ![[TYPE24:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo25(_: i128, _: i128) { }
-// CHECK: define{{.*}}foo25{{.*}}!type ![[TYPE25:[0-9]+]]
+// CHECK: define{{.*}}foo25{{.*}}!type ![[TYPE25:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo26(_: i128, _: i128, _: i128) { }
-// CHECK: define{{.*}}foo26{{.*}}!type ![[TYPE26:[0-9]+]]
+// CHECK: define{{.*}}foo26{{.*}}!type ![[TYPE26:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo27(_: isize) { }
-// CHECK: define{{.*}}foo27{{.*}}!type ![[TYPE27:[0-9]+]]
+// CHECK: define{{.*}}foo27{{.*}}!type ![[TYPE27:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo28(_: isize, _: isize) { }
-// CHECK: define{{.*}}foo28{{.*}}!type ![[TYPE28:[0-9]+]]
+// CHECK: define{{.*}}foo28{{.*}}!type ![[TYPE28:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo29(_: isize, _: isize, _: isize) { }
-// CHECK: define{{.*}}foo29{{.*}}!type ![[TYPE29:[0-9]+]]
+// CHECK: define{{.*}}foo29{{.*}}!type ![[TYPE29:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo30(_: u8) { }
-// CHECK: define{{.*}}foo30{{.*}}!type ![[TYPE30:[0-9]+]]
+// CHECK: define{{.*}}foo30{{.*}}!type ![[TYPE30:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo31(_: u8, _: u8) { }
-// CHECK: define{{.*}}foo31{{.*}}!type ![[TYPE31:[0-9]+]]
+// CHECK: define{{.*}}foo31{{.*}}!type ![[TYPE31:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo32(_: u8, _: u8, _: u8) { }
-// CHECK: define{{.*}}foo32{{.*}}!type ![[TYPE32:[0-9]+]]
+// CHECK: define{{.*}}foo32{{.*}}!type ![[TYPE32:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo33(_: u16) { }
-// CHECK: define{{.*}}foo33{{.*}}!type ![[TYPE33:[0-9]+]]
+// CHECK: define{{.*}}foo33{{.*}}!type ![[TYPE33:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo34(_: u16, _: u16) { }
-// CHECK: define{{.*}}foo34{{.*}}!type ![[TYPE34:[0-9]+]]
+// CHECK: define{{.*}}foo34{{.*}}!type ![[TYPE34:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo35(_: u16, _: u16, _: u16) { }
-// CHECK: define{{.*}}foo35{{.*}}!type ![[TYPE35:[0-9]+]]
+// CHECK: define{{.*}}foo35{{.*}}!type ![[TYPE35:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo36(_: u32) { }
-// CHECK: define{{.*}}foo36{{.*}}!type ![[TYPE36:[0-9]+]]
+// CHECK: define{{.*}}foo36{{.*}}!type ![[TYPE36:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo37(_: u32, _: u32) { }
-// CHECK: define{{.*}}foo37{{.*}}!type ![[TYPE37:[0-9]+]]
+// CHECK: define{{.*}}foo37{{.*}}!type ![[TYPE37:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo38(_: u32, _: u32, _: u32) { }
-// CHECK: define{{.*}}foo38{{.*}}!type ![[TYPE38:[0-9]+]]
+// CHECK: define{{.*}}foo38{{.*}}!type ![[TYPE38:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo39(_: u64) { }
-// CHECK: define{{.*}}foo39{{.*}}!type ![[TYPE39:[0-9]+]]
+// CHECK: define{{.*}}foo39{{.*}}!type ![[TYPE39:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo40(_: u64, _: u64) { }
-// CHECK: define{{.*}}foo40{{.*}}!type ![[TYPE40:[0-9]+]]
+// CHECK: define{{.*}}foo40{{.*}}!type ![[TYPE40:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo41(_: u64, _: u64, _: u64) { }
-// CHECK: define{{.*}}foo41{{.*}}!type ![[TYPE41:[0-9]+]]
+// CHECK: define{{.*}}foo41{{.*}}!type ![[TYPE41:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo42(_: u128) { }
-// CHECK: define{{.*}}foo42{{.*}}!type ![[TYPE42:[0-9]+]]
+// CHECK: define{{.*}}foo42{{.*}}!type ![[TYPE42:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo43(_: u128, _: u128) { }
-// CHECK: define{{.*}}foo43{{.*}}!type ![[TYPE43:[0-9]+]]
+// CHECK: define{{.*}}foo43{{.*}}!type ![[TYPE43:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo44(_: u128, _: u128, _: u128) { }
-// CHECK: define{{.*}}foo44{{.*}}!type ![[TYPE44:[0-9]+]]
+// CHECK: define{{.*}}foo44{{.*}}!type ![[TYPE44:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo45(_: usize) { }
-// CHECK: define{{.*}}foo45{{.*}}!type ![[TYPE45:[0-9]+]]
+// CHECK: define{{.*}}foo45{{.*}}!type ![[TYPE45:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo46(_: usize, _: usize) { }
-// CHECK: define{{.*}}foo46{{.*}}!type ![[TYPE46:[0-9]+]]
+// CHECK: define{{.*}}foo46{{.*}}!type ![[TYPE46:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo47(_: usize, _: usize, _: usize) { }
-// CHECK: define{{.*}}foo47{{.*}}!type ![[TYPE47:[0-9]+]]
+// CHECK: define{{.*}}foo47{{.*}}!type ![[TYPE47:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo48(_: f32) { }
-// CHECK: define{{.*}}foo48{{.*}}!type ![[TYPE48:[0-9]+]]
+// CHECK: define{{.*}}foo48{{.*}}!type ![[TYPE48:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo49(_: f32, _: f32) { }
-// CHECK: define{{.*}}foo49{{.*}}!type ![[TYPE49:[0-9]+]]
+// CHECK: define{{.*}}foo49{{.*}}!type ![[TYPE49:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo50(_: f32, _: f32, _: f32) { }
-// CHECK: define{{.*}}foo50{{.*}}!type ![[TYPE50:[0-9]+]]
+// CHECK: define{{.*}}foo50{{.*}}!type ![[TYPE50:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo51(_: f64) { }
-// CHECK: define{{.*}}foo51{{.*}}!type ![[TYPE51:[0-9]+]]
+// CHECK: define{{.*}}foo51{{.*}}!type ![[TYPE51:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo52(_: f64, _: f64) { }
-// CHECK: define{{.*}}foo52{{.*}}!type ![[TYPE52:[0-9]+]]
+// CHECK: define{{.*}}foo52{{.*}}!type ![[TYPE52:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo53(_: f64, _: f64, _: f64) { }
-// CHECK: define{{.*}}foo53{{.*}}!type ![[TYPE53:[0-9]+]]
+// CHECK: define{{.*}}foo53{{.*}}!type ![[TYPE53:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo54(_: char) { }
-// CHECK: define{{.*}}foo54{{.*}}!type ![[TYPE54:[0-9]+]]
+// CHECK: define{{.*}}foo54{{.*}}!type ![[TYPE54:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo55(_: char, _: char) { }
-// CHECK: define{{.*}}foo55{{.*}}!type ![[TYPE55:[0-9]+]]
+// CHECK: define{{.*}}foo55{{.*}}!type ![[TYPE55:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo56(_: char, _: char, _: char) { }
-// CHECK: define{{.*}}foo56{{.*}}!type ![[TYPE56:[0-9]+]]
+// CHECK: define{{.*}}foo56{{.*}}!type ![[TYPE56:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo57(_: &str) { }
-// CHECK: define{{.*}}foo57{{.*}}!type ![[TYPE57:[0-9]+]]
+// CHECK: define{{.*}}foo57{{.*}}!type ![[TYPE57:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo58(_: &str, _: &str) { }
-// CHECK: define{{.*}}foo58{{.*}}!type ![[TYPE58:[0-9]+]]
+// CHECK: define{{.*}}foo58{{.*}}!type ![[TYPE58:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo59(_: &str, _: &str, _: &str) { }
-// CHECK: define{{.*}}foo59{{.*}}!type ![[TYPE59:[0-9]+]]
+// CHECK: define{{.*}}foo59{{.*}}!type ![[TYPE59:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo60(_: (i32, i32)) { }
-// CHECK: define{{.*}}foo60{{.*}}!type ![[TYPE60:[0-9]+]]
+// CHECK: define{{.*}}foo60{{.*}}!type ![[TYPE60:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo61(_: (i32, i32), _: (i32, i32)) { }
-// CHECK: define{{.*}}foo61{{.*}}!type ![[TYPE61:[0-9]+]]
+// CHECK: define{{.*}}foo61{{.*}}!type ![[TYPE61:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo62(_: (i32, i32), _: (i32, i32), _: (i32, i32)) { }
-// CHECK: define{{.*}}foo62{{.*}}!type ![[TYPE62:[0-9]+]]
+// CHECK: define{{.*}}foo62{{.*}}!type ![[TYPE62:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo63(_: [i32; 32]) { }
-// CHECK: define{{.*}}foo63{{.*}}!type ![[TYPE63:[0-9]+]]
+// CHECK: define{{.*}}foo63{{.*}}!type ![[TYPE63:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo64(_: [i32; 32], _: [i32; 32]) { }
-// CHECK: define{{.*}}foo64{{.*}}!type ![[TYPE64:[0-9]+]]
+// CHECK: define{{.*}}foo64{{.*}}!type ![[TYPE64:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo65(_: [i32; 32], _: [i32; 32], _: [i32; 32]) { }
-// CHECK: define{{.*}}foo65{{.*}}!type ![[TYPE65:[0-9]+]]
+// CHECK: define{{.*}}foo65{{.*}}!type ![[TYPE65:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo66(_: &[i32]) { }
-// CHECK: define{{.*}}foo66{{.*}}!type ![[TYPE66:[0-9]+]]
+// CHECK: define{{.*}}foo66{{.*}}!type ![[TYPE66:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo67(_: &[i32], _: &[i32]) { }
-// CHECK: define{{.*}}foo67{{.*}}!type ![[TYPE67:[0-9]+]]
+// CHECK: define{{.*}}foo67{{.*}}!type ![[TYPE67:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo68(_: &[i32], _: &[i32], _: &[i32]) { }
-// CHECK: define{{.*}}foo68{{.*}}!type ![[TYPE68:[0-9]+]]
+// CHECK: define{{.*}}foo68{{.*}}!type ![[TYPE68:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo69(_: &Struct1::<i32>) { }
-// CHECK: define{{.*}}foo69{{.*}}!type ![[TYPE69:[0-9]+]]
+// CHECK: define{{.*}}foo69{{.*}}!type ![[TYPE69:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo70(_: &Struct1::<i32>, _: &Struct1::<i32>) { }
-// CHECK: define{{.*}}foo70{{.*}}!type ![[TYPE70:[0-9]+]]
+// CHECK: define{{.*}}foo70{{.*}}!type ![[TYPE70:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo71(_: &Struct1::<i32>, _: &Struct1::<i32>, _: &Struct1::<i32>) { }
-// CHECK: define{{.*}}foo71{{.*}}!type ![[TYPE71:[0-9]+]]
+// CHECK: define{{.*}}foo71{{.*}}!type ![[TYPE71:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo72(_: &Enum1::<i32>) { }
-// CHECK: define{{.*}}foo72{{.*}}!type ![[TYPE72:[0-9]+]]
+// CHECK: define{{.*}}foo72{{.*}}!type ![[TYPE72:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo73(_: &Enum1::<i32>, _: &Enum1::<i32>) { }
-// CHECK: define{{.*}}foo73{{.*}}!type ![[TYPE73:[0-9]+]]
+// CHECK: define{{.*}}foo73{{.*}}!type ![[TYPE73:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo74(_: &Enum1::<i32>, _: &Enum1::<i32>, _: &Enum1::<i32>) { }
-// CHECK: define{{.*}}foo74{{.*}}!type ![[TYPE74:[0-9]+]]
+// CHECK: define{{.*}}foo74{{.*}}!type ![[TYPE74:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo75(_: &Union1::<i32>) { }
-// CHECK: define{{.*}}foo75{{.*}}!type ![[TYPE75:[0-9]+]]
+// CHECK: define{{.*}}foo75{{.*}}!type ![[TYPE75:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo76(_: &Union1::<i32>, _: &Union1::<i32>) { }
-// CHECK: define{{.*}}foo76{{.*}}!type ![[TYPE76:[0-9]+]]
+// CHECK: define{{.*}}foo76{{.*}}!type ![[TYPE76:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo77(_: &Union1::<i32>, _: &Union1::<i32>, _: &Union1::<i32>) { }
-// CHECK: define{{.*}}foo77{{.*}}!type ![[TYPE77:[0-9]+]]
+// CHECK: define{{.*}}foo77{{.*}}!type ![[TYPE77:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo78(_: *mut type1) { }
-// CHECK: define{{.*}}foo78{{.*}}!type ![[TYPE78:[0-9]+]]
+// CHECK: define{{.*}}foo78{{.*}}!type ![[TYPE78:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo79(_: *mut type1, _: *mut type1) { }
-// CHECK: define{{.*}}foo79{{.*}}!type ![[TYPE79:[0-9]+]]
+// CHECK: define{{.*}}foo79{{.*}}!type ![[TYPE79:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo80(_: *mut type1, _: *mut type1, _: *mut type1) { }
-// CHECK: define{{.*}}foo80{{.*}}!type ![[TYPE80:[0-9]+]]
+// CHECK: define{{.*}}foo80{{.*}}!type ![[TYPE80:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo81(_: &mut i32) { }
-// CHECK: define{{.*}}foo81{{.*}}!type ![[TYPE81:[0-9]+]]
+// CHECK: define{{.*}}foo81{{.*}}!type ![[TYPE81:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo82(_: &mut i32, _: &i32) { }
-// CHECK: define{{.*}}foo82{{.*}}!type ![[TYPE82:[0-9]+]]
+// CHECK: define{{.*}}foo82{{.*}}!type ![[TYPE82:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo83(_: &mut i32, _: &i32, _: &i32) { }
-// CHECK: define{{.*}}foo83{{.*}}!type ![[TYPE83:[0-9]+]]
+// CHECK: define{{.*}}foo83{{.*}}!type ![[TYPE83:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo84(_: &i32) { }
-// CHECK: define{{.*}}foo84{{.*}}!type ![[TYPE84:[0-9]+]]
+// CHECK: define{{.*}}foo84{{.*}}!type ![[TYPE84:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo85(_: &i32, _: &mut i32) { }
-// CHECK: define{{.*}}foo85{{.*}}!type ![[TYPE85:[0-9]+]]
+// CHECK: define{{.*}}foo85{{.*}}!type ![[TYPE85:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo86(_: &i32, _: &mut i32, _: &mut i32) { }
-// CHECK: define{{.*}}foo86{{.*}}!type ![[TYPE86:[0-9]+]]
+// CHECK: define{{.*}}foo86{{.*}}!type ![[TYPE86:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo87(_: *mut i32) { }
-// CHECK: define{{.*}}foo87{{.*}}!type ![[TYPE87:[0-9]+]]
+// CHECK: define{{.*}}foo87{{.*}}!type ![[TYPE87:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo88(_: *mut i32, _: *const i32) { }
-// CHECK: define{{.*}}foo88{{.*}}!type ![[TYPE88:[0-9]+]]
+// CHECK: define{{.*}}foo88{{.*}}!type ![[TYPE88:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo89(_: *mut i32, _: *const i32, _: *const i32) { }
-// CHECK: define{{.*}}foo89{{.*}}!type ![[TYPE89:[0-9]+]]
+// CHECK: define{{.*}}foo89{{.*}}!type ![[TYPE89:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo90(_: *const i32) { }
-// CHECK: define{{.*}}foo90{{.*}}!type ![[TYPE90:[0-9]+]]
+// CHECK: define{{.*}}foo90{{.*}}!type ![[TYPE90:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo91(_: *const i32, _: *mut i32) { }
-// CHECK: define{{.*}}foo91{{.*}}!type ![[TYPE91:[0-9]+]]
+// CHECK: define{{.*}}foo91{{.*}}!type ![[TYPE91:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo92(_: *const i32, _: *mut i32, _: *mut i32) { }
-// CHECK: define{{.*}}foo92{{.*}}!type ![[TYPE92:[0-9]+]]
+// CHECK: define{{.*}}foo92{{.*}}!type ![[TYPE92:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo93(_: fn(i32) -> i32) { }
-// CHECK: define{{.*}}foo93{{.*}}!type ![[TYPE93:[0-9]+]]
+// CHECK: define{{.*}}foo93{{.*}}!type ![[TYPE93:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo94(_: fn(i32) -> i32, _: fn(i32) -> i32) { }
-// CHECK: define{{.*}}foo94{{.*}}!type ![[TYPE94:[0-9]+]]
+// CHECK: define{{.*}}foo94{{.*}}!type ![[TYPE94:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo95(_: fn(i32) -> i32, _: fn(i32) -> i32, _: fn(i32) -> i32) { }
-// CHECK: define{{.*}}foo95{{.*}}!type ![[TYPE95:[0-9]+]]
+// CHECK: define{{.*}}foo95{{.*}}!type ![[TYPE95:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo96(_: &dyn Fn(i32) -> i32) { }
-// CHECK: define{{.*}}foo96{{.*}}!type ![[TYPE96:[0-9]+]]
+// CHECK: define{{.*}}foo96{{.*}}!type ![[TYPE96:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo97(_: &dyn Fn(i32) -> i32, _: &dyn Fn(i32) -> i32) { }
-// CHECK: define{{.*}}foo97{{.*}}!type ![[TYPE97:[0-9]+]]
+// CHECK: define{{.*}}foo97{{.*}}!type ![[TYPE97:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo98(_: &dyn Fn(i32) -> i32, _: &dyn Fn(i32) -> i32, _: &dyn Fn(i32) -> i32) { }
-// CHECK: define{{.*}}foo98{{.*}}!type ![[TYPE98:[0-9]+]]
+// CHECK: define{{.*}}foo98{{.*}}!type ![[TYPE98:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo99(_: &dyn FnMut(i32) -> i32) { }
-// CHECK: define{{.*}}foo99{{.*}}!type ![[TYPE99:[0-9]+]]
+// CHECK: define{{.*}}foo99{{.*}}!type ![[TYPE99:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo100(_: &dyn FnMut(i32) -> i32, _: &dyn FnMut(i32) -> i32) { }
-// CHECK: define{{.*}}foo100{{.*}}!type ![[TYPE100:[0-9]+]]
+// CHECK: define{{.*}}foo100{{.*}}!type ![[TYPE100:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo101(_: &dyn FnMut(i32) -> i32, _: &dyn FnMut(i32) -> i32, _: &dyn FnMut(i32) -> i32) { }
-// CHECK: define{{.*}}foo101{{.*}}!type ![[TYPE101:[0-9]+]]
+// CHECK: define{{.*}}foo101{{.*}}!type ![[TYPE101:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo102(_: &dyn FnOnce(i32) -> i32) { }
-// CHECK: define{{.*}}foo102{{.*}}!type ![[TYPE102:[0-9]+]]
+// CHECK: define{{.*}}foo102{{.*}}!type ![[TYPE102:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo103(_: &dyn FnOnce(i32) -> i32, _: &dyn FnOnce(i32) -> i32) { }
-// CHECK: define{{.*}}foo103{{.*}}!type ![[TYPE103:[0-9]+]]
+// CHECK: define{{.*}}foo103{{.*}}!type ![[TYPE103:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo104(_: &dyn FnOnce(i32) -> i32, _: &dyn FnOnce(i32) -> i32, _: &dyn FnOnce(i32) -> i32) {}
-// CHECK: define{{.*}}foo104{{.*}}!type ![[TYPE104:[0-9]+]]
+// CHECK: define{{.*}}foo104{{.*}}!type ![[TYPE104:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo105(_: &dyn Send) { }
-// CHECK: define{{.*}}foo105{{.*}}!type ![[TYPE105:[0-9]+]]
+// CHECK: define{{.*}}foo105{{.*}}!type ![[TYPE105:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo106(_: &dyn Send, _: &dyn Send) { }
-// CHECK: define{{.*}}foo106{{.*}}!type ![[TYPE106:[0-9]+]]
+// CHECK: define{{.*}}foo106{{.*}}!type ![[TYPE106:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo107(_: &dyn Send, _: &dyn Send, _: &dyn Send) { }
-// CHECK: define{{.*}}foo107{{.*}}!type ![[TYPE107:[0-9]+]]
+// CHECK: define{{.*}}foo107{{.*}}!type ![[TYPE107:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo108(_: Type1) { }
-// CHECK: define{{.*}}foo108{{.*}}!type ![[TYPE108:[0-9]+]]
+// CHECK: define{{.*}}foo108{{.*}}!type ![[TYPE108:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo109(_: Type1, _: Type1) { }
-// CHECK: define{{.*}}foo109{{.*}}!type ![[TYPE109:[0-9]+]]
+// CHECK: define{{.*}}foo109{{.*}}!type ![[TYPE109:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo110(_: Type1, _: Type1, _: Type1) { }
-// CHECK: define{{.*}}foo110{{.*}}!type ![[TYPE110:[0-9]+]]
+// CHECK: define{{.*}}foo110{{.*}}!type ![[TYPE110:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo111(_: Type2) { }
-// CHECK: define{{.*}}foo111{{.*}}!type ![[TYPE111:[0-9]+]]
+// CHECK: define{{.*}}foo111{{.*}}!type ![[TYPE111:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo112(_: Type2, _: Type2) { }
-// CHECK: define{{.*}}foo112{{.*}}!type ![[TYPE112:[0-9]+]]
+// CHECK: define{{.*}}foo112{{.*}}!type ![[TYPE112:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo113(_: Type2, _: Type2, _: Type2) { }
-// CHECK: define{{.*}}foo113{{.*}}!type ![[TYPE113:[0-9]+]]
+// CHECK: define{{.*}}foo113{{.*}}!type ![[TYPE113:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo114(_: Type3) { }
-// CHECK: define{{.*}}foo114{{.*}}!type ![[TYPE114:[0-9]+]]
+// CHECK: define{{.*}}foo114{{.*}}!type ![[TYPE114:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo115(_: Type3, _: Type3) { }
-// CHECK: define{{.*}}foo115{{.*}}!type ![[TYPE115:[0-9]+]]
+// CHECK: define{{.*}}foo115{{.*}}!type ![[TYPE115:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo116(_: Type3, _: Type3, _: Type3) { }
-// CHECK: define{{.*}}foo116{{.*}}!type ![[TYPE116:[0-9]+]]
+// CHECK: define{{.*}}foo116{{.*}}!type ![[TYPE116:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo117(_: Type4) { }
-// CHECK: define{{.*}}foo117{{.*}}!type ![[TYPE117:[0-9]+]]
+// CHECK: define{{.*}}foo117{{.*}}!type ![[TYPE117:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo118(_: Type4, _: Type4) { }
-// CHECK: define{{.*}}foo118{{.*}}!type ![[TYPE118:[0-9]+]]
+// CHECK: define{{.*}}foo118{{.*}}!type ![[TYPE118:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo119(_: Type4, _: Type4, _: Type4) { }
-// CHECK: define{{.*}}foo119{{.*}}!type ![[TYPE119:[0-9]+]]
+// CHECK: define{{.*}}foo119{{.*}}!type ![[TYPE119:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo120(_: Type5) { }
-// CHECK: define{{.*}}foo120{{.*}}!type ![[TYPE120:[0-9]+]]
+// CHECK: define{{.*}}foo120{{.*}}!type ![[TYPE120:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo121(_: Type5, _: Type5) { }
-// CHECK: define{{.*}}foo121{{.*}}!type ![[TYPE121:[0-9]+]]
+// CHECK: define{{.*}}foo121{{.*}}!type ![[TYPE121:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo122(_: Type5, _: Type5, _: Type5) { }
-// CHECK: define{{.*}}foo122{{.*}}!type ![[TYPE122:[0-9]+]]
+// CHECK: define{{.*}}foo122{{.*}}!type ![[TYPE122:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo123(_: Type6) { }
-// CHECK: define{{.*}}foo123{{.*}}!type ![[TYPE123:[0-9]+]]
+// CHECK: define{{.*}}foo123{{.*}}!type ![[TYPE123:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo124(_: Type6, _: Type6) { }
-// CHECK: define{{.*}}foo124{{.*}}!type ![[TYPE124:[0-9]+]]
+// CHECK: define{{.*}}foo124{{.*}}!type ![[TYPE124:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo125(_: Type6, _: Type6, _: Type6) { }
-// CHECK: define{{.*}}foo125{{.*}}!type ![[TYPE125:[0-9]+]]
+// CHECK: define{{.*}}foo125{{.*}}!type ![[TYPE125:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo126(_: Type7) { }
-// CHECK: define{{.*}}foo126{{.*}}!type ![[TYPE126:[0-9]+]]
+// CHECK: define{{.*}}foo126{{.*}}!type ![[TYPE126:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo127(_: Type7, _: Type7) { }
-// CHECK: define{{.*}}foo127{{.*}}!type ![[TYPE127:[0-9]+]]
+// CHECK: define{{.*}}foo127{{.*}}!type ![[TYPE127:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo128(_: Type7, _: Type7, _: Type7) { }
-// CHECK: define{{.*}}foo128{{.*}}!type ![[TYPE128:[0-9]+]]
+// CHECK: define{{.*}}foo128{{.*}}!type ![[TYPE128:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo129(_: Type8) { }
-// CHECK: define{{.*}}foo129{{.*}}!type ![[TYPE129:[0-9]+]]
+// CHECK: define{{.*}}foo129{{.*}}!type ![[TYPE129:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo130(_: Type8, _: Type8) { }
-// CHECK: define{{.*}}foo130{{.*}}!type ![[TYPE130:[0-9]+]]
+// CHECK: define{{.*}}foo130{{.*}}!type ![[TYPE130:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo131(_: Type8, _: Type8, _: Type8) { }
-// CHECK: define{{.*}}foo131{{.*}}!type ![[TYPE131:[0-9]+]]
+// CHECK: define{{.*}}foo131{{.*}}!type ![[TYPE131:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo132(_: Type9) { }
-// CHECK: define{{.*}}foo132{{.*}}!type ![[TYPE132:[0-9]+]]
+// CHECK: define{{.*}}foo132{{.*}}!type ![[TYPE132:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo133(_: Type9, _: Type9) { }
-// CHECK: define{{.*}}foo133{{.*}}!type ![[TYPE133:[0-9]+]]
+// CHECK: define{{.*}}foo133{{.*}}!type ![[TYPE133:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo134(_: Type9, _: Type9, _: Type9) { }
-// CHECK: define{{.*}}foo134{{.*}}!type ![[TYPE134:[0-9]+]]
+// CHECK: define{{.*}}foo134{{.*}}!type ![[TYPE134:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo135(_: Type10) { }
-// CHECK: define{{.*}}foo135{{.*}}!type ![[TYPE135:[0-9]+]]
+// CHECK: define{{.*}}foo135{{.*}}!type ![[TYPE135:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo136(_: Type10, _: Type10) { }
-// CHECK: define{{.*}}foo136{{.*}}!type ![[TYPE136:[0-9]+]]
+// CHECK: define{{.*}}foo136{{.*}}!type ![[TYPE136:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo137(_: Type10, _: Type10, _: Type10) { }
-// CHECK: define{{.*}}foo137{{.*}}!type ![[TYPE137:[0-9]+]]
+// CHECK: define{{.*}}foo137{{.*}}!type ![[TYPE137:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo138(_: Type11) { }
-// CHECK: define{{.*}}foo138{{.*}}!type ![[TYPE138:[0-9]+]]
+// CHECK: define{{.*}}foo138{{.*}}!type ![[TYPE138:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo139(_: Type11, _: Type11) { }
-// CHECK: define{{.*}}foo139{{.*}}!type ![[TYPE139:[0-9]+]]
+// CHECK: define{{.*}}foo139{{.*}}!type ![[TYPE139:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo140(_: Type11, _: Type11, _: Type11) { }
-// CHECK: define{{.*}}foo140{{.*}}!type ![[TYPE140:[0-9]+]]
+// CHECK: define{{.*}}foo140{{.*}}!type ![[TYPE140:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo141(_: Type12) { }
-// CHECK: define{{.*}}foo141{{.*}}!type ![[TYPE141:[0-9]+]]
+// CHECK: define{{.*}}foo141{{.*}}!type ![[TYPE141:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo142(_: Type12, _: Type12) { }
-// CHECK: define{{.*}}foo142{{.*}}!type ![[TYPE142:[0-9]+]]
+// CHECK: define{{.*}}foo142{{.*}}!type ![[TYPE142:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo143(_: Type12, _: Type12, _: Type12) { }
-// CHECK: define{{.*}}foo143{{.*}}!type ![[TYPE143:[0-9]+]]
+// CHECK: define{{.*}}foo143{{.*}}!type ![[TYPE143:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo144(_: Type13) { }
-// CHECK: define{{.*}}foo144{{.*}}!type ![[TYPE144:[0-9]+]]
+// CHECK: define{{.*}}foo144{{.*}}!type ![[TYPE144:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo145(_: Type13, _: Type13) { }
-// CHECK: define{{.*}}foo145{{.*}}!type ![[TYPE145:[0-9]+]]
+// CHECK: define{{.*}}foo145{{.*}}!type ![[TYPE145:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo146(_: Type13, _: Type13, _: Type13) { }
-// CHECK: define{{.*}}foo146{{.*}}!type ![[TYPE146:[0-9]+]]
+// CHECK: define{{.*}}foo146{{.*}}!type ![[TYPE146:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo147(_: Type14<Bar>) { }
-// CHECK: define{{.*}}foo147{{.*}}!type ![[TYPE147:[0-9]+]]
+// CHECK: define{{.*}}foo147{{.*}}!type ![[TYPE147:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo148(_: Type14<Bar>, _: Type14<Bar>) { }
-// CHECK: define{{.*}}foo148{{.*}}!type ![[TYPE148:[0-9]+]]
+// CHECK: define{{.*}}foo148{{.*}}!type ![[TYPE148:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo149(_: Type14<Bar>, _: Type14<Bar>, _: Type14<Bar>) { }
-// CHECK: define{{.*}}foo149{{.*}}!type ![[TYPE149:[0-9]+]]
+// CHECK: define{{.*}}foo149{{.*}}!type ![[TYPE149:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 
 // CHECK: ![[TYPE0]] = !{i64 0, !"_ZTSFvvE"}
 // CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvvvE"}
@@ -535,15 +548,15 @@ pub fn foo149(_: Type14<Bar>, _: Type14<Bar>, _: Type14<Bar>) { }
 // CHECK: ![[TYPE93]] = !{i64 0, !"_ZTSFvPFu3i32S_EE"}
 // CHECK: ![[TYPE94]] = !{i64 0, !"_ZTSFvPFu3i32S_ES0_E"}
 // CHECK: ![[TYPE95]] = !{i64 0, !"_ZTSFvPFu3i32S_ES0_S0_E"}
-// CHECK: ![[TYPE96]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function2FnIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEEE"}
-// CHECK: ![[TYPE97]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function2FnIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEES5_E"}
-// CHECK: ![[TYPE98]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function2FnIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEES5_S5_E"}
-// CHECK: ![[TYPE99]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function5FnMutIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEEE"}
-// CHECK: ![[TYPE100]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function5FnMutIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEES5_E"}
-// CHECK: ![[TYPE101]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function5FnMutIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEES5_S5_E"}
-// CHECK: ![[TYPE102]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnceIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEEE"}
-// CHECK: ![[TYPE103]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnceIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEES5_E"}
-// CHECK: ![[TYPE104]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnceIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEES5_S5_E"}
+// CHECK: ![[TYPE96]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function2FnIu5paramEu6regionEEE"}
+// CHECK: ![[TYPE97]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function2FnIu5paramEu6regionEES3_E"}
+// CHECK: ![[TYPE98]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function2FnIu5paramEu6regionEES3_S3_E"}
+// CHECK: ![[TYPE99]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function5FnMutIu5paramEu6regionEEE"}
+// CHECK: ![[TYPE100]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function5FnMutIu5paramEu6regionEES3_E"}
+// CHECK: ![[TYPE101]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function5FnMutIu5paramEu6regionEES3_S3_E"}
+// CHECK: ![[TYPE102]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnceIu5paramEu6regionEEE"}
+// CHECK: ![[TYPE103]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnceIu5paramEu6regionEES3_E"}
+// CHECK: ![[TYPE104]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnceIu5paramEu6regionEES3_S3_E"}
 // CHECK: ![[TYPE105]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtC{{[[:print:]]+}}_4core6marker4Sendu6regionEEE"}
 // CHECK: ![[TYPE106]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtC{{[[:print:]]+}}_4core6marker4Sendu6regionEES2_E"}
 // CHECK: ![[TYPE107]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtC{{[[:print:]]+}}_4core6marker4Sendu6regionEES2_S2_E"}
@@ -565,9 +578,9 @@ pub fn foo149(_: Type14<Bar>, _: Type14<Bar>, _: Type14<Bar>) { }
 // CHECK: ![[TYPE123]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3fn18{{[{}][{}]}}impl{{[}][}]}}3fooIu3i32EE"}
 // CHECK: ![[TYPE124]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3fn18{{[{}][{}]}}impl{{[}][}]}}3fooIu3i32ES0_E"}
 // CHECK: ![[TYPE125]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3fn18{{[{}][{}]}}impl{{[}][}]}}3fooIu3i32ES0_S0_E"}
-// CHECK: ![[TYPE126]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait1Iu3i32Eu6regionES_EE"}
-// CHECK: ![[TYPE127]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait1Iu3i32Eu6regionES_ES3_E"}
-// CHECK: ![[TYPE128]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait1Iu3i32Eu6regionES_ES3_S3_E"}
+// CHECK: ![[TYPE126]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait1Iu5paramEu6regionEu3i32EE"}
+// CHECK: ![[TYPE127]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait1Iu5paramEu6regionEu3i32ES4_E"}
+// CHECK: ![[TYPE128]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait1Iu5paramEu6regionEu3i32ES4_S4_E"}
 // CHECK: ![[TYPE129]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3i32S_EE"}
 // CHECK: ![[TYPE130]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3i32S_ES0_E"}
 // CHECK: ![[TYPE131]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3i32S_ES0_S0_E"}
@@ -586,6 +599,6 @@ pub fn foo149(_: Type14<Bar>, _: Type14<Bar>, _: Type14<Bar>) { }
 // CHECK: ![[TYPE144]] = !{i64 0, !"_ZTSFvu3refIvEE"}
 // CHECK: ![[TYPE145]] = !{i64 0, !"_ZTSFvu3refIvES_E"}
 // CHECK: ![[TYPE146]] = !{i64 0, !"_ZTSFvu3refIvES_S_E"}
-// CHECK: ![[TYPE147]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3BarE
-// CHECK: ![[TYPE148]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3BarS_E
-// CHECK: ![[TYPE149]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3BarS_S_E
+// CHECK: ![[TYPE147]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3BarE"}
+// CHECK: ![[TYPE148]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3BarS_E"}
+// CHECK: ![[TYPE149]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3BarS_S_E"}
diff --git a/tests/codegen/sanitizer-cfi-emit-type-metadata-itanium-cxx-abi-generalized.rs b/tests/codegen/sanitizer-cfi-emit-type-metadata-itanium-cxx-abi-generalized.rs
new file mode 100644
index 00000000000..d200ed9798a
--- /dev/null
+++ b/tests/codegen/sanitizer-cfi-emit-type-metadata-itanium-cxx-abi-generalized.rs
@@ -0,0 +1,31 @@
+// Verifies that generalized type metadata for functions are emitted.
+//
+// needs-sanitizer-cfi
+// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-generalize-pointers
+
+#![crate_type="lib"]
+
+pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
+    // CHECK-LABEL: define{{.*}}foo
+    // CHECK-SAME:  {{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test(ptr {{%f|%0}}, metadata !"_ZTSFu3i32S_E.generalized")
+    f(arg)
+}
+
+pub fn bar(f: fn(i32, i32) -> i32, arg1: i32, arg2: i32) -> i32 {
+    // CHECK-LABEL: define{{.*}}bar
+    // CHECK-SAME:  {{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test(ptr {{%f|%0}}, metadata !"_ZTSFu3i32S_S_E.generalized")
+    f(arg1, arg2)
+}
+
+pub fn baz(f: fn(i32, i32, i32) -> i32, arg1: i32, arg2: i32, arg3: i32) -> i32 {
+    // CHECK-LABEL: define{{.*}}baz
+    // CHECK-SAME:  {{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test(ptr {{%f|%0}}, metadata !"_ZTSFu3i32S_S_S_E.generalized")
+    f(arg1, arg2, arg3)
+}
+
+// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFu3i32PKvS_E.generalized"}
+// CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFu3i32PKvS_S_E.generalized"}
+// CHECK: ![[TYPE3]] = !{i64 0, !"_ZTSFu3i32PKvS_S_S_E.generalized"}
diff --git a/tests/codegen/sanitizer-cfi-emit-type-metadata-itanium-cxx-abi-normalized-generalized.rs b/tests/codegen/sanitizer-cfi-emit-type-metadata-itanium-cxx-abi-normalized-generalized.rs
new file mode 100644
index 00000000000..cdefec17a1c
--- /dev/null
+++ b/tests/codegen/sanitizer-cfi-emit-type-metadata-itanium-cxx-abi-normalized-generalized.rs
@@ -0,0 +1,31 @@
+// Verifies that normalized and generalized type metadata for functions are emitted.
+//
+// needs-sanitizer-cfi
+// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-normalize-integers -Zsanitizer-cfi-generalize-pointers
+
+#![crate_type="lib"]
+
+pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
+    // CHECK-LABEL: define{{.*}}foo
+    // CHECK-SAME:  {{.*}}![[TYPE1:[0-9]+]]
+    // CHECK:       call i1 @llvm.type.test(ptr {{%f|%0}}, metadata !"_ZTSFu3i32S_E.normalized.generalized")
+    f(arg)
+}
+
+pub fn bar(f: fn(i32, i32) -> i32, arg1: i32, arg2: i32) -> i32 {
+    // CHECK-LABEL: define{{.*}}bar
+    // CHECK-SAME:  {{.*}}![[TYPE2:[0-9]+]]
+    // CHECK:       call i1 @llvm.type.test(ptr {{%f|%0}}, metadata !"_ZTSFu3i32S_S_E.normalized.generalized")
+    f(arg1, arg2)
+}
+
+pub fn baz(f: fn(i32, i32, i32) -> i32, arg1: i32, arg2: i32, arg3: i32) -> i32 {
+    // CHECK-LABEL: define{{.*}}baz
+    // CHECK-SAME:  {{.*}}![[TYPE3:[0-9]+]]
+    // CHECK:       call i1 @llvm.type.test(ptr {{%f|%0}}, metadata !"_ZTSFu3i32S_S_S_E.normalized.generalized")
+    f(arg1, arg2, arg3)
+}
+
+// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFu3i32PKvS_E.normalized.generalized"}
+// CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFu3i32PKvS_S_E.normalized.generalized"}
+// CHECK: ![[TYPE3]] = !{i64 0, !"_ZTSFu3i32PKvS_S_S_E.normalized.generalized"}
diff --git a/tests/codegen/sanitizer-cfi-emit-type-metadata-itanium-cxx-abi-normalized.rs b/tests/codegen/sanitizer-cfi-emit-type-metadata-itanium-cxx-abi-normalized.rs
new file mode 100644
index 00000000000..f360b33ddcf
--- /dev/null
+++ b/tests/codegen/sanitizer-cfi-emit-type-metadata-itanium-cxx-abi-normalized.rs
@@ -0,0 +1,31 @@
+// Verifies that normalized type metadata for functions are emitted.
+//
+// needs-sanitizer-cfi
+// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-normalize-integers
+
+#![crate_type="lib"]
+
+pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
+    // CHECK-LABEL: define{{.*}}foo
+    // CHECK-SAME:  {{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test(ptr {{%f|%0}}, metadata !"_ZTSFu3i32S_E.normalized")
+    f(arg)
+}
+
+pub fn bar(f: fn(i32, i32) -> i32, arg1: i32, arg2: i32) -> i32 {
+    // CHECK-LABEL: define{{.*}}bar
+    // CHECK-SAME:  {{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test(ptr {{%f|%0}}, metadata !"_ZTSFu3i32S_S_E.normalized")
+    f(arg1, arg2)
+}
+
+pub fn baz(f: fn(i32, i32, i32) -> i32, arg1: i32, arg2: i32, arg3: i32) -> i32 {
+    // CHECK-LABEL: define{{.*}}baz
+    // CHECK-SAME:  {{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test(ptr {{%f|%0}}, metadata !"_ZTSFu3i32S_S_S_E.normalized")
+    f(arg1, arg2, arg3)
+}
+
+// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFu3i32PFS_S_ES_E.normalized"}
+// CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFu3i32PFS_S_S_ES_S_E.normalized"}
+// CHECK: ![[TYPE3]] = !{i64 0, !"_ZTSFu3i32PFS_S_S_S_ES_S_S_E.normalized"}
diff --git a/tests/codegen/sanitizer-cfi-emit-type-metadata-itanium-cxx-abi.rs b/tests/codegen/sanitizer-cfi-emit-type-metadata-itanium-cxx-abi.rs
index bafc4c6592f..3cb817b212d 100644
--- a/tests/codegen/sanitizer-cfi-emit-type-metadata-itanium-cxx-abi.rs
+++ b/tests/codegen/sanitizer-cfi-emit-type-metadata-itanium-cxx-abi.rs
@@ -7,22 +7,22 @@
 
 pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
     // CHECK-LABEL: define{{.*}}foo
-    // CHECK-SAME: {{.*}}!type ![[TYPE1:[0-9]+]]
-    // CHECK:       call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0}}, metadata !"_ZTSFu3i32S_E")
+    // CHECK-SAME:  {{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test(ptr {{%f|%0}}, metadata !"_ZTSFu3i32S_E")
     f(arg)
 }
 
 pub fn bar(f: fn(i32, i32) -> i32, arg1: i32, arg2: i32) -> i32 {
     // CHECK-LABEL: define{{.*}}bar
-    // CHECK-SAME: {{.*}}!type ![[TYPE2:[0-9]+]]
-    // CHECK:       call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0}}, metadata !"_ZTSFu3i32S_S_E")
+    // CHECK-SAME:  {{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test(ptr {{%f|%0}}, metadata !"_ZTSFu3i32S_S_E")
     f(arg1, arg2)
 }
 
 pub fn baz(f: fn(i32, i32, i32) -> i32, arg1: i32, arg2: i32, arg3: i32) -> i32 {
     // CHECK-LABEL: define{{.*}}baz
-    // CHECK-SAME: {{.*}}!type ![[TYPE3:[0-9]+]]
-    // CHECK:       call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0}}, metadata !"_ZTSFu3i32S_S_S_E")
+    // CHECK-SAME:  {{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test(ptr {{%f|%0}}, metadata !"_ZTSFu3i32S_S_S_E")
     f(arg1, arg2, arg3)
 }
 
diff --git a/tests/codegen/sanitizer-cfi-emit-type-metadata-trait-objects.rs b/tests/codegen/sanitizer-cfi-emit-type-metadata-trait-objects.rs
new file mode 100644
index 00000000000..b69e57261a8
--- /dev/null
+++ b/tests/codegen/sanitizer-cfi-emit-type-metadata-trait-objects.rs
@@ -0,0 +1,149 @@
+// Verifies that type metadata identifiers for trait objects are emitted correctly.
+//
+// needs-sanitizer-cfi
+// compile-flags: -Clto -Cno-prepopulate-passes -Copt-level=0 -Ctarget-feature=-crt-static -Zsanitizer=cfi
+
+#![crate_type="lib"]
+
+pub trait Trait1 {
+    fn foo(&self);
+}
+
+#[derive(Clone, Copy)]
+pub struct Type1;
+
+impl Trait1 for Type1 {
+    fn foo(&self) {
+    }
+}
+
+pub trait Trait2<T> {
+    fn bar(&self);
+}
+
+pub struct Type2;
+
+impl Trait2<i32> for Type2 {
+    fn bar(&self) {
+    }
+}
+
+pub trait Trait3<T> {
+    fn baz(&self, _: &T);
+}
+
+pub struct Type3;
+
+impl<T, U> Trait3<U> for T {
+    fn baz(&self, _: &U) {
+    }
+}
+
+pub trait Trait4<'a, T> {
+    type Output: 'a;
+    fn qux(&self, _: &T) -> Self::Output;
+}
+
+pub struct Type4;
+
+impl<'a, T, U> Trait4<'a, U> for T {
+    type Output = &'a i32;
+    fn qux(&self, _: &U) -> Self::Output {
+        &0
+    }
+}
+
+pub trait Trait5<T, const N: usize> {
+    fn quux(&self, _: &[T; N]);
+}
+
+#[derive(Copy, Clone)]
+pub struct Type5;
+
+impl<T, U, const N: usize> Trait5<U, N> for T {
+    fn quux(&self, _: &[U; N]) {
+    }
+}
+
+pub fn foo1(a: &dyn Trait1) {
+    a.foo();
+    // CHECK-LABEL: define{{.*}}4foo1{{.*}}!type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE1:[[:print:]]+]]")
+}
+
+pub fn bar1() {
+    let a = Type1;
+    let b = &a as &dyn Trait1;
+    b.foo();
+    // CHECK-LABEL: define{{.*}}4bar1{{.*}}!type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE2:[[:print:]]+]]")
+}
+
+pub fn foo2<T>(a: &dyn Trait2<T>) {
+    a.bar();
+    // CHECK-LABEL: define{{.*}}4foo2{{.*}}!type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE2:[[:print:]]+]]")
+}
+
+pub fn bar2() {
+    let a = Type2;
+    foo2(&a);
+    let b = &a as &dyn Trait2<i32>;
+    b.bar();
+    // CHECK-LABEL: define{{.*}}4bar2{{.*}}!type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE2:[[:print:]]+]]")
+}
+
+pub fn foo3(a: &dyn Trait3<Type3>) {
+    let b = Type3;
+    a.baz(&b);
+    // CHECK-LABEL: define{{.*}}4foo3{{.*}}!type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE3:[[:print:]]+]]")
+}
+
+pub fn bar3() {
+    let a = Type3;
+    foo3(&a);
+    let b = &a as &dyn Trait3<Type3>;
+    b.baz(&a);
+    // CHECK-LABEL: define{{.*}}4bar3{{.*}}!type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE3:[[:print:]]+]]")
+}
+
+pub fn foo4<'a>(a: &dyn Trait4<'a, Type4, Output = &'a i32>) {
+    let b = Type4;
+    a.qux(&b);
+    // CHECK-LABEL: define{{.*}}4foo4{{.*}}!type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE4:[[:print:]]+]]")
+}
+
+pub fn bar4<'a>() {
+    let a = Type4;
+    foo4(&a);
+    let b = &a as &dyn Trait4<'a, Type4, Output = &'a i32>;
+    b.qux(&a);
+    // CHECK-LABEL: define{{.*}}4bar4{{.*}}!type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE4:[[:print:]]+]]")
+}
+
+pub fn foo5(a: &dyn Trait5<Type5, 32>) {
+    let b = &[Type5; 32];
+    a.quux(&b);
+    // CHECK-LABEL: define{{.*}}4foo5{{.*}}!type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE5:[[:print:]]+]]")
+}
+
+pub fn bar5() {
+    let a = &[Type5; 32];
+    foo5(&a);
+    let b = &a as &dyn Trait5<Type5, 32>;
+    b.quux(&a);
+    // CHECK-LABEL: define{{.*}}4bar5{{.*}}!type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE5:[[:print:]]+]]")
+}
+
+// CHECK: !{{[0-9]+}} = !{i64 0, !"[[TYPE1]]"}
+// CHECK: !{{[0-9]+}} = !{i64 0, !"[[TYPE2]]"}
+// CHECK: !{{[0-9]+}} = !{i64 0, !"[[TYPE3]]"}
+// CHECK: !{{[0-9]+}} = !{i64 0, !"[[TYPE4]]"}
+// CHECK: !{{[0-9]+}} = !{i64 0, !"[[TYPE5]]"}
diff --git a/tests/codegen/sanitizer-cfi-generalize-pointers.rs b/tests/codegen/sanitizer-cfi-generalize-pointers.rs
new file mode 100644
index 00000000000..677ebdb27ec
--- /dev/null
+++ b/tests/codegen/sanitizer-cfi-generalize-pointers.rs
@@ -0,0 +1,46 @@
+// Verifies that pointer types are generalized.
+//
+// needs-sanitizer-cfi
+// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-generalize-pointers
+
+#![crate_type="lib"]
+
+extern crate core;
+
+pub fn foo0(_: &mut i32) { }
+// CHECK: define{{.*}}foo0{{.*}}!type ![[TYPE0:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo1(_: &mut i32, _: &mut i32) { }
+// CHECK: define{{.*}}foo1{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo2(_: &mut i32, _: &mut i32, _: &mut i32) { }
+// CHECK: define{{.*}}foo2{{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo3(_: &i32) { }
+// CHECK: define{{.*}}foo3{{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo4(_: &i32, _: &i32) { }
+// CHECK: define{{.*}}foo4{{.*}}!type ![[TYPE4:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo5(_: &i32, _: &i32, _: &i32) { }
+// CHECK: define{{.*}}foo5{{.*}}!type ![[TYPE5:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo6(_: *mut i32) { }
+// CHECK: define{{.*}}foo6{{.*}}!type ![[TYPE6:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo7(_: *mut i32, _: *mut i32) { }
+// CHECK: define{{.*}}foo7{{.*}}!type ![[TYPE7:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo8(_: *mut i32, _: *mut i32, _: *mut i32) { }
+// CHECK: define{{.*}}foo8{{.*}}!type ![[TYPE8:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo9(_: *const i32) { }
+// CHECK: define{{.*}}foo9{{.*}}!type ![[TYPE9:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo10(_: *const i32, _: *const i32) { }
+// CHECK: define{{.*}}foo10{{.*}}!type ![[TYPE10:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo11(_: *const i32, _: *const i32, _: *const i32) { }
+// CHECK: define{{.*}}foo11{{.*}}!type ![[TYPE11:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}}
+
+// CHECK: ![[TYPE0]] = !{i64 0, !"_ZTSFvU3mutu3refIvEE.generalized"}
+// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvU3mutu3refIvES0_E.generalized"}
+// CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFvU3mutu3refIvES0_S0_E.generalized"}
+// CHECK: ![[TYPE3]] = !{i64 0, !"_ZTSFvu3refIvEE.generalized"}
+// CHECK: ![[TYPE4]] = !{i64 0, !"_ZTSFvu3refIvES_E.generalized"}
+// CHECK: ![[TYPE5]] = !{i64 0, !"_ZTSFvu3refIvES_S_E.generalized"}
+// CHECK: ![[TYPE6]] = !{i64 0, !"_ZTSFvPvE.generalized"}
+// CHECK: ![[TYPE7]] = !{i64 0, !"_ZTSFvPvS_E.generalized"}
+// CHECK: ![[TYPE8]] = !{i64 0, !"_ZTSFvPvS_S_E.generalized"}
+// CHECK: ![[TYPE9]] = !{i64 0, !"_ZTSFvPKvE.generalized"}
+// CHECK: ![[TYPE10]] = !{i64 0, !"_ZTSFvPKvS0_E.generalized"}
+// CHECK: ![[TYPE11]] = !{i64 0, !"_ZTSFvPKvS0_S0_E.generalized"}
diff --git a/tests/codegen/sanitizer-cfi-normalize-integers.rs b/tests/codegen/sanitizer-cfi-normalize-integers.rs
new file mode 100644
index 00000000000..aa3913cb8e7
--- /dev/null
+++ b/tests/codegen/sanitizer-cfi-normalize-integers.rs
@@ -0,0 +1,83 @@
+// Verifies that integer types are normalized.
+//
+// needs-sanitizer-cfi
+// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-normalize-integers
+
+#![crate_type="lib"]
+
+extern crate core;
+use core::ffi::*;
+
+pub fn foo0(_: bool) { }
+// CHECK: define{{.*}}foo0{{.*}}!type ![[TYPE0:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo1(_: bool, _: c_uchar) { }
+// CHECK: define{{.*}}foo1{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo2(_: bool, _: c_uchar, _: c_uchar) { }
+// CHECK: define{{.*}}foo2{{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo3(_: isize) { }
+// CHECK: define{{.*}}foo3{{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo4(_: isize, _: c_long) { }
+// CHECK: define{{.*}}foo4{{.*}}!type ![[TYPE4:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo5(_: isize, _: c_long, _: c_longlong) { }
+// CHECK: define{{.*}}foo5{{.*}}!type ![[TYPE5:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo6(_: usize) { }
+// CHECK: define{{.*}}foo6{{.*}}!type ![[TYPE6:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo7(_: usize, _: c_ulong) { }
+// CHECK: define{{.*}}foo7{{.*}}!type ![[TYPE7:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo8(_: usize, _: c_ulong, _: c_ulonglong) { }
+// CHECK: define{{.*}}foo8{{.*}}!type ![[TYPE8:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo9(_: c_schar) { }
+// CHECK: define{{.*}}foo9{{.*}}!type ![[TYPE9:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo10(_: c_char, _: c_schar) { }
+// CHECK: define{{.*}}foo10{{.*}}!type ![[TYPE10:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo11(_: c_char, _: c_schar, _: c_schar) { }
+// CHECK: define{{.*}}foo11{{.*}}!type ![[TYPE11:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo12(_: c_int) { }
+// CHECK: define{{.*}}foo12{{.*}}!type ![[TYPE12:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo13(_: c_int, _: c_int) { }
+// CHECK: define{{.*}}foo13{{.*}}!type ![[TYPE13:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo14(_: c_int, _: c_int, _: c_int) { }
+// CHECK: define{{.*}}foo14{{.*}}!type ![[TYPE14:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo15(_: c_short) { }
+// CHECK: define{{.*}}foo15{{.*}}!type ![[TYPE15:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo16(_: c_short, _: c_short) { }
+// CHECK: define{{.*}}foo16{{.*}}!type ![[TYPE16:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo17(_: c_short, _: c_short, _: c_short) { }
+// CHECK: define{{.*}}foo17{{.*}}!type ![[TYPE17:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo18(_: c_uint) { }
+// CHECK: define{{.*}}foo18{{.*}}!type ![[TYPE18:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo19(_: c_uint, _: c_uint) { }
+// CHECK: define{{.*}}foo19{{.*}}!type ![[TYPE19:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo20(_: c_uint, _: c_uint, _: c_uint) { }
+// CHECK: define{{.*}}foo20{{.*}}!type ![[TYPE20:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo21(_: c_ushort) { }
+// CHECK: define{{.*}}foo21{{.*}}!type ![[TYPE21:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo22(_: c_ushort, _: c_ushort) { }
+// CHECK: define{{.*}}foo22{{.*}}!type ![[TYPE22:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo23(_: c_ushort, _: c_ushort, _: c_ushort) { }
+// CHECK: define{{.*}}foo23{{.*}}!type ![[TYPE23:[0-9]+]] !type !{{[0-9]+}}
+
+// CHECK: ![[TYPE0]] = !{i64 0, !"_ZTSFvu2u8E.normalized"}
+// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvu2u8S_E.normalized"}
+// CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFvu2u8S_S_E.normalized"}
+// CHECK: ![[TYPE3]] = !{i64 0, !"_ZTSFv{{u3i16|u3i32|u3i64}}E.normalized"}
+// CHECK: ![[TYPE4]] = !{i64 0, !"_ZTSFv{{u3i16|u3i32|u3i64}}{{u3i32|u3i64|S_}}E.normalized"}
+// CHECK: ![[TYPE5]] = !{i64 0, !"_ZTSFv{{u3i16|u3i32|u3i64}}{{u3i32|u3i64|S_}}{{u3i64|S_|S0_}}E.normalized"}
+// CHECK: ![[TYPE6]] = !{i64 0, !"_ZTSFv{{u3u16|u3u32|u3u64}}E.normalized"}
+// CHECK: ![[TYPE7]] = !{i64 0, !"_ZTSFv{{u3u16|u3u32|u3u64}}{{u3u32|u3u64|S_}}E.normalized"}
+// CHECK: ![[TYPE8]] = !{i64 0, !"_ZTSFv{{u3u16|u3u32|u3u64}}{{u3u32|u3u64|S_}}{{u3u64|S_|S0_}}E.normalized"}
+// CHECK: ![[TYPE9]] = !{i64 0, !"_ZTSFvu2i8E.normalized"}
+// CHECK: ![[TYPE10]] = !{i64 0, !"_ZTSFv{{u2i8S_|u2u8u2i8}}E.normalized"}
+// CHECK: ![[TYPE11]] = !{i64 0, !"_ZTSFv{{u2i8S_S_|u2u8u2i8S0_}}E.normalized"}
+// CHECK: ![[TYPE12]] = !{i64 0, !"_ZTSFv{{u3i16|u3i32|u3i64}}E.normalized"}
+// CHECK: ![[TYPE13]] = !{i64 0, !"_ZTSFv{{u3i16|u3i32|u3i64}}S_E.normalized"}
+// CHECK: ![[TYPE14]] = !{i64 0, !"_ZTSFv{{u3i16|u3i32|u3i64}}S_S_E.normalized"}
+// CHECK: ![[TYPE15]] = !{i64 0, !"_ZTSFvu3i16E.normalized"}
+// CHECK: ![[TYPE16]] = !{i64 0, !"_ZTSFvu3i16S_E.normalized"}
+// CHECK: ![[TYPE17]] = !{i64 0, !"_ZTSFvu3i16S_S_E.normalized"}
+// CHECK: ![[TYPE18]] = !{i64 0, !"_ZTSFv{{u3u16|u3u32|u3u64}}E.normalized"}
+// CHECK: ![[TYPE19]] = !{i64 0, !"_ZTSFv{{u3u16|u3u32|u3u64}}S_E.normalized"}
+// CHECK: ![[TYPE20]] = !{i64 0, !"_ZTSFv{{u3u16|u3u32|u3u64}}S_S_E.normalized"}
+// CHECK: ![[TYPE21]] = !{i64 0, !"_ZTSFvu3u16E.normalized"}
+// CHECK: ![[TYPE22]] = !{i64 0, !"_ZTSFvu3u16S_E.normalized"}
+// CHECK: ![[TYPE23]] = !{i64 0, !"_ZTSFvu3u16S_S_E.normalized"}
diff --git a/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-attr-no-sanitize.rs b/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-attr-no-sanitize.rs
new file mode 100644
index 00000000000..bb317e4a2fa
--- /dev/null
+++ b/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-attr-no-sanitize.rs
@@ -0,0 +1,30 @@
+// Verifies that KCFI operand bundles are omitted.
+//
+// revisions: aarch64 x86_64
+// [aarch64] compile-flags: --target aarch64-unknown-none
+// [aarch64] needs-llvm-components: aarch64
+// [x86_64] compile-flags: --target x86_64-unknown-none
+// [x86_64] needs-llvm-components:
+// compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi -Copt-level=0
+
+#![crate_type="lib"]
+#![feature(no_core, no_sanitize, lang_items)]
+#![no_core]
+
+#[lang="sized"]
+trait Sized { }
+#[lang="copy"]
+trait Copy { }
+
+impl Copy for i32 {}
+
+#[no_sanitize(kcfi)]
+pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
+    // CHECK-LABEL: sanitizer_kcfi_emit_kcfi_operand_bundle_attr_no_sanitize::foo
+    // CHECK:       Function Attrs: {{.*}}
+    // CHECK-LABEL: define{{.*}}foo{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+    // CHECK:       start:
+    // CHECK-NOT:   {{%.+}} = call {{(noundef )*}}i32 %f(i32 {{(noundef )*}}%arg){{.*}}[ "kcfi"(i32 {{[-0-9]+}}) ]
+    // CHECK:       ret i32 {{%.+}}
+    f(arg)
+}
diff --git a/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi-generalized.rs b/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi-generalized.rs
new file mode 100644
index 00000000000..29e4df3511f
--- /dev/null
+++ b/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi-generalized.rs
@@ -0,0 +1,44 @@
+// Verifies that generalized KCFI type metadata for functions are emitted.
+//
+// revisions: aarch64 x86_64
+// [aarch64] compile-flags: --target aarch64-unknown-none
+// [aarch64] needs-llvm-components: aarch64
+// [x86_64] compile-flags: --target x86_64-unknown-none
+// [x86_64] needs-llvm-components:
+// compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi -Zsanitizer-cfi-generalize-pointers
+
+#![crate_type="lib"]
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang="sized"]
+trait Sized { }
+#[lang="copy"]
+trait Copy { }
+
+impl Copy for i32 {}
+
+pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
+    // CHECK-LABEL: define{{.*}}foo
+    // CHECK-SAME:  {{.*}}!{{<unknown kind #36>|kcfi_type}} ![[TYPE1:[0-9]+]]
+    // CHECK:       {{%.+}} = call {{(noundef )*}}i32 %f(i32 {{(noundef )*}}%arg){{.*}}[ "kcfi"(i32 233085384) ]
+    f(arg)
+}
+
+pub fn bar(f: fn(i32, i32) -> i32, arg1: i32, arg2: i32) -> i32 {
+    // CHECK-LABEL: define{{.*}}bar
+    // CHECK-SAME:  {{.*}}!{{<unknown kind #36>|kcfi_type}} ![[TYPE2:[0-9]+]]
+    // CHECK:       {{%.+}} = call {{(noundef )*}}i32 %f(i32 {{(noundef )*}}%arg1, i32 {{(noundef )*}}%arg2){{.*}}[ "kcfi"(i32 435418021) ]
+    f(arg1, arg2)
+}
+
+pub fn baz(f: fn(i32, i32, i32) -> i32, arg1: i32, arg2: i32, arg3: i32) -> i32 {
+    // CHECK-LABEL: define{{.*}}baz
+    // CHECK-SAME:  {{.*}}!{{<unknown kind #36>|kcfi_type}} ![[TYPE3:[0-9]+]]
+    // CHECK:       {{%.+}} = call {{(noundef )*}}i32 %f(i32 {{(noundef )*}}%arg1, i32 {{(noundef )*}}%arg2, i32 {{(noundef )*}}%arg3){{.*}}[ "kcfi"(i32 -1003721339) ]
+    f(arg1, arg2, arg3)
+}
+
+// CHECK: ![[TYPE1]] = !{i32 -1741689296}
+// CHECK: ![[TYPE2]] = !{i32 489439372}
+// CHECK: ![[TYPE3]] = !{i32 2026563871}
diff --git a/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi-normalized-generalized.rs b/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi-normalized-generalized.rs
new file mode 100644
index 00000000000..84d678a33ba
--- /dev/null
+++ b/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi-normalized-generalized.rs
@@ -0,0 +1,44 @@
+// Verifies that normalized and generalized KCFI type metadata for functions are emitted.
+//
+// revisions: aarch64 x86_64
+// [aarch64] compile-flags: --target aarch64-unknown-none
+// [aarch64] needs-llvm-components: aarch64
+// [x86_64] compile-flags: --target x86_64-unknown-none
+// [x86_64] needs-llvm-components:
+// compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi -Zsanitizer-cfi-normalize-integers -Zsanitizer-cfi-generalize-pointers
+
+#![crate_type="lib"]
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang="sized"]
+trait Sized { }
+#[lang="copy"]
+trait Copy { }
+
+impl Copy for i32 {}
+
+pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
+    // CHECK-LABEL: define{{.*}}foo
+    // CHECK-SAME:  {{.*}}!{{<unknown kind #36>|kcfi_type}} ![[TYPE1:[0-9]+]]
+    // CHECK:       {{%.+}} = call {{(noundef )*}}i32 %f(i32 {{(noundef )*}}%arg){{.*}}[ "kcfi"(i32 -686570305) ]
+    f(arg)
+}
+
+pub fn bar(f: fn(i32, i32) -> i32, arg1: i32, arg2: i32) -> i32 {
+    // CHECK-LABEL: define{{.*}}bar
+    // CHECK-SAME:  {{.*}}!{{<unknown kind #36>|kcfi_type}} ![[TYPE2:[0-9]+]]
+    // CHECK:       {{%.+}} = call {{(noundef )*}}i32 %f(i32 {{(noundef )*}}%arg1, i32 {{(noundef )*}}%arg2){{.*}}[ "kcfi"(i32 1281038450) ]
+    f(arg1, arg2)
+}
+
+pub fn baz(f: fn(i32, i32, i32) -> i32, arg1: i32, arg2: i32, arg3: i32) -> i32 {
+    // CHECK-LABEL: define{{.*}}baz
+    // CHECK-SAME:  {{.*}}!{{<unknown kind #36>|kcfi_type}} ![[TYPE3:[0-9]+]]
+    // CHECK:       {{%.+}} = call {{(noundef )*}}i32 %f(i32 {{(noundef )*}}%arg1, i32 {{(noundef )*}}%arg2, i32 {{(noundef )*}}%arg3){{.*}}[ "kcfi"(i32 -1751512973) ]
+    f(arg1, arg2, arg3)
+}
+
+// CHECK: ![[TYPE1]] = !{i32 975484707}
+// CHECK: ![[TYPE2]] = !{i32 1658833102}
+// CHECK: ![[TYPE3]] = !{i32 230429758}
diff --git a/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi-normalized.rs b/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi-normalized.rs
new file mode 100644
index 00000000000..761c37a9e06
--- /dev/null
+++ b/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi-normalized.rs
@@ -0,0 +1,44 @@
+// Verifies that normalized KCFI type metadata for functions are emitted.
+//
+// revisions: aarch64 x86_64
+// [aarch64] compile-flags: --target aarch64-unknown-none
+// [aarch64] needs-llvm-components: aarch64
+// [x86_64] compile-flags: --target x86_64-unknown-none
+// [x86_64] needs-llvm-components:
+// compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi -Zsanitizer-cfi-normalize-integers
+
+#![crate_type="lib"]
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang="sized"]
+trait Sized { }
+#[lang="copy"]
+trait Copy { }
+
+impl Copy for i32 {}
+
+pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
+    // CHECK-LABEL: define{{.*}}foo
+    // CHECK-SAME:  {{.*}}!{{<unknown kind #36>|kcfi_type}} ![[TYPE1:[0-9]+]]
+    // CHECK:       {{%.+}} = call {{(noundef )*}}i32 %f(i32 {{(noundef )*}}%arg){{.*}}[ "kcfi"(i32 -841055669) ]
+    f(arg)
+}
+
+pub fn bar(f: fn(i32, i32) -> i32, arg1: i32, arg2: i32) -> i32 {
+    // CHECK-LABEL: define{{.*}}bar
+    // CHECK-SAME:  {{.*}}!{{<unknown kind #36>|kcfi_type}} ![[TYPE2:[0-9]+]]
+    // CHECK:       {{%.+}} = call {{(noundef )*}}i32 %f(i32 {{(noundef )*}}%arg1, i32 {{(noundef )*}}%arg2){{.*}}[ "kcfi"(i32 1390819368) ]
+    f(arg1, arg2)
+}
+
+pub fn baz(f: fn(i32, i32, i32) -> i32, arg1: i32, arg2: i32, arg3: i32) -> i32 {
+    // CHECK-LABEL: define{{.*}}baz
+    // CHECK-SAME:  {{.*}}!{{<unknown kind #36>|kcfi_type}} ![[TYPE3:[0-9]+]]
+    // CHECK:       {{%.+}} = call {{(noundef )*}}i32 %f(i32 {{(noundef )*}}%arg1, i32 {{(noundef )*}}%arg2, i32 {{(noundef )*}}%arg3){{.*}}[ "kcfi"(i32 586925835) ]
+    f(arg1, arg2, arg3)
+}
+
+// CHECK: ![[TYPE1]] = !{i32 -458317079}
+// CHECK: ![[TYPE2]] = !{i32 1737138182}
+// CHECK: ![[TYPE3]] = !{i32 197182412}
diff --git a/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi.rs b/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi.rs
index 2537df80a90..83cda0ef136 100644
--- a/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi.rs
+++ b/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi.rs
@@ -20,22 +20,22 @@ impl Copy for i32 {}
 
 pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
     // CHECK-LABEL: define{{.*}}foo
-    // CHECK-SAME: {{.*}}!{{<unknown kind #36>|kcfi_type}} ![[TYPE1:[0-9]+]]
-    // CHECK: call i32 %f(i32 %arg){{.*}}[ "kcfi"(i32 -1666898348) ]
+    // CHECK-SAME:  {{.*}}!{{<unknown kind #36>|kcfi_type}} ![[TYPE1:[0-9]+]]
+    // CHECK:       {{%.+}} = call {{(noundef )*}}i32 %f(i32 {{(noundef )*}}%arg){{.*}}[ "kcfi"(i32 -1666898348) ]
     f(arg)
 }
 
 pub fn bar(f: fn(i32, i32) -> i32, arg1: i32, arg2: i32) -> i32 {
     // CHECK-LABEL: define{{.*}}bar
-    // CHECK-SAME: {{.*}}!{{<unknown kind #36>|kcfi_type}} ![[TYPE2:[0-9]+]]
-    // CHECK: call i32 %f(i32 %arg1, i32 %arg2){{.*}}[ "kcfi"(i32 -1789026986) ]
+    // CHECK-SAME:  {{.*}}!{{<unknown kind #36>|kcfi_type}} ![[TYPE2:[0-9]+]]
+    // CHECK:       {{%.+}} = call {{(noundef )*}}i32 %f(i32 {{(noundef )*}}%arg1, i32 {{(noundef )*}}%arg2){{.*}}[ "kcfi"(i32 -1789026986) ]
     f(arg1, arg2)
 }
 
 pub fn baz(f: fn(i32, i32, i32) -> i32, arg1: i32, arg2: i32, arg3: i32) -> i32 {
     // CHECK-LABEL: define{{.*}}baz
-    // CHECK-SAME: {{.*}}!{{<unknown kind #36>|kcfi_type}} ![[TYPE3:[0-9]+]]
-    // CHECK: call i32 %f(i32 %arg1, i32 %arg2, i32 %arg3){{.*}}[ "kcfi"(i32 1248878270) ]
+    // CHECK-SAME:  {{.*}}!{{<unknown kind #36>|kcfi_type}} ![[TYPE3:[0-9]+]]
+    // CHECK:       {{%.+}} = call {{(noundef )*}}i32 %f(i32 {{(noundef )*}}%arg1, i32 {{(noundef )*}}%arg2, i32 {{(noundef )*}}%arg3){{.*}}[ "kcfi"(i32 1248878270) ]
     f(arg1, arg2, arg3)
 }
 
diff --git a/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle.rs b/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle.rs
new file mode 100644
index 00000000000..e1d617b5ee1
--- /dev/null
+++ b/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle.rs
@@ -0,0 +1,27 @@
+// Verifies that KCFI operand bundles are emitted.
+//
+// revisions: aarch64 x86_64
+// [aarch64] compile-flags: --target aarch64-unknown-none
+// [aarch64] needs-llvm-components: aarch64
+// [x86_64] compile-flags: --target x86_64-unknown-none
+// [x86_64] needs-llvm-components:
+// compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi -Copt-level=0
+
+#![crate_type="lib"]
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang="sized"]
+trait Sized { }
+#[lang="copy"]
+trait Copy { }
+
+impl Copy for i32 {}
+
+pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
+    // CHECK-LABEL: define{{.*}}foo{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+    // CHECK:       start:
+    // CHECK-NEXT:  {{%.+}} = call {{(noundef )*}}i32 %f(i32 {{(noundef )*}}%arg){{.*}}[ "kcfi"(i32 {{[-0-9]+}}) ]
+    // CHECK-NEXT:  ret i32 {{%.+}}
+    f(arg)
+}
diff --git a/tests/codegen/sanitizer-kcfi-emit-type-metadata-trait-objects.rs b/tests/codegen/sanitizer-kcfi-emit-type-metadata-trait-objects.rs
new file mode 100644
index 00000000000..7aed137f215
--- /dev/null
+++ b/tests/codegen/sanitizer-kcfi-emit-type-metadata-trait-objects.rs
@@ -0,0 +1,174 @@
+// Verifies that type metadata identifiers for trait objects are emitted correctly.
+//
+// revisions: aarch64 x86_64
+// [aarch64] compile-flags: --target aarch64-unknown-none
+// [aarch64] needs-llvm-components: aarch64
+// [x86_64] compile-flags: --target x86_64-unknown-none
+// [x86_64] needs-llvm-components:
+// compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi -Copt-level=0
+
+#![crate_type="lib"]
+#![feature(arbitrary_self_types, no_core, lang_items)]
+#![no_core]
+
+#[lang="sized"]
+trait Sized { }
+#[lang="copy"]
+trait Copy { }
+#[lang="receiver"]
+trait Receiver { }
+#[lang="dispatch_from_dyn"]
+trait DispatchFromDyn<T> { }
+impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {}
+#[lang = "unsize"]
+trait Unsize<T: ?Sized> { }
+#[lang = "coerce_unsized"]
+pub trait CoerceUnsized<T: ?Sized> { }
+impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
+#[lang="freeze"]
+trait Freeze { }
+#[lang="drop_in_place"]
+fn drop_in_place_fn<T>() { }
+
+pub trait Trait1 {
+    fn foo(&self);
+}
+
+pub struct Type1;
+
+impl Trait1 for Type1 {
+    fn foo(&self) {
+    }
+}
+
+pub trait Trait2<T> {
+    fn bar(&self);
+}
+
+pub struct Type2;
+
+impl Trait2<i32> for Type2 {
+    fn bar(&self) {
+    }
+}
+
+pub trait Trait3<T> {
+    fn baz(&self, _: &T);
+}
+
+pub struct Type3;
+
+impl<T, U> Trait3<U> for T {
+    fn baz(&self, _: &U) {
+    }
+}
+
+pub trait Trait4<'a, T> {
+    type Output: 'a;
+    fn qux(&self, _: &T) -> Self::Output;
+}
+
+pub struct Type4;
+
+impl<'a, T, U> Trait4<'a, U> for T {
+    type Output = &'a i32;
+    fn qux(&self, _: &U) -> Self::Output {
+        &0
+    }
+}
+
+pub trait Trait5<T, const N: usize> {
+    fn quux(&self, _: &[T; N]);
+}
+
+pub struct Type5;
+
+impl Copy for Type5 {}
+
+impl<T, U, const N: usize> Trait5<U, N> for T {
+    fn quux(&self, _: &[U; N]) {
+    }
+}
+
+pub fn foo1(a: &dyn Trait1) {
+    a.foo();
+    // CHECK-LABEL: define{{.*}}4foo1{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+    // CHECK:       call void %{{[0-9]}}(ptr align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE1:[[:print:]]+]]) ]
+}
+
+pub fn bar1() {
+    let a = Type1;
+    let b = &a as &dyn Trait1;
+    b.foo();
+    // CHECK-LABEL: define{{.*}}4bar1{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+    // CHECK:       call void %{{[0-9]}}(ptr align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE1:[[:print:]]+]]) ]
+}
+
+pub fn foo2<T>(a: &dyn Trait2<T>) {
+    a.bar();
+    // CHECK-LABEL: define{{.*}}4foo2{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+    // CHECK:       call void %{{[0-9]}}(ptr align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE2:[[:print:]]+]]) ]
+}
+
+pub fn bar2() {
+    let a = Type2;
+    foo2(&a);
+    let b = &a as &dyn Trait2<i32>;
+    b.bar();
+    // CHECK-LABEL: define{{.*}}4bar2{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+    // CHECK:       call void %{{[0-9]}}(ptr align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE2:[[:print:]]+]]) ]
+}
+
+pub fn foo3(a: &dyn Trait3<Type3>) {
+    let b = Type3;
+    a.baz(&b);
+    // CHECK-LABEL: define{{.*}}4foo3{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+    // CHECK:       call void %{{[0-9]}}(ptr align 1 {{%[a-z]\.0|%_[0-9]}}, ptr align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE3:[[:print:]]+]]) ]
+}
+
+pub fn bar3() {
+    let a = Type3;
+    foo3(&a);
+    let b = &a as &dyn Trait3<Type3>;
+    b.baz(&a);
+    // CHECK-LABEL: define{{.*}}4bar3{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+    // CHECK:       call void %{{[0-9]}}(ptr align 1 {{%[a-z]\.0|%_[0-9]}}, ptr align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE3:[[:print:]]+]]) ]
+}
+
+pub fn foo4<'a>(a: &dyn Trait4<'a, Type4, Output = &'a i32>) {
+    let b = Type4;
+    a.qux(&b);
+    // CHECK-LABEL: define{{.*}}4foo4{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+    // CHECK:       call align 4 ptr %{{[0-9]}}(ptr align 1 {{%[a-z]\.0|%_[0-9]}}, ptr align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE4:[[:print:]]+]]) ]
+}
+
+pub fn bar4<'a>() {
+    let a = Type4;
+    foo4(&a);
+    let b = &a as &dyn Trait4<'a, Type4, Output = &'a i32>;
+    b.qux(&a);
+    // CHECK-LABEL: define{{.*}}4bar4{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+    // CHECK:       call align 4 ptr %{{[0-9]}}(ptr align 1 {{%[a-z]\.0|%_[0-9]}}, ptr align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE4:[[:print:]]+]]) ]
+}
+
+pub fn foo5(a: &dyn Trait5<Type5, 32>) {
+    let b = &[Type5; 32];
+    a.quux(&b);
+    // CHECK-LABEL: define{{.*}}4foo5{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+    // CHECK:       call void %{{[0-9]}}(ptr align 1 {{%[a-z](\.0)*|%_[0-9]+]}}, ptr align 1 {{%[a-z](\.0)*|%_[0-9]+}}){{.*}}[ "kcfi"(i32 [[TYPE5:[[:print:]]+]]) ]
+}
+
+pub fn bar5() {
+    let a = &[Type5; 32];
+    foo5(&a);
+    let b = &a as &dyn Trait5<Type5, 32>;
+    b.quux(&a);
+    // CHECK-LABEL: define{{.*}}4bar5{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+    // CHECK:       call void %{{[0-9]}}(ptr align 1 {{%[a-z](\.0)*|%_[0-9]+]}}, ptr align 1 {{%[a-z](\.0)*|%_[0-9]+}}){{.*}}[ "kcfi"(i32 [[TYPE5:[[:print:]]+]]) ]
+}
+
+// CHECK: !{{[0-9]+}} = !{i32 [[TYPE1]]}
+// CHECK: !{{[0-9]+}} = !{i32 [[TYPE2]]}
+// CHECK: !{{[0-9]+}} = !{i32 [[TYPE3]]}
+// CHECK: !{{[0-9]+}} = !{i32 [[TYPE4]]}
+// CHECK: !{{[0-9]+}} = !{i32 [[TYPE5]]}
diff --git a/tests/codegen/sanitizer-safestack-attr-check.rs b/tests/codegen/sanitizer-safestack-attr-check.rs
new file mode 100644
index 00000000000..b73ed00e730
--- /dev/null
+++ b/tests/codegen/sanitizer-safestack-attr-check.rs
@@ -0,0 +1,11 @@
+// This tests that the safestack attribute is applied when enabling the safe-stack sanitizer.
+//
+// needs-sanitizer-safestack
+// compile-flags: -Zsanitizer=safestack
+
+#![crate_type = "lib"]
+
+// CHECK: ; Function Attrs:{{.*}}safestack
+pub fn tagged() {}
+
+// CHECK: attributes #0 = {{.*}}safestack
diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs
index faac7566a0c..0bcfacec6d7 100644
--- a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs
+++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs
@@ -116,150 +116,150 @@ extern "platform-intrinsic" {
     fn simd_saturating_sub<T>(x: T, y: T) -> T;
 }
 
-// NOTE(eddyb) `%{{x|1}}` is used because on some targets (e.g. WASM)
+// NOTE(eddyb) `%{{x|0}}` is used because on some targets (e.g. WASM)
 // SIMD vectors are passed directly, resulting in `%x` being a vector,
 // while on others they're passed indirectly, resulting in `%x` being
-// a pointer to a vector, and `%1` a vector loaded from that pointer.
+// a pointer to a vector, and `%0` a vector loaded from that pointer.
 // This is controlled by the target spec option `simd_types_indirect`.
-// The same applies to `%{{y|2}}` as well.
+// The same applies to `%{{y|1}}` as well.
 
 // CHECK-LABEL: @sadd_i8x2
 #[no_mangle]
 pub unsafe fn sadd_i8x2(x: i8x2, y: i8x2) -> i8x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> %{{x|1}}, <2 x i8> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> %{{x|0}}, <2 x i8> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @sadd_i8x4
 #[no_mangle]
 pub unsafe fn sadd_i8x4(x: i8x4, y: i8x4) -> i8x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.sadd.sat.v4i8(<4 x i8> %{{x|1}}, <4 x i8> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.sadd.sat.v4i8(<4 x i8> %{{x|0}}, <4 x i8> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @sadd_i8x8
 #[no_mangle]
 pub unsafe fn sadd_i8x8(x: i8x8, y: i8x8) -> i8x8 {
-    // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.sadd.sat.v8i8(<8 x i8> %{{x|1}}, <8 x i8> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.sadd.sat.v8i8(<8 x i8> %{{x|0}}, <8 x i8> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @sadd_i8x16
 #[no_mangle]
 pub unsafe fn sadd_i8x16(x: i8x16, y: i8x16) -> i8x16 {
-    // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.sadd.sat.v16i8(<16 x i8> %{{x|1}}, <16 x i8> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.sadd.sat.v16i8(<16 x i8> %{{x|0}}, <16 x i8> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @sadd_i8x32
 #[no_mangle]
 pub unsafe fn sadd_i8x32(x: i8x32, y: i8x32) -> i8x32 {
-    // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.sadd.sat.v32i8(<32 x i8> %{{x|1}}, <32 x i8> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.sadd.sat.v32i8(<32 x i8> %{{x|0}}, <32 x i8> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @sadd_i8x64
 #[no_mangle]
 pub unsafe fn sadd_i8x64(x: i8x64, y: i8x64) -> i8x64 {
-    // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.sadd.sat.v64i8(<64 x i8> %{{x|1}}, <64 x i8> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.sadd.sat.v64i8(<64 x i8> %{{x|0}}, <64 x i8> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @sadd_i16x2
 #[no_mangle]
 pub unsafe fn sadd_i16x2(x: i16x2, y: i16x2) -> i16x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.sadd.sat.v2i16(<2 x i16> %{{x|1}}, <2 x i16> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.sadd.sat.v2i16(<2 x i16> %{{x|0}}, <2 x i16> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @sadd_i16x4
 #[no_mangle]
 pub unsafe fn sadd_i16x4(x: i16x4, y: i16x4) -> i16x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.sadd.sat.v4i16(<4 x i16> %{{x|1}}, <4 x i16> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.sadd.sat.v4i16(<4 x i16> %{{x|0}}, <4 x i16> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @sadd_i16x8
 #[no_mangle]
 pub unsafe fn sadd_i16x8(x: i16x8, y: i16x8) -> i16x8 {
-    // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.sadd.sat.v8i16(<8 x i16> %{{x|1}}, <8 x i16> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.sadd.sat.v8i16(<8 x i16> %{{x|0}}, <8 x i16> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @sadd_i16x16
 #[no_mangle]
 pub unsafe fn sadd_i16x16(x: i16x16, y: i16x16) -> i16x16 {
-    // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.sadd.sat.v16i16(<16 x i16> %{{x|1}}, <16 x i16> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.sadd.sat.v16i16(<16 x i16> %{{x|0}}, <16 x i16> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @sadd_i16x32
 #[no_mangle]
 pub unsafe fn sadd_i16x32(x: i16x32, y: i16x32) -> i16x32 {
-    // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.sadd.sat.v32i16(<32 x i16> %{{x|1}}, <32 x i16> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.sadd.sat.v32i16(<32 x i16> %{{x|0}}, <32 x i16> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @sadd_i32x2
 #[no_mangle]
 pub unsafe fn sadd_i32x2(x: i32x2, y: i32x2) -> i32x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.sadd.sat.v2i32(<2 x i32> %{{x|1}}, <2 x i32> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.sadd.sat.v2i32(<2 x i32> %{{x|0}}, <2 x i32> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @sadd_i32x4
 #[no_mangle]
 pub unsafe fn sadd_i32x4(x: i32x4, y: i32x4) -> i32x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.sadd.sat.v4i32(<4 x i32> %{{x|1}}, <4 x i32> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.sadd.sat.v4i32(<4 x i32> %{{x|0}}, <4 x i32> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @sadd_i32x8
 #[no_mangle]
 pub unsafe fn sadd_i32x8(x: i32x8, y: i32x8) -> i32x8 {
-    // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.sadd.sat.v8i32(<8 x i32> %{{x|1}}, <8 x i32> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.sadd.sat.v8i32(<8 x i32> %{{x|0}}, <8 x i32> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @sadd_i32x16
 #[no_mangle]
 pub unsafe fn sadd_i32x16(x: i32x16, y: i32x16) -> i32x16 {
-    // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.sadd.sat.v16i32(<16 x i32> %{{x|1}}, <16 x i32> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.sadd.sat.v16i32(<16 x i32> %{{x|0}}, <16 x i32> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @sadd_i64x2
 #[no_mangle]
 pub unsafe fn sadd_i64x2(x: i64x2, y: i64x2) -> i64x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.sadd.sat.v2i64(<2 x i64> %{{x|1}}, <2 x i64> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.sadd.sat.v2i64(<2 x i64> %{{x|0}}, <2 x i64> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @sadd_i64x4
 #[no_mangle]
 pub unsafe fn sadd_i64x4(x: i64x4, y: i64x4) -> i64x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.sadd.sat.v4i64(<4 x i64> %{{x|1}}, <4 x i64> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.sadd.sat.v4i64(<4 x i64> %{{x|0}}, <4 x i64> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @sadd_i64x8
 #[no_mangle]
 pub unsafe fn sadd_i64x8(x: i64x8, y: i64x8) -> i64x8 {
-    // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.sadd.sat.v8i64(<8 x i64> %{{x|1}}, <8 x i64> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.sadd.sat.v8i64(<8 x i64> %{{x|0}}, <8 x i64> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @sadd_i128x2
 #[no_mangle]
 pub unsafe fn sadd_i128x2(x: i128x2, y: i128x2) -> i128x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.sadd.sat.v2i128(<2 x i128> %{{x|1}}, <2 x i128> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.sadd.sat.v2i128(<2 x i128> %{{x|0}}, <2 x i128> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @sadd_i128x4
 #[no_mangle]
 pub unsafe fn sadd_i128x4(x: i128x4, y: i128x4) -> i128x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.sadd.sat.v4i128(<4 x i128> %{{x|1}}, <4 x i128> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.sadd.sat.v4i128(<4 x i128> %{{x|0}}, <4 x i128> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
@@ -268,140 +268,140 @@ pub unsafe fn sadd_i128x4(x: i128x4, y: i128x4) -> i128x4 {
 // CHECK-LABEL: @uadd_u8x2
 #[no_mangle]
 pub unsafe fn uadd_u8x2(x: u8x2, y: u8x2) -> u8x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> %{{x|1}}, <2 x i8> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> %{{x|0}}, <2 x i8> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @uadd_u8x4
 #[no_mangle]
 pub unsafe fn uadd_u8x4(x: u8x4, y: u8x4) -> u8x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.uadd.sat.v4i8(<4 x i8> %{{x|1}}, <4 x i8> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.uadd.sat.v4i8(<4 x i8> %{{x|0}}, <4 x i8> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @uadd_u8x8
 #[no_mangle]
 pub unsafe fn uadd_u8x8(x: u8x8, y: u8x8) -> u8x8 {
-    // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.uadd.sat.v8i8(<8 x i8> %{{x|1}}, <8 x i8> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.uadd.sat.v8i8(<8 x i8> %{{x|0}}, <8 x i8> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @uadd_u8x16
 #[no_mangle]
 pub unsafe fn uadd_u8x16(x: u8x16, y: u8x16) -> u8x16 {
-    // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.uadd.sat.v16i8(<16 x i8> %{{x|1}}, <16 x i8> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.uadd.sat.v16i8(<16 x i8> %{{x|0}}, <16 x i8> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @uadd_u8x32
 #[no_mangle]
 pub unsafe fn uadd_u8x32(x: u8x32, y: u8x32) -> u8x32 {
-    // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.uadd.sat.v32i8(<32 x i8> %{{x|1}}, <32 x i8> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.uadd.sat.v32i8(<32 x i8> %{{x|0}}, <32 x i8> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @uadd_u8x64
 #[no_mangle]
 pub unsafe fn uadd_u8x64(x: u8x64, y: u8x64) -> u8x64 {
-    // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.uadd.sat.v64i8(<64 x i8> %{{x|1}}, <64 x i8> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.uadd.sat.v64i8(<64 x i8> %{{x|0}}, <64 x i8> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @uadd_u16x2
 #[no_mangle]
 pub unsafe fn uadd_u16x2(x: u16x2, y: u16x2) -> u16x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.uadd.sat.v2i16(<2 x i16> %{{x|1}}, <2 x i16> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.uadd.sat.v2i16(<2 x i16> %{{x|0}}, <2 x i16> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @uadd_u16x4
 #[no_mangle]
 pub unsafe fn uadd_u16x4(x: u16x4, y: u16x4) -> u16x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.uadd.sat.v4i16(<4 x i16> %{{x|1}}, <4 x i16> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.uadd.sat.v4i16(<4 x i16> %{{x|0}}, <4 x i16> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @uadd_u16x8
 #[no_mangle]
 pub unsafe fn uadd_u16x8(x: u16x8, y: u16x8) -> u16x8 {
-    // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.uadd.sat.v8i16(<8 x i16> %{{x|1}}, <8 x i16> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.uadd.sat.v8i16(<8 x i16> %{{x|0}}, <8 x i16> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @uadd_u16x16
 #[no_mangle]
 pub unsafe fn uadd_u16x16(x: u16x16, y: u16x16) -> u16x16 {
-    // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.uadd.sat.v16i16(<16 x i16> %{{x|1}}, <16 x i16> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.uadd.sat.v16i16(<16 x i16> %{{x|0}}, <16 x i16> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @uadd_u16x32
 #[no_mangle]
 pub unsafe fn uadd_u16x32(x: u16x32, y: u16x32) -> u16x32 {
-    // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.uadd.sat.v32i16(<32 x i16> %{{x|1}}, <32 x i16> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.uadd.sat.v32i16(<32 x i16> %{{x|0}}, <32 x i16> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @uadd_u32x2
 #[no_mangle]
 pub unsafe fn uadd_u32x2(x: u32x2, y: u32x2) -> u32x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.uadd.sat.v2i32(<2 x i32> %{{x|1}}, <2 x i32> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.uadd.sat.v2i32(<2 x i32> %{{x|0}}, <2 x i32> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @uadd_u32x4
 #[no_mangle]
 pub unsafe fn uadd_u32x4(x: u32x4, y: u32x4) -> u32x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.uadd.sat.v4i32(<4 x i32> %{{x|1}}, <4 x i32> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.uadd.sat.v4i32(<4 x i32> %{{x|0}}, <4 x i32> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @uadd_u32x8
 #[no_mangle]
 pub unsafe fn uadd_u32x8(x: u32x8, y: u32x8) -> u32x8 {
-    // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.uadd.sat.v8i32(<8 x i32> %{{x|1}}, <8 x i32> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.uadd.sat.v8i32(<8 x i32> %{{x|0}}, <8 x i32> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @uadd_u32x16
 #[no_mangle]
 pub unsafe fn uadd_u32x16(x: u32x16, y: u32x16) -> u32x16 {
-    // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.uadd.sat.v16i32(<16 x i32> %{{x|1}}, <16 x i32> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.uadd.sat.v16i32(<16 x i32> %{{x|0}}, <16 x i32> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @uadd_u64x2
 #[no_mangle]
 pub unsafe fn uadd_u64x2(x: u64x2, y: u64x2) -> u64x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.uadd.sat.v2i64(<2 x i64> %{{x|1}}, <2 x i64> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.uadd.sat.v2i64(<2 x i64> %{{x|0}}, <2 x i64> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @uadd_u64x4
 #[no_mangle]
 pub unsafe fn uadd_u64x4(x: u64x4, y: u64x4) -> u64x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.uadd.sat.v4i64(<4 x i64> %{{x|1}}, <4 x i64> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.uadd.sat.v4i64(<4 x i64> %{{x|0}}, <4 x i64> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @uadd_u64x8
 #[no_mangle]
 pub unsafe fn uadd_u64x8(x: u64x8, y: u64x8) -> u64x8 {
-    // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.uadd.sat.v8i64(<8 x i64> %{{x|1}}, <8 x i64> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.uadd.sat.v8i64(<8 x i64> %{{x|0}}, <8 x i64> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @uadd_u128x2
 #[no_mangle]
 pub unsafe fn uadd_u128x2(x: u128x2, y: u128x2) -> u128x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.uadd.sat.v2i128(<2 x i128> %{{x|1}}, <2 x i128> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.uadd.sat.v2i128(<2 x i128> %{{x|0}}, <2 x i128> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
 // CHECK-LABEL: @uadd_u128x4
 #[no_mangle]
 pub unsafe fn uadd_u128x4(x: u128x4, y: u128x4) -> u128x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.uadd.sat.v4i128(<4 x i128> %{{x|1}}, <4 x i128> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.uadd.sat.v4i128(<4 x i128> %{{x|0}}, <4 x i128> %{{y|1}})
     simd_saturating_add(x, y)
 }
 
@@ -412,140 +412,140 @@ pub unsafe fn uadd_u128x4(x: u128x4, y: u128x4) -> u128x4 {
 // CHECK-LABEL: @ssub_i8x2
 #[no_mangle]
 pub unsafe fn ssub_i8x2(x: i8x2, y: i8x2) -> i8x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> %{{x|1}}, <2 x i8> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> %{{x|0}}, <2 x i8> %{{y|1}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @ssub_i8x4
 #[no_mangle]
 pub unsafe fn ssub_i8x4(x: i8x4, y: i8x4) -> i8x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.ssub.sat.v4i8(<4 x i8> %{{x|1}}, <4 x i8> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.ssub.sat.v4i8(<4 x i8> %{{x|0}}, <4 x i8> %{{y|1}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @ssub_i8x8
 #[no_mangle]
 pub unsafe fn ssub_i8x8(x: i8x8, y: i8x8) -> i8x8 {
-    // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.ssub.sat.v8i8(<8 x i8> %{{x|1}}, <8 x i8> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.ssub.sat.v8i8(<8 x i8> %{{x|0}}, <8 x i8> %{{y|1}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @ssub_i8x16
 #[no_mangle]
 pub unsafe fn ssub_i8x16(x: i8x16, y: i8x16) -> i8x16 {
-    // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.ssub.sat.v16i8(<16 x i8> %{{x|1}}, <16 x i8> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.ssub.sat.v16i8(<16 x i8> %{{x|0}}, <16 x i8> %{{y|1}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @ssub_i8x32
 #[no_mangle]
 pub unsafe fn ssub_i8x32(x: i8x32, y: i8x32) -> i8x32 {
-    // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.ssub.sat.v32i8(<32 x i8> %{{x|1}}, <32 x i8> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.ssub.sat.v32i8(<32 x i8> %{{x|0}}, <32 x i8> %{{y|1}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @ssub_i8x64
 #[no_mangle]
 pub unsafe fn ssub_i8x64(x: i8x64, y: i8x64) -> i8x64 {
-    // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.ssub.sat.v64i8(<64 x i8> %{{x|1}}, <64 x i8> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.ssub.sat.v64i8(<64 x i8> %{{x|0}}, <64 x i8> %{{y|1}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @ssub_i16x2
 #[no_mangle]
 pub unsafe fn ssub_i16x2(x: i16x2, y: i16x2) -> i16x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.ssub.sat.v2i16(<2 x i16> %{{x|1}}, <2 x i16> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.ssub.sat.v2i16(<2 x i16> %{{x|0}}, <2 x i16> %{{y|1}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @ssub_i16x4
 #[no_mangle]
 pub unsafe fn ssub_i16x4(x: i16x4, y: i16x4) -> i16x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.ssub.sat.v4i16(<4 x i16> %{{x|1}}, <4 x i16> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.ssub.sat.v4i16(<4 x i16> %{{x|0}}, <4 x i16> %{{y|1}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @ssub_i16x8
 #[no_mangle]
 pub unsafe fn ssub_i16x8(x: i16x8, y: i16x8) -> i16x8 {
-    // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.ssub.sat.v8i16(<8 x i16> %{{x|1}}, <8 x i16> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.ssub.sat.v8i16(<8 x i16> %{{x|0}}, <8 x i16> %{{y|1}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @ssub_i16x16
 #[no_mangle]
 pub unsafe fn ssub_i16x16(x: i16x16, y: i16x16) -> i16x16 {
-    // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.ssub.sat.v16i16(<16 x i16> %{{x|1}}, <16 x i16> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.ssub.sat.v16i16(<16 x i16> %{{x|0}}, <16 x i16> %{{y|1}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @ssub_i16x32
 #[no_mangle]
 pub unsafe fn ssub_i16x32(x: i16x32, y: i16x32) -> i16x32 {
-    // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.ssub.sat.v32i16(<32 x i16> %{{x|1}}, <32 x i16> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.ssub.sat.v32i16(<32 x i16> %{{x|0}}, <32 x i16> %{{y|1}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @ssub_i32x2
 #[no_mangle]
 pub unsafe fn ssub_i32x2(x: i32x2, y: i32x2) -> i32x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.ssub.sat.v2i32(<2 x i32> %{{x|1}}, <2 x i32> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.ssub.sat.v2i32(<2 x i32> %{{x|0}}, <2 x i32> %{{y|1}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @ssub_i32x4
 #[no_mangle]
 pub unsafe fn ssub_i32x4(x: i32x4, y: i32x4) -> i32x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.ssub.sat.v4i32(<4 x i32> %{{x|1}}, <4 x i32> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.ssub.sat.v4i32(<4 x i32> %{{x|0}}, <4 x i32> %{{y|1}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @ssub_i32x8
 #[no_mangle]
 pub unsafe fn ssub_i32x8(x: i32x8, y: i32x8) -> i32x8 {
-    // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.ssub.sat.v8i32(<8 x i32> %{{x|1}}, <8 x i32> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.ssub.sat.v8i32(<8 x i32> %{{x|0}}, <8 x i32> %{{y|1}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @ssub_i32x16
 #[no_mangle]
 pub unsafe fn ssub_i32x16(x: i32x16, y: i32x16) -> i32x16 {
-    // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.ssub.sat.v16i32(<16 x i32> %{{x|1}}, <16 x i32> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.ssub.sat.v16i32(<16 x i32> %{{x|0}}, <16 x i32> %{{y|1}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @ssub_i64x2
 #[no_mangle]
 pub unsafe fn ssub_i64x2(x: i64x2, y: i64x2) -> i64x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.ssub.sat.v2i64(<2 x i64> %{{x|1}}, <2 x i64> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.ssub.sat.v2i64(<2 x i64> %{{x|0}}, <2 x i64> %{{y|1}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @ssub_i64x4
 #[no_mangle]
 pub unsafe fn ssub_i64x4(x: i64x4, y: i64x4) -> i64x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.ssub.sat.v4i64(<4 x i64> %{{x|1}}, <4 x i64> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.ssub.sat.v4i64(<4 x i64> %{{x|0}}, <4 x i64> %{{y|1}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @ssub_i64x8
 #[no_mangle]
 pub unsafe fn ssub_i64x8(x: i64x8, y: i64x8) -> i64x8 {
-    // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.ssub.sat.v8i64(<8 x i64> %{{x|1}}, <8 x i64> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.ssub.sat.v8i64(<8 x i64> %{{x|0}}, <8 x i64> %{{y|1}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @ssub_i128x2
 #[no_mangle]
 pub unsafe fn ssub_i128x2(x: i128x2, y: i128x2) -> i128x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.ssub.sat.v2i128(<2 x i128> %{{x|1}}, <2 x i128> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.ssub.sat.v2i128(<2 x i128> %{{x|0}}, <2 x i128> %{{y|1}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @ssub_i128x4
 #[no_mangle]
 pub unsafe fn ssub_i128x4(x: i128x4, y: i128x4) -> i128x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.ssub.sat.v4i128(<4 x i128> %{{x|1}}, <4 x i128> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.ssub.sat.v4i128(<4 x i128> %{{x|0}}, <4 x i128> %{{y|1}})
     simd_saturating_sub(x, y)
 }
 
@@ -554,139 +554,139 @@ pub unsafe fn ssub_i128x4(x: i128x4, y: i128x4) -> i128x4 {
 // CHECK-LABEL: @usub_u8x2
 #[no_mangle]
 pub unsafe fn usub_u8x2(x: u8x2, y: u8x2) -> u8x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> %{{x|1}}, <2 x i8> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> %{{x|0}}, <2 x i8> %{{y|1}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @usub_u8x4
 #[no_mangle]
 pub unsafe fn usub_u8x4(x: u8x4, y: u8x4) -> u8x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.usub.sat.v4i8(<4 x i8> %{{x|1}}, <4 x i8> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.usub.sat.v4i8(<4 x i8> %{{x|0}}, <4 x i8> %{{y|1}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @usub_u8x8
 #[no_mangle]
 pub unsafe fn usub_u8x8(x: u8x8, y: u8x8) -> u8x8 {
-    // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.usub.sat.v8i8(<8 x i8> %{{x|1}}, <8 x i8> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.usub.sat.v8i8(<8 x i8> %{{x|0}}, <8 x i8> %{{y|1}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @usub_u8x16
 #[no_mangle]
 pub unsafe fn usub_u8x16(x: u8x16, y: u8x16) -> u8x16 {
-    // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.usub.sat.v16i8(<16 x i8> %{{x|1}}, <16 x i8> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.usub.sat.v16i8(<16 x i8> %{{x|0}}, <16 x i8> %{{y|1}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @usub_u8x32
 #[no_mangle]
 pub unsafe fn usub_u8x32(x: u8x32, y: u8x32) -> u8x32 {
-    // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.usub.sat.v32i8(<32 x i8> %{{x|1}}, <32 x i8> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.usub.sat.v32i8(<32 x i8> %{{x|0}}, <32 x i8> %{{y|1}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @usub_u8x64
 #[no_mangle]
 pub unsafe fn usub_u8x64(x: u8x64, y: u8x64) -> u8x64 {
-    // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.usub.sat.v64i8(<64 x i8> %{{x|1}}, <64 x i8> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.usub.sat.v64i8(<64 x i8> %{{x|0}}, <64 x i8> %{{y|1}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @usub_u16x2
 #[no_mangle]
 pub unsafe fn usub_u16x2(x: u16x2, y: u16x2) -> u16x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> %{{x|1}}, <2 x i16> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> %{{x|0}}, <2 x i16> %{{y|1}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @usub_u16x4
 #[no_mangle]
 pub unsafe fn usub_u16x4(x: u16x4, y: u16x4) -> u16x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.usub.sat.v4i16(<4 x i16> %{{x|1}}, <4 x i16> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.usub.sat.v4i16(<4 x i16> %{{x|0}}, <4 x i16> %{{y|1}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @usub_u16x8
 #[no_mangle]
 pub unsafe fn usub_u16x8(x: u16x8, y: u16x8) -> u16x8 {
-    // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.usub.sat.v8i16(<8 x i16> %{{x|1}}, <8 x i16> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.usub.sat.v8i16(<8 x i16> %{{x|0}}, <8 x i16> %{{y|1}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @usub_u16x16
 #[no_mangle]
 pub unsafe fn usub_u16x16(x: u16x16, y: u16x16) -> u16x16 {
-    // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.usub.sat.v16i16(<16 x i16> %{{x|1}}, <16 x i16> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.usub.sat.v16i16(<16 x i16> %{{x|0}}, <16 x i16> %{{y|1}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @usub_u16x32
 #[no_mangle]
 pub unsafe fn usub_u16x32(x: u16x32, y: u16x32) -> u16x32 {
-    // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.usub.sat.v32i16(<32 x i16> %{{x|1}}, <32 x i16> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.usub.sat.v32i16(<32 x i16> %{{x|0}}, <32 x i16> %{{y|1}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @usub_u32x2
 #[no_mangle]
 pub unsafe fn usub_u32x2(x: u32x2, y: u32x2) -> u32x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.usub.sat.v2i32(<2 x i32> %{{x|1}}, <2 x i32> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.usub.sat.v2i32(<2 x i32> %{{x|0}}, <2 x i32> %{{y|1}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @usub_u32x4
 #[no_mangle]
 pub unsafe fn usub_u32x4(x: u32x4, y: u32x4) -> u32x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.usub.sat.v4i32(<4 x i32> %{{x|1}}, <4 x i32> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.usub.sat.v4i32(<4 x i32> %{{x|0}}, <4 x i32> %{{y|1}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @usub_u32x8
 #[no_mangle]
 pub unsafe fn usub_u32x8(x: u32x8, y: u32x8) -> u32x8 {
-    // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.usub.sat.v8i32(<8 x i32> %{{x|1}}, <8 x i32> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.usub.sat.v8i32(<8 x i32> %{{x|0}}, <8 x i32> %{{y|1}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @usub_u32x16
 #[no_mangle]
 pub unsafe fn usub_u32x16(x: u32x16, y: u32x16) -> u32x16 {
-    // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.usub.sat.v16i32(<16 x i32> %{{x|1}}, <16 x i32> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.usub.sat.v16i32(<16 x i32> %{{x|0}}, <16 x i32> %{{y|1}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @usub_u64x2
 #[no_mangle]
 pub unsafe fn usub_u64x2(x: u64x2, y: u64x2) -> u64x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.usub.sat.v2i64(<2 x i64> %{{x|1}}, <2 x i64> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.usub.sat.v2i64(<2 x i64> %{{x|0}}, <2 x i64> %{{y|1}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @usub_u64x4
 #[no_mangle]
 pub unsafe fn usub_u64x4(x: u64x4, y: u64x4) -> u64x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.usub.sat.v4i64(<4 x i64> %{{x|1}}, <4 x i64> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.usub.sat.v4i64(<4 x i64> %{{x|0}}, <4 x i64> %{{y|1}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @usub_u64x8
 #[no_mangle]
 pub unsafe fn usub_u64x8(x: u64x8, y: u64x8) -> u64x8 {
-    // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.usub.sat.v8i64(<8 x i64> %{{x|1}}, <8 x i64> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.usub.sat.v8i64(<8 x i64> %{{x|0}}, <8 x i64> %{{y|1}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @usub_u128x2
 #[no_mangle]
 pub unsafe fn usub_u128x2(x: u128x2, y: u128x2) -> u128x2 {
-    // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.usub.sat.v2i128(<2 x i128> %{{x|1}}, <2 x i128> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.usub.sat.v2i128(<2 x i128> %{{x|0}}, <2 x i128> %{{y|1}})
     simd_saturating_sub(x, y)
 }
 
 // CHECK-LABEL: @usub_u128x4
 #[no_mangle]
 pub unsafe fn usub_u128x4(x: u128x4, y: u128x4) -> u128x4 {
-    // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.usub.sat.v4i128(<4 x i128> %{{x|1}}, <4 x i128> %{{y|2}})
+    // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.usub.sat.v4i128(<4 x i128> %{{x|0}}, <4 x i128> %{{y|1}})
     simd_saturating_sub(x, y)
 }
diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs
index 80583dec195..a5d2509d000 100644
--- a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs
+++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs
@@ -35,13 +35,13 @@ pub unsafe fn extract_s(v: S<4>, i: u32) -> f32  {
 // CHECK-LABEL: @insert_m
 #[no_mangle]
 pub unsafe fn insert_m(v: M, i: u32, j: f32) -> M  {
-    // CHECK: insertelement <4 x float> %{{v|1|2}}, float %j, i32 %i
+    // CHECK: insertelement <4 x float> %{{v|0|1}}, float %j, i32 %i
     simd_insert(v, i, j)
 }
 
 // CHECK-LABEL: @insert_s
 #[no_mangle]
 pub unsafe fn insert_s(v: S<4>, i: u32, j: f32) -> S<4>  {
-    // CHECK: insertelement <4 x float> %{{v|1|2}}, float %j, i32 %i
+    // CHECK: insertelement <4 x float> %{{v|0|1}}, float %j, i32 %i
     simd_insert(v, i, j)
 }
diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-gather.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-gather.rs
index cacc32f2f1b..7fe3ffd2086 100644
--- a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-gather.rs
+++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-gather.rs
@@ -23,7 +23,7 @@ extern "platform-intrinsic" {
 #[no_mangle]
 pub unsafe fn gather_f32x2(pointers: Vec2<*const f32>, mask: Vec2<i32>,
                            values: Vec2<f32>) -> Vec2<f32> {
-    // CHECK: call <2 x float> @llvm.masked.gather.v2f32.{{.+}}(<2 x {{float\*|ptr}}> {{.*}}, i32 {{.*}}, <2 x i1> {{.*}}, <2 x float> {{.*}})
+    // CHECK: call <2 x float> @llvm.masked.gather.v2f32.{{.+}}(<2 x ptr> {{.*}}, i32 {{.*}}, <2 x i1> {{.*}}, <2 x float> {{.*}})
     simd_gather(values, pointers, mask)
 }
 
@@ -31,6 +31,6 @@ pub unsafe fn gather_f32x2(pointers: Vec2<*const f32>, mask: Vec2<i32>,
 #[no_mangle]
 pub unsafe fn gather_pf32x2(pointers: Vec2<*const *const f32>, mask: Vec2<i32>,
                            values: Vec2<*const f32>) -> Vec2<*const f32> {
-    // CHECK: call <2 x {{float\*|ptr}}> @llvm.masked.gather.{{.+}}(<2 x {{float\*\*|ptr}}> {{.*}}, i32 {{.*}}, <2 x i1> {{.*}}, <2 x {{float\*|ptr}}> {{.*}})
+    // CHECK: call <2 x ptr> @llvm.masked.gather.{{.+}}(<2 x ptr> {{.*}}, i32 {{.*}}, <2 x i1> {{.*}}, <2 x ptr> {{.*}})
     simd_gather(values, pointers, mask)
 }
diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-scatter.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-scatter.rs
index 94ecaf6096d..5c917474e45 100644
--- a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-scatter.rs
+++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-scatter.rs
@@ -23,7 +23,7 @@ extern "platform-intrinsic" {
 #[no_mangle]
 pub unsafe fn scatter_f32x2(pointers: Vec2<*mut f32>, mask: Vec2<i32>,
                             values: Vec2<f32>) {
-    // CHECK: call void @llvm.masked.scatter.v2f32.v2p0{{.*}}(<2 x float> {{.*}}, <2 x {{float\*|ptr}}> {{.*}}, i32 {{.*}}, <2 x i1> {{.*}})
+    // CHECK: call void @llvm.masked.scatter.v2f32.v2p0{{.*}}(<2 x float> {{.*}}, <2 x ptr> {{.*}}, i32 {{.*}}, <2 x i1> {{.*}})
     simd_scatter(values, pointers, mask)
 }
 
@@ -32,6 +32,6 @@ pub unsafe fn scatter_f32x2(pointers: Vec2<*mut f32>, mask: Vec2<i32>,
 #[no_mangle]
 pub unsafe fn scatter_pf32x2(pointers: Vec2<*mut *const f32>, mask: Vec2<i32>,
                              values: Vec2<*const f32>) {
-    // CHECK: call void @llvm.masked.scatter.v2p0{{.*}}.v2p0{{.*}}(<2 x {{float\*|ptr}}> {{.*}}, <2 x {{float\*\*|ptr}}> {{.*}}, i32 {{.*}}, <2 x i1> {{.*}})
+    // CHECK: call void @llvm.masked.scatter.v2p0{{.*}}.v2p0{{.*}}(<2 x ptr> {{.*}}, <2 x ptr> {{.*}}, i32 {{.*}}, <2 x i1> {{.*}})
     simd_scatter(values, pointers, mask)
 }
diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs
index fd488a14bd3..eb4ce307e70 100644
--- a/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs
+++ b/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs
@@ -2,7 +2,6 @@
 // compile-flags: -C no-prepopulate-passes
 
 #![crate_type = "lib"]
-
 #![allow(non_camel_case_types)]
 #![feature(repr_simd, platform_intrinsics)]
 #![feature(inline_const)]
@@ -43,8 +42,8 @@ pub fn build_array_s(x: [f32; 4]) -> S<4> {
 // CHECK-LABEL: @build_array_transmute_s
 #[no_mangle]
 pub fn build_array_transmute_s(x: [f32; 4]) -> S<4> {
-    // CHECK: %[[VAL:.+]] = load <4 x float>, {{ptr %x|.+>\* %.+}}, align [[ARRAY_ALIGN]]
-    // CHECK: store <4 x float> %[[VAL:.+]], {{ptr %0|.+>\* %.+}}, align [[VECTOR_ALIGN]]
+    // CHECK: %[[VAL:.+]] = load <4 x float>, ptr %x, align [[ARRAY_ALIGN]]
+    // CHECK: store <4 x float> %[[VAL:.+]], ptr %_0, align [[VECTOR_ALIGN]]
     unsafe { std::mem::transmute(x) }
 }
 
@@ -58,8 +57,8 @@ pub fn build_array_t(x: [f32; 4]) -> T {
 // CHECK-LABEL: @build_array_transmute_t
 #[no_mangle]
 pub fn build_array_transmute_t(x: [f32; 4]) -> T {
-    // CHECK: %[[VAL:.+]] = load <4 x float>, {{ptr %x|.+>\* %.+}}, align [[ARRAY_ALIGN]]
-    // CHECK: store <4 x float> %[[VAL:.+]], {{ptr %0|.+>\* %.+}}, align [[VECTOR_ALIGN]]
+    // CHECK: %[[VAL:.+]] = load <4 x float>, ptr %x, align [[ARRAY_ALIGN]]
+    // CHECK: store <4 x float> %[[VAL:.+]], ptr %_0, align [[VECTOR_ALIGN]]
     unsafe { std::mem::transmute(x) }
 }
 
@@ -77,7 +76,7 @@ pub fn build_array_u(x: [f32; 4]) -> U {
 // CHECK-LABEL: @build_array_transmute_u
 #[no_mangle]
 pub fn build_array_transmute_u(x: [f32; 4]) -> U {
-    // CHECK: %[[VAL:.+]] = load <4 x float>, {{ptr %x|.+>\* %.+}}, align [[ARRAY_ALIGN]]
-    // CHECK: store <4 x float> %[[VAL:.+]], {{ptr %0|.+>\* %.+}}, align [[VECTOR_ALIGN]]
+    // CHECK: %[[VAL:.+]] = load <4 x float>, ptr %x, align [[ARRAY_ALIGN]]
+    // CHECK: store <4 x float> %[[VAL:.+]], ptr %_0, align [[VECTOR_ALIGN]]
     unsafe { std::mem::transmute(x) }
 }
diff --git a/tests/codegen/simd-wide-sum.rs b/tests/codegen/simd-wide-sum.rs
index db2aa20bde7..3116f9597bc 100644
--- a/tests/codegen/simd-wide-sum.rs
+++ b/tests/codegen/simd-wide-sum.rs
@@ -1,6 +1,11 @@
+// revisions: llvm mir-opt3
 // compile-flags: -C opt-level=3 -Z merge-functions=disabled --edition=2021
 // only-x86_64
 // ignore-debug: the debug assertions get in the way
+// [mir-opt3]compile-flags: -Zmir-opt-level=3
+// [mir-opt3]build-pass
+
+// mir-opt3 is a regression test for https://github.com/rust-lang/rust/issues/98016
 
 #![crate_type = "lib"]
 #![feature(portable_simd)]
@@ -47,9 +52,8 @@ pub fn wider_reduce_iter(x: Simd<u8, N>) -> u16 {
 #[no_mangle]
 // CHECK-LABEL: @wider_reduce_into_iter
 pub fn wider_reduce_into_iter(x: Simd<u8, N>) -> u16 {
-    // FIXME MIR inlining messes up LLVM optimizations.
-    // WOULD-CHECK: zext <8 x i8>
-    // WOULD-CHECK-SAME: to <8 x i16>
-    // WOULD-CHECK: call i16 @llvm.vector.reduce.add.v8i16(<8 x i16>
+    // CHECK: zext <8 x i8>
+    // CHECK-SAME: to <8 x i16>
+    // CHECK: call i16 @llvm.vector.reduce.add.v8i16(<8 x i16>
     x.to_array().into_iter().map(u16::from).sum()
 }
diff --git a/tests/codegen/simd_arith_offset.rs b/tests/codegen/simd_arith_offset.rs
index f2333777391..1ee73de1186 100644
--- a/tests/codegen/simd_arith_offset.rs
+++ b/tests/codegen/simd_arith_offset.rs
@@ -21,6 +21,6 @@ pub struct Simd<T, const LANES: usize>([T; LANES]);
 // CHECK-LABEL: smoke
 #[no_mangle]
 pub fn smoke(ptrs: SimdConstPtr<u8, 8>, offsets: Simd<usize, 8>) -> SimdConstPtr<u8, 8> {
-    // CHECK: getelementptr i8, <8 x {{i8\*|ptr}}> %1, <8 x i64> %2
+    // CHECK: getelementptr i8, <8 x ptr> %0, <8 x i64> %1
     unsafe { simd_arith_offset(ptrs, offsets) }
 }
diff --git a/tests/codegen/slice-init.rs b/tests/codegen/slice-init.rs
index 794b773a776..c0bf1a04119 100644
--- a/tests/codegen/slice-init.rs
+++ b/tests/codegen/slice-init.rs
@@ -8,7 +8,7 @@ pub fn zero_sized_elem() {
     // CHECK-NOT: br label %repeat_loop_header{{.*}}
     // CHECK-NOT: call void @llvm.memset.p0
     let x = [(); 4];
-    drop(&x);
+    opaque(&x);
 }
 
 // CHECK-LABEL: @zero_len_array
@@ -17,16 +17,16 @@ pub fn zero_len_array() {
     // CHECK-NOT: br label %repeat_loop_header{{.*}}
     // CHECK-NOT: call void @llvm.memset.p0
     let x = [4; 0];
-    drop(&x);
+    opaque(&x);
 }
 
 // CHECK-LABEL: @byte_array
 #[no_mangle]
 pub fn byte_array() {
-    // CHECK: call void @llvm.memset.{{.+}}({{i8\*|ptr}} {{.*}}, i8 7, i{{[0-9]+}} 4
+    // CHECK: call void @llvm.memset.{{.+}}(ptr {{.*}}, i8 7, i{{[0-9]+}} 4
     // CHECK-NOT: br label %repeat_loop_header{{.*}}
     let x = [7u8; 4];
-    drop(&x);
+    opaque(&x);
 }
 
 #[allow(dead_code)]
@@ -39,19 +39,19 @@ enum Init {
 // CHECK-LABEL: @byte_enum_array
 #[no_mangle]
 pub fn byte_enum_array() {
-    // CHECK: call void @llvm.memset.{{.+}}({{i8\*|ptr}} {{.*}}, i8 {{.*}}, i{{[0-9]+}} 4
+    // CHECK: call void @llvm.memset.{{.+}}(ptr {{.*}}, i8 {{.*}}, i{{[0-9]+}} 4
     // CHECK-NOT: br label %repeat_loop_header{{.*}}
     let x = [Init::Memset; 4];
-    drop(&x);
+    opaque(&x);
 }
 
 // CHECK-LABEL: @zeroed_integer_array
 #[no_mangle]
 pub fn zeroed_integer_array() {
-    // CHECK: call void @llvm.memset.{{.+}}({{i8\*|ptr}} {{.*}}, i8 0, i{{[0-9]+}} 16
+    // CHECK: call void @llvm.memset.{{.+}}(ptr {{.*}}, i8 0, i{{[0-9]+}} 16
     // CHECK-NOT: br label %repeat_loop_header{{.*}}
     let x = [0u32; 4];
-    drop(&x);
+    opaque(&x);
 }
 
 // CHECK-LABEL: @nonzero_integer_array
@@ -60,5 +60,9 @@ pub fn nonzero_integer_array() {
     // CHECK: br label %repeat_loop_header{{.*}}
     // CHECK-NOT: call void @llvm.memset.p0
     let x = [0x1a_2b_3c_4d_u32; 4];
-    drop(&x);
+    opaque(&x);
 }
+
+// Use an opaque function to prevent rustc from removing useless drops.
+#[inline(never)]
+pub fn opaque(_: impl Sized) {}
diff --git a/tests/codegen/slice-iter-fold.rs b/tests/codegen/slice-iter-fold.rs
new file mode 100644
index 00000000000..9391c176130
--- /dev/null
+++ b/tests/codegen/slice-iter-fold.rs
@@ -0,0 +1,14 @@
+// ignore-debug: the debug assertions get in the way
+// compile-flags: -O
+// min-llvm-version: 16
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @slice_fold_to_last
+#[no_mangle]
+pub fn slice_fold_to_last(slice: &[i32]) -> Option<&i32> {
+    // CHECK-NOT: loop
+    // CHECK-NOT: br
+    // CHECK-NOT: call
+    // CHECK: ret
+    slice.iter().fold(None, |_, i| Some(i))
+}
diff --git a/tests/codegen/slice-iter-len-eq-zero.rs b/tests/codegen/slice-iter-len-eq-zero.rs
index 894b0ec3de4..c7515ce35a3 100644
--- a/tests/codegen/slice-iter-len-eq-zero.rs
+++ b/tests/codegen/slice-iter-len-eq-zero.rs
@@ -9,8 +9,8 @@ type Demo = [u8; 3];
 #[no_mangle]
 pub fn slice_iter_len_eq_zero(y: std::slice::Iter<'_, Demo>) -> bool {
     // CHECK-NOT: sub
-    // CHECK: %2 = icmp eq {{i8\*|ptr}} {{%1|%0}}, {{%1|%0}}
-    // CHECK: ret i1 %2
+    // CHECK: %[[RET:.+]] = icmp eq ptr {{%1|%0}}, {{%1|%0}}
+    // CHECK: ret i1 %[[RET]]
     y.len() == 0
 }
 
@@ -22,7 +22,7 @@ pub fn array_into_iter_len_eq_zero(y: std::array::IntoIter<Demo, 123>) -> bool {
 
     // CHECK-NOT: icmp
     // CHECK-NOT: sub
-    // CHECK: %1 = icmp eq {{i16|i32|i64}}
-    // CHECK: ret i1 %1
+    // CHECK: %_0 = icmp eq {{i16|i32|i64}}
+    // CHECK: ret i1 %_0
     y.len() == 0
 }
diff --git a/tests/codegen/slice-iter-nonnull.rs b/tests/codegen/slice-iter-nonnull.rs
new file mode 100644
index 00000000000..f7d164bc856
--- /dev/null
+++ b/tests/codegen/slice-iter-nonnull.rs
@@ -0,0 +1,116 @@
+// no-system-llvm
+// compile-flags: -O
+// ignore-debug (these add extra checks that make it hard to verify)
+#![crate_type = "lib"]
+#![feature(exact_size_is_empty)]
+
+// The slice iterator used to `assume` that the `start` pointer was non-null.
+// That ought to be unneeded, though, since the type is `NonNull`, so this test
+// confirms that the appropriate metadata is included to denote that.
+
+// It also used to `assume` the `end` pointer was non-null, but that's no longer
+// needed as the code changed to read it as a `NonNull`, and thus gets the
+// appropriate `!nonnull` annotations naturally.
+
+// CHECK-LABEL: @slice_iter_next(
+#[no_mangle]
+pub fn slice_iter_next<'a>(it: &mut std::slice::Iter<'a, u32>) -> Option<&'a u32> {
+    // CHECK: %[[ENDP:.+]] = getelementptr{{.+}}ptr %it,{{.+}} 1
+    // CHECK: %[[END:.+]] = load ptr, ptr %[[ENDP]]
+    // CHECK-SAME: !nonnull
+    // CHECK-SAME: !noundef
+    // CHECK: %[[START:.+]] = load ptr, ptr %it,
+    // CHECK-SAME: !nonnull
+    // CHECK-SAME: !noundef
+    // CHECK: icmp eq ptr %[[START]], %[[END]]
+
+    // CHECK: store ptr{{.+}}, ptr %it,
+
+    it.next()
+}
+
+// CHECK-LABEL: @slice_iter_next_back(
+#[no_mangle]
+pub fn slice_iter_next_back<'a>(it: &mut std::slice::Iter<'a, u32>) -> Option<&'a u32> {
+    // CHECK: %[[ENDP:.+]] = getelementptr{{.+}}ptr %it,{{.+}} 1
+    // CHECK: %[[END:.+]] = load ptr, ptr %[[ENDP]]
+    // CHECK-SAME: !nonnull
+    // CHECK-SAME: !noundef
+    // CHECK: %[[START:.+]] = load ptr, ptr %it,
+    // CHECK-SAME: !nonnull
+    // CHECK-SAME: !noundef
+    // CHECK: icmp eq ptr %[[START]], %[[END]]
+
+    // CHECK: store ptr{{.+}}, ptr %[[ENDP]],
+
+    it.next_back()
+}
+
+// The slice iterator `new` methods used to `assume` that the pointer is non-null,
+// but passing slices already requires that, to the extent that LLVM actually
+// removed the `call @llvm.assume` anyway.  These tests just demonstrate that the
+// attribute is there, and confirms adding the assume back doesn't do anything.
+
+// CHECK-LABEL: @slice_iter_new
+// CHECK-SAME: (ptr noalias noundef nonnull {{.+}} %slice.0, {{.+}} noundef %slice.1)
+#[no_mangle]
+pub fn slice_iter_new(slice: &[u32]) -> std::slice::Iter<'_, u32> {
+    // CHECK-NOT: slice
+    // CHECK: %[[END:.+]] = getelementptr inbounds i32{{.+}} %slice.0{{.+}} %slice.1
+    // CHECK-NOT: slice
+    // CHECK: insertvalue {{.+}} ptr %slice.0, 0
+    // CHECK-NOT: slice
+    // CHECK: insertvalue {{.+}} ptr %[[END]], 1
+    // CHECK-NOT: slice
+    // CHECK: }
+    slice.iter()
+}
+
+// CHECK-LABEL: @slice_iter_mut_new
+// CHECK-SAME: (ptr noalias noundef nonnull {{.+}} %slice.0, {{.+}} noundef %slice.1)
+#[no_mangle]
+pub fn slice_iter_mut_new(slice: &mut [u32]) -> std::slice::IterMut<'_, u32> {
+    // CHECK-NOT: slice
+    // CHECK: %[[END:.+]] = getelementptr inbounds i32{{.+}} %slice.0{{.+}} %slice.1
+    // CHECK-NOT: slice
+    // CHECK: insertvalue {{.+}} ptr %slice.0, 0
+    // CHECK-NOT: slice
+    // CHECK: insertvalue {{.+}} ptr %[[END]], 1
+    // CHECK-NOT: slice
+    // CHECK: }
+    slice.iter_mut()
+}
+
+// CHECK-LABEL: @slice_iter_is_empty
+#[no_mangle]
+pub fn slice_iter_is_empty(it: &std::slice::Iter<'_, u32>) -> bool {
+    // CHECK: %[[ENDP:.+]] = getelementptr{{.+}}ptr %it,{{.+}} 1
+    // CHECK: %[[END:.+]] = load ptr, ptr %[[ENDP]]
+    // CHECK-SAME: !nonnull
+    // CHECK-SAME: !noundef
+    // CHECK: %[[START:.+]] = load ptr, ptr %it,
+    // CHECK-SAME: !nonnull
+    // CHECK-SAME: !noundef
+
+    // CHECK: %[[RET:.+]] = icmp eq ptr %[[START]], %[[END]]
+    // CHECK: ret i1 %[[RET]]
+    it.is_empty()
+}
+
+// CHECK-LABEL: @slice_iter_len
+#[no_mangle]
+pub fn slice_iter_len(it: &std::slice::Iter<'_, u32>) -> usize {
+    // CHECK: %[[START:.+]] = load ptr, ptr %it,
+    // CHECK-SAME: !nonnull
+    // CHECK-SAME: !noundef
+    // CHECK: %[[ENDP:.+]] = getelementptr{{.+}}ptr %it,{{.+}} 1
+    // CHECK: %[[END:.+]] = load ptr, ptr %[[ENDP]]
+    // CHECK-SAME: !nonnull
+    // CHECK-SAME: !noundef
+
+    // CHECK: ptrtoint
+    // CHECK: ptrtoint
+    // CHECK: sub nuw
+    // CHECK: lshr exact
+    it.len()
+}
diff --git a/tests/codegen/slice-ref-equality.rs b/tests/codegen/slice-ref-equality.rs
index 8f0adab35e7..4d0dce7b074 100644
--- a/tests/codegen/slice-ref-equality.rs
+++ b/tests/codegen/slice-ref-equality.rs
@@ -25,7 +25,7 @@ pub fn is_zero_slice_long(data: &[u8; 456]) -> bool {
 // CHECK-LABEL: @is_zero_slice_short
 #[no_mangle]
 pub fn is_zero_slice_short(data: &[u8; 4]) -> bool {
-    // CHECK: %[[LOAD:.+]] = load i32, {{i32\*|ptr}} %{{.+}}, align 1
+    // CHECK: %[[LOAD:.+]] = load i32, ptr %{{.+}}, align 1
     // CHECK-NEXT: %[[EQ:.+]] = icmp eq i32 %[[LOAD]], 0
     // CHECK-NEXT: ret i1 %[[EQ]]
     &data[..] == [0; 4]
@@ -34,7 +34,7 @@ pub fn is_zero_slice_short(data: &[u8; 4]) -> bool {
 // CHECK-LABEL: @is_zero_array
 #[no_mangle]
 pub fn is_zero_array(data: &[u8; 4]) -> bool {
-    // CHECK: %[[LOAD:.+]] = load i32, {{i32\*|ptr}} %{{.+}}, align 1
+    // CHECK: %[[LOAD:.+]] = load i32, ptr %{{.+}}, align 1
     // CHECK-NEXT: %[[EQ:.+]] = icmp eq i32 %[[LOAD]], 0
     // CHECK-NEXT: ret i1 %[[EQ]]
     *data == [0; 4]
@@ -44,49 +44,49 @@ pub fn is_zero_array(data: &[u8; 4]) -> bool {
 // equality for non-byte types also just emit a `bcmp`, not a loop.
 
 // CHECK-LABEL: @eq_slice_of_nested_u8(
-// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %1
-// CHECK-SAME: [[USIZE]] noundef %3
+// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %x.1
+// CHECK-SAME: [[USIZE]] noundef %y.1
 #[no_mangle]
 fn eq_slice_of_nested_u8(x: &[[u8; 3]], y: &[[u8; 3]]) -> bool {
-    // CHECK: icmp eq [[USIZE]] %1, %3
-    // CHECK: %[[BYTES:.+]] = mul nsw [[USIZE]] %1, 3
-    // CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}({{i8\*|ptr}}
+    // CHECK: icmp eq [[USIZE]] %x.1, %y.1
+    // CHECK: %[[BYTES:.+]] = mul nsw [[USIZE]] %x.1, 3
+    // CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}(ptr
     // CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]])
     x == y
 }
 
 // CHECK-LABEL: @eq_slice_of_i32(
-// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %1
-// CHECK-SAME: [[USIZE]] noundef %3
+// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %x.1
+// CHECK-SAME: [[USIZE]] noundef %y.1
 #[no_mangle]
 fn eq_slice_of_i32(x: &[i32], y: &[i32]) -> bool {
-    // CHECK: icmp eq [[USIZE]] %1, %3
-    // CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %1, 2
-    // CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}({{i32\*|ptr}}
+    // CHECK: icmp eq [[USIZE]] %x.1, %y.1
+    // CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %x.1, 2
+    // CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}(ptr
     // CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]])
     x == y
 }
 
 // CHECK-LABEL: @eq_slice_of_nonzero(
-// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %1
-// CHECK-SAME: [[USIZE]] noundef %3
+// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %x.1
+// CHECK-SAME: [[USIZE]] noundef %y.1
 #[no_mangle]
 fn eq_slice_of_nonzero(x: &[NonZeroU32], y: &[NonZeroU32]) -> bool {
-    // CHECK: icmp eq [[USIZE]] %1, %3
-    // CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %1, 2
-    // CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}({{i32\*|ptr}}
+    // CHECK: icmp eq [[USIZE]] %x.1, %y.1
+    // CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %x.1, 2
+    // CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}(ptr
     // CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]])
     x == y
 }
 
 // CHECK-LABEL: @eq_slice_of_option_of_nonzero(
-// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %1
-// CHECK-SAME: [[USIZE]] noundef %3
+// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %x.1
+// CHECK-SAME: [[USIZE]] noundef %y.1
 #[no_mangle]
 fn eq_slice_of_option_of_nonzero(x: &[Option<NonZeroI16>], y: &[Option<NonZeroI16>]) -> bool {
-    // CHECK: icmp eq [[USIZE]] %1, %3
-    // CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %1, 1
-    // CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}({{i16\*|ptr}}
+    // CHECK: icmp eq [[USIZE]] %x.1, %y.1
+    // CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %x.1, 1
+    // CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}(ptr
     // CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]])
     x == y
 }
diff --git a/tests/codegen/slice_as_from_ptr_range.rs b/tests/codegen/slice_as_from_ptr_range.rs
index 0e3fefd9728..3d8ab0a4b5f 100644
--- a/tests/codegen/slice_as_from_ptr_range.rs
+++ b/tests/codegen/slice_as_from_ptr_range.rs
@@ -1,7 +1,6 @@
 // compile-flags: -O
 // only-64bit (because we're using [ui]size)
 // ignore-debug (because the assertions get in the way)
-// min-llvm-version: 15.0 (because this is a relatively new instcombine)
 
 #![crate_type = "lib"]
 #![feature(slice_from_ptr_range)]
diff --git a/tests/codegen/split-lto-unit.rs b/tests/codegen/split-lto-unit.rs
new file mode 100644
index 00000000000..dc6570be32b
--- /dev/null
+++ b/tests/codegen/split-lto-unit.rs
@@ -0,0 +1,11 @@
+// Verifies that "EnableSplitLTOUnit" module flag is added.
+//
+// needs-sanitizer-cfi
+// compile-flags: -Clto -Ctarget-feature=-crt-static -Zsplit-lto-unit
+
+#![crate_type="lib"]
+
+pub fn foo() {
+}
+
+// CHECK: !{{[0-9]+}} = !{i32 4, !"EnableSplitLTOUnit", i32 1}
diff --git a/tests/codegen/stack-protector.rs b/tests/codegen/stack-protector.rs
index a24e6f1e4f1..a680789af15 100644
--- a/tests/codegen/stack-protector.rs
+++ b/tests/codegen/stack-protector.rs
@@ -10,25 +10,25 @@
 pub fn foo() {
     // CHECK: @foo() unnamed_addr #0
 
-    // all-NOT: attributes #0 = { {{.*}} sspstrong {{.*}} }
-    // all-NOT: attributes #0 = { {{.*}} ssp {{.*}} }
-    // all: attributes #0 = { {{.*}} sspreq {{.*}} }
-    // all-NOT: attributes #0 = { {{.*}} sspstrong {{.*}} }
-    // all-NOT: attributes #0 = { {{.*}} ssp {{.*}} }
+    // all-NOT: attributes #0 = { {{.*}}sspstrong {{.*}} }
+    // all-NOT: attributes #0 = { {{.*}}ssp {{.*}} }
+    // all: attributes #0 = { {{.*}}sspreq {{.*}} }
+    // all-NOT: attributes #0 = { {{.*}}sspstrong {{.*}} }
+    // all-NOT: attributes #0 = { {{.*}}ssp {{.*}} }
 
-    // strong-NOT: attributes #0 = { {{.*}} sspreq {{.*}} }
-    // strong-NOT: attributes #0 = { {{.*}} ssp {{.*}} }
-    // strong: attributes #0 = { {{.*}} sspstrong {{.*}} }
-    // strong-NOT: attributes #0 = { {{.*}} sspreq {{.*}} }
-    // strong-NOT: attributes #0 = { {{.*}} ssp {{.*}} }
+    // strong-NOT: attributes #0 = { {{.*}}sspreq {{.*}} }
+    // strong-NOT: attributes #0 = { {{.*}}ssp {{.*}} }
+    // strong: attributes #0 = { {{.*}}sspstrong {{.*}} }
+    // strong-NOT: attributes #0 = { {{.*}}sspreq {{.*}} }
+    // strong-NOT: attributes #0 = { {{.*}}ssp {{.*}} }
 
-    // basic-NOT: attributes #0 = { {{.*}} sspreq {{.*}} }
-    // basic-NOT: attributes #0 = { {{.*}} sspstrong {{.*}} }
-    // basic: attributes #0 = { {{.*}} ssp {{.*}} }
-    // basic-NOT: attributes #0 = { {{.*}} sspreq {{.*}} }
-    // basic-NOT: attributes #0 = { {{.*}} sspstrong {{.*}} }
+    // basic-NOT: attributes #0 = { {{.*}}sspreq {{.*}} }
+    // basic-NOT: attributes #0 = { {{.*}}sspstrong {{.*}} }
+    // basic: attributes #0 = { {{.*}}ssp {{.*}} }
+    // basic-NOT: attributes #0 = { {{.*}}sspreq {{.*}} }
+    // basic-NOT: attributes #0 = { {{.*}}sspstrong {{.*}} }
 
-    // none-NOT: attributes #0 = { {{.*}} sspreq {{.*}} }
-    // none-NOT: attributes #0 = { {{.*}} sspstrong {{.*}} }
-    // none-NOT: attributes #0 = { {{.*}} ssp {{.*}} }
+    // none-NOT: attributes #0 = { {{.*}}sspreq {{.*}} }
+    // none-NOT: attributes #0 = { {{.*}}sspstrong {{.*}} }
+    // none-NOT: attributes #0 = { {{.*}}ssp {{.*}} }
 }
diff --git a/tests/codegen/stores.rs b/tests/codegen/stores.rs
index 837256e5369..a8e155c4c8a 100644
--- a/tests/codegen/stores.rs
+++ b/tests/codegen/stores.rs
@@ -17,8 +17,8 @@ pub struct Bytes {
 pub fn small_array_alignment(x: &mut [i8; 4], y: [i8; 4]) {
 // CHECK: [[TMP:%.+]] = alloca i32
 // CHECK: %y = alloca [4 x i8]
-// CHECK: store i32 %0, {{i32\*|ptr}} [[TMP]]
-// CHECK: call void @llvm.memcpy.{{.*}}({{i8\*|ptr}} align 1 {{.+}}, {{i8\*|ptr}} align 4 {{.+}}, i{{[0-9]+}} 4, i1 false)
+// CHECK: store i32 %0, ptr [[TMP]]
+// CHECK: call void @llvm.memcpy.{{.*}}(ptr align 1 {{.+}}, ptr align 4 {{.+}}, i{{[0-9]+}} 4, i1 false)
     *x = y;
 }
 
@@ -29,7 +29,7 @@ pub fn small_array_alignment(x: &mut [i8; 4], y: [i8; 4]) {
 pub fn small_struct_alignment(x: &mut Bytes, y: Bytes) {
 // CHECK: [[TMP:%.+]] = alloca i32
 // CHECK: %y = alloca %Bytes
-// CHECK: store i32 %0, {{i32\*|ptr}} [[TMP]]
-// CHECK: call void @llvm.memcpy.{{.*}}({{i8\*|ptr}} align 1 {{.+}}, {{i8\*|ptr}} align 4 {{.+}}, i{{[0-9]+}} 4, i1 false)
+// CHECK: store i32 %0, ptr [[TMP]]
+// CHECK: call void @llvm.memcpy.{{.*}}(ptr align 1 {{.+}}, ptr align 4 {{.+}}, i{{[0-9]+}} 4, i1 false)
     *x = y;
 }
diff --git a/tests/codegen/swap-large-types.rs b/tests/codegen/swap-large-types.rs
index 4a68403578d..7b6611f3da4 100644
--- a/tests/codegen/swap-large-types.rs
+++ b/tests/codegen/swap-large-types.rs
@@ -83,9 +83,9 @@ pub struct BigButHighlyAligned([u8; 64 * 3]);
 #[no_mangle]
 pub fn swap_big_aligned(x: &mut BigButHighlyAligned, y: &mut BigButHighlyAligned) {
 // CHECK-NOT: call void @llvm.memcpy
-// CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} noundef nonnull align 64 dereferenceable(192)
-// CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} noundef nonnull align 64 dereferenceable(192)
-// CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} noundef nonnull align 64 dereferenceable(192)
+// CHECK: call void @llvm.memcpy.{{.+}}(ptr noundef nonnull align 64 dereferenceable(192)
+// CHECK: call void @llvm.memcpy.{{.+}}(ptr noundef nonnull align 64 dereferenceable(192)
+// CHECK: call void @llvm.memcpy.{{.+}}(ptr noundef nonnull align 64 dereferenceable(192)
 // CHECK-NOT: call void @llvm.memcpy
     swap(x, y)
 }
diff --git a/tests/codegen/swap-simd-types.rs b/tests/codegen/swap-simd-types.rs
index c90b277eb44..3472a42b0e6 100644
--- a/tests/codegen/swap-simd-types.rs
+++ b/tests/codegen/swap-simd-types.rs
@@ -30,3 +30,12 @@ pub fn swap_m256_slice(x: &mut [__m256], y: &mut [__m256]) {
         x.swap_with_slice(y);
     }
 }
+
+// CHECK-LABEL: @swap_bytes32
+#[no_mangle]
+pub fn swap_bytes32(x: &mut [u8; 32], y: &mut [u8; 32]) {
+// CHECK-NOT: alloca
+// CHECK: load <32 x i8>{{.+}}align 1
+// CHECK: store <32 x i8>{{.+}}align 1
+    swap(x, y)
+}
diff --git a/tests/codegen/swap-small-types.rs b/tests/codegen/swap-small-types.rs
index 03e2a2327fc..419645a3fc6 100644
--- a/tests/codegen/swap-small-types.rs
+++ b/tests/codegen/swap-small-types.rs
@@ -1,4 +1,4 @@
-// compile-flags: -O
+// compile-flags: -O -Z merge-functions=disabled
 // only-x86_64
 // ignore-debug: the debug assertions get in the way
 
@@ -8,13 +8,28 @@ use std::mem::swap;
 
 type RGB48 = [u16; 3];
 
+// CHECK-LABEL: @swap_rgb48_manually(
+#[no_mangle]
+pub fn swap_rgb48_manually(x: &mut RGB48, y: &mut RGB48) {
+    // CHECK-NOT: alloca
+    // CHECK: %[[TEMP0:.+]] = load <3 x i16>, ptr %x, align 2
+    // CHECK: %[[TEMP1:.+]] = load <3 x i16>, ptr %y, align 2
+    // CHECK: store <3 x i16> %[[TEMP1]], ptr %x, align 2
+    // CHECK: store <3 x i16> %[[TEMP0]], ptr %y, align 2
+
+    let temp = *x;
+    *x = *y;
+    *y = temp;
+}
+
 // CHECK-LABEL: @swap_rgb48
 #[no_mangle]
 pub fn swap_rgb48(x: &mut RGB48, y: &mut RGB48) {
-    // FIXME MIR inlining messes up LLVM optimizations.
-// WOULD-CHECK-NOT: alloca
-// WOULD-CHECK: load i48
-// WOULD-CHECK: store i48
+    // CHECK-NOT: alloca
+    // CHECK: load <3 x i16>
+    // CHECK: load <3 x i16>
+    // CHECK: store <3 x i16>
+    // CHECK: store <3 x i16>
     swap(x, y)
 }
 
diff --git a/tests/codegen/target-feature-inline-closure.rs b/tests/codegen/target-feature-inline-closure.rs
new file mode 100644
index 00000000000..d075706173f
--- /dev/null
+++ b/tests/codegen/target-feature-inline-closure.rs
@@ -0,0 +1,33 @@
+// only-x86_64
+// compile-flags: -Copt-level=3
+
+#![crate_type = "lib"]
+#![feature(target_feature_11)]
+
+#[cfg(target_arch = "x86_64")]
+use std::arch::x86_64::*;
+
+// CHECK-LABEL: @with_avx
+#[no_mangle]
+#[cfg(target_arch = "x86_64")]
+#[target_feature(enable = "avx")]
+fn with_avx(x: __m256) -> __m256 {
+    // CHECK: fadd
+    let add = {
+        #[inline(always)]
+        |x, y| unsafe { _mm256_add_ps(x, y) }
+    };
+    add(x, x)
+}
+
+// CHECK-LABEL: @without_avx
+#[no_mangle]
+#[cfg(target_arch = "x86_64")]
+unsafe fn without_avx(x: __m256) -> __m256 {
+    // CHECK-NOT: fadd
+    let add = {
+        #[inline(always)]
+        |x, y| unsafe { _mm256_add_ps(x, y) }
+    };
+    add(x, x)
+}
diff --git a/tests/codegen/tied-features-strength.rs b/tests/codegen/tied-features-strength.rs
new file mode 100644
index 00000000000..51334c12158
--- /dev/null
+++ b/tests/codegen/tied-features-strength.rs
@@ -0,0 +1,29 @@
+// ignore-tidy-linelength
+// revisions: ENABLE_SVE DISABLE_SVE DISABLE_NEON ENABLE_NEON
+// compile-flags: --crate-type=rlib --target=aarch64-unknown-linux-gnu
+// needs-llvm-components: aarch64
+
+// The "+v8a" feature is matched as optional as it isn't added when we
+// are targeting older LLVM versions. Once the min supported version
+// is LLVM-14 we can remove the optional regex matching for this feature.
+
+// [ENABLE_SVE] compile-flags: -C target-feature=+sve
+// ENABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(\+sve,?)|(\+neon,?))*}}" }
+
+// [DISABLE_SVE] compile-flags: -C target-feature=-sve
+// DISABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(-sve,?)|(\+neon,?))*}}" }
+
+// [DISABLE_NEON] compile-flags: -C target-feature=-neon
+// DISABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(-fp-armv8,?)|(-neon,?))*}}" }
+
+// [ENABLE_NEON] compile-flags: -C target-feature=+neon
+// ENABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(\+fp-armv8,?)|(\+neon,?))*}}" }
+
+
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+
+pub fn test() {}
diff --git a/tests/codegen/transmute-optimized.rs b/tests/codegen/transmute-optimized.rs
new file mode 100644
index 00000000000..b8c51b08499
--- /dev/null
+++ b/tests/codegen/transmute-optimized.rs
@@ -0,0 +1,108 @@
+// compile-flags: -O -Z merge-functions=disabled
+// ignore-debug
+
+#![crate_type = "lib"]
+
+// This tests that LLVM can optimize based on the niches in the source or
+// destination types for transmutes.
+
+#[repr(u32)]
+pub enum AlwaysZero32 { X = 0 }
+
+// CHECK-LABEL: i32 @issue_109958(i32
+#[no_mangle]
+pub fn issue_109958(x: AlwaysZero32) -> i32 {
+    // CHECK: ret i32 0
+    unsafe { std::mem::transmute(x) }
+}
+
+// CHECK-LABEL: i1 @reference_is_null(ptr
+#[no_mangle]
+pub fn reference_is_null(x: &i32) -> bool {
+    // CHECK: ret i1 false
+    let p: *const i32 = unsafe { std::mem::transmute(x) };
+    p.is_null()
+}
+
+// CHECK-LABEL: i1 @non_null_is_null(ptr
+#[no_mangle]
+pub fn non_null_is_null(x: std::ptr::NonNull<i32>) -> bool {
+    // CHECK: ret i1 false
+    let p: *const i32 = unsafe { std::mem::transmute(x) };
+    p.is_null()
+}
+
+// CHECK-LABEL: i1 @non_zero_is_null(
+#[no_mangle]
+pub fn non_zero_is_null(x: std::num::NonZeroUsize) -> bool {
+    // CHECK: ret i1 false
+    let p: *const i32 = unsafe { std::mem::transmute(x) };
+    p.is_null()
+}
+
+// CHECK-LABEL: i1 @non_null_is_zero(ptr
+#[no_mangle]
+pub fn non_null_is_zero(x: std::ptr::NonNull<i32>) -> bool {
+    // CHECK: ret i1 false
+    let a: isize = unsafe { std::mem::transmute(x) };
+    a == 0
+}
+
+// CHECK-LABEL: i1 @bool_ordering_is_ge(i1
+#[no_mangle]
+pub fn bool_ordering_is_ge(x: bool) -> bool {
+    // CHECK: ret i1 true
+    let y: std::cmp::Ordering = unsafe { std::mem::transmute(x) };
+    y.is_ge()
+}
+
+// CHECK-LABEL: i1 @ordering_is_ge_then_transmute_to_bool(i8
+#[no_mangle]
+pub fn ordering_is_ge_then_transmute_to_bool(x: std::cmp::Ordering) -> bool {
+    let r = x.is_ge();
+    let _: bool = unsafe { std::mem::transmute(x) };
+    r
+}
+
+// CHECK-LABEL: i32 @normal_div(i32
+#[no_mangle]
+pub fn normal_div(a: u32, b: u32) -> u32 {
+    // CHECK: call core::panicking::panic
+    a / b
+}
+
+// CHECK-LABEL: i32 @div_transmute_nonzero(i32
+#[no_mangle]
+pub fn div_transmute_nonzero(a: u32, b: std::num::NonZeroI32) -> u32 {
+    // CHECK-NOT: call core::panicking::panic
+    // CHECK: %[[R:.+]] = udiv i32 %a, %b
+    // CHECK-NEXT: ret i32 %[[R]]
+    // CHECK-NOT: call core::panicking::panic
+    let d: u32 = unsafe { std::mem::transmute(b) };
+    a / d
+}
+
+#[repr(i8)]
+pub enum OneTwoThree { One = 1, Two = 2, Three = 3 }
+
+// CHECK-LABEL: i8 @ordering_transmute_onetwothree(i8
+#[no_mangle]
+pub unsafe fn ordering_transmute_onetwothree(x: std::cmp::Ordering) -> OneTwoThree {
+    // CHECK: ret i8 1
+    std::mem::transmute(x)
+}
+
+// CHECK-LABEL: i8 @onetwothree_transmute_ordering(i8
+#[no_mangle]
+pub unsafe fn onetwothree_transmute_ordering(x: OneTwoThree) -> std::cmp::Ordering {
+    // CHECK: ret i8 1
+    std::mem::transmute(x)
+}
+
+// CHECK-LABEL: i1 @char_is_negative(i32
+#[no_mangle]
+pub fn char_is_negative(c: char) -> bool {
+    // CHECK: ret i1 false
+    let x: i32 = unsafe { std::mem::transmute(c) };
+    x < 0
+}
diff --git a/tests/codegen/transmute-scalar.rs b/tests/codegen/transmute-scalar.rs
index af2cef472ec..39126b024a6 100644
--- a/tests/codegen/transmute-scalar.rs
+++ b/tests/codegen/transmute-scalar.rs
@@ -1,5 +1,4 @@
-// compile-flags: -O -C no-prepopulate-passes
-// min-llvm-version: 15.0 # this test assumes `ptr`s and thus no `pointercast`s
+// compile-flags: -C opt-level=0 -C no-prepopulate-passes
 
 #![crate_type = "lib"]
 
@@ -10,48 +9,48 @@
 // However, `bitcast`s and `ptrtoint`s and `inttoptr`s are still worth doing when
 // that allows us to avoid the `alloca`s entirely; see `rvalue_creates_operand`.
 
-// CHECK-LABEL: define{{.*}}i32 @f32_to_bits(float noundef %x)
-// CHECK: %0 = bitcast float %x to i32
-// CHECK-NEXT: ret i32 %0
+// CHECK-LABEL: define{{.*}}i32 @f32_to_bits(float %x)
+// CHECK: %_0 = bitcast float %x to i32
+// CHECK-NEXT: ret i32 %_0
 #[no_mangle]
 pub fn f32_to_bits(x: f32) -> u32 {
     unsafe { std::mem::transmute(x) }
 }
 
-// CHECK-LABEL: define{{.*}}i8 @bool_to_byte(i1 noundef zeroext %b)
-// CHECK: %0 = zext i1 %b to i8
-// CHECK-NEXT: ret i8 %0
+// CHECK-LABEL: define{{.*}}i8 @bool_to_byte(i1 zeroext %b)
+// CHECK: %_0 = zext i1 %b to i8
+// CHECK-NEXT: ret i8 %_0
 #[no_mangle]
 pub fn bool_to_byte(b: bool) -> u8 {
     unsafe { std::mem::transmute(b) }
 }
 
-// CHECK-LABEL: define{{.*}}noundef zeroext i1 @byte_to_bool(i8 noundef %byte)
-// CHECK: %0 = trunc i8 %byte to i1
-// CHECK-NEXT: ret i1 %0
+// CHECK-LABEL: define{{.*}}zeroext i1 @byte_to_bool(i8 %byte)
+// CHECK: %_0 = trunc i8 %byte to i1
+// CHECK-NEXT: ret i1 %_0
 #[no_mangle]
 pub unsafe fn byte_to_bool(byte: u8) -> bool {
     std::mem::transmute(byte)
 }
 
-// CHECK-LABEL: define{{.*}}ptr @ptr_to_ptr(ptr noundef %p)
+// CHECK-LABEL: define{{.*}}ptr @ptr_to_ptr(ptr %p)
 // CHECK: ret ptr %p
 #[no_mangle]
 pub fn ptr_to_ptr(p: *mut u16) -> *mut u8 {
     unsafe { std::mem::transmute(p) }
 }
 
-// CHECK: define{{.*}}[[USIZE:i[0-9]+]] @ptr_to_int(ptr noundef %p)
-// CHECK: %0 = ptrtoint ptr %p to [[USIZE]]
-// CHECK-NEXT: ret [[USIZE]] %0
+// CHECK: define{{.*}}[[USIZE:i[0-9]+]] @ptr_to_int(ptr %p)
+// CHECK: %_0 = ptrtoint ptr %p to [[USIZE]]
+// CHECK-NEXT: ret [[USIZE]] %_0
 #[no_mangle]
 pub fn ptr_to_int(p: *mut u16) -> usize {
     unsafe { std::mem::transmute(p) }
 }
 
-// CHECK: define{{.*}}ptr @int_to_ptr([[USIZE]] noundef %i)
-// CHECK: %0 = inttoptr [[USIZE]] %i to ptr
-// CHECK-NEXT: ret ptr %0
+// CHECK: define{{.*}}ptr @int_to_ptr([[USIZE]] %i)
+// CHECK: %_0 = inttoptr [[USIZE]] %i to ptr
+// CHECK-NEXT: ret ptr %_0
 #[no_mangle]
 pub fn int_to_ptr(i: usize) -> *mut u16 {
     unsafe { std::mem::transmute(i) }
diff --git a/tests/codegen/try_question_mark_nop.rs b/tests/codegen/try_question_mark_nop.rs
index d239387768e..9d34155bdd7 100644
--- a/tests/codegen/try_question_mark_nop.rs
+++ b/tests/codegen/try_question_mark_nop.rs
@@ -1,4 +1,3 @@
-// min-llvm-version: 15.0
 // compile-flags: -O -Z merge-functions=disabled --edition=2021
 // only-x86_64
 
diff --git a/tests/codegen/tuple-layout-opt.rs b/tests/codegen/tuple-layout-opt.rs
index 35f76085145..309fe1d5ec9 100644
--- a/tests/codegen/tuple-layout-opt.rs
+++ b/tests/codegen/tuple-layout-opt.rs
@@ -6,31 +6,31 @@
 #![crate_type="lib"]
 
 type ScalarZstLast = (u128, ());
-// CHECK: define i128 @test_ScalarZstLast(i128 %_1)
+// CHECK: define {{(dso_local )?}}i128 @test_ScalarZstLast(i128 %_1)
 #[no_mangle]
 pub fn test_ScalarZstLast(_: ScalarZstLast) -> ScalarZstLast { loop {} }
 
 type ScalarZstFirst = ((), u128);
-// CHECK: define i128 @test_ScalarZstFirst(i128 %_1)
+// CHECK: define {{(dso_local )?}}i128 @test_ScalarZstFirst(i128 %_1)
 #[no_mangle]
 pub fn test_ScalarZstFirst(_: ScalarZstFirst) -> ScalarZstFirst { loop {} }
 
 type ScalarPairZstLast = (u8, u128, ());
-// CHECK: define { i128, i8 } @test_ScalarPairZstLast(i128 %_1.0, i8 %_1.1)
+// CHECK: define {{(dso_local )?}}{ i128, i8 } @test_ScalarPairZstLast(i128 %_1.0, i8 %_1.1)
 #[no_mangle]
 pub fn test_ScalarPairZstLast(_: ScalarPairZstLast) -> ScalarPairZstLast { loop {} }
 
 type ScalarPairZstFirst = ((), u8, u128);
-// CHECK: define { i8, i128 } @test_ScalarPairZstFirst(i8 %_1.0, i128 %_1.1)
+// CHECK: define {{(dso_local )?}}{ i8, i128 } @test_ScalarPairZstFirst(i8 %_1.0, i128 %_1.1)
 #[no_mangle]
 pub fn test_ScalarPairZstFirst(_: ScalarPairZstFirst) -> ScalarPairZstFirst { loop {} }
 
 type ScalarPairLotsOfZsts = ((), u8, (), u128, ());
-// CHECK: define { i128, i8 } @test_ScalarPairLotsOfZsts(i128 %_1.0, i8 %_1.1)
+// CHECK: define {{(dso_local )?}}{ i128, i8 } @test_ScalarPairLotsOfZsts(i128 %_1.0, i8 %_1.1)
 #[no_mangle]
 pub fn test_ScalarPairLotsOfZsts(_: ScalarPairLotsOfZsts) -> ScalarPairLotsOfZsts { loop {} }
 
 type ScalarPairLottaNesting = (((), ((), u8, (), u128, ())), ());
-// CHECK: define { i128, i8 } @test_ScalarPairLottaNesting(i128 %_1.0, i8 %_1.1)
+// CHECK: define {{(dso_local )?}}{ i128, i8 } @test_ScalarPairLottaNesting(i128 %_1.0, i8 %_1.1)
 #[no_mangle]
 pub fn test_ScalarPairLottaNesting(_: ScalarPairLottaNesting) -> ScalarPairLottaNesting { loop {} }
diff --git a/tests/codegen/unchecked_shifts.rs b/tests/codegen/unchecked_shifts.rs
index 60d0cb09aca..d5f53bedd54 100644
--- a/tests/codegen/unchecked_shifts.rs
+++ b/tests/codegen/unchecked_shifts.rs
@@ -1,5 +1,4 @@
 // compile-flags: -O
-// min-llvm-version: 15.0 (LLVM 13 in CI does this differently from submodule LLVM)
 // ignore-debug (because unchecked is checked in debug)
 
 #![crate_type = "lib"]
@@ -8,6 +7,7 @@
 // CHECK-LABEL: @unchecked_shl_unsigned_same
 #[no_mangle]
 pub unsafe fn unchecked_shl_unsigned_same(a: u32, b: u32) -> u32 {
+    // CHECK-NOT: assume
     // CHECK-NOT: and i32
     // CHECK: shl i32 %a, %b
     // CHECK-NOT: and i32
@@ -30,6 +30,7 @@ pub unsafe fn unchecked_shl_unsigned_smaller(a: u16, b: u32) -> u16 {
 // CHECK-LABEL: @unchecked_shl_unsigned_bigger
 #[no_mangle]
 pub unsafe fn unchecked_shl_unsigned_bigger(a: u64, b: u32) -> u64 {
+    // CHECK-NOT: assume
     // CHECK: %[[EXT:.+]] = zext i32 %b to i64
     // CHECK: shl i64 %a, %[[EXT]]
     a.unchecked_shl(b)
@@ -38,6 +39,7 @@ pub unsafe fn unchecked_shl_unsigned_bigger(a: u64, b: u32) -> u64 {
 // CHECK-LABEL: @unchecked_shr_signed_same
 #[no_mangle]
 pub unsafe fn unchecked_shr_signed_same(a: i32, b: u32) -> i32 {
+    // CHECK-NOT: assume
     // CHECK-NOT: and i32
     // CHECK: ashr i32 %a, %b
     // CHECK-NOT: and i32
@@ -60,6 +62,7 @@ pub unsafe fn unchecked_shr_signed_smaller(a: i16, b: u32) -> i16 {
 // CHECK-LABEL: @unchecked_shr_signed_bigger
 #[no_mangle]
 pub unsafe fn unchecked_shr_signed_bigger(a: i64, b: u32) -> i64 {
+    // CHECK-NOT: assume
     // CHECK: %[[EXT:.+]] = zext i32 %b to i64
     // CHECK: ashr i64 %a, %[[EXT]]
     a.unchecked_shr(b)
diff --git a/tests/codegen/uninit-consts.rs b/tests/codegen/uninit-consts.rs
index 54e9a9e9bb8..1313e67634a 100644
--- a/tests/codegen/uninit-consts.rs
+++ b/tests/codegen/uninit-consts.rs
@@ -8,7 +8,7 @@ use std::mem::MaybeUninit;
 
 pub struct PartiallyUninit {
     x: u32,
-    y: MaybeUninit<[u8; 10]>
+    y: MaybeUninit<[u8; 10]>,
 }
 
 // CHECK: [[FULLY_UNINIT:@[0-9]+]] = private unnamed_addr constant <{ [10 x i8] }> undef
@@ -25,7 +25,7 @@ pub struct PartiallyUninit {
 #[no_mangle]
 pub const fn fully_uninit() -> MaybeUninit<[u8; 10]> {
     const M: MaybeUninit<[u8; 10]> = MaybeUninit::uninit();
-    // CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 1 %{{[0-9]+}}, {{i8\*|ptr}} align 1 {{.*}}[[FULLY_UNINIT]]{{.*}}, i{{(32|64)}} 10, i1 false)
+    // CHECK: call void @llvm.memcpy.{{.+}}(ptr align 1 %_0, ptr align 1 {{.*}}[[FULLY_UNINIT]]{{.*}}, i{{(32|64)}} 10, i1 false)
     M
 }
 
@@ -33,7 +33,7 @@ pub const fn fully_uninit() -> MaybeUninit<[u8; 10]> {
 #[no_mangle]
 pub const fn partially_uninit() -> PartiallyUninit {
     const X: PartiallyUninit = PartiallyUninit { x: 0xdeadbeef, y: MaybeUninit::uninit() };
-    // CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 4 %{{[0-9]+}}, {{i8\*|ptr}} align 4 {{.*}}[[PARTIALLY_UNINIT]]{{.*}}, i{{(32|64)}} 16, i1 false)
+    // CHECK: call void @llvm.memcpy.{{.+}}(ptr align 4 %_0, ptr align 4 {{.*}}[[PARTIALLY_UNINIT]]{{.*}}, i{{(32|64)}} 16, i1 false)
     X
 }
 
@@ -41,7 +41,7 @@ pub const fn partially_uninit() -> PartiallyUninit {
 #[no_mangle]
 pub const fn uninit_padding_huge() -> [(u32, u8); 4096] {
     const X: [(u32, u8); 4096] = [(123, 45); 4096];
-    // CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 4 %{{[0-9]+}}, {{i8\*|ptr}} align 4 {{.*}}[[UNINIT_PADDING_HUGE]]{{.*}}, i{{(32|64)}} 32768, i1 false)
+    // CHECK: call void @llvm.memcpy.{{.+}}(ptr align 4 %_0, ptr align 4 {{.*}}[[UNINIT_PADDING_HUGE]]{{.*}}, i{{(32|64)}} 32768, i1 false)
     X
 }
 
@@ -49,6 +49,6 @@ pub const fn uninit_padding_huge() -> [(u32, u8); 4096] {
 #[no_mangle]
 pub const fn fully_uninit_huge() -> MaybeUninit<[u32; 4096]> {
     const F: MaybeUninit<[u32; 4096]> = MaybeUninit::uninit();
-    // CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 4 %{{[0-9]+}}, {{i8\*|ptr}} align 4 {{.*}}[[FULLY_UNINIT_HUGE]]{{.*}}, i{{(32|64)}} 16384, i1 false)
+    // CHECK: call void @llvm.memcpy.{{.+}}(ptr align 4 %_0, ptr align 4 {{.*}}[[FULLY_UNINIT_HUGE]]{{.*}}, i{{(32|64)}} 16384, i1 false)
     F
 }
diff --git a/tests/codegen/union-abi.rs b/tests/codegen/union-abi.rs
index c18f2a49fc3..4878ae5c3b6 100644
--- a/tests/codegen/union-abi.rs
+++ b/tests/codegen/union-abi.rs
@@ -17,60 +17,60 @@ pub struct i64x4(i64, i64, i64, i64);
 #[derive(Copy, Clone)]
 pub union UnionI64x4{ a:(), b: i64x4 }
 
-// CHECK: define void @test_UnionI64x4({{<4 x i64>\*|ptr}} {{.*}} %_1)
+// CHECK: define {{(dso_local )?}}void @test_UnionI64x4(ptr {{.*}} %_1)
 #[no_mangle]
 pub fn test_UnionI64x4(_: UnionI64x4) { loop {} }
 
 pub union UnionI64x4_{ a: i64x4, b: (), c:i64x4, d: Unhab, e: ((),()), f: UnionI64x4 }
 
-// CHECK: define void @test_UnionI64x4_({{<4 x i64>\*|ptr}} {{.*}} %_1)
+// CHECK: define {{(dso_local )?}}void @test_UnionI64x4_(ptr {{.*}} %_1)
 #[no_mangle]
 pub fn test_UnionI64x4_(_: UnionI64x4_) { loop {} }
 
 pub union UnionI64x4I64{ a: i64x4, b: i64 }
 
-// CHECK: define void @test_UnionI64x4I64({{%UnionI64x4I64\*|ptr}} {{.*}} %_1)
+// CHECK: define {{(dso_local )?}}void @test_UnionI64x4I64(ptr {{.*}} %_1)
 #[no_mangle]
 pub fn test_UnionI64x4I64(_: UnionI64x4I64) { loop {} }
 
 pub union UnionI64x4Tuple{ a: i64x4, b: (i64, i64, i64, i64) }
 
-// CHECK: define void @test_UnionI64x4Tuple({{%UnionI64x4Tuple\*|ptr}} {{.*}} %_1)
+// CHECK: define {{(dso_local )?}}void @test_UnionI64x4Tuple(ptr {{.*}} %_1)
 #[no_mangle]
 pub fn test_UnionI64x4Tuple(_: UnionI64x4Tuple) { loop {} }
 
 
 pub union UnionF32{a:f32}
 
-// CHECK: define float @test_UnionF32(float %_1)
+// CHECK: define {{(dso_local )?}}float @test_UnionF32(float %_1)
 #[no_mangle]
 pub fn test_UnionF32(_: UnionF32) -> UnionF32 { loop {} }
 
 pub union UnionF32F32{a:f32, b:f32}
 
-// CHECK: define float @test_UnionF32F32(float %_1)
+// CHECK: define {{(dso_local )?}}float @test_UnionF32F32(float %_1)
 #[no_mangle]
 pub fn test_UnionF32F32(_: UnionF32F32) -> UnionF32F32 { loop {} }
 
 pub union UnionF32U32{a:f32, b:u32}
 
-// CHECK: define i32 @test_UnionF32U32(i32{{( %0)?}})
+// CHECK: define {{(dso_local )?}}i32 @test_UnionF32U32(i32{{( %0)?}})
 #[no_mangle]
 pub fn test_UnionF32U32(_: UnionF32U32) -> UnionF32U32 { loop {} }
 
 pub union UnionU128{a:u128}
-// CHECK: define i128 @test_UnionU128(i128 %_1)
+// CHECK: define {{(dso_local )?}}i128 @test_UnionU128(i128 %_1)
 #[no_mangle]
 pub fn test_UnionU128(_: UnionU128) -> UnionU128 { loop {} }
 
 #[repr(C)]
 pub union CUnionU128{a:u128}
-// CHECK: define void @test_CUnionU128({{%CUnionU128\*|ptr}} {{.*}} %_1)
+// CHECK: define {{(dso_local )?}}void @test_CUnionU128(ptr {{.*}} %_1)
 #[no_mangle]
 pub fn test_CUnionU128(_: CUnionU128) { loop {} }
 
 pub union UnionBool { b:bool }
-// CHECK: define noundef zeroext i1 @test_UnionBool(i8 %b)
+// CHECK: define {{(dso_local )?}}noundef zeroext i1 @test_UnionBool(i8 %b)
 #[no_mangle]
 pub fn test_UnionBool(b: UnionBool) -> bool { unsafe { b.b }  }
-// CHECK: %0 = trunc i8 %b to i1
+// CHECK: %_0 = trunc i8 %b to i1
diff --git a/tests/codegen/unwind-abis/c-unwind-abi.rs b/tests/codegen/unwind-abis/c-unwind-abi.rs
index e258dbcacd2..fa5b6bad75c 100644
--- a/tests/codegen/unwind-abis/c-unwind-abi.rs
+++ b/tests/codegen/unwind-abis/c-unwind-abi.rs
@@ -1,4 +1,5 @@
 // compile-flags: -C opt-level=0
+// needs-unwind
 
 // Test that `nounwind` attributes are correctly applied to exported `C` and `C-unwind` extern
 // functions. `C-unwind` functions MUST NOT have this attribute. We disable optimizations above
diff --git a/tests/codegen/unwind-abis/cdecl-unwind-abi.rs b/tests/codegen/unwind-abis/cdecl-unwind-abi.rs
index 19a7228839a..64746d32175 100644
--- a/tests/codegen/unwind-abis/cdecl-unwind-abi.rs
+++ b/tests/codegen/unwind-abis/cdecl-unwind-abi.rs
@@ -1,4 +1,5 @@
 // compile-flags: -C opt-level=0
+// needs-unwind
 
 // Test that `nounwind` attributes are correctly applied to exported `cdecl` and
 // `cdecl-unwind` extern functions. `cdecl-unwind` functions MUST NOT have this attribute. We
diff --git a/tests/codegen/unwind-abis/nounwind-on-stable-panic-unwind.rs b/tests/codegen/unwind-abis/nounwind-on-stable-panic-unwind.rs
index c1c5bbdda34..dc3911cd4eb 100644
--- a/tests/codegen/unwind-abis/nounwind-on-stable-panic-unwind.rs
+++ b/tests/codegen/unwind-abis/nounwind-on-stable-panic-unwind.rs
@@ -1,5 +1,6 @@
 // compile-flags: -C opt-level=0
 // ignore-wasm32-bare compiled with panic=abort by default
+// needs-unwind
 
 #![crate_type = "lib"]
 
diff --git a/tests/codegen/unwind-abis/system-unwind-abi.rs b/tests/codegen/unwind-abis/system-unwind-abi.rs
index 2591c1d4814..f274a33b099 100644
--- a/tests/codegen/unwind-abis/system-unwind-abi.rs
+++ b/tests/codegen/unwind-abis/system-unwind-abi.rs
@@ -1,4 +1,5 @@
 // compile-flags: -C opt-level=0
+// needs-unwind
 
 // Test that `nounwind` attributes are correctly applied to exported `system` and `system-unwind`
 // extern functions. `system-unwind` functions MUST NOT have this attribute. We disable
diff --git a/tests/codegen/unwind-extern-exports.rs b/tests/codegen/unwind-extern-exports.rs
index 6ac3c079f81..4e1e719d5cd 100644
--- a/tests/codegen/unwind-extern-exports.rs
+++ b/tests/codegen/unwind-extern-exports.rs
@@ -1,5 +1,6 @@
 // compile-flags: -C opt-level=0
 // ignore-wasm32-bare compiled with panic=abort by default
+// needs-unwind
 
 #![crate_type = "lib"]
 #![feature(c_unwind)]
diff --git a/tests/codegen/unwind-extern-imports.rs b/tests/codegen/unwind-extern-imports.rs
index e33e3e80521..260dcc628cc 100644
--- a/tests/codegen/unwind-extern-imports.rs
+++ b/tests/codegen/unwind-extern-imports.rs
@@ -1,5 +1,6 @@
 // compile-flags: -C no-prepopulate-passes
 // ignore-wasm32-bare compiled with panic=abort by default
+// needs-unwind
 
 #![crate_type = "lib"]
 #![feature(c_unwind)]
diff --git a/tests/codegen/var-names.rs b/tests/codegen/var-names.rs
index 53841df32e8..d4715efad73 100644
--- a/tests/codegen/var-names.rs
+++ b/tests/codegen/var-names.rs
@@ -9,7 +9,7 @@ pub fn test(a: u32, b: u32) -> u32 {
     // CHECK: %c = add i32 %a, %b
     let d = c;
     let e = d * a;
-    // CHECK-NEXT: %0 = mul i32 %c, %a
+    // CHECK-NEXT: %e = mul i32 %c, %a
     e
-    // CHECK-NEXT: ret i32 %0
+    // CHECK-NEXT: ret i32 %e
 }
diff --git a/tests/codegen/vec-as-ptr.rs b/tests/codegen/vec-as-ptr.rs
index 8ff7ba9cb64..76098bc08a3 100644
--- a/tests/codegen/vec-as-ptr.rs
+++ b/tests/codegen/vec-as-ptr.rs
@@ -4,7 +4,7 @@
 
 // Test that even though we return a *const u8 not a &[u8] or a NonNull<u8>, LLVM knows that this
 // pointer is nonnull.
-// CHECK: nonnull {{i8\*|ptr}} @vec_as_ptr
+// CHECK: nonnull ptr @vec_as_ptr
 #[no_mangle]
 pub fn vec_as_ptr(v: &Vec<u8>) -> *const u8 {
     v.as_ptr()
@@ -12,7 +12,7 @@ pub fn vec_as_ptr(v: &Vec<u8>) -> *const u8 {
 
 // Test that even though we return a *const u8 not a &[u8] or a NonNull<u8>, LLVM knows that this
 // pointer is nonnull.
-// CHECK: nonnull {{i8\*|ptr}} @vec_as_mut_ptr
+// CHECK: nonnull ptr @vec_as_mut_ptr
 #[no_mangle]
 pub fn vec_as_mut_ptr(v: &mut Vec<u8>) -> *mut u8 {
     v.as_mut_ptr()
diff --git a/tests/codegen/vec-calloc.rs b/tests/codegen/vec-calloc.rs
index 4481a9d1e99..a5fda7b2449 100644
--- a/tests/codegen/vec-calloc.rs
+++ b/tests/codegen/vec-calloc.rs
@@ -1,7 +1,6 @@
 // compile-flags: -O -Z merge-functions=disabled
 // only-x86_64
 // ignore-debug
-// min-llvm-version: 15.0
 
 #![crate_type = "lib"]
 
diff --git a/tests/codegen/vec-optimizes-away.rs b/tests/codegen/vec-optimizes-away.rs
index 9143fad2340..6f477a796b6 100644
--- a/tests/codegen/vec-optimizes-away.rs
+++ b/tests/codegen/vec-optimizes-away.rs
@@ -1,12 +1,13 @@
 // ignore-debug: the debug assertions get in the way
 // no-system-llvm
 // compile-flags: -O
-#![crate_type="lib"]
+#![crate_type = "lib"]
 
 #[no_mangle]
 pub fn sum_me() -> i32 {
     // CHECK-LABEL: @sum_me
     // CHECK-NEXT: {{^.*:$}}
+    // CHECK-NEXT: {{.*}} load volatile i8, ptr @__rust_no_alloc_shim_is_unstable, align 1
     // CHECK-NEXT: ret i32 6
     vec![1, 2, 3].iter().sum::<i32>()
 }
diff --git a/tests/codegen/vec-shrink-panik.rs b/tests/codegen/vec-shrink-panik.rs
index b3c3483fea9..14fef4e2cd5 100644
--- a/tests/codegen/vec-shrink-panik.rs
+++ b/tests/codegen/vec-shrink-panik.rs
@@ -5,6 +5,7 @@
 // [new]min-llvm-version: 17
 // compile-flags: -O
 // ignore-debug: the debug assertions get in the way
+// needs-unwind
 #![crate_type = "lib"]
 #![feature(shrink_to)]
 
@@ -25,7 +26,7 @@ pub fn issue71861(vec: Vec<u32>) -> Box<[u32]> {
 
     // Call to panic_cannot_unwind in case of double-panic is expected
     // on LLVM 16 and older, but other panics are not.
-    // CHECK: cleanup
+    // old: filter
     // old-NEXT: ; call core::panicking::panic_cannot_unwind
     // old-NEXT: panic_cannot_unwind
 
@@ -37,14 +38,6 @@ pub fn issue71861(vec: Vec<u32>) -> Box<[u32]> {
 #[no_mangle]
 pub fn issue75636<'a>(iter: &[&'a str]) -> Box<[&'a str]> {
     // CHECK-NOT: panic
-
-    // Call to panic_cannot_unwind in case of double-panic is expected,
-    // on LLVM 16 and older, but other panics are not.
-    // CHECK: cleanup
-    // old-NEXT: ; call core::panicking::panic_cannot_unwind
-    // old-NEXT: panic_cannot_unwind
-
-    // CHECK-NOT: panic
     iter.iter().copied().collect()
 }
 
diff --git a/tests/codegen/wasm_exceptions.rs b/tests/codegen/wasm_exceptions.rs
new file mode 100644
index 00000000000..2b2359f5b6c
--- /dev/null
+++ b/tests/codegen/wasm_exceptions.rs
@@ -0,0 +1,51 @@
+// only-wasm32-bare
+// compile-flags: -C panic=unwind
+
+#![crate_type = "lib"]
+#![feature(core_intrinsics)]
+#![feature(rustc_attrs)]
+
+extern {
+    fn may_panic();
+
+    #[rustc_nounwind]
+    fn log_number(number: usize);
+}
+
+struct LogOnDrop;
+
+impl Drop for LogOnDrop {
+    fn drop(&mut self) {
+        unsafe { log_number(0); }
+    }
+}
+
+// CHECK-LABEL: @test_cleanup() {{.*}} @__gxx_wasm_personality_v0
+#[no_mangle]
+pub fn test_cleanup() {
+    let _log_on_drop = LogOnDrop;
+    unsafe { may_panic(); }
+
+    // CHECK-NOT: call
+    // CHECK: invoke void @may_panic()
+    // CHECK: %cleanuppad = cleanuppad within none []
+}
+
+// CHECK-LABEL: @test_rtry() {{.*}} @__gxx_wasm_personality_v0
+#[no_mangle]
+pub fn test_rtry() {
+    unsafe {
+        core::intrinsics::r#try(|_| {
+            may_panic();
+        }, core::ptr::null_mut(), |data, exception| {
+            log_number(data as usize);
+            log_number(exception as usize);
+        });
+    }
+
+    // CHECK-NOT: call
+    // CHECK: invoke void @may_panic()
+    // CHECK: {{.*}} = catchswitch within none [label {{.*}}] unwind to caller
+    // CHECK: {{.*}} = catchpad within {{.*}} [ptr null]
+    // CHECK: catchret
+}