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/abi-main-signature-16bit-c-int.rs1
-rw-r--r--tests/codegen/call-llvm-intrinsics.rs1
-rw-r--r--tests/codegen/catch-unwind.rs2
-rw-r--r--tests/codegen/enable-lto-unit-splitting.rs10
-rw-r--r--tests/codegen/global_asm.rs1
-rw-r--r--tests/codegen/global_asm_include.rs1
-rw-r--r--tests/codegen/global_asm_x2.rs1
-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/repr-transparent-aggregates-1.rs1
-rw-r--r--tests/codegen/repr-transparent-aggregates-2.rs1
-rw-r--r--tests/codegen/repr-transparent.rs1
-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.rs3
-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.rs319
-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.rs6
-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/split-lto-unit.rs11
31 files changed, 1014 insertions, 171 deletions
diff --git a/tests/codegen/abi-main-signature-16bit-c-int.rs b/tests/codegen/abi-main-signature-16bit-c-int.rs
index 3548cc06a5b..353e7489b55 100644
--- a/tests/codegen/abi-main-signature-16bit-c-int.rs
+++ b/tests/codegen/abi-main-signature-16bit-c-int.rs
@@ -17,6 +17,7 @@
 // ignore-wasm32
 // ignore-x86
 // ignore-x86_64
+// ignore-loongarch64
 
 fn main() {
 }
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/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/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/global_asm.rs b/tests/codegen/global_asm.rs
index 9912b1e75bf..41a99530ad2 100644
--- a/tests/codegen/global_asm.rs
+++ b/tests/codegen/global_asm.rs
@@ -18,6 +18,7 @@
 // ignore-wasm32
 // ignore-wasm64
 // ignore-emscripten
+// ignore-loongarch64
 // 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..e25c164f407 100644
--- a/tests/codegen/global_asm_include.rs
+++ b/tests/codegen/global_asm_include.rs
@@ -18,6 +18,7 @@
 // ignore-wasm32
 // ignore-wasm64
 // ignore-emscripten
+// ignore-loongarch64
 // 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..71ecef124f1 100644
--- a/tests/codegen/global_asm_x2.rs
+++ b/tests/codegen/global_asm_x2.rs
@@ -18,6 +18,7 @@
 // ignore-wasm32
 // ignore-wasm64
 // ignore-emscripten
+// ignore-loongarch64
 // compile-flags: -C no-prepopulate-passes
 
 #![crate_type = "lib"]
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/repr-transparent-aggregates-1.rs b/tests/codegen/repr-transparent-aggregates-1.rs
index f733de12b35..9c4b0e58e71 100644
--- a/tests/codegen/repr-transparent-aggregates-1.rs
+++ b/tests/codegen/repr-transparent-aggregates-1.rs
@@ -10,6 +10,7 @@
 // ignore-riscv64 see codegen/riscv-abi
 // ignore-s390x
 // ignore-windows
+// ignore-loongarch64
 // See repr-transparent.rs
 
 #![feature(transparent_unions)]
diff --git a/tests/codegen/repr-transparent-aggregates-2.rs b/tests/codegen/repr-transparent-aggregates-2.rs
index e9fa5143b18..a7bde2d05c3 100644
--- a/tests/codegen/repr-transparent-aggregates-2.rs
+++ b/tests/codegen/repr-transparent-aggregates-2.rs
@@ -12,6 +12,7 @@
 // ignore-sparc64
 // ignore-x86
 // ignore-x86_64
+// ignore-loongarch64
 // See repr-transparent.rs
 
 #![feature(transparent_unions)]
diff --git a/tests/codegen/repr-transparent.rs b/tests/codegen/repr-transparent.rs
index 311cbfbaa09..759ddea67a5 100644
--- a/tests/codegen/repr-transparent.rs
+++ b/tests/codegen/repr-transparent.rs
@@ -3,6 +3,7 @@
 // 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
 
 #![crate_type="lib"]
 #![feature(repr_simd, transparent_unions)]
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..cea6aac8b8b 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-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..71e26e3fe8a 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)
@@ -113,9 +113,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 +132,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"}
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..78ef0c2c7d6
--- /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({{i8\*|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({{i8\*|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({{i8\*|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..3b72459c4b0
--- /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({{i8\*|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({{i8\*|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({{i8\*|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..9218e9947bf
--- /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({{i8\*|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({{i8\*|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({{i8\*|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..f9fd816dedb 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,21 +7,21 @@
 
 pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
     // CHECK-LABEL: define{{.*}}foo
-    // CHECK-SAME: {{.*}}!type ![[TYPE1:[0-9]+]]
+    // CHECK-SAME:  {{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
     // CHECK:       call i1 @llvm.type.test({{i8\*|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-SAME:  {{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
     // CHECK:       call i1 @llvm.type.test({{i8\*|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-SAME:  {{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
     // CHECK:       call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0}}, metadata !"_ZTSFu3i32S_S_S_E")
     f(arg1, arg2, arg3)
 }
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/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}