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/README.md24
-rw-r--r--tests/codegen/abi-efiapi.rs33
-rw-r--r--tests/codegen/abi-main-signature-16bit-c-int.rs25
-rw-r--r--tests/codegen/abi-main-signature-32bit-c-int.rs10
-rw-r--r--tests/codegen/abi-repr-ext.rs57
-rw-r--r--tests/codegen/abi-sysv64.rs22
-rw-r--r--tests/codegen/abi-x86-interrupt.rs22
-rw-r--r--tests/codegen/abi-x86_64_sysv.rs29
-rw-r--r--tests/codegen/addr-of-mutate.rs34
-rw-r--r--tests/codegen/adjustments.rs29
-rw-r--r--tests/codegen/align-enum.rs34
-rw-r--r--tests/codegen/align-fn.rs49
-rw-r--r--tests/codegen/align-offset.rs78
-rw-r--r--tests/codegen/align-struct.rs71
-rw-r--r--tests/codegen/alloc-optimisation.rs14
-rw-r--r--tests/codegen/array-clone.rs15
-rw-r--r--tests/codegen/array-codegen.rs35
-rw-r--r--tests/codegen/array-equality.rs102
-rw-r--r--tests/codegen/array-map.rs38
-rw-r--r--tests/codegen/ascii-char.rs37
-rw-r--r--tests/codegen/asm-clobber_abi.rs36
-rw-r--r--tests/codegen/asm-clobbers.rs20
-rw-r--r--tests/codegen/asm-may_unwind.rs39
-rw-r--r--tests/codegen/asm-multiple-options.rs54
-rw-r--r--tests/codegen/asm-options.rs104
-rw-r--r--tests/codegen/asm-powerpc-clobbers.rs47
-rw-r--r--tests/codegen/asm-sanitize-llvm.rs34
-rw-r--r--tests/codegen/asm-target-clobbers.rs29
-rw-r--r--tests/codegen/async-fn-debug-awaitee-field.rs25
-rw-r--r--tests/codegen/async-fn-debug-msvc.rs54
-rw-r--r--tests/codegen/async-fn-debug.rs58
-rw-r--r--tests/codegen/atomic-operations.rs83
-rw-r--r--tests/codegen/autovectorize-f32x4.rs42
-rw-r--r--tests/codegen/auxiliary/extern_decl.rs11
-rw-r--r--tests/codegen/auxiliary/nounwind.rs3
-rw-r--r--tests/codegen/auxiliary/thread_local_aux.rs5
-rw-r--r--tests/codegen/avr/avr-func-addrspace.rs136
-rw-r--r--tests/codegen/binary-search-index-no-bound-check.rs40
-rw-r--r--tests/codegen/bool-cmp.rs18
-rw-r--r--tests/codegen/box-maybe-uninit-llvm14.rs34
-rw-r--r--tests/codegen/box-maybe-uninit.rs33
-rw-r--r--tests/codegen/bpf-alu32.rs11
-rw-r--r--tests/codegen/branch-protection.rs45
-rw-r--r--tests/codegen/c-variadic-copy.rs16
-rw-r--r--tests/codegen/c-variadic-opt.rs30
-rw-r--r--tests/codegen/c-variadic.rs72
-rw-r--r--tests/codegen/call-llvm-intrinsics.rs30
-rw-r--r--tests/codegen/call-metadata.rs17
-rw-r--r--tests/codegen/catch-unwind.rs33
-rw-r--r--tests/codegen/cdylib-external-inline-fns.rs43
-rw-r--r--tests/codegen/cf-protection.rs38
-rw-r--r--tests/codegen/cfguard-checks.rs11
-rw-r--r--tests/codegen/cfguard-disabled.rs11
-rw-r--r--tests/codegen/cfguard-nochecks.rs11
-rw-r--r--tests/codegen/cfguard-non-msvc.rs11
-rw-r--r--tests/codegen/codemodels.rs20
-rw-r--r--tests/codegen/coercions.rs19
-rw-r--r--tests/codegen/cold-call-declare-and-call.rs18
-rw-r--r--tests/codegen/comparison-operators-2-tuple.rs121
-rw-r--r--tests/codegen/comparison-operators-newtype.rs49
-rw-r--r--tests/codegen/const_scalar_pair.rs10
-rw-r--r--tests/codegen/consts.rs56
-rw-r--r--tests/codegen/dealloc-no-unwind.rs22
-rw-r--r--tests/codegen/debug-alignment.rs8
-rw-r--r--tests/codegen/debug-column-msvc.rs16
-rw-r--r--tests/codegen/debug-column.rs24
-rw-r--r--tests/codegen/debug-compile-unit-path.rs9
-rw-r--r--tests/codegen/debug-limited.rs27
-rw-r--r--tests/codegen/debug-line-directives-only.rs27
-rw-r--r--tests/codegen/debug-line-tables-only.rs27
-rw-r--r--tests/codegen/debug-linkage-name.rs42
-rw-r--r--tests/codegen/debug-vtable.rs113
-rw-r--r--tests/codegen/debuginfo-constant-locals.rs28
-rw-r--r--tests/codegen/debuginfo-generic-closure-env-names.rs89
-rw-r--r--tests/codegen/deduced-param-attrs.rs60
-rw-r--r--tests/codegen/default-requires-uwtable.rs16
-rw-r--r--tests/codegen/dllimports/auxiliary/dummy.rs6
-rw-r--r--tests/codegen/dllimports/auxiliary/wrapper.rs14
-rw-r--r--tests/codegen/dllimports/main.rs43
-rw-r--r--tests/codegen/drop-in-place-noalias.rs38
-rw-r--r--tests/codegen/drop.rs37
-rw-r--r--tests/codegen/dst-vtable-align-nonzero.rs61
-rw-r--r--tests/codegen/dst-vtable-size-range.rs35
-rw-r--r--tests/codegen/enable-lto-unit-splitting.rs10
-rw-r--r--tests/codegen/enum-bounds-check-derived-idx.rs24
-rw-r--r--tests/codegen/enum-bounds-check-issue-13926.rs18
-rw-r--r--tests/codegen/enum-bounds-check-issue-82871.rs18
-rw-r--r--tests/codegen/enum-bounds-check.rs26
-rw-r--r--tests/codegen/enum-debug-clike.rs23
-rw-r--r--tests/codegen/enum-debug-niche-2.rs50
-rw-r--r--tests/codegen/enum-debug-niche.rs29
-rw-r--r--tests/codegen/enum-debug-tagged.rs27
-rw-r--r--tests/codegen/enum-discriminant-value.rs27
-rw-r--r--tests/codegen/enum-match.rs112
-rw-r--r--tests/codegen/enum-u128.rs27
-rw-r--r--tests/codegen/export-no-mangle.rs31
-rw-r--r--tests/codegen/external-no-mangle-fns.rs75
-rw-r--r--tests/codegen/external-no-mangle-statics.rs77
-rw-r--r--tests/codegen/fastcall-inreg.rs41
-rw-r--r--tests/codegen/fatptr.rs12
-rw-r--r--tests/codegen/fewer-names.rs20
-rw-r--r--tests/codegen/ffi-const.rs13
-rw-r--r--tests/codegen/ffi-out-of-bounds-loads.rs25
-rw-r--r--tests/codegen/ffi-pure.rs13
-rw-r--r--tests/codegen/ffi-returns-twice.rs11
-rw-r--r--tests/codegen/float_math.rs50
-rw-r--r--tests/codegen/fn-impl-trait-self.rs16
-rw-r--r--tests/codegen/foo.s3
-rw-r--r--tests/codegen/force-frame-pointers.rs6
-rw-r--r--tests/codegen/force-no-unwind-tables.rs11
-rw-r--r--tests/codegen/force-unwind-tables.rs6
-rw-r--r--tests/codegen/frame-pointer.rs35
-rw-r--r--tests/codegen/function-arguments-noopt.rs69
-rw-r--r--tests/codegen/function-arguments.rs290
-rw-r--r--tests/codegen/gdb_debug_script_load.rs17
-rw-r--r--tests/codegen/generator-debug-msvc.rs59
-rw-r--r--tests/codegen/generator-debug.rs62
-rw-r--r--tests/codegen/generic-debug.rs17
-rw-r--r--tests/codegen/global_asm.rs46
-rw-r--r--tests/codegen/global_asm_include.rs39
-rw-r--r--tests/codegen/global_asm_x2.rs65
-rw-r--r--tests/codegen/i686-macosx-deployment-target.rs27
-rw-r--r--tests/codegen/i686-no-macosx-deployment-target.rs27
-rw-r--r--tests/codegen/inherit_overflow.rs14
-rw-r--r--tests/codegen/inline-always-works-always.rs21
-rw-r--r--tests/codegen/inline-debuginfo.rs17
-rw-r--r--tests/codegen/inline-function-args-debug-info.rs20
-rw-r--r--tests/codegen/inline-hint.rs31
-rw-r--r--tests/codegen/instrument-coverage.rs17
-rw-r--r--tests/codegen/instrument-mcount.rs7
-rw-r--r--tests/codegen/instrument-xray/basic.rs9
-rw-r--r--tests/codegen/instrument-xray/options-combine.rs12
-rw-r--r--tests/codegen/instrument-xray/options-override.rs11
-rw-r--r--tests/codegen/integer-cmp.rs28
-rw-r--r--tests/codegen/integer-overflow.rs26
-rw-r--r--tests/codegen/internalize-closures.rs14
-rw-r--r--tests/codegen/intrinsic-no-unnamed-attr.rs12
-rw-r--r--tests/codegen/intrinsics/const_eval_select.rs18
-rw-r--r--tests/codegen/intrinsics/exact_div.rs20
-rw-r--r--tests/codegen/intrinsics/likely.rs30
-rw-r--r--tests/codegen/intrinsics/mask.rs12
-rw-r--r--tests/codegen/intrinsics/nearby.rs18
-rw-r--r--tests/codegen/intrinsics/nontemporal.rs13
-rw-r--r--tests/codegen/intrinsics/offset.rs34
-rw-r--r--tests/codegen/intrinsics/offset_from.rs36
-rw-r--r--tests/codegen/intrinsics/prefetch.rs63
-rw-r--r--tests/codegen/intrinsics/transmute-niched.rs184
-rw-r--r--tests/codegen/intrinsics/transmute-x64.rs35
-rw-r--r--tests/codegen/intrinsics/transmute.rs470
-rw-r--r--tests/codegen/intrinsics/unchecked_math.rs46
-rw-r--r--tests/codegen/intrinsics/volatile.rs55
-rw-r--r--tests/codegen/intrinsics/volatile_order.rs18
-rw-r--r--tests/codegen/issues/auxiliary/static_dllimport_aux.rs13
-rw-r--r--tests/codegen/issues/issue-101048.rs13
-rw-r--r--tests/codegen/issues/issue-101082.rs17
-rw-r--r--tests/codegen/issues/issue-101814.rs20
-rw-r--r--tests/codegen/issues/issue-103132.rs16
-rw-r--r--tests/codegen/issues/issue-103285-ptr-addr-overflow-check.rs16
-rw-r--r--tests/codegen/issues/issue-103327.rs18
-rw-r--r--tests/codegen/issues/issue-103840.rs10
-rw-r--r--tests/codegen/issues/issue-105386-ub-in-debuginfo.rs24
-rw-r--r--tests/codegen/issues/issue-106369.rs15
-rw-r--r--tests/codegen/issues/issue-111603.rs40
-rw-r--r--tests/codegen/issues/issue-13018.rs11
-rw-r--r--tests/codegen/issues/issue-15953.rs29
-rw-r--r--tests/codegen/issues/issue-27130.rs21
-rw-r--r--tests/codegen/issues/issue-32031.rs23
-rw-r--r--tests/codegen/issues/issue-32364.rs18
-rw-r--r--tests/codegen/issues/issue-34634.rs16
-rw-r--r--tests/codegen/issues/issue-34947-pow-i32.rs13
-rw-r--r--tests/codegen/issues/issue-37945.rs35
-rw-r--r--tests/codegen/issues/issue-44056-macos-tls-align.rs28
-rw-r--r--tests/codegen/issues/issue-45222.rs63
-rw-r--r--tests/codegen/issues/issue-45466.rs15
-rw-r--r--tests/codegen/issues/issue-45964-bounds-check-slice-pos.rs39
-rw-r--r--tests/codegen/issues/issue-47278.rs9
-rw-r--r--tests/codegen/issues/issue-47442.rs22
-rw-r--r--tests/codegen/issues/issue-56267-2.rs18
-rw-r--r--tests/codegen/issues/issue-56267.rs18
-rw-r--r--tests/codegen/issues/issue-56927.rs43
-rw-r--r--tests/codegen/issues/issue-58881.rs21
-rw-r--r--tests/codegen/issues/issue-59352.rs18
-rw-r--r--tests/codegen/issues/issue-69101-bounds-check.rs44
-rw-r--r--tests/codegen/issues/issue-73031.rs26
-rw-r--r--tests/codegen/issues/issue-73258.rs38
-rw-r--r--tests/codegen/issues/issue-73338-effecient-cmp.rs39
-rw-r--r--tests/codegen/issues/issue-73396-bounds-check-after-position.rs95
-rw-r--r--tests/codegen/issues/issue-73827-bounds-check-index-in-subexpr.rs17
-rw-r--r--tests/codegen/issues/issue-75525-bounds-checks.rs26
-rw-r--r--tests/codegen/issues/issue-75546.rs15
-rw-r--r--tests/codegen/issues/issue-75659.rs63
-rw-r--r--tests/codegen/issues/issue-75978.rs19
-rw-r--r--tests/codegen/issues/issue-77812.rs32
-rw-r--r--tests/codegen/issues/issue-81408-dllimport-thinlto-windows.rs15
-rw-r--r--tests/codegen/issues/issue-84268.rs23
-rw-r--r--tests/codegen/issues/issue-85872-multiple-reverse.rs20
-rw-r--r--tests/codegen/issues/issue-86106.rs51
-rw-r--r--tests/codegen/issues/issue-96274.rs17
-rw-r--r--tests/codegen/issues/issue-96497-slice-size-nowrap.rs29
-rw-r--r--tests/codegen/issues/issue-98156-const-arg-temp-lifetime.rs27
-rw-r--r--tests/codegen/issues/issue-98294-get-mut-copy-from-slice-opt.rs19
-rw-r--r--tests/codegen/issues/issue-99960.rs15
-rw-r--r--tests/codegen/iter-repeat-n-trivial-drop.rs56
-rw-r--r--tests/codegen/layout-size-checks.rs31
-rw-r--r--tests/codegen/lifetime_start_end.rs34
-rw-r--r--tests/codegen/link-dead-code.rs22
-rw-r--r--tests/codegen/link_section.rs35
-rw-r--r--tests/codegen/loads.rs152
-rw-r--r--tests/codegen/local-generics-in-exe-internalized.rs14
-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/lto-removes-invokes.rs21
-rw-r--r--tests/codegen/mainsubprogram.rs13
-rw-r--r--tests/codegen/mainsubprogramstart.rs14
-rw-r--r--tests/codegen/match-optimized.rs60
-rw-r--r--tests/codegen/match-optimizes-away.rs34
-rw-r--r--tests/codegen/match-unoptimized.rs23
-rw-r--r--tests/codegen/mem-replace-big-type.rs33
-rw-r--r--tests/codegen/mem-replace-simple-type.rs45
-rw-r--r--tests/codegen/merge-functions.rs16
-rw-r--r--tests/codegen/mir-inlined-line-numbers.rs25
-rw-r--r--tests/codegen/mir_zst_stores.rs17
-rw-r--r--tests/codegen/move-operands.rs12
-rw-r--r--tests/codegen/naked-functions.rs32
-rw-r--r--tests/codegen/naked-nocoverage.rs19
-rw-r--r--tests/codegen/naked-noinline.rs31
-rw-r--r--tests/codegen/no-assumes-on-casts.rs19
-rw-r--r--tests/codegen/no-dllimport-w-cross-lang-lto.rs13
-rw-r--r--tests/codegen/no-jump-tables.rs22
-rw-r--r--tests/codegen/no-plt.rs17
-rw-r--r--tests/codegen/noalias-box-off.rs11
-rw-r--r--tests/codegen/noalias-box.rs8
-rw-r--r--tests/codegen/noalias-flag.rs23
-rw-r--r--tests/codegen/noalias-refcell.rs14
-rw-r--r--tests/codegen/noalias-rwlockreadguard.rs14
-rw-r--r--tests/codegen/noalias-unpin.rs15
-rw-r--r--tests/codegen/non-terminate/infinite-loop-1.rs17
-rw-r--r--tests/codegen/non-terminate/infinite-loop-2.rs19
-rw-r--r--tests/codegen/non-terminate/infinite-recursion.rs14
-rw-r--r--tests/codegen/non-terminate/nonempty-infinite-loop.rs28
-rw-r--r--tests/codegen/noreturn-uninhabited.rs31
-rw-r--r--tests/codegen/noreturnflag.rs22
-rw-r--r--tests/codegen/nounwind.rs16
-rw-r--r--tests/codegen/nrvo.rs17
-rw-r--r--tests/codegen/optimize-attr-1.rs47
-rw-r--r--tests/codegen/option-as-slice.rs38
-rw-r--r--tests/codegen/option-nonzero-eq.rs38
-rw-r--r--tests/codegen/packed.rs153
-rw-r--r--tests/codegen/panic-abort-windows.rs18
-rw-r--r--tests/codegen/panic-in-drop-abort.rs57
-rw-r--r--tests/codegen/panic-unwind-default-uwtable.rs6
-rw-r--r--tests/codegen/personality_lifetimes.rs33
-rw-r--r--tests/codegen/pgo-counter-bias.rs10
-rw-r--r--tests/codegen/pgo-instrumentation.rs22
-rw-r--r--tests/codegen/pic-relocation-model.rs19
-rw-r--r--tests/codegen/pie-relocation-model.rs22
-rw-r--r--tests/codegen/ptr-read-metadata.rs96
-rw-r--r--tests/codegen/refs.rs23
-rw-r--r--tests/codegen/remap_path_prefix/aux_mod.rs6
-rw-r--r--tests/codegen/remap_path_prefix/auxiliary/remap_path_prefix_aux.rs8
-rw-r--r--tests/codegen/remap_path_prefix/auxiliary/xcrate-generic.rs8
-rw-r--r--tests/codegen/remap_path_prefix/issue-73167-remap-std.rs15
-rw-r--r--tests/codegen/remap_path_prefix/main.rs28
-rw-r--r--tests/codegen/remap_path_prefix/xcrate-generic.rs14
-rw-r--r--tests/codegen/repeat-trusted-len.rs20
-rw-r--r--tests/codegen/repr-transparent-aggregates-1.rs89
-rw-r--r--tests/codegen/repr-transparent-aggregates-2.rs90
-rw-r--r--tests/codegen/repr-transparent-aggregates-3.rs79
-rw-r--r--tests/codegen/repr-transparent-sysv64.rs28
-rw-r--r--tests/codegen/repr-transparent.rs171
-rw-r--r--tests/codegen/riscv-abi/call-llvm-intrinsics.rs30
-rw-r--r--tests/codegen/riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs189
-rw-r--r--tests/codegen/riscv-abi/riscv64-lp64d-abi.rs293
-rw-r--r--tests/codegen/riscv-abi/riscv64-lp64f-lp64d-abi.rs277
-rw-r--r--tests/codegen/sanitizer-cfi-add-canonical-jump-tables-flag.rs11
-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.rs19
-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.rs604
-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.rs31
-rw-r--r--tests/codegen/sanitizer-cfi-emit-type-metadata-trait-objects.rs120
-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-kasan-emits-instrumentation.rs47
-rw-r--r--tests/codegen/sanitizer-kcfi-add-kcfi-flag.rs11
-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.rs44
-rw-r--r--tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle.rs27
-rw-r--r--tests/codegen/sanitizer-kcfi-emit-type-metadata-trait-objects.rs144
-rw-r--r--tests/codegen/sanitizer-memory-track-orgins.rs30
-rw-r--r--tests/codegen/sanitizer-no-sanitize-inlining.rs30
-rw-r--r--tests/codegen/sanitizer-no-sanitize.rs29
-rw-r--r--tests/codegen/sanitizer-recover.rs49
-rw-r--r--tests/codegen/sanitizer-safestack-attr-check.rs11
-rw-r--r--tests/codegen/sanitizer_memtag_attr_check.rs12
-rw-r--r--tests/codegen/sanitizer_scs_attr_check.rs17
-rw-r--r--tests/codegen/scalar-pair-bool.rs45
-rw-r--r--tests/codegen/set-discriminant-invalid.rs43
-rw-r--r--tests/codegen/simd-intrinsic/simd-intrinsic-float-abs.rs92
-rw-r--r--tests/codegen/simd-intrinsic/simd-intrinsic-float-ceil.rs92
-rw-r--r--tests/codegen/simd-intrinsic/simd-intrinsic-float-cos.rs92
-rw-r--r--tests/codegen/simd-intrinsic/simd-intrinsic-float-exp.rs92
-rw-r--r--tests/codegen/simd-intrinsic/simd-intrinsic-float-exp2.rs92
-rw-r--r--tests/codegen/simd-intrinsic/simd-intrinsic-float-floor.rs92
-rw-r--r--tests/codegen/simd-intrinsic/simd-intrinsic-float-fma.rs92
-rw-r--r--tests/codegen/simd-intrinsic/simd-intrinsic-float-fsqrt.rs92
-rw-r--r--tests/codegen/simd-intrinsic/simd-intrinsic-float-log.rs92
-rw-r--r--tests/codegen/simd-intrinsic/simd-intrinsic-float-log10.rs92
-rw-r--r--tests/codegen/simd-intrinsic/simd-intrinsic-float-log2.rs92
-rw-r--r--tests/codegen/simd-intrinsic/simd-intrinsic-float-minmax.rs29
-rw-r--r--tests/codegen/simd-intrinsic/simd-intrinsic-float-pow.rs92
-rw-r--r--tests/codegen/simd-intrinsic/simd-intrinsic-float-powi.rs92
-rw-r--r--tests/codegen/simd-intrinsic/simd-intrinsic-float-sin.rs92
-rw-r--r--tests/codegen/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs692
-rw-r--r--tests/codegen/simd-intrinsic/simd-intrinsic-generic-bitmask.rs63
-rw-r--r--tests/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs47
-rw-r--r--tests/codegen/simd-intrinsic/simd-intrinsic-generic-gather.rs36
-rw-r--r--tests/codegen/simd-intrinsic/simd-intrinsic-generic-scatter.rs37
-rw-r--r--tests/codegen/simd-intrinsic/simd-intrinsic-generic-select.rs37
-rw-r--r--tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs82
-rw-r--r--tests/codegen/simd-wide-sum.rs55
-rw-r--r--tests/codegen/simd_arith_offset.rs26
-rw-r--r--tests/codegen/slice-as_chunks.rs33
-rw-r--r--tests/codegen/slice-indexing.rs35
-rw-r--r--tests/codegen/slice-init.rs64
-rw-r--r--tests/codegen/slice-iter-fold.rs14
-rw-r--r--tests/codegen/slice-iter-len-eq-zero.rs28
-rw-r--r--tests/codegen/slice-iter-nonnull.rs77
-rw-r--r--tests/codegen/slice-position-bounds-check.rs32
-rw-r--r--tests/codegen/slice-ref-equality.rs92
-rw-r--r--tests/codegen/slice-reverse.rs27
-rw-r--r--tests/codegen/slice-windows-no-bounds-check.rs35
-rw-r--r--tests/codegen/slice_as_from_ptr_range.rs23
-rw-r--r--tests/codegen/some-abis-do-extend-params-to-32-bits.rs204
-rw-r--r--tests/codegen/some-global-nonnull.rs25
-rw-r--r--tests/codegen/sparc-struct-abi.rs103
-rw-r--r--tests/codegen/split-lto-unit.rs11
-rw-r--r--tests/codegen/src-hash-algorithm/src-hash-algorithm-md5.rs6
-rw-r--r--tests/codegen/src-hash-algorithm/src-hash-algorithm-sha1.rs6
-rw-r--r--tests/codegen/src-hash-algorithm/src-hash-algorithm-sha256.rs6
-rw-r--r--tests/codegen/sse42-implies-crc32.rs15
-rw-r--r--tests/codegen/stack-probes-call.rs24
-rw-r--r--tests/codegen/stack-probes-inline.rs32
-rw-r--r--tests/codegen/stack-protector.rs34
-rw-r--r--tests/codegen/static-relocation-model-msvc.rs26
-rw-r--r--tests/codegen/staticlib-external-inline-fns.rs43
-rw-r--r--tests/codegen/stores.rs35
-rw-r--r--tests/codegen/swap-large-types.rs91
-rw-r--r--tests/codegen/swap-simd-types.rs41
-rw-r--r--tests/codegen/swap-small-types.rs78
-rw-r--r--tests/codegen/target-cpu-on-functions.rs21
-rw-r--r--tests/codegen/target-feature-overrides.rs47
-rw-r--r--tests/codegen/thread-local.rs50
-rw-r--r--tests/codegen/tied-features-strength.rs29
-rw-r--r--tests/codegen/to_vec.rs10
-rw-r--r--tests/codegen/transmute-optimized.rs109
-rw-r--r--tests/codegen/transmute-scalar.rs58
-rw-r--r--tests/codegen/try_identity.rs34
-rw-r--r--tests/codegen/try_question_mark_nop.rs54
-rw-r--r--tests/codegen/tune-cpu-on-functions.rs21
-rw-r--r--tests/codegen/tuple-layout-opt.rs36
-rw-r--r--tests/codegen/unchecked-float-casts.rs36
-rw-r--r--tests/codegen/unchecked_shifts.rs70
-rw-r--r--tests/codegen/uninit-consts.rs55
-rw-r--r--tests/codegen/union-abi.rs76
-rw-r--r--tests/codegen/unpadded-simd.rs14
-rw-r--r--tests/codegen/unwind-abis/aapcs-unwind-abi.rs31
-rw-r--r--tests/codegen/unwind-abis/c-unwind-abi-panic-abort.rs28
-rw-r--r--tests/codegen/unwind-abis/c-unwind-abi.rs30
-rw-r--r--tests/codegen/unwind-abis/cdecl-unwind-abi.rs30
-rw-r--r--tests/codegen/unwind-abis/fastcall-unwind-abi.rs31
-rw-r--r--tests/codegen/unwind-abis/nounwind-on-stable-panic-abort.rs16
-rw-r--r--tests/codegen/unwind-abis/nounwind-on-stable-panic-unwind.rs18
-rw-r--r--tests/codegen/unwind-abis/nounwind.rs17
-rw-r--r--tests/codegen/unwind-abis/stdcall-unwind-abi.rs31
-rw-r--r--tests/codegen/unwind-abis/system-unwind-abi.rs30
-rw-r--r--tests/codegen/unwind-abis/sysv64-unwind-abi.rs31
-rw-r--r--tests/codegen/unwind-abis/thiscall-unwind-abi.rs31
-rw-r--r--tests/codegen/unwind-abis/vectorcall-unwind-abi.rs31
-rw-r--r--tests/codegen/unwind-abis/win64-unwind-abi.rs31
-rw-r--r--tests/codegen/unwind-and-panic-abort.rs17
-rw-r--r--tests/codegen/unwind-extern-exports.rs17
-rw-r--r--tests/codegen/unwind-extern-imports.rs23
-rw-r--r--tests/codegen/used_with_arg.rs10
-rw-r--r--tests/codegen/var-names.rs15
-rw-r--r--tests/codegen/vec-as-ptr.rs19
-rw-r--r--tests/codegen/vec-calloc-llvm14.rs144
-rw-r--r--tests/codegen/vec-calloc.rs184
-rw-r--r--tests/codegen/vec-in-place.rs93
-rw-r--r--tests/codegen/vec-iter-collect-len.rs12
-rw-r--r--tests/codegen/vec-optimizes-away.rs13
-rw-r--r--tests/codegen/vec-shrink-panik.rs45
-rw-r--r--tests/codegen/vecdeque_no_panic.rs19
-rw-r--r--tests/codegen/virtual-function-elimination-32bit.rs35
-rw-r--r--tests/codegen/virtual-function-elimination.rs101
-rw-r--r--tests/codegen/wasm_casts_trapping.rs157
-rw-r--r--tests/codegen/wasm_exceptions.rs51
-rw-r--r--tests/codegen/x86_64-macosx-deployment-target.rs27
-rw-r--r--tests/codegen/x86_64-no-macosx-deployment-target.rs27
-rw-r--r--tests/codegen/zip.rs21
-rw-r--r--tests/codegen/zst-offset.rs43
408 files changed, 18120 insertions, 0 deletions
diff --git a/tests/codegen/README.md b/tests/codegen/README.md
new file mode 100644
index 00000000000..8f2daaafcc7
--- /dev/null
+++ b/tests/codegen/README.md
@@ -0,0 +1,24 @@
+The files here use the LLVM FileCheck framework, documented at
+<https://llvm.org/docs/CommandGuide/FileCheck.html>.
+
+One extension worth noting is the use of revisions as custom prefixes for
+FileCheck. If your codegen test has different behavior based on the chosen
+target or different compiler flags that you want to exercise, you can use a
+revisions annotation, like so:
+
+```rust
+// revisions: aaa bbb
+// [bbb] compile-flags: --flags-for-bbb
+```
+
+After specifying those variations, you can write different expected, or
+explicitly *unexpected* output by using `<prefix>-SAME:` and `<prefix>-NOT:`,
+like so:
+
+```rust
+// CHECK: expected code
+// aaa-SAME: emitted-only-for-aaa
+// aaa-NOT:                        emitted-only-for-bbb
+// bbb-NOT:  emitted-only-for-aaa
+// bbb-SAME:                       emitted-only-for-bbb
+```
diff --git a/tests/codegen/abi-efiapi.rs b/tests/codegen/abi-efiapi.rs
new file mode 100644
index 00000000000..9502ebf59af
--- /dev/null
+++ b/tests/codegen/abi-efiapi.rs
@@ -0,0 +1,33 @@
+// Checks if the correct annotation for the efiapi ABI is passed to llvm.
+
+// revisions:x86_64 i686 aarch64 arm riscv
+//[x86_64] compile-flags: --target x86_64-unknown-uefi
+//[x86_64] needs-llvm-components: aarch64 arm riscv
+//[i686] compile-flags: --target i686-unknown-linux-musl
+//[i686] needs-llvm-components: aarch64 arm riscv
+//[aarch64] compile-flags: --target aarch64-unknown-none
+//[aarch64] needs-llvm-components: aarch64 arm riscv
+//[arm] compile-flags: --target armv7r-none-eabi
+//[arm] needs-llvm-components: aarch64 arm riscv
+//[riscv] compile-flags: --target riscv64gc-unknown-none-elf
+//[riscv] needs-llvm-components: aarch64 arm riscv
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang="sized"]
+trait Sized { }
+#[lang="freeze"]
+trait Freeze { }
+#[lang="copy"]
+trait Copy { }
+
+//x86_64: define win64cc void @has_efiapi
+//i686: define void @has_efiapi
+//aarch64: define dso_local void @has_efiapi
+//arm: define dso_local arm_aapcscc void @has_efiapi
+//riscv: define dso_local void @has_efiapi
+#[no_mangle]
+pub extern "efiapi" fn has_efiapi() {}
diff --git a/tests/codegen/abi-main-signature-16bit-c-int.rs b/tests/codegen/abi-main-signature-16bit-c-int.rs
new file mode 100644
index 00000000000..353e7489b55
--- /dev/null
+++ b/tests/codegen/abi-main-signature-16bit-c-int.rs
@@ -0,0 +1,25 @@
+// Checks the signature of the implicitly generated native main()
+// 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
+// ignore-loongarch64
+
+fn main() {
+}
+
+// CHECK: define i16 @main(i16, i8**)
diff --git a/tests/codegen/abi-main-signature-32bit-c-int.rs b/tests/codegen/abi-main-signature-32bit-c-int.rs
new file mode 100644
index 00000000000..7f22ddcfc12
--- /dev/null
+++ b/tests/codegen/abi-main-signature-32bit-c-int.rs
@@ -0,0 +1,10 @@
+// Checks the signature of the implicitly generated native main()
+// entry point. It must match C's `int main(int, char **)`.
+
+// This test is for targets with 32bit c_int only.
+// ignore-msp430
+
+fn main() {
+}
+
+// CHECK: define{{( hidden)?}} i32 @main(i32{{( %0)?}}, {{i8\*\*|ptr}}{{( %1)?}})
diff --git a/tests/codegen/abi-repr-ext.rs b/tests/codegen/abi-repr-ext.rs
new file mode 100644
index 00000000000..23ade3c7216
--- /dev/null
+++ b/tests/codegen/abi-repr-ext.rs
@@ -0,0 +1,57 @@
+// compile-flags: -O
+
+// revisions:x86_64 i686 aarch64-apple aarch64-windows aarch64-linux arm riscv
+
+//[x86_64] compile-flags: --target x86_64-unknown-uefi
+//[x86_64] needs-llvm-components: x86
+//[i686] compile-flags: --target i686-unknown-linux-musl
+//[i686] needs-llvm-components: x86
+//[aarch64-windows] compile-flags: --target aarch64-pc-windows-msvc
+//[aarch64-windows] needs-llvm-components: aarch64
+//[aarch64-linux] compile-flags: --target aarch64-unknown-linux-gnu
+//[aarch64-linux] needs-llvm-components: aarch64
+//[aarch64-apple] compile-flags: --target aarch64-apple-darwin
+//[aarch64-apple] needs-llvm-components: aarch64
+//[arm] compile-flags: --target armv7r-none-eabi
+//[arm] needs-llvm-components: arm
+//[riscv] compile-flags: --target riscv64gc-unknown-none-elf
+//[riscv] needs-llvm-components: riscv
+
+// See bottom of file for a corresponding C source file that is meant to yield
+// equivalent declarations.
+#![feature(no_core, lang_items)]
+#![crate_type = "lib"]
+#![no_std]
+#![no_core]
+
+#[lang="sized"] trait Sized { }
+#[lang="freeze"] trait Freeze { }
+#[lang="copy"] trait Copy { }
+
+#[repr(i8)]
+pub enum Type {
+    Type1 = 0,
+    Type2 = 1
+}
+
+// To accommodate rust#97800, one might consider writing the below as:
+//
+// `define{{( dso_local)?}} noundef{{( signext)?}} i8 @test()`
+//
+// but based on rust#80556, it seems important to actually check for the
+// presence of the `signext` for those targets where we expect it.
+
+// CHECK: define{{( dso_local)?}} noundef
+// x86_64-SAME:                 signext
+// aarch64-apple-SAME:          signext
+// aarch64-windows-NOT: signext
+// aarch64-linux-NOT:   signext
+// arm-SAME:                    signext
+// riscv-SAME:                  signext
+// CHECK-SAME: i8 @test()
+
+
+#[no_mangle]
+pub extern "C" fn test() -> Type {
+    Type::Type1
+}
diff --git a/tests/codegen/abi-sysv64.rs b/tests/codegen/abi-sysv64.rs
new file mode 100644
index 00000000000..3c2d4e719d4
--- /dev/null
+++ b/tests/codegen/abi-sysv64.rs
@@ -0,0 +1,22 @@
+// Checks if the correct annotation for the sysv64 ABI is passed to
+// llvm. Also checks that the abi-sysv64 feature gate allows usage
+// of the sysv64 abi.
+//
+// needs-llvm-components: x86
+// compile-flags: -C no-prepopulate-passes --target=x86_64-unknown-linux-gnu -Copt-level=0
+
+#![crate_type = "lib"]
+#![no_core]
+#![feature(abi_x86_interrupt, no_core, lang_items)]
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+impl Copy for i64 {}
+
+// CHECK: define x86_64_sysvcc i64 @has_sysv64_abi
+#[no_mangle]
+pub extern "sysv64" fn has_sysv64_abi(a: i64) -> i64 {
+    a
+}
diff --git a/tests/codegen/abi-x86-interrupt.rs b/tests/codegen/abi-x86-interrupt.rs
new file mode 100644
index 00000000000..928ad5a9bbd
--- /dev/null
+++ b/tests/codegen/abi-x86-interrupt.rs
@@ -0,0 +1,22 @@
+// Checks if the correct annotation for the x86-interrupt ABI is passed to
+// llvm. Also checks that the abi_x86_interrupt feature gate allows usage
+// of the x86-interrupt abi.
+
+// needs-llvm-components: x86
+// compile-flags: -C no-prepopulate-passes --target=x86_64-unknown-linux-gnu -Copt-level=0
+
+#![crate_type = "lib"]
+#![no_core]
+#![feature(abi_x86_interrupt, no_core, lang_items)]
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+impl Copy for i64 {}
+
+// CHECK: define x86_intrcc i64 @has_x86_interrupt_abi
+#[no_mangle]
+pub extern "x86-interrupt" fn has_x86_interrupt_abi(a: i64) -> i64 {
+    a
+}
diff --git a/tests/codegen/abi-x86_64_sysv.rs b/tests/codegen/abi-x86_64_sysv.rs
new file mode 100644
index 00000000000..84e06023e9c
--- /dev/null
+++ b/tests/codegen/abi-x86_64_sysv.rs
@@ -0,0 +1,29 @@
+// only-x86_64
+
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+pub struct S24 {
+  a: i8,
+  b: i8,
+  c: i8,
+}
+
+pub struct S48 {
+  a: i16,
+  b: i16,
+  c: i8,
+}
+
+// CHECK: i24 @struct_24_bits(i24
+#[no_mangle]
+pub extern "sysv64" fn struct_24_bits(a: S24) -> S24 {
+  a
+}
+
+// CHECK: i48 @struct_48_bits(i48
+#[no_mangle]
+pub extern "sysv64" fn struct_48_bits(a: S48) -> S48 {
+  a
+}
diff --git a/tests/codegen/addr-of-mutate.rs b/tests/codegen/addr-of-mutate.rs
new file mode 100644
index 00000000000..bea1aad2352
--- /dev/null
+++ b/tests/codegen/addr-of-mutate.rs
@@ -0,0 +1,34 @@
+// compile-flags: -C opt-level=3 -C no-prepopulate-passes
+// min-llvm-version: 15.0 (for opaque pointers)
+
+#![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 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 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 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
new file mode 100644
index 00000000000..b53a68a5588
--- /dev/null
+++ b/tests/codegen/adjustments.rs
@@ -0,0 +1,29 @@
+// compile-flags: -C no-prepopulate-passes -Copt-level=0
+
+#![crate_type = "lib"]
+
+// Hack to get the correct size for the length part in slices
+// CHECK: @helper([[USIZE:i[0-9]+]] %_1)
+#[no_mangle]
+pub fn helper(_: usize) {
+}
+
+// CHECK-LABEL: @no_op_slice_adjustment
+#[no_mangle]
+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
+    { x }
+}
+
+// CHECK-LABEL: @no_op_slice_adjustment2
+#[no_mangle]
+pub fn no_op_slice_adjustment2(x: &[u8]) -> &[u8] {
+    // We used to generate an extra alloca and memcpy for the function's return value, so check
+    // that there's no memcpy (the slice is written to sret_slot element-wise)
+// CHECK-NOT: call void @llvm.memcpy.
+    no_op_slice_adjustment(x)
+}
diff --git a/tests/codegen/align-enum.rs b/tests/codegen/align-enum.rs
new file mode 100644
index 00000000000..70f09ace006
--- /dev/null
+++ b/tests/codegen/align-enum.rs
@@ -0,0 +1,34 @@
+// compile-flags: -C no-prepopulate-passes -Z mir-opt-level=0
+//
+
+#![crate_type = "lib"]
+
+#[repr(align(64))]
+pub enum Align64 {
+    A(u32),
+    B(u32),
+}
+// CHECK: %Align64 = type { i32, [15 x i32] }
+
+pub struct Nested64 {
+    a: u8,
+    b: Align64,
+    c: u16,
+}
+
+// CHECK-LABEL: @align64
+#[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)
+    let a64 = Align64::A(a);
+    a64
+}
+
+// CHECK-LABEL: @nested64
+#[no_mangle]
+pub fn nested64(a: u8, b: u32, c: u16) -> Nested64 {
+// CHECK: %n64 = alloca %Nested64, align 64
+    let n64 = Nested64 { a, b: Align64::B(b), c };
+    n64
+}
diff --git a/tests/codegen/align-fn.rs b/tests/codegen/align-fn.rs
new file mode 100644
index 00000000000..f3cf614e185
--- /dev/null
+++ b/tests/codegen/align-fn.rs
@@ -0,0 +1,49 @@
+// compile-flags: -C no-prepopulate-passes -Z mir-opt-level=0
+
+#![crate_type = "lib"]
+#![feature(fn_align)]
+
+// CHECK: align 16
+#[no_mangle]
+#[repr(align(16))]
+pub fn fn_align() {}
+
+pub struct A;
+
+impl A {
+    // CHECK: align 16
+    #[no_mangle]
+    #[repr(align(16))]
+    pub fn method_align(self) {}
+
+    // CHECK: align 16
+    #[no_mangle]
+    #[repr(align(16))]
+    pub fn associated_fn() {}
+}
+
+trait T: Sized {
+    fn trait_fn() {}
+
+    // CHECK: align 32
+    #[repr(align(32))]
+    fn trait_method(self) {}
+}
+
+impl T for A {
+    // CHECK: align 16
+    #[no_mangle]
+    #[repr(align(16))]
+    fn trait_fn() {}
+
+    // CHECK: align 16
+    #[no_mangle]
+    #[repr(align(16))]
+    fn trait_method(self) {}
+}
+
+impl T for () {}
+
+pub fn foo() {
+    ().trait_method();
+}
diff --git a/tests/codegen/align-offset.rs b/tests/codegen/align-offset.rs
new file mode 100644
index 00000000000..7c7660c5a55
--- /dev/null
+++ b/tests/codegen/align-offset.rs
@@ -0,0 +1,78 @@
+// compile-flags: -O
+// min-llvm-version: 15.0 (because we're using opaque pointers)
+// 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
new file mode 100644
index 00000000000..a2f47354b2b
--- /dev/null
+++ b/tests/codegen/align-struct.rs
@@ -0,0 +1,71 @@
+// compile-flags: -C no-prepopulate-passes -Z mir-opt-level=0
+//
+
+#![crate_type = "lib"]
+
+#[repr(align(64))]
+pub struct Align64(i32);
+// CHECK: %Align64 = type { i32, [15 x i32] }
+
+pub struct Nested64 {
+    a: Align64,
+    b: i32,
+    c: i32,
+    d: i8,
+}
+// CHECK: %Nested64 = type { %Align64, i32, i32, i8, [55 x i8] }
+
+pub enum Enum4 {
+    A(i32),
+    B(i32),
+}
+// No Aggregate type, and hence nothing in LLVM IR.
+
+pub enum Enum64 {
+    A(Align64),
+    B(i32),
+}
+// CHECK: %Enum64 = type { i32, [31 x i32] }
+// CHECK: %"Enum64::A" = type { [8 x i64], %Align64 }
+
+// CHECK-LABEL: @align64
+#[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)
+    let a64 = Align64(i);
+    a64
+}
+
+// For issue 54028: make sure that we are specifying the correct alignment for fields of aligned
+// structs
+// CHECK-LABEL: @align64_load
+#[no_mangle]
+pub fn align64_load(a: Align64) -> i32 {
+// CHECK: {{%.*}} = load i32, {{i32\*|ptr}} {{%.*}}, align 64
+    a.0
+}
+
+// CHECK-LABEL: @nested64
+#[no_mangle]
+pub fn nested64(a: Align64, b: i32, c: i32, d: i8) -> Nested64 {
+// CHECK: %n64 = alloca %Nested64, align 64
+    let n64 = Nested64 { a, b, c, d };
+    n64
+}
+
+// CHECK-LABEL: @enum4
+#[no_mangle]
+pub fn enum4(a: i32) -> Enum4 {
+// CHECK: %e4 = alloca { i32, i32 }, align 4
+    let e4 = Enum4::A(a);
+    e4
+}
+
+// CHECK-LABEL: @enum64
+#[no_mangle]
+pub fn enum64(a: Align64) -> Enum64 {
+// CHECK: %e64 = alloca %Enum64, align 64
+    let e64 = Enum64::A(a);
+    e64
+}
diff --git a/tests/codegen/alloc-optimisation.rs b/tests/codegen/alloc-optimisation.rs
new file mode 100644
index 00000000000..f88d695d87e
--- /dev/null
+++ b/tests/codegen/alloc-optimisation.rs
@@ -0,0 +1,14 @@
+//
+// no-system-llvm
+// compile-flags: -O
+#![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-clone.rs b/tests/codegen/array-clone.rs
new file mode 100644
index 00000000000..0d42963bcd2
--- /dev/null
+++ b/tests/codegen/array-clone.rs
@@ -0,0 +1,15 @@
+// compile-flags: -O
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @array_clone
+#[no_mangle]
+pub fn array_clone(a: &[u8; 2]) -> [u8; 2] {
+    // CHECK-NOT: getelementptr
+    // CHECK-NOT: load i8
+    // CHECK-NOT: zext
+    // CHECK-NOT: shl
+    // CHECK: load i16
+    // CHECK-NEXT: ret i16
+    a.clone()
+}
diff --git a/tests/codegen/array-codegen.rs b/tests/codegen/array-codegen.rs
new file mode 100644
index 00000000000..71acd781549
--- /dev/null
+++ b/tests/codegen/array-codegen.rs
@@ -0,0 +1,35 @@
+// compile-flags: -O -C no-prepopulate-passes
+// min-llvm-version: 15.0 (for opaque pointers)
+
+#![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
new file mode 100644
index 00000000000..abfe295f8b6
--- /dev/null
+++ b/tests/codegen/array-equality.rs
@@ -0,0 +1,102 @@
+// compile-flags: -O -Z merge-functions=disabled
+// only-x86_64
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @array_eq_value
+#[no_mangle]
+pub fn array_eq_value(a: [u16; 3], b: [u16; 3]) -> bool {
+    // CHECK-NEXT: start:
+    // CHECK-NEXT: %2 = icmp eq i48 %0, %1
+    // CHECK-NEXT: ret i1 %2
+    a == b
+}
+
+// CHECK-LABEL: @array_eq_ref
+#[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: icmp eq i48
+    // CHECK-NEXT: ret
+    a == b
+}
+
+// CHECK-LABEL: @array_eq_value_still_passed_by_pointer
+#[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-NEXT: %[[EQ:.+]] = icmp eq i32 %[[CMP]], 0
+    // CHECK-NEXT: ret i1 %[[EQ]]
+    a == b
+}
+
+// CHECK-LABEL: @array_eq_long
+#[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-NEXT: %[[EQ:.+]] = icmp eq i32 %[[CMP]], 0
+    // CHECK-NEXT: ret i1 %[[EQ]]
+    a == b
+}
+
+// CHECK-LABEL: @array_char_eq
+#[no_mangle]
+pub fn array_char_eq(a: [char; 2], b: [char; 2]) -> bool {
+    // CHECK-NEXT: start:
+    // CHECK-NEXT: %[[EQ:.+]] = icmp eq i64 %0, %1
+    // CHECK-NEXT: ret i1 %[[EQ]]
+    a == b
+}
+
+// CHECK-LABEL: @array_eq_zero_short(i48
+#[no_mangle]
+pub fn array_eq_zero_short(x: [u16; 3]) -> bool {
+    // CHECK-NEXT: start:
+    // CHECK-NEXT: %[[EQ:.+]] = icmp eq i48 %0, 0
+    // CHECK-NEXT: ret i1 %[[EQ]]
+    x == [0; 3]
+}
+
+// CHECK-LABEL: @array_eq_none_short(i40
+#[no_mangle]
+pub fn array_eq_none_short(x: [Option<std::num::NonZeroU8>; 5]) -> bool {
+    // CHECK-NEXT: start:
+    // CHECK-NEXT: %[[EQ:.+]] = icmp eq i40 %0, 0
+    // CHECK-NEXT: ret i1 %[[EQ]]
+    x == [None; 5]
+}
+
+// CHECK-LABEL: @array_eq_zero_nested(
+#[no_mangle]
+pub fn array_eq_zero_nested(x: [[u8; 3]; 3]) -> bool {
+    // CHECK: %[[VAL:.+]] = load i72
+    // CHECK-SAME: align 1
+    // CHECK: %[[EQ:.+]] = icmp eq i72 %[[VAL]], 0
+    // CHECK: ret i1 %[[EQ]]
+    x == [[0; 3]; 3]
+}
+
+// CHECK-LABEL: @array_eq_zero_mid(
+#[no_mangle]
+pub fn array_eq_zero_mid(x: [u16; 8]) -> bool {
+    // CHECK-NEXT: start:
+    // CHECK: %[[LOAD:.+]] = load i128,
+    // CHECK-NEXT: %[[EQ:.+]] = icmp eq i128 %[[LOAD]], 0
+    // CHECK-NEXT: ret i1 %[[EQ]]
+    x == [0; 8]
+}
+
+// CHECK-LABEL: @array_eq_zero_long(
+#[no_mangle]
+pub fn array_eq_zero_long(x: [u16; 1234]) -> bool {
+    // CHECK-NEXT: start:
+    // CHECK-NOT: alloca
+    // CHECK: %[[CMP:.+]] = tail call i32 @{{bcmp|memcmp}}(
+    // CHECK-NEXT: %[[EQ:.+]] = icmp eq i32 %[[CMP]], 0
+    // CHECK-NEXT: ret i1 %[[EQ]]
+    x == [0; 1234]
+}
diff --git a/tests/codegen/array-map.rs b/tests/codegen/array-map.rs
new file mode 100644
index 00000000000..24f3f43d078
--- /dev/null
+++ b/tests/codegen/array-map.rs
@@ -0,0 +1,38 @@
+// compile-flags: -C opt-level=3 -C target-cpu=x86-64-v3
+// no-system-llvm
+// only-x86_64
+// ignore-debug (the extra assertions get in the way)
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @short_integer_map
+#[no_mangle]
+pub fn short_integer_map(x: [u32; 8]) -> [u32; 8] {
+    // CHECK: load <8 x i32>
+    // CHECK: shl <8 x i32>
+    // CHECK: or <8 x i32>
+    // CHECK: store <8 x i32>
+    x.map(|x| 2 * x + 1)
+}
+
+// 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
+// hard-to-eliminate `memcpy` and that the iteration counts needed to be written
+// out to stack every iteration, even for infallible operations on `Copy` types.
+//
+// This is still imperfect, as there's more copies than would be ideal,
+// but hopefully work like #103830 will improve that in future,
+// and update this test to be stricter.
+//
+// CHECK-LABEL: @long_integer_map
+#[no_mangle]
+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>
+    x.map(|x| 13 * x + 7)
+}
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/asm-clobber_abi.rs b/tests/codegen/asm-clobber_abi.rs
new file mode 100644
index 00000000000..f70caea2fb9
--- /dev/null
+++ b/tests/codegen/asm-clobber_abi.rs
@@ -0,0 +1,36 @@
+// compile-flags: -O
+// only-x86_64
+
+#![crate_type = "rlib"]
+
+use std::arch::asm;
+
+// CHECK-LABEL: @clobber_sysv64
+// CHECK: ={ax},={cx},={dx},={si},={di},={r8},={r9},={r10},={r11},={xmm0},={xmm1},={xmm2},={xmm3},={xmm4},={xmm5},={xmm6},={xmm7},={xmm8},={xmm9},={xmm10},={xmm11},={xmm12},={xmm13},={xmm14},={xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{k0},~{k1},~{k2},~{k3},~{k4},~{k5},~{k6},~{k7},~{st},~{st(1)},~{st(2)},~{st(3)},~{st(4)},~{st(5)},~{st(6)},~{st(7)},~{tmm0},~{tmm1},~{tmm2},~{tmm3},~{tmm4},~{tmm5},~{tmm6},~{tmm7},~{dirflag},~{fpsr},~{flags},~{memory}
+#[no_mangle]
+pub unsafe fn clobber_sysv64() {
+    asm!("", clobber_abi("sysv64"));
+}
+
+// CHECK-LABEL: @clobber_win64
+// CHECK: ={ax},={cx},={dx},={r8},={r9},={r10},={r11},={xmm0},={xmm1},={xmm2},={xmm3},={xmm4},={xmm5},={xmm6},={xmm7},={xmm8},={xmm9},={xmm10},={xmm11},={xmm12},={xmm13},={xmm14},={xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{k0},~{k1},~{k2},~{k3},~{k4},~{k5},~{k6},~{k7},~{st},~{st(1)},~{st(2)},~{st(3)},~{st(4)},~{st(5)},~{st(6)},~{st(7)},~{tmm0},~{tmm1},~{tmm2},~{tmm3},~{tmm4},~{tmm5},~{tmm6},~{tmm7},~{dirflag},~{fpsr},~{flags},~{memory}
+#[no_mangle]
+pub unsafe fn clobber_win64() {
+    asm!("", clobber_abi("win64"));
+}
+
+// CHECK-LABEL: @clobber_sysv64
+// CHECK: =&{dx},={ax},={cx},={si},={di},={r8},={r9},={r10},={r11},={xmm0},={xmm1},={xmm2},={xmm3},={xmm4},={xmm5},={xmm6},={xmm7},={xmm8},={xmm9},={xmm10},={xmm11},={xmm12},={xmm13},={xmm14},={xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{k0},~{k1},~{k2},~{k3},~{k4},~{k5},~{k6},~{k7},~{st},~{st(1)},~{st(2)},~{st(3)},~{st(4)},~{st(5)},~{st(6)},~{st(7)},~{tmm0},~{tmm1},~{tmm2},~{tmm3},~{tmm4},~{tmm5},~{tmm6},~{tmm7},~{dirflag},~{fpsr},~{flags},~{memory}
+#[no_mangle]
+pub unsafe fn clobber_sysv64_edx() {
+    let foo: i32;
+    asm!("", out("edx") foo, clobber_abi("sysv64"));
+}
+
+// CHECK-LABEL: @clobber_win64
+// CHECK: =&{dx},={ax},={cx},={r8},={r9},={r10},={r11},={xmm0},={xmm1},={xmm2},={xmm3},={xmm4},={xmm5},={xmm6},={xmm7},={xmm8},={xmm9},={xmm10},={xmm11},={xmm12},={xmm13},={xmm14},={xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{k0},~{k1},~{k2},~{k3},~{k4},~{k5},~{k6},~{k7},~{st},~{st(1)},~{st(2)},~{st(3)},~{st(4)},~{st(5)},~{st(6)},~{st(7)},~{tmm0},~{tmm1},~{tmm2},~{tmm3},~{tmm4},~{tmm5},~{tmm6},~{tmm7},~{dirflag},~{fpsr},~{flags},~{memory}
+#[no_mangle]
+pub unsafe fn clobber_win64_edx() {
+    let foo: i32;
+    asm!("", out("edx") foo, clobber_abi("win64"));
+}
diff --git a/tests/codegen/asm-clobbers.rs b/tests/codegen/asm-clobbers.rs
new file mode 100644
index 00000000000..2ef10a2837d
--- /dev/null
+++ b/tests/codegen/asm-clobbers.rs
@@ -0,0 +1,20 @@
+// compile-flags: -O
+// only-x86_64
+
+#![crate_type = "rlib"]
+
+use std::arch::asm;
+
+// CHECK-LABEL: @x87_clobber
+// CHECK: ~{st},~{st(1)},~{st(2)},~{st(3)},~{st(4)},~{st(5)},~{st(6)},~{st(7)}
+#[no_mangle]
+pub unsafe fn x87_clobber() {
+    asm!("foo", out("st") _);
+}
+
+// CHECK-LABEL: @mmx_clobber
+// CHECK: ~{st},~{st(1)},~{st(2)},~{st(3)},~{st(4)},~{st(5)},~{st(6)},~{st(7)}
+#[no_mangle]
+pub unsafe fn mmx_clobber() {
+    asm!("bar", out("mm0") _, out("mm1") _);
+}
diff --git a/tests/codegen/asm-may_unwind.rs b/tests/codegen/asm-may_unwind.rs
new file mode 100644
index 00000000000..c97933035d1
--- /dev/null
+++ b/tests/codegen/asm-may_unwind.rs
@@ -0,0 +1,39 @@
+// compile-flags: -O
+// only-x86_64
+
+#![crate_type = "rlib"]
+#![feature(asm_unwind)]
+
+use std::arch::asm;
+
+#[no_mangle]
+pub extern "C" fn panicky() {}
+
+struct Foo;
+
+impl Drop for Foo {
+    fn drop(&mut self) {
+        println!();
+    }
+}
+
+// CHECK-LABEL: @asm_may_unwind
+#[no_mangle]
+pub unsafe fn asm_may_unwind() {
+    let _m = Foo;
+    // CHECK: invoke void asm sideeffect alignstack inteldialect unwind ""
+    asm!("", options(may_unwind));
+}
+
+// CHECK-LABEL: @asm_with_result_may_unwind
+#[no_mangle]
+pub unsafe fn asm_with_result_may_unwind() -> u64 {
+    let _m = Foo;
+    let res: u64;
+    // CHECK: [[RES:%[0-9]+]] = invoke i64 asm sideeffect alignstack inteldialect unwind
+    // CHECK-NEXT: to label %[[NORMALBB:[a-b0-9]+]]
+    asm!("mov {}, 1", out(reg) res, options(may_unwind));
+    // CHECK: [[NORMALBB]]:
+    // CHECK: ret i64 [[RES:%[0-9]+]]
+    res
+}
diff --git a/tests/codegen/asm-multiple-options.rs b/tests/codegen/asm-multiple-options.rs
new file mode 100644
index 00000000000..1ae37d627d6
--- /dev/null
+++ b/tests/codegen/asm-multiple-options.rs
@@ -0,0 +1,54 @@
+// compile-flags: -O
+// only-x86_64
+
+#![crate_type = "rlib"]
+
+use std::arch::asm;
+
+// CHECK-LABEL: @pure
+// CHECK-NOT: asm
+// CHECK: ret void
+#[no_mangle]
+pub unsafe fn pure(x: i32) {
+    let y: i32;
+    asm!("", out("ax") y, in("cx") x, options(pure), options(nomem));
+}
+
+pub static mut VAR: i32 = 0;
+pub static mut DUMMY_OUTPUT: i32 = 0;
+
+// CHECK-LABEL: @readonly
+// CHECK: call i32 asm
+// CHECK: ret i32 1
+#[no_mangle]
+pub unsafe fn readonly() -> i32 {
+    VAR = 1;
+    asm!("", out("ax") DUMMY_OUTPUT, options(pure), options(readonly));
+    VAR
+}
+
+// CHECK-LABEL: @nomem
+// CHECK-NOT: store
+// CHECK: call i32 asm
+// CHECK: store
+// CHECK: ret i32 2
+#[no_mangle]
+pub unsafe fn nomem() -> i32 {
+    VAR = 1;
+    asm!("", out("ax") DUMMY_OUTPUT, options(pure), options(nomem));
+    VAR = 2;
+    VAR
+}
+
+// CHECK-LABEL: @not_nomem
+// CHECK: store
+// CHECK: call i32 asm
+// CHECK: store
+// CHECK: ret i32 2
+#[no_mangle]
+pub unsafe fn not_nomem() -> i32 {
+    VAR = 1;
+    asm!("", out("ax") DUMMY_OUTPUT, options(pure), options(readonly));
+    VAR = 2;
+    VAR
+}
diff --git a/tests/codegen/asm-options.rs b/tests/codegen/asm-options.rs
new file mode 100644
index 00000000000..963b60cfe35
--- /dev/null
+++ b/tests/codegen/asm-options.rs
@@ -0,0 +1,104 @@
+// compile-flags: -O
+// only-x86_64
+
+#![crate_type = "rlib"]
+
+use std::arch::asm;
+
+// CHECK-LABEL: @pure
+// CHECK-NOT: asm
+// CHECK: ret void
+#[no_mangle]
+pub unsafe fn pure(x: i32) {
+    let y: i32;
+    asm!("", out("ax") y, in("cx") x, options(pure, nomem));
+}
+
+// CHECK-LABEL: @noreturn
+// CHECK: call void asm
+// CHECK-NEXT: unreachable
+#[no_mangle]
+pub unsafe fn noreturn() {
+    asm!("", options(noreturn));
+}
+
+pub static mut VAR: i32 = 0;
+pub static mut DUMMY_OUTPUT: i32 = 0;
+
+// CHECK-LABEL: @readonly
+// CHECK: call i32 asm
+// CHECK: ret i32 1
+#[no_mangle]
+pub unsafe fn readonly() -> i32 {
+    VAR = 1;
+    asm!("", out("ax") DUMMY_OUTPUT, options(pure, readonly));
+    VAR
+}
+
+// CHECK-LABEL: @not_readonly
+// CHECK: call i32 asm
+// CHECK: ret i32 %
+#[no_mangle]
+pub unsafe fn not_readonly() -> i32 {
+    VAR = 1;
+    asm!("", out("ax") DUMMY_OUTPUT, options());
+    VAR
+}
+
+// CHECK-LABEL: @nomem
+// CHECK-NOT: store
+// CHECK: call i32 asm
+// CHECK: store
+// CHECK: ret i32 2
+#[no_mangle]
+pub unsafe fn nomem() -> i32 {
+    VAR = 1;
+    asm!("", out("ax") DUMMY_OUTPUT, options(pure, nomem));
+    VAR = 2;
+    VAR
+}
+
+// CHECK-LABEL: @nomem_nopure
+// CHECK-NOT: store
+// CHECK: call i32 asm
+// CHECK: store
+// CHECK: ret i32 2
+#[no_mangle]
+pub unsafe fn nomem_nopure() -> i32 {
+    VAR = 1;
+    asm!("", out("ax") DUMMY_OUTPUT, options(nomem));
+    VAR = 2;
+    VAR
+}
+
+// CHECK-LABEL: @not_nomem
+// CHECK: store
+// CHECK: call i32 asm
+// CHECK: store
+// CHECK: ret i32 2
+#[no_mangle]
+pub unsafe fn not_nomem() -> i32 {
+    VAR = 1;
+    asm!("", out("ax") DUMMY_OUTPUT, options(pure, readonly));
+    VAR = 2;
+    VAR
+}
+
+// CHECK-LABEL: @dont_remove_nonpure
+// CHECK: call void asm
+// CHECK: call void asm
+// CHECK: call void asm
+// CHECK: ret void
+#[no_mangle]
+pub unsafe fn dont_remove_nonpure() {
+    asm!("", options());
+    asm!("", options(nomem));
+    asm!("", options(readonly));
+}
+
+// CHECK-LABEL: @raw
+// CHECK: call void asm sideeffect inteldialect "{} {}", ""()
+#[no_mangle]
+pub unsafe fn raw() {
+    asm!("{} {}", options(nostack, nomem, preserves_flags, raw));
+}
diff --git a/tests/codegen/asm-powerpc-clobbers.rs b/tests/codegen/asm-powerpc-clobbers.rs
new file mode 100644
index 00000000000..10b20ba6beb
--- /dev/null
+++ b/tests/codegen/asm-powerpc-clobbers.rs
@@ -0,0 +1,47 @@
+// revisions: powerpc powerpc64 powerpc64le
+//[powerpc] compile-flags: --target powerpc-unknown-linux-gnu
+//[powerpc] needs-llvm-components: powerpc
+//[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu
+//[powerpc64] needs-llvm-components: powerpc
+//[powerpc64le] compile-flags: --target powerpc64le-unknown-linux-gnu
+//[powerpc64le] needs-llvm-components: powerpc
+
+#![crate_type = "rlib"]
+#![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+    () => {};
+}
+
+// CHECK-LABEL: @cr_clobber
+// CHECK: call void asm sideeffect "", "~{cr}"()
+#[no_mangle]
+pub unsafe fn cr_clobber() {
+    asm!("", out("cr") _, options(nostack, nomem));
+}
+
+// CHECK-LABEL: @cr0_clobber
+// CHECK: call void asm sideeffect "", "~{cr0}"()
+#[no_mangle]
+pub unsafe fn cr0_clobber() {
+    asm!("", out("cr0") _, options(nostack, nomem));
+}
+
+// CHECK-LABEL: @cr5_clobber
+// CHECK: call void asm sideeffect "", "~{cr5}"()
+#[no_mangle]
+pub unsafe fn cr5_clobber() {
+    asm!("", out("cr5") _, options(nostack, nomem));
+}
+
+// CHECK-LABEL: @xer_clobber
+// CHECK: call void asm sideeffect "", "~{xer}"()
+#[no_mangle]
+pub unsafe fn xer_clobber() {
+    asm!("", out("xer") _, options(nostack, nomem));
+}
diff --git a/tests/codegen/asm-sanitize-llvm.rs b/tests/codegen/asm-sanitize-llvm.rs
new file mode 100644
index 00000000000..6dcacd08cac
--- /dev/null
+++ b/tests/codegen/asm-sanitize-llvm.rs
@@ -0,0 +1,34 @@
+// FIXME(nagisa): remove the flags below once all targets support `asm!`.
+// compile-flags: --target x86_64-unknown-linux-gnu
+// needs-llvm-components: x86
+
+// Verify we sanitize the special tokens for the LLVM inline-assembly, ensuring people won't
+// inadvertently rely on the LLVM-specific syntax and features.
+#![no_core]
+#![feature(no_core, lang_items, rustc_attrs)]
+#![crate_type = "rlib"]
+#![allow(named_asm_labels)]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+    () => {};
+}
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+pub unsafe fn we_escape_dollar_signs() {
+    // CHECK: call void asm sideeffect alignstack inteldialect "banana$$:"
+    asm!(
+        r"banana$:",
+    )
+}
+
+pub unsafe fn we_escape_escapes_too() {
+    // CHECK: call void asm sideeffect alignstack inteldialect "banana\{{(\\|5C)}}36:"
+    asm!(
+        r"banana\36:",
+    )
+}
diff --git a/tests/codegen/asm-target-clobbers.rs b/tests/codegen/asm-target-clobbers.rs
new file mode 100644
index 00000000000..ac30e18ec52
--- /dev/null
+++ b/tests/codegen/asm-target-clobbers.rs
@@ -0,0 +1,29 @@
+// only-x86_64
+// revisions: base avx512
+// [avx512]compile-flags: -C target-feature=+avx512f
+
+#![crate_type = "rlib"]
+
+use std::arch::asm;
+
+// CHECK-LABEL: @amx_clobber
+// base: call void asm sideeffect inteldialect "", "~{tmm0}"()
+#[no_mangle]
+pub unsafe fn amx_clobber() {
+    asm!("", out("tmm0") _, options(nostack, nomem, preserves_flags));
+}
+
+// CHECK-LABEL: @avx512_clobber
+// base: call void asm sideeffect inteldialect "", "~{xmm31}"()
+// avx512: call float asm sideeffect inteldialect "", "=&{xmm31}"()
+#[no_mangle]
+pub unsafe fn avx512_clobber() {
+    asm!("", out("zmm31") _, options(nostack, nomem, preserves_flags));
+}
+
+// CHECK-LABEL: @eax_clobber
+// CHECK: call i32 asm sideeffect inteldialect "", "=&{ax}"()
+#[no_mangle]
+pub unsafe fn eax_clobber() {
+    asm!("", out("eax") _, options(nostack, nomem, preserves_flags));
+}
diff --git a/tests/codegen/async-fn-debug-awaitee-field.rs b/tests/codegen/async-fn-debug-awaitee-field.rs
new file mode 100644
index 00000000000..bc268615814
--- /dev/null
+++ b/tests/codegen/async-fn-debug-awaitee-field.rs
@@ -0,0 +1,25 @@
+// This test makes sure that the generator field capturing the awaitee in a `.await` expression
+// is called "__awaitee" in debuginfo. This name must not be changed since debuggers and debugger
+// extensions rely on the field having this name.
+
+// ignore-tidy-linelength
+// compile-flags: -C debuginfo=2 --edition=2018
+
+async fn foo() {}
+
+async fn async_fn_test() {
+    foo().await;
+}
+
+// NONMSVC: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}", scope: [[GEN_SCOPE:![0-9]*]],
+// MSVC: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "enum2$<async_fn_debug_awaitee_field::async_fn_test::async_fn_env$0>",
+// NONMSVC: [[GEN_SCOPE:!.*]] = !DINamespace(name: "async_fn_test",
+// CHECK: [[SUSPEND_STRUCT:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend0", scope: [[GEN]],
+// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "__awaitee", scope: [[SUSPEND_STRUCT]], {{.*}}, baseType: [[AWAITEE_TYPE:![0-9]*]],
+// NONMSVC: [[AWAITEE_TYPE]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}", scope: [[AWAITEE_SCOPE:![0-9]*]],
+// MSVC: [[AWAITEE_TYPE]] = !DICompositeType(tag: DW_TAG_union_type, name: "enum2$<async_fn_debug_awaitee_field::foo::async_fn_env$0>",
+// NONMSVC: [[AWAITEE_SCOPE]] = !DINamespace(name: "foo",
+
+fn main() {
+    let _fn = async_fn_test();
+}
diff --git a/tests/codegen/async-fn-debug-msvc.rs b/tests/codegen/async-fn-debug-msvc.rs
new file mode 100644
index 00000000000..73c652c9dd1
--- /dev/null
+++ b/tests/codegen/async-fn-debug-msvc.rs
@@ -0,0 +1,54 @@
+// Verify debuginfo for generators:
+//  - Each variant points to the file and line of its yield point
+//  - The discriminants are marked artificial
+//  - Other fields are not marked artificial
+//
+//
+// compile-flags: -C debuginfo=2 --edition=2018
+// only-msvc
+
+async fn foo() {}
+async fn async_fn_test() {
+    foo().await;
+    let s = String::from("foo");
+    foo().await;
+}
+
+// FIXME: No way to reliably check the filename.
+
+// CHECK-DAG:  [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "enum2$<async_fn_debug_msvc::async_fn_test::async_fn_env$0>",
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant0", scope: [[GEN]],
+// For brevity, we only check the struct name and members of the last variant.
+// CHECK-SAME: file: [[FILE:![0-9]*]], line: 11,
+// CHECK-NOT:  flags: DIFlagArtificial
+// CHECK-SAME: )
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant1", scope: [[GEN]],
+// CHECK-SAME: file: [[FILE]], line: 15,
+// CHECK-NOT:  flags: DIFlagArtificial
+// CHECK-SAME: )
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant2", scope: [[GEN]],
+// CHECK-SAME: file: [[FILE]], line: 15,
+// CHECK-NOT:  flags: DIFlagArtificial
+// CHECK-SAME: )
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant3", scope: [[GEN]],
+// CHECK-SAME: file: [[FILE]], line: 12,
+// CHECK-NOT:  flags: DIFlagArtificial
+// CHECK-SAME: )
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant4", scope: [[GEN]],
+// CHECK-SAME: file: [[FILE]], line: 14,
+// CHECK-SAME: baseType: [[VARIANT_WRAPPER:![0-9]*]]
+// CHECK-NOT:  flags: DIFlagArtificial
+// CHECK-SAME: )
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "value", scope: [[VARIANT_WRAPPER]], file: !2, baseType: [[VARIANT:![0-9]*]],
+// CHECK:      [[VARIANT]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN]],
+// CHECK-NOT:  flags: DIFlagArtificial
+// CHECK-SAME: )
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[VARIANT]]
+// CHECK-NOT:  flags: DIFlagArtificial
+// CHECK-SAME: )
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "tag", scope: [[GEN]],
+// CHECK-NOT: flags: DIFlagArtificial
+
+fn main() {
+    let _dummy = async_fn_test();
+}
diff --git a/tests/codegen/async-fn-debug.rs b/tests/codegen/async-fn-debug.rs
new file mode 100644
index 00000000000..9f6058a71b3
--- /dev/null
+++ b/tests/codegen/async-fn-debug.rs
@@ -0,0 +1,58 @@
+// Verify debuginfo for async fn:
+//  - Each variant points to the file and line of its yield point
+//  - The discriminants are marked artificial
+//  - Other fields are not marked artificial
+//
+//
+// compile-flags: -C debuginfo=2 --edition=2018
+// ignore-msvc
+
+async fn foo() {}
+async fn async_fn_test() {
+    foo().await;
+    let s = String::from("foo");
+    foo().await;
+}
+
+// FIXME: No way to reliably check the filename.
+
+// CHECK-DAG:  [[ASYNC_FN:!.*]] = !DINamespace(name: "async_fn_test"
+// CHECK-DAG:  [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}", scope: [[ASYNC_FN]]
+// CHECK:      [[VARIANT:!.*]] = !DICompositeType(tag: DW_TAG_variant_part, scope: [[GEN]],
+// CHECK-NOT:  flags: DIFlagArtificial
+// CHECK-SAME: discriminator: [[DISC:![0-9]*]]
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "0", scope: [[VARIANT]],
+// CHECK-SAME: file: [[FILE:![0-9]*]], line: 11,
+// CHECK-NOT:  flags: DIFlagArtificial
+// CHECK-SAME: )
+// CHECK:      {{!.*}} = !DICompositeType(tag: DW_TAG_structure_type, name: "Unresumed", scope: [[GEN]],
+// CHECK-NOT:  flags: DIFlagArtificial
+// CHECK-SAME: )
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "1", scope: [[VARIANT]],
+// CHECK-SAME: file: [[FILE]], line: 15,
+// CHECK-NOT:  flags: DIFlagArtificial
+// CHECK-SAME: )
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "2", scope: [[VARIANT]],
+// CHECK-SAME: file: [[FILE]], line: 15,
+// CHECK-NOT:  flags: DIFlagArtificial
+// CHECK-SAME: )
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "3", scope: [[VARIANT]],
+// CHECK-SAME: file: [[FILE]], line: 12,
+// CHECK-NOT:  flags: DIFlagArtificial
+// CHECK-SAME: )
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "4", scope: [[VARIANT]],
+// CHECK-SAME: file: [[FILE]], line: 14,
+// CHECK-NOT:  flags: DIFlagArtificial
+// CHECK-SAME: )
+// CHECK:      [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN]],
+// CHECK-NOT:  flags: DIFlagArtificial
+// CHECK-SAME: )
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[S1]]
+// CHECK-NOT:  flags: DIFlagArtificial
+// CHECK-SAME: )
+// CHECK:      [[DISC]] = !DIDerivedType(tag: DW_TAG_member, name: "__state", scope: [[GEN]],
+// CHECK-SAME: flags: DIFlagArtificial
+
+fn main() {
+    let _dummy = async_fn_test();
+}
diff --git a/tests/codegen/atomic-operations.rs b/tests/codegen/atomic-operations.rs
new file mode 100644
index 00000000000..d2bc618dfc5
--- /dev/null
+++ b/tests/codegen/atomic-operations.rs
@@ -0,0 +1,83 @@
+// Code generation of atomic operations.
+// compile-flags: -O
+#![crate_type = "lib"]
+
+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
+    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
+    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
+    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
+    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
+    let _ = a.compare_exchange(0, 50, SeqCst, Relaxed);
+    let _ = a.compare_exchange(0, 51, SeqCst, Acquire);
+    let _ = a.compare_exchange(0, 52, SeqCst, SeqCst);
+}
+
+// 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
+    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
+    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
+    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
+    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
+    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
new file mode 100644
index 00000000000..54392be707f
--- /dev/null
+++ b/tests/codegen/autovectorize-f32x4.rs
@@ -0,0 +1,42 @@
+// compile-flags: -C opt-level=3 -Z merge-functions=disabled
+// only-x86_64
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @auto_vectorize_direct
+#[no_mangle]
+pub fn auto_vectorize_direct(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[0] + b[0],
+        a[1] + b[1],
+        a[2] + b[2],
+        a[3] + b[3],
+    ]
+}
+
+// CHECK-LABEL: @auto_vectorize_loop
+#[no_mangle]
+pub fn auto_vectorize_loop(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>
+    let mut c = [0.0; 4];
+    for i in 0..4 {
+        c[i] = a[i] + b[i];
+    }
+    c
+}
+
+// CHECK-LABEL: @auto_vectorize_array_from_fn
+#[no_mangle]
+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>
+    std::array::from_fn(|i| a[i] + b[i])
+}
diff --git a/tests/codegen/auxiliary/extern_decl.rs b/tests/codegen/auxiliary/extern_decl.rs
new file mode 100644
index 00000000000..edc48351869
--- /dev/null
+++ b/tests/codegen/auxiliary/extern_decl.rs
@@ -0,0 +1,11 @@
+// Auxiliary crate that exports a function and static. Both always
+// evaluate to `71`. We force mutability on the static to prevent
+// it from being inlined as constant.
+
+#![crate_type = "lib"]
+
+#[no_mangle]
+pub fn extern_fn() -> u8 { unsafe { extern_static } }
+
+#[no_mangle]
+pub static mut extern_static: u8 = 71;
diff --git a/tests/codegen/auxiliary/nounwind.rs b/tests/codegen/auxiliary/nounwind.rs
new file mode 100644
index 00000000000..73c5aee3387
--- /dev/null
+++ b/tests/codegen/auxiliary/nounwind.rs
@@ -0,0 +1,3 @@
+#[no_mangle]
+pub fn bar() {
+}
diff --git a/tests/codegen/auxiliary/thread_local_aux.rs b/tests/codegen/auxiliary/thread_local_aux.rs
new file mode 100644
index 00000000000..bebaa7754dd
--- /dev/null
+++ b/tests/codegen/auxiliary/thread_local_aux.rs
@@ -0,0 +1,5 @@
+#![crate_type = "lib"]
+
+use std::cell::Cell;
+
+thread_local!(pub static A: Cell<u64> = const { Cell::new(0) });
diff --git a/tests/codegen/avr/avr-func-addrspace.rs b/tests/codegen/avr/avr-func-addrspace.rs
new file mode 100644
index 00000000000..83baae9e432
--- /dev/null
+++ b/tests/codegen/avr/avr-func-addrspace.rs
@@ -0,0 +1,136 @@
+// compile-flags: -O --target=avr-unknown-gnu-atmega328 --crate-type=rlib
+// needs-llvm-components: avr
+
+// This test validates that function pointers can be stored in global variables
+// and called upon. It ensures that Rust emits function pointers in the correct
+// address space to LLVM so that an assertion error relating to casting is
+// not triggered.
+//
+// It also validates that functions can be called through function pointers
+// through traits.
+
+#![feature(no_core, lang_items, intrinsics, unboxed_closures, arbitrary_self_types)]
+#![crate_type = "lib"]
+#![no_core]
+
+#[lang = "sized"]
+pub trait Sized { }
+#[lang = "copy"]
+pub trait Copy { }
+#[lang = "receiver"]
+pub trait Receiver { }
+#[lang = "tuple_trait"]
+pub trait Tuple { }
+
+pub struct Result<T, E> { _a: T, _b: E }
+
+impl Copy for usize {}
+impl Copy for &usize {}
+
+#[lang = "drop_in_place"]
+pub unsafe fn drop_in_place<T: ?Sized>(_: *mut T) {}
+
+#[lang = "fn_once"]
+pub trait FnOnce<Args: Tuple> {
+    #[lang = "fn_once_output"]
+    type Output;
+
+    extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
+}
+
+#[lang = "fn_mut"]
+pub trait FnMut<Args: Tuple> : FnOnce<Args> {
+    extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
+}
+
+#[lang = "fn"]
+pub trait Fn<Args: Tuple>: FnOnce<Args> {
+    /// Performs the call operation.
+    extern "rust-call" fn call(&self, args: Args) -> Self::Output;
+}
+
+extern "rust-intrinsic" {
+    pub fn transmute<Src, Dst>(src: Src) -> Dst;
+}
+
+pub static mut STORAGE_FOO: fn(&usize, &mut u32) -> Result<(), ()> = arbitrary_black_box;
+pub static mut STORAGE_BAR: u32 = 12;
+
+fn arbitrary_black_box(ptr: &usize, _: &mut u32) -> Result<(), ()> {
+    let raw_ptr = ptr as *const usize;
+    let _v: usize = unsafe { *raw_ptr };
+    loop {}
+}
+
+#[inline(never)]
+#[no_mangle]
+fn call_through_fn_trait(a: &mut impl Fn<(), Output=()>) {
+    (*a)()
+}
+
+#[inline(never)]
+fn update_bar_value() {
+    unsafe {
+        STORAGE_BAR = 88;
+    }
+}
+
+// CHECK: define dso_local void @test(){{.+}}addrspace(1)
+#[no_mangle]
+pub extern "C" fn test() {
+    let mut buf = 7;
+
+    // A call through the Fn trait must use address space 1.
+    //
+    // CHECK: call{{.+}}addrspace(1) void @call_through_fn_trait()
+    call_through_fn_trait(&mut update_bar_value);
+
+    // A call through a global variable must use address space 1.
+    // CHECK: load {{.*}}addrspace(1){{.+}}FOO
+    unsafe {
+        STORAGE_FOO(&1, &mut buf);
+    }
+}
+
+// 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)
+#[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),
+    // as long as it doesn't cause a verifier error by using `bitcast`.
+    transmute(x)
+}
+
+// CHECK: define{{.+}}{{\{\}\*|ptr}} @transmute_fn_ptr_to_data({{void \(\) addrspace\(1\)\*|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),
+    // as long as it doesn't cause a verifier error by using `bitcast`.
+    transmute(x)
+}
+
+pub enum Either<T, U> { A(T), B(U) }
+
+// Previously, we would codegen this as passing/returning a scalar pair of `{ i8, ptr }`,
+// 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)
+#[no_mangle]
+#[inline(never)]
+pub fn should_not_combine_addrspace(x: Either<&i32, fn()>) -> Either<&i32, fn()> {
+    x
+}
+
+// The incorrectness described above would result in us producing (after optimizations)
+// a `ptrtoint`/`inttoptr` roundtrip to convert from `ptr` to `ptr addrspace(1)`.
+
+// CHECK-LABEL: @call_with_fn_ptr
+#[no_mangle]
+pub fn call_with_fn_ptr<'a>(f: fn()) -> Either<&'a i32, fn()> {
+    // CHECK-NOT: ptrtoint
+    // CHECK-NOT: inttoptr
+    // CHECK: call addrspace(1) void @should_not_combine_addrspace
+    should_not_combine_addrspace(Either::B(f))
+}
diff --git a/tests/codegen/binary-search-index-no-bound-check.rs b/tests/codegen/binary-search-index-no-bound-check.rs
new file mode 100644
index 00000000000..595969a8979
--- /dev/null
+++ b/tests/codegen/binary-search-index-no-bound-check.rs
@@ -0,0 +1,40 @@
+// compile-flags: -O
+// ignore-debug: the debug assertions get in the way
+#![crate_type = "lib"]
+
+// Make sure no bounds checks are emitted when slicing or indexing
+// with an index from `binary_search`.
+
+// CHECK-LABEL: @binary_search_index_no_bounds_check
+#[no_mangle]
+pub fn binary_search_index_no_bounds_check(s: &[u8]) -> u8 {
+    // CHECK-NOT: panic
+    // 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 {
+        42
+    }
+}
+
+// Similarly, check that `partition_point` is known to return a valid fencepost.
+
+// CHECK-LABEL: @unknown_split
+#[no_mangle]
+pub fn unknown_split(x: &[i32], i: usize) -> (&[i32], &[i32]) {
+    // This just makes sure that the subsequent function is looking for the
+    // absence of something that might actually be there.
+
+    // CHECK: call core::panicking::panic
+    x.split_at(i)
+}
+
+// CHECK-LABEL: @partition_point_split_no_bounds_check
+#[no_mangle]
+pub fn partition_point_split_no_bounds_check(x: &[i32], needle: i32) -> (&[i32], &[i32]) {
+    // CHECK-NOT: call core::panicking::panic
+    let i = x.partition_point(|p| p < &needle);
+    x.split_at(i)
+}
diff --git a/tests/codegen/bool-cmp.rs b/tests/codegen/bool-cmp.rs
new file mode 100644
index 00000000000..5090f7c378c
--- /dev/null
+++ b/tests/codegen/bool-cmp.rs
@@ -0,0 +1,18 @@
+// This is a test for optimal Ord trait implementation for bool.
+// See <https://github.com/rust-lang/rust/issues/66780> for more info.
+
+// compile-flags: -C opt-level=3
+
+#![crate_type = "lib"]
+
+use std::cmp::Ordering;
+
+// CHECK-LABEL: @cmp_bool
+#[no_mangle]
+pub fn cmp_bool(a: bool, b: bool) -> Ordering {
+// LLVM 10 produces (zext a) + (sext b), but the final lowering is (zext a) - (zext b).
+// CHECK: zext i1
+// CHECK: {{z|s}}ext i1
+// CHECK: {{sub|add}} nsw
+    a.cmp(&b)
+}
diff --git a/tests/codegen/box-maybe-uninit-llvm14.rs b/tests/codegen/box-maybe-uninit-llvm14.rs
new file mode 100644
index 00000000000..c9f88fb3fe4
--- /dev/null
+++ b/tests/codegen/box-maybe-uninit-llvm14.rs
@@ -0,0 +1,34 @@
+// compile-flags: -O
+
+// Once we're done with llvm 14 and earlier, this test can be deleted.
+
+#![crate_type = "lib"]
+
+use std::mem::MaybeUninit;
+
+// Boxing a `MaybeUninit` value should not copy junk from the stack
+#[no_mangle]
+pub fn box_uninitialized() -> Box<MaybeUninit<usize>> {
+    // CHECK-LABEL: @box_uninitialized
+    // CHECK-NOT: store
+    // CHECK-NOT: alloca
+    // CHECK-NOT: memcpy
+    // CHECK-NOT: memset
+    Box::new(MaybeUninit::uninit())
+}
+
+// https://github.com/rust-lang/rust/issues/58201
+#[no_mangle]
+pub fn box_uninitialized2() -> Box<MaybeUninit<[usize; 1024 * 1024]>> {
+    // CHECK-LABEL: @box_uninitialized2
+    // CHECK-NOT: store
+    // CHECK-NOT: alloca
+    // CHECK-NOT: memcpy
+    // CHECK-NOT: memset
+    Box::new(MaybeUninit::uninit())
+}
+
+// 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 {{(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
new file mode 100644
index 00000000000..5c08b5832ad
--- /dev/null
+++ b/tests/codegen/box-maybe-uninit.rs
@@ -0,0 +1,33 @@
+// compile-flags: -O
+// min-llvm-version: 15.0
+#![crate_type = "lib"]
+
+use std::mem::MaybeUninit;
+
+// Boxing a `MaybeUninit` value should not copy junk from the stack
+#[no_mangle]
+pub fn box_uninitialized() -> Box<MaybeUninit<usize>> {
+    // CHECK-LABEL: @box_uninitialized
+    // CHECK-NOT: store
+    // CHECK-NOT: alloca
+    // CHECK-NOT: memcpy
+    // CHECK-NOT: memset
+    Box::new(MaybeUninit::uninit())
+}
+
+// https://github.com/rust-lang/rust/issues/58201
+#[no_mangle]
+pub fn box_uninitialized2() -> Box<MaybeUninit<[usize; 1024 * 1024]>> {
+    // CHECK-LABEL: @box_uninitialized2
+    // CHECK-NOT: store
+    // CHECK-NOT: alloca
+    // CHECK-NOT: memcpy
+    // CHECK-NOT: memset
+    Box::new(MaybeUninit::uninit())
+}
+
+// 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 {{(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" {{.*}} }
diff --git a/tests/codegen/bpf-alu32.rs b/tests/codegen/bpf-alu32.rs
new file mode 100644
index 00000000000..c68bffd03e2
--- /dev/null
+++ b/tests/codegen/bpf-alu32.rs
@@ -0,0 +1,11 @@
+// only-bpf
+#![crate_type = "lib"]
+#![feature(bpf_target_feature)]
+#![no_std]
+
+#[no_mangle]
+#[target_feature(enable = "alu32")]
+// CHECK: define i8 @foo(i8 returned %arg) unnamed_addr #0 {
+pub unsafe fn foo(arg: u8) -> u8 {
+    arg
+}
diff --git a/tests/codegen/branch-protection.rs b/tests/codegen/branch-protection.rs
new file mode 100644
index 00000000000..994c71b2619
--- /dev/null
+++ b/tests/codegen/branch-protection.rs
@@ -0,0 +1,45 @@
+// Test that the correct module flags are emitted with different branch protection flags.
+
+// revisions: BTI PACRET LEAF BKEY NONE
+// needs-llvm-components: aarch64
+// [BTI] compile-flags: -Z branch-protection=bti
+// [PACRET] compile-flags: -Z branch-protection=pac-ret
+// [LEAF] compile-flags: -Z branch-protection=pac-ret,leaf
+// [BKEY] compile-flags: -Z branch-protection=pac-ret,b-key
+// compile-flags: --target aarch64-unknown-linux-gnu
+
+#![crate_type = "lib"]
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang="sized"]
+trait Sized { }
+
+// A basic test function.
+pub fn test() {
+}
+
+// BTI: !"branch-target-enforcement", i32 1
+// BTI: !"sign-return-address", i32 0
+// BTI: !"sign-return-address-all", i32 0
+// BTI: !"sign-return-address-with-bkey", i32 0
+
+// PACRET: !"branch-target-enforcement", i32 0
+// PACRET: !"sign-return-address", i32 1
+// PACRET: !"sign-return-address-all", i32 0
+// PACRET: !"sign-return-address-with-bkey", i32 0
+
+// LEAF: !"branch-target-enforcement", i32 0
+// LEAF: !"sign-return-address", i32 1
+// LEAF: !"sign-return-address-all", i32 1
+// LEAF: !"sign-return-address-with-bkey", i32 0
+
+// BKEY: !"branch-target-enforcement", i32 0
+// BKEY: !"sign-return-address", i32 1
+// BKEY: !"sign-return-address-all", i32 0
+// BKEY: !"sign-return-address-with-bkey", i32 1
+
+// NONE-NOT: branch-target-enforcement
+// NONE-NOT: sign-return-address
+// NONE-NOT: sign-return-address-all
+// NONE-NOT: sign-return-address-with-bkey
diff --git a/tests/codegen/c-variadic-copy.rs b/tests/codegen/c-variadic-copy.rs
new file mode 100644
index 00000000000..4c61c4fcf68
--- /dev/null
+++ b/tests/codegen/c-variadic-copy.rs
@@ -0,0 +1,16 @@
+// Tests that `VaListImpl::clone` gets inlined into a call to `llvm.va_copy`
+
+#![crate_type = "lib"]
+#![feature(c_variadic)]
+#![no_std]
+use core::ffi::VaList;
+
+extern "C" {
+    fn foreign_c_variadic_1(_: VaList, ...);
+}
+
+pub unsafe extern "C" fn clone_variadic(ap: VaList) {
+    let mut ap2 = ap.clone();
+    // CHECK: call void @llvm.va_copy
+    foreign_c_variadic_1(ap2.as_va_list(), 42i32);
+}
diff --git a/tests/codegen/c-variadic-opt.rs b/tests/codegen/c-variadic-opt.rs
new file mode 100644
index 00000000000..969dce80f58
--- /dev/null
+++ b/tests/codegen/c-variadic-opt.rs
@@ -0,0 +1,30 @@
+// compile-flags: -C opt-level=3
+
+#![crate_type = "lib"]
+#![feature(c_variadic)]
+#![no_std]
+use core::ffi::VaList;
+
+extern "C" {
+    fn vprintf(fmt: *const i8, ap: VaList) -> i32;
+}
+
+// Ensure that `va_start` and `va_end` are properly injected even
+// when the "spoofed" `VaListImpl` is not used.
+#[no_mangle]
+pub unsafe extern "C" fn c_variadic_no_use(fmt: *const i8, mut ap: ...) -> i32 {
+    // CHECK: call void @llvm.va_start
+    vprintf(fmt, ap.as_va_list())
+    // CHECK: call void @llvm.va_end
+}
+
+// Check that `VaListImpl::clone` gets inlined into a direct call to `llvm.va_copy`
+#[no_mangle]
+pub unsafe extern "C" fn c_variadic_clone(fmt: *const i8, mut ap: ...) -> i32 {
+    // CHECK: call void @llvm.va_start
+    let mut ap2 = ap.clone();
+    // CHECK: call void @llvm.va_copy
+    let res = vprintf(fmt, ap2.as_va_list());
+    res
+    // CHECK: call void @llvm.va_end
+}
diff --git a/tests/codegen/c-variadic.rs b/tests/codegen/c-variadic.rs
new file mode 100644
index 00000000000..cab32652210
--- /dev/null
+++ b/tests/codegen/c-variadic.rs
@@ -0,0 +1,72 @@
+// ignore-wasm32-bare compiled with panic=abort by default
+// compile-flags: -C no-prepopulate-passes -Copt-level=0
+//
+
+#![crate_type = "lib"]
+#![feature(c_variadic)]
+#![feature(c_unwind)]
+#![no_std]
+use core::ffi::VaList;
+
+extern "C" {
+    fn foreign_c_variadic_0(_: i32, ...);
+    fn foreign_c_variadic_1(_: VaList, ...);
+}
+
+pub unsafe extern "C" fn use_foreign_c_variadic_0() {
+    // Ensure that we correctly call foreign C-variadic functions.
+    // CHECK: call void (i32, ...) @foreign_c_variadic_0([[PARAM:i32( signext)?]] 0)
+    foreign_c_variadic_0(0);
+    // CHECK: call void (i32, ...) @foreign_c_variadic_0([[PARAM]] 0, [[PARAM]] 42)
+    foreign_c_variadic_0(0, 42i32);
+    // CHECK: call void (i32, ...) @foreign_c_variadic_0([[PARAM]] 0, [[PARAM]] 42, [[PARAM]] 1024)
+    foreign_c_variadic_0(0, 42i32, 1024i32);
+    // CHECK: call void (i32, ...) @foreign_c_variadic_0([[PARAM]] 0, [[PARAM]] 42, [[PARAM]] 1024, [[PARAM]] 0)
+    foreign_c_variadic_0(0, 42i32, 1024i32, 0i32);
+}
+
+// Ensure that we do not remove the `va_list` passed to the foreign function when
+// removing the "spoofed" `VaListImpl` that is used by Rust defined C-variadics.
+pub unsafe extern "C" fn use_foreign_c_variadic_1_0(ap: VaList) {
+    // CHECK: call void ({{.*}}, ...) @foreign_c_variadic_1({{.*}} %ap)
+    foreign_c_variadic_1(ap);
+}
+
+pub unsafe extern "C" fn use_foreign_c_variadic_1_1(ap: VaList) {
+    // CHECK: call void ({{.*}}, ...) @foreign_c_variadic_1({{.*}} %ap, [[PARAM]] 42)
+    foreign_c_variadic_1(ap, 42i32);
+}
+pub unsafe extern "C" fn use_foreign_c_variadic_1_2(ap: VaList) {
+    // CHECK: call void ({{.*}}, ...) @foreign_c_variadic_1({{.*}} %ap, [[PARAM]] 2, [[PARAM]] 42)
+    foreign_c_variadic_1(ap, 2i32, 42i32);
+}
+
+pub unsafe extern "C" fn use_foreign_c_variadic_1_3(ap: VaList) {
+    // CHECK: call void ({{.*}}, ...) @foreign_c_variadic_1({{.*}} %ap, [[PARAM]] 2, [[PARAM]] 42, [[PARAM]] 0)
+    foreign_c_variadic_1(ap, 2i32, 42i32, 0i32);
+}
+
+// Ensure that `va_start` and `va_end` are properly injected.
+#[no_mangle]
+pub unsafe extern "C" fn c_variadic(n: i32, mut ap: ...) -> i32 {
+    // CHECK: call void @llvm.va_start
+    let mut sum = 0;
+    for _ in 0..n {
+        sum += ap.arg::<i32>();
+    }
+    sum
+    // CHECK: call void @llvm.va_end
+}
+
+// Ensure that we generate the correct `call` signature when calling a Rust
+// defined C-variadic.
+pub unsafe fn test_c_variadic_call() {
+    // CHECK: call [[RET:(signext )?i32]] (i32, ...) @c_variadic([[PARAM]] 0)
+    c_variadic(0);
+    // CHECK: call [[RET]] (i32, ...) @c_variadic([[PARAM]] 0, [[PARAM]] 42)
+    c_variadic(0, 42i32);
+    // CHECK: call [[RET]] (i32, ...) @c_variadic([[PARAM]] 0, [[PARAM]] 42, [[PARAM]] 1024)
+    c_variadic(0, 42i32, 1024i32);
+    // CHECK: call [[RET]] (i32, ...) @c_variadic([[PARAM]] 0, [[PARAM]] 42, [[PARAM]] 1024, [[PARAM]] 0)
+    c_variadic(0, 42i32, 1024i32, 0i32);
+}
diff --git a/tests/codegen/call-llvm-intrinsics.rs b/tests/codegen/call-llvm-intrinsics.rs
new file mode 100644
index 00000000000..11f2917717c
--- /dev/null
+++ b/tests/codegen/call-llvm-intrinsics.rs
@@ -0,0 +1,30 @@
+// compile-flags: -C no-prepopulate-passes -Copt-level=0
+
+// ignore-riscv64
+// ignore-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: call float @llvm.sqrt.f32(float 4.000000e+00
+        sqrt(4.0);
+    }
+}
diff --git a/tests/codegen/call-metadata.rs b/tests/codegen/call-metadata.rs
new file mode 100644
index 00000000000..07cc0c96371
--- /dev/null
+++ b/tests/codegen/call-metadata.rs
@@ -0,0 +1,17 @@
+// Checks that range metadata gets emitted on calls to functions returning a
+// scalar value.
+
+// compile-flags: -O -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+pub fn test() {
+    // CHECK: call noundef i8 @some_true(){{( #[0-9]+)?}}, !range [[R0:![0-9]+]]
+    // CHECK: [[R0]] = !{i8 0, i8 3}
+    some_true();
+}
+
+#[no_mangle]
+fn some_true() -> Option<bool> {
+    Some(true)
+}
diff --git a/tests/codegen/catch-unwind.rs b/tests/codegen/catch-unwind.rs
new file mode 100644
index 00000000000..6b63b83ef45
--- /dev/null
+++ b/tests/codegen/catch-unwind.rs
@@ -0,0 +1,33 @@
+// compile-flags: -O
+
+// On x86 the closure is inlined in foo() producing something like
+// define i32 @foo() [...] {
+// tail call void @bar() [...]
+// ret i32 0
+// }
+// On riscv the closure is another function, placed before fn foo so CHECK can't
+// find it
+// 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)]
+
+extern "C" {
+    fn bar();
+}
+
+// CHECK-LABEL: @foo
+#[no_mangle]
+pub unsafe fn foo() -> i32 {
+    // CHECK: call void @bar
+    // CHECK: ret i32 0
+    std::panic::catch_unwind(|| {
+        bar();
+        0
+    })
+    .unwrap()
+}
diff --git a/tests/codegen/cdylib-external-inline-fns.rs b/tests/codegen/cdylib-external-inline-fns.rs
new file mode 100644
index 00000000000..9118afd43d8
--- /dev/null
+++ b/tests/codegen/cdylib-external-inline-fns.rs
@@ -0,0 +1,43 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "cdylib"]
+
+// CHECK: define{{( dso_local)?}} void @a()
+#[no_mangle]
+#[inline]
+pub extern "C" fn a() {}
+
+// CHECK: define{{( dso_local)?}} void @b()
+#[export_name = "b"]
+#[inline]
+pub extern "C" fn b() {}
+
+// CHECK: define{{( dso_local)?}} void @c()
+#[no_mangle]
+#[inline]
+extern "C" fn c() {}
+
+// CHECK: define{{( dso_local)?}} void @d()
+#[export_name = "d"]
+#[inline]
+extern "C" fn d() {}
+
+// CHECK: define{{( dso_local)?}} void @e()
+#[no_mangle]
+#[inline(always)]
+pub extern "C" fn e() {}
+
+// CHECK: define{{( dso_local)?}} void @f()
+#[export_name = "f"]
+#[inline(always)]
+pub extern "C" fn f() {}
+
+// CHECK: define{{( dso_local)?}} void @g()
+#[no_mangle]
+#[inline(always)]
+extern "C" fn g() {}
+
+// CHECK: define{{( dso_local)?}} void @h()
+#[export_name = "h"]
+#[inline(always)]
+extern "C" fn h() {}
diff --git a/tests/codegen/cf-protection.rs b/tests/codegen/cf-protection.rs
new file mode 100644
index 00000000000..ccbc863f571
--- /dev/null
+++ b/tests/codegen/cf-protection.rs
@@ -0,0 +1,38 @@
+// Test that the correct module flags are emitted with different control-flow protection flags.
+
+// revisions: undefined none branch return full
+// needs-llvm-components: x86
+// [undefined] compile-flags:
+// [none] compile-flags: -Z cf-protection=none
+// [branch] compile-flags: -Z cf-protection=branch
+// [return] compile-flags: -Z cf-protection=return
+// [full] compile-flags: -Z cf-protection=full
+// compile-flags: --target x86_64-unknown-linux-gnu
+
+#![crate_type = "lib"]
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang="sized"]
+trait Sized { }
+
+// A basic test function.
+pub fn test() {
+}
+
+// undefined-NOT: !"cf-protection-branch"
+// undefined-NOT: !"cf-protection-return"
+
+// none-NOT: !"cf-protection-branch"
+// none-NOT: !"cf-protection-return"
+
+// branch-NOT: !"cf-protection-return"
+// branch: !"cf-protection-branch", i32 1
+// branch-NOT: !"cf-protection-return"
+
+// return-NOT: !"cf-protection-branch"
+// return: !"cf-protection-return", i32 1
+// return-NOT: !"cf-protection-branch"
+
+// full: !"cf-protection-branch", i32 1
+// full: !"cf-protection-return", i32 1
diff --git a/tests/codegen/cfguard-checks.rs b/tests/codegen/cfguard-checks.rs
new file mode 100644
index 00000000000..571a2654bcb
--- /dev/null
+++ b/tests/codegen/cfguard-checks.rs
@@ -0,0 +1,11 @@
+// compile-flags: -C control-flow-guard=checks
+// only-msvc
+
+#![crate_type = "lib"]
+
+// A basic test function.
+pub fn test() {
+}
+
+// Ensure the module flag cfguard=2 is present
+// CHECK: !"cfguard", i32 2
diff --git a/tests/codegen/cfguard-disabled.rs b/tests/codegen/cfguard-disabled.rs
new file mode 100644
index 00000000000..c3f8f411681
--- /dev/null
+++ b/tests/codegen/cfguard-disabled.rs
@@ -0,0 +1,11 @@
+// compile-flags: -C control-flow-guard=no
+// only-msvc
+
+#![crate_type = "lib"]
+
+// A basic test function.
+pub fn test() {
+}
+
+// Ensure the module flag cfguard is not present
+// CHECK-NOT: !"cfguard"
diff --git a/tests/codegen/cfguard-nochecks.rs b/tests/codegen/cfguard-nochecks.rs
new file mode 100644
index 00000000000..3847c3e81ed
--- /dev/null
+++ b/tests/codegen/cfguard-nochecks.rs
@@ -0,0 +1,11 @@
+// compile-flags: -C control-flow-guard=nochecks
+// only-msvc
+
+#![crate_type = "lib"]
+
+// A basic test function.
+pub fn test() {
+}
+
+// Ensure the module flag cfguard=1 is present
+// CHECK: !"cfguard", i32 1
diff --git a/tests/codegen/cfguard-non-msvc.rs b/tests/codegen/cfguard-non-msvc.rs
new file mode 100644
index 00000000000..6278a951e35
--- /dev/null
+++ b/tests/codegen/cfguard-non-msvc.rs
@@ -0,0 +1,11 @@
+// compile-flags: -C control-flow-guard
+// ignore-msvc
+
+#![crate_type = "lib"]
+
+// A basic test function.
+pub fn test() {
+}
+
+// Ensure the cfguard module flag is not added for non-MSVC targets.
+// CHECK-NOT: !"cfguard"
diff --git a/tests/codegen/codemodels.rs b/tests/codegen/codemodels.rs
new file mode 100644
index 00000000000..2328f5feb4e
--- /dev/null
+++ b/tests/codegen/codemodels.rs
@@ -0,0 +1,20 @@
+// only-x86_64
+
+// revisions: NOMODEL MODEL-SMALL MODEL-KERNEL MODEL-MEDIUM MODEL-LARGE
+//[NOMODEL] compile-flags:
+//[MODEL-SMALL] compile-flags: -C code-model=small
+//[MODEL-KERNEL] compile-flags: -C code-model=kernel
+//[MODEL-MEDIUM] compile-flags: -C code-model=medium
+//[MODEL-LARGE] compile-flags: -C code-model=large
+
+#![crate_type = "lib"]
+
+// MODEL-SMALL: !llvm.module.flags = !{{{.*}}}
+// MODEL-SMALL: !{{[0-9]+}} = !{i32 1, !"Code Model", i32 1}
+// MODEL-KERNEL: !llvm.module.flags = !{{{.*}}}
+// MODEL-KERNEL: !{{[0-9]+}} = !{i32 1, !"Code Model", i32 2}
+// MODEL-MEDIUM: !llvm.module.flags = !{{{.*}}}
+// MODEL-MEDIUM: !{{[0-9]+}} = !{i32 1, !"Code Model", i32 3}
+// MODEL-LARGE: !llvm.module.flags = !{{{.*}}}
+// MODEL-LARGE: !{{[0-9]+}} = !{i32 1, !"Code Model", i32 4}
+// NOMODEL-NOT: Code Model
diff --git a/tests/codegen/coercions.rs b/tests/codegen/coercions.rs
new file mode 100644
index 00000000000..d645ca6b13a
--- /dev/null
+++ b/tests/codegen/coercions.rs
@@ -0,0 +1,19 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+static X: i32 = 5;
+
+// CHECK-LABEL: @raw_ptr_to_raw_ptr_noop
+// CHECK-NOT: alloca
+#[no_mangle]
+pub fn raw_ptr_to_raw_ptr_noop() -> *const i32{
+    &X as *const i32
+}
+
+// CHECK-LABEL: @reference_to_raw_ptr_noop
+// CHECK-NOT: alloca
+#[no_mangle]
+pub fn reference_to_raw_ptr_noop() -> *const i32 {
+    &X
+}
diff --git a/tests/codegen/cold-call-declare-and-call.rs b/tests/codegen/cold-call-declare-and-call.rs
new file mode 100644
index 00000000000..71d49478bfc
--- /dev/null
+++ b/tests/codegen/cold-call-declare-and-call.rs
@@ -0,0 +1,18 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+#![feature(rust_cold_cc)]
+
+// wasm marks the definition as `dso_local`, so allow that as optional.
+
+// CHECK: define{{( dso_local)?}} coldcc void @this_should_never_happen(i16
+// CHECK: call coldcc void @this_should_never_happen(i16
+
+#[no_mangle]
+pub extern "rust-cold" fn this_should_never_happen(x: u16) {}
+
+pub fn do_things(x: u16) {
+    if x == 12345 {
+        this_should_never_happen(54321);
+    }
+}
diff --git a/tests/codegen/comparison-operators-2-tuple.rs b/tests/codegen/comparison-operators-2-tuple.rs
new file mode 100644
index 00000000000..a9d25e3b53c
--- /dev/null
+++ b/tests/codegen/comparison-operators-2-tuple.rs
@@ -0,0 +1,121 @@
+// compile-flags: -C opt-level=1 -Z merge-functions=disabled
+// min-llvm-version: 15.0
+// only-x86_64
+
+#![crate_type = "lib"]
+
+use std::cmp::Ordering;
+
+type TwoTuple = (i16, u16);
+
+//
+// The operators are all overridden directly, so should optimize easily.
+//
+// Yes, the `s[lg]t` is correct for the `[lg]e` version because it's only used
+// in the side of the select where we know the values are *not* equal.
+//
+
+// CHECK-LABEL: @check_lt_direct
+// CHECK-SAME: (i16 noundef %[[A0:.+]], i16 noundef %[[A1:.+]], i16 noundef %[[B0:.+]], i16 noundef %[[B1:.+]])
+#[no_mangle]
+pub fn check_lt_direct(a: TwoTuple, b: TwoTuple) -> bool {
+    // CHECK-DAG: %[[EQ:.+]] = icmp eq i16 %[[A0]], %[[B0]]
+    // CHECK-DAG: %[[CMP0:.+]] = icmp slt i16 %[[A0]], %[[B0]]
+    // CHECK-DAG: %[[CMP1:.+]] = icmp ult i16 %[[A1]], %[[B1]]
+    // CHECK: %[[R:.+]] = select i1 %[[EQ]], i1 %[[CMP1]], i1 %[[CMP0]]
+    // CHECK: ret i1 %[[R]]
+    a < b
+}
+
+// CHECK-LABEL: @check_le_direct
+// CHECK-SAME: (i16 noundef %[[A0:.+]], i16 noundef %[[A1:.+]], i16 noundef %[[B0:.+]], i16 noundef %[[B1:.+]])
+#[no_mangle]
+pub fn check_le_direct(a: TwoTuple, b: TwoTuple) -> bool {
+    // CHECK-DAG: %[[EQ:.+]] = icmp eq i16 %[[A0]], %[[B0]]
+    // CHECK-DAG: %[[CMP0:.+]] = icmp slt i16 %[[A0]], %[[B0]]
+    // CHECK-DAG: %[[CMP1:.+]] = icmp ule i16 %[[A1]], %[[B1]]
+    // CHECK: %[[R:.+]] = select i1 %[[EQ]], i1 %[[CMP1]], i1 %[[CMP0]]
+    // CHECK: ret i1 %[[R]]
+    a <= b
+}
+
+// CHECK-LABEL: @check_gt_direct
+// CHECK-SAME: (i16 noundef %[[A0:.+]], i16 noundef %[[A1:.+]], i16 noundef %[[B0:.+]], i16 noundef %[[B1:.+]])
+#[no_mangle]
+pub fn check_gt_direct(a: TwoTuple, b: TwoTuple) -> bool {
+    // CHECK-DAG: %[[EQ:.+]] = icmp eq i16 %[[A0]], %[[B0]]
+    // CHECK-DAG: %[[CMP0:.+]] = icmp sgt i16 %[[A0]], %[[B0]]
+    // CHECK-DAG: %[[CMP1:.+]] = icmp ugt i16 %[[A1]], %[[B1]]
+    // CHECK: %[[R:.+]] = select i1 %[[EQ]], i1 %[[CMP1]], i1 %[[CMP0]]
+    // CHECK: ret i1 %[[R]]
+    a > b
+}
+
+// CHECK-LABEL: @check_ge_direct
+// CHECK-SAME: (i16 noundef %[[A0:.+]], i16 noundef %[[A1:.+]], i16 noundef %[[B0:.+]], i16 noundef %[[B1:.+]])
+#[no_mangle]
+pub fn check_ge_direct(a: TwoTuple, b: TwoTuple) -> bool {
+    // CHECK-DAG: %[[EQ:.+]] = icmp eq i16 %[[A0]], %[[B0]]
+    // CHECK-DAG: %[[CMP0:.+]] = icmp sgt i16 %[[A0]], %[[B0]]
+    // CHECK-DAG: %[[CMP1:.+]] = icmp uge i16 %[[A1]], %[[B1]]
+    // CHECK: %[[R:.+]] = select i1 %[[EQ]], i1 %[[CMP1]], i1 %[[CMP0]]
+    // CHECK: ret i1 %[[R]]
+    a >= b
+}
+
+//
+// These ones are harder, since there are more intermediate values to remove.
+//
+// `<` seems to be getting lucky right now, so test that doesn't regress.
+//
+// The others, however, aren't managing to optimize away the extra `select`s yet.
+// See <https://github.com/rust-lang/rust/issues/106107> for more about this.
+//
+
+// CHECK-LABEL: @check_lt_via_cmp
+// CHECK-SAME: (i16 noundef %[[A0:.+]], i16 noundef %[[A1:.+]], i16 noundef %[[B0:.+]], i16 noundef %[[B1:.+]])
+#[no_mangle]
+pub fn check_lt_via_cmp(a: TwoTuple, b: TwoTuple) -> bool {
+    // CHECK-DAG: %[[EQ:.+]] = icmp eq i16 %[[A0]], %[[B0]]
+    // CHECK-DAG: %[[CMP0:.+]] = icmp slt i16 %[[A0]], %[[B0]]
+    // CHECK-DAG: %[[CMP1:.+]] = icmp ult i16 %[[A1]], %[[B1]]
+    // CHECK: %[[R:.+]] = select i1 %[[EQ]], i1 %[[CMP1]], i1 %[[CMP0]]
+    // CHECK: ret i1 %[[R]]
+    Ord::cmp(&a, &b).is_lt()
+}
+
+// CHECK-LABEL: @check_le_via_cmp
+// CHECK-SAME: (i16 noundef %[[A0:.+]], i16 noundef %[[A1:.+]], i16 noundef %[[B0:.+]], i16 noundef %[[B1:.+]])
+#[no_mangle]
+pub fn check_le_via_cmp(a: TwoTuple, b: TwoTuple) -> bool {
+    // FIXME-CHECK-DAG: %[[EQ:.+]] = icmp eq i16 %[[A0]], %[[B0]]
+    // FIXME-CHECK-DAG: %[[CMP0:.+]] = icmp sle i16 %[[A0]], %[[B0]]
+    // FIXME-CHECK-DAG: %[[CMP1:.+]] = icmp ule i16 %[[A1]], %[[B1]]
+    // FIXME-CHECK: %[[R:.+]] = select i1 %[[EQ]], i1 %[[CMP1]], i1 %[[CMP0]]
+    // FIXME-CHECK: ret i1 %[[R]]
+    Ord::cmp(&a, &b).is_le()
+}
+
+// CHECK-LABEL: @check_gt_via_cmp
+// CHECK-SAME: (i16 noundef %[[A0:.+]], i16 noundef %[[A1:.+]], i16 noundef %[[B0:.+]], i16 noundef %[[B1:.+]])
+#[no_mangle]
+pub fn check_gt_via_cmp(a: TwoTuple, b: TwoTuple) -> bool {
+    // FIXME-CHECK-DAG: %[[EQ:.+]] = icmp eq i16 %[[A0]], %[[B0]]
+    // FIXME-CHECK-DAG: %[[CMP0:.+]] = icmp sgt i16 %[[A0]], %[[B0]]
+    // FIXME-CHECK-DAG: %[[CMP1:.+]] = icmp ugt i16 %[[A1]], %[[B1]]
+    // FIXME-CHECK: %[[R:.+]] = select i1 %[[EQ]], i1 %[[CMP1]], i1 %[[CMP0]]
+    // FIXME-CHECK: ret i1 %[[R]]
+    Ord::cmp(&a, &b).is_gt()
+}
+
+// CHECK-LABEL: @check_ge_via_cmp
+// CHECK-SAME: (i16 noundef %[[A0:.+]], i16 noundef %[[A1:.+]], i16 noundef %[[B0:.+]], i16 noundef %[[B1:.+]])
+#[no_mangle]
+pub fn check_ge_via_cmp(a: TwoTuple, b: TwoTuple) -> bool {
+    // FIXME-CHECK-DAG: %[[EQ:.+]] = icmp eq i16 %[[A0]], %[[B0]]
+    // FIXME-CHECK-DAG: %[[CMP0:.+]] = icmp sge i16 %[[A0]], %[[B0]]
+    // FIXME-CHECK-DAG: %[[CMP1:.+]] = icmp uge i16 %[[A1]], %[[B1]]
+    // FIXME-CHECK: %[[R:.+]] = select i1 %[[EQ]], i1 %[[CMP1]], i1 %[[CMP0]]
+    // FIXME-CHECK: ret i1 %[[R]]
+    Ord::cmp(&a, &b).is_ge()
+}
diff --git a/tests/codegen/comparison-operators-newtype.rs b/tests/codegen/comparison-operators-newtype.rs
new file mode 100644
index 00000000000..683a2bd4fbb
--- /dev/null
+++ b/tests/codegen/comparison-operators-newtype.rs
@@ -0,0 +1,49 @@
+// The `derive(PartialOrd)` for a newtype doesn't override `lt`/`le`/`gt`/`ge`.
+// This double-checks that the `Option<Ordering>` intermediate values used
+// in the operators for such a type all optimize away.
+
+// compile-flags: -C opt-level=1
+// min-llvm-version: 15.0
+
+#![crate_type = "lib"]
+
+use std::cmp::Ordering;
+
+#[derive(PartialOrd, PartialEq)]
+pub struct Foo(u16);
+
+// CHECK-LABEL: @check_lt
+// CHECK-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]])
+#[no_mangle]
+pub fn check_lt(a: Foo, b: Foo) -> bool {
+    // CHECK: %[[R:.+]] = icmp ult i16 %[[A]], %[[B]]
+    // CHECK-NEXT: ret i1 %[[R]]
+    a < b
+}
+
+// CHECK-LABEL: @check_le
+// CHECK-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]])
+#[no_mangle]
+pub fn check_le(a: Foo, b: Foo) -> bool {
+    // CHECK: %[[R:.+]] = icmp ule i16 %[[A]], %[[B]]
+    // CHECK-NEXT: ret i1 %[[R]]
+    a <= b
+}
+
+// CHECK-LABEL: @check_gt
+// CHECK-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]])
+#[no_mangle]
+pub fn check_gt(a: Foo, b: Foo) -> bool {
+    // CHECK: %[[R:.+]] = icmp ugt i16 %[[A]], %[[B]]
+    // CHECK-NEXT: ret i1 %[[R]]
+    a > b
+}
+
+// CHECK-LABEL: @check_ge
+// CHECK-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]])
+#[no_mangle]
+pub fn check_ge(a: Foo, b: Foo) -> bool {
+    // CHECK: %[[R:.+]] = icmp uge i16 %[[A]], %[[B]]
+    // CHECK-NEXT: ret i1 %[[R]]
+    a >= b
+}
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
new file mode 100644
index 00000000000..810da581ce9
--- /dev/null
+++ b/tests/codegen/consts.rs
@@ -0,0 +1,56 @@
+// compile-flags: -C no-prepopulate-passes
+// min-llvm-version: 15.0 (for opaque pointers)
+
+#![crate_type = "lib"]
+
+// Below, these constants are defined as enum variants that by itself would
+// have a lower alignment than the enum type. Ensure that we mark them
+// correctly with the higher alignment of the enum.
+
+// CHECK: @STATIC = {{.*}}, align 4
+
+// This checks the constants from inline_enum_const
+// CHECK: @alloc_af1f8e8e6f4b341431a1d405e652df2d = {{.*}}, align 2
+
+// This checks the constants from {low,high}_align_const, they share the same
+// constant, but the alignment differs, so the higher one should be used
+// CHECK: [[LOW_HIGH:@alloc_[a-f0-9]+]] = {{.*}}, align 4
+
+#[derive(Copy, Clone)]
+// repr(i16) is required for the {low,high}_align_const test
+#[repr(i16)]
+pub enum E<A, B> {
+    A(A),
+    B(B),
+}
+
+#[no_mangle]
+pub static STATIC: E<i16, i32> = E::A(0);
+
+// CHECK-LABEL: @static_enum_const
+#[no_mangle]
+pub fn static_enum_const() -> E<i16, i32> {
+    STATIC
+}
+
+// CHECK-LABEL: @inline_enum_const
+#[no_mangle]
+pub fn inline_enum_const() -> E<i8, i16> {
+    *&E::A(0)
+}
+
+// CHECK-LABEL: @low_align_const
+#[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.{{.+}}(ptr align 2 %_0, ptr align 2 {{.*}}[[LOW_HIGH]]{{.*}}, i{{(32|64)}} 8, i1 false)
+    *&E::A(0)
+}
+
+// CHECK-LABEL: @high_align_const
+#[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.{{.+}}(ptr align 4 %_0, ptr align 4 {{.*}}[[LOW_HIGH]]{{.*}}, i{{(32|64)}} 8, i1 false)
+    *&E::A(0)
+}
diff --git a/tests/codegen/dealloc-no-unwind.rs b/tests/codegen/dealloc-no-unwind.rs
new file mode 100644
index 00000000000..3812ef44ff2
--- /dev/null
+++ b/tests/codegen/dealloc-no-unwind.rs
@@ -0,0 +1,22 @@
+// no-system-llvm
+// compile-flags: -O
+
+#![crate_type="lib"]
+
+struct A;
+
+impl Drop for A {
+    fn drop(&mut self) {
+        extern "C" { fn foo(); }
+        unsafe { foo(); }
+    }
+}
+
+#[no_mangle]
+pub fn a(a: Box<i32>) {
+    // CHECK-LABEL: define{{.*}}void @a
+    // CHECK: call void @__rust_dealloc
+    // CHECK-NEXT: call void @foo
+    let _a = A;
+    drop(a);
+}
diff --git a/tests/codegen/debug-alignment.rs b/tests/codegen/debug-alignment.rs
new file mode 100644
index 00000000000..f6c1062e0fc
--- /dev/null
+++ b/tests/codegen/debug-alignment.rs
@@ -0,0 +1,8 @@
+// Verifies that DWARF alignment is specified properly.
+//
+// compile-flags: -C debuginfo=2
+#![crate_type = "lib"]
+
+// CHECK: !DIGlobalVariable
+// CHECK: align: 32
+pub static A: u32 = 1;
diff --git a/tests/codegen/debug-column-msvc.rs b/tests/codegen/debug-column-msvc.rs
new file mode 100644
index 00000000000..aad8b372a8a
--- /dev/null
+++ b/tests/codegen/debug-column-msvc.rs
@@ -0,0 +1,16 @@
+// Verify that no column information is emitted for MSVC targets
+//
+// only-msvc
+// compile-flags: -C debuginfo=2
+
+// CHECK-NOT: !DILexicalBlock({{.*}}column: {{.*}})
+// CHECK-NOT: !DILocation({{.*}}column: {{.*}})
+
+pub fn add(a: u32, b: u32) -> u32 {
+    a + b
+}
+
+fn main() {
+    let c = add(1, 2);
+    println!("{}", c);
+}
diff --git a/tests/codegen/debug-column.rs b/tests/codegen/debug-column.rs
new file mode 100644
index 00000000000..f3b19a2eb2f
--- /dev/null
+++ b/tests/codegen/debug-column.rs
@@ -0,0 +1,24 @@
+// Verify that debuginfo column numbers are 1-based byte offsets.
+//
+// ignore-windows
+// compile-flags: -C debuginfo=2
+
+fn main() {
+    unsafe {
+        // Column numbers are 1-based. Regression test for #65437.
+        // CHECK: call void @giraffe(){{( #[0-9]+)?}}, !dbg [[A:!.*]]
+        giraffe();
+
+        // Column numbers use byte offests. Regression test for #67360
+        // CHECK: call void @turtle(){{( #[0-9]+)?}}, !dbg [[B:!.*]]
+/* ż */ turtle();
+
+        // CHECK: [[A]] = !DILocation(line: 10, column: 9,
+        // CHECK: [[B]] = !DILocation(line: 14, column: 10,
+    }
+}
+
+extern "C" {
+    fn giraffe();
+    fn turtle();
+}
diff --git a/tests/codegen/debug-compile-unit-path.rs b/tests/codegen/debug-compile-unit-path.rs
new file mode 100644
index 00000000000..3661be046d0
--- /dev/null
+++ b/tests/codegen/debug-compile-unit-path.rs
@@ -0,0 +1,9 @@
+// compile-flags: -g --remap-path-prefix={{cwd}}=/cwd/ --remap-path-prefix={{src-base}}=/base/
+//
+//
+// Ensure that we remap the compile unit directory and that we set it to the compilers current
+// working directory and not something else.
+#![crate_type="rlib"]
+
+// CHECK-DAG: [[FILE:![0-9]*]] = !DIFile(filename: "/base/debug-compile-unit-path.rs{{.*}}", directory: "/cwd/")
+// CHECK-DAG: {{![0-9]*}} = distinct !DICompileUnit({{.*}}file: [[FILE]]
diff --git a/tests/codegen/debug-limited.rs b/tests/codegen/debug-limited.rs
new file mode 100644
index 00000000000..48d676887fd
--- /dev/null
+++ b/tests/codegen/debug-limited.rs
@@ -0,0 +1,27 @@
+// Verify that the limited debuginfo option emits llvm's FullDebugInfo, but no type info.
+//
+// compile-flags: -C debuginfo=limited
+
+#[repr(C)]
+struct StructType {
+    a: i64,
+    b: i32,
+}
+
+extern "C" {
+    fn creator() -> *mut StructType;
+    fn save(p: *const StructType);
+}
+
+fn main() {
+    unsafe {
+        let value: &mut StructType = &mut *creator();
+        value.a = 7;
+        save(value as *const StructType)
+    }
+}
+
+// CHECK: !DICompileUnit
+// CHECK: emissionKind: FullDebug
+// CHECK: !DILocation
+// CHECK-NOT: !DIBasicType
diff --git a/tests/codegen/debug-line-directives-only.rs b/tests/codegen/debug-line-directives-only.rs
new file mode 100644
index 00000000000..750bdd49de0
--- /dev/null
+++ b/tests/codegen/debug-line-directives-only.rs
@@ -0,0 +1,27 @@
+// Verify that the only debuginfo generated are the line directives.
+//
+// compile-flags: -C debuginfo=line-directives-only
+
+#[repr(C)]
+struct StructType {
+    a: i64,
+    b: i32,
+}
+
+extern "C" {
+    fn creator() -> *mut StructType;
+    fn save(p: *const StructType);
+}
+
+fn main() {
+    unsafe {
+        let value: &mut StructType = &mut *creator();
+        value.a = 7;
+        save(value as *const StructType)
+    }
+}
+
+// CHECK: !DICompileUnit
+// CHECK: emissionKind: DebugDirectivesOnly
+// CHECK: !DILocation
+// CHECK-NOT: !DIBasicType
diff --git a/tests/codegen/debug-line-tables-only.rs b/tests/codegen/debug-line-tables-only.rs
new file mode 100644
index 00000000000..3ed165a6f69
--- /dev/null
+++ b/tests/codegen/debug-line-tables-only.rs
@@ -0,0 +1,27 @@
+// Verify that the only debuginfo generated are the line tables.
+//
+// compile-flags: -C debuginfo=line-tables-only
+
+#[repr(C)]
+struct StructType {
+    a: i64,
+    b: i32,
+}
+
+extern "C" {
+    fn creator() -> *mut StructType;
+    fn save(p: *const StructType);
+}
+
+fn main() {
+    unsafe {
+        let value: &mut StructType = &mut *creator();
+        value.a = 7;
+        save(value as *const StructType)
+    }
+}
+
+// CHECK: !DICompileUnit
+// CHECK: emissionKind: LineTablesOnly
+// CHECK: !DILocation
+// CHECK-NOT: !DIBasicType
diff --git a/tests/codegen/debug-linkage-name.rs b/tests/codegen/debug-linkage-name.rs
new file mode 100644
index 00000000000..9011a7da51d
--- /dev/null
+++ b/tests/codegen/debug-linkage-name.rs
@@ -0,0 +1,42 @@
+// Verifies that linkage name is omitted when it is
+// the same as variable / function name.
+//
+// compile-flags: -C no-prepopulate-passes
+// compile-flags: -C debuginfo=2
+#![crate_type = "lib"]
+
+pub mod xyz {
+    // CHECK: !DIGlobalVariable(name: "A",
+    // CHECK:                   linkageName:
+    // CHECK-SAME:              line: 12,
+    pub static A: u32 = 1;
+
+    // CHECK: !DIGlobalVariable(name: "B",
+    // CHECK-NOT:               linkageName:
+    // CHECK-SAME:              line: 18,
+    #[no_mangle]
+    pub static B: u32 = 2;
+
+    // CHECK: !DIGlobalVariable(name: "C",
+    // CHECK-NOT:               linkageName:
+    // CHECK-SAME:              line: 24,
+    #[export_name = "C"]
+    pub static C: u32 = 2;
+
+    // CHECK: !DISubprogram(name: "e",
+    // CHECK:               linkageName:
+    // CHECK-SAME:          line: 29,
+    pub extern "C" fn e() {}
+
+    // CHECK: !DISubprogram(name: "f",
+    // CHECK-NOT:           linkageName:
+    // CHECK-SAME:          line: 35,
+    #[no_mangle]
+    pub extern "C" fn f() {}
+
+    // CHECK: !DISubprogram(name: "g",
+    // CHECK-NOT:           linkageName:
+    // CHECK-SAME:          line: 41,
+    #[export_name = "g"]
+    pub extern "C" fn g() {}
+}
diff --git a/tests/codegen/debug-vtable.rs b/tests/codegen/debug-vtable.rs
new file mode 100644
index 00000000000..e52392b260b
--- /dev/null
+++ b/tests/codegen/debug-vtable.rs
@@ -0,0 +1,113 @@
+// This test checks the debuginfo for the expected 3 vtables is generated for correct names and number
+// of entries.
+
+// Use the v0 symbol mangling scheme to codegen order independent of rustc version.
+// Unnamed items like shims are generated in lexicographical order of their symbol name and in the
+// legacy mangling scheme rustc version and generic parameters are both hashed into a single part
+// of the name, thus randomizing item order with respect to rustc version.
+
+// compile-flags: -Cdebuginfo=2 -Copt-level=0 -Csymbol-mangling-version=v0
+// ignore-tidy-linelength
+
+// 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.2 = private constant <{
+// CHECK: @vtable.3 = private constant <{
+// CHECK: @vtable.4 = private constant <{
+
+// NONMSVC: ![[USIZE:[0-9]+]] = !DIBasicType(name: "usize"
+// MSVC: ![[USIZE:[0-9]+]] = !DIDerivedType(tag: DW_TAG_typedef, name: "usize"
+// NONMSVC: ![[PTR:[0-9]+]] = !DIDerivedType(tag: DW_TAG_pointer_type, name: "*const ()"
+// MSVC: ![[PTR:[0-9]+]] = !DIDerivedType(tag: DW_TAG_pointer_type, name: "ptr_const$<tuple$<> >"
+
+// NONMSVC: !DIGlobalVariable(name: "<debug_vtable::Foo as debug_vtable::SomeTrait>::{vtable}"
+// MSVC: !DIGlobalVariable(name: "impl$<debug_vtable::Foo, debug_vtable::SomeTrait>::vtable$"
+
+// NONMSVC: ![[VTABLE_TY0:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "<debug_vtable::Foo as debug_vtable::SomeTrait>::{vtable_type}", {{.*}} size: {{320|160}}, align: {{64|32}}, flags: DIFlagArtificial, {{.*}} vtableHolder: ![[FOO_TYPE:[0-9]+]],
+// MSVC: ![[VTABLE_TY0:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "impl$<debug_vtable::Foo, debug_vtable::SomeTrait>::vtable_type$", {{.*}} size: {{320|160}}, align: {{64|32}}, flags: DIFlagArtificial, {{.*}} vtableHolder: ![[FOO_TYPE:[0-9]+]],
+// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "drop_in_place", scope: ![[VTABLE_TY0]], {{.*}} baseType: ![[PTR]], size: {{64|32}}, align: {{64|32}})
+// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "size", scope: ![[VTABLE_TY0]], {{.*}} baseType: ![[USIZE]], size: {{64|32}}, align: {{64|32}}, offset: {{64|32}})
+// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "align", scope: ![[VTABLE_TY0]], {{.*}} baseType: ![[USIZE]], size: {{64|32}}, align: {{64|32}}, offset: {{128|64}})
+// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "__method3", scope: ![[VTABLE_TY0]], {{.*}} baseType: ![[PTR]], size: {{64|32}}, align: {{64|32}}, offset: {{192|96}})
+// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "__method4", scope: ![[VTABLE_TY0]], {{.*}} baseType: ![[PTR]], size: {{64|32}}, align: {{64|32}}, offset: {{256|128}})
+// CHECK: ![[FOO_TYPE]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Foo",
+
+// NONMSVC: !DIGlobalVariable(name: "<debug_vtable::Foo as debug_vtable::SomeTraitWithGenerics<u64, i8>>::{vtable}"
+// MSVC: !DIGlobalVariable(name: "impl$<debug_vtable::Foo, debug_vtable::SomeTraitWithGenerics<u64,i8> >::vtable$"
+
+// NONMSVC: ![[VTABLE_TY1:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "<debug_vtable::Foo as debug_vtable::SomeTraitWithGenerics<u64, i8>>::{vtable_type}", {{.*}}, size: {{256|128}}, align: {{64|32}}, flags: DIFlagArtificial, {{.*}}, vtableHolder: ![[FOO_TYPE]],
+// MSVC: ![[VTABLE_TY1:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "impl$<debug_vtable::Foo, debug_vtable::SomeTraitWithGenerics<u64,i8> >::vtable_type$", {{.*}}, size: {{256|128}}, align: {{64|32}}, flags: DIFlagArtificial, {{.*}}, vtableHolder: ![[FOO_TYPE]],
+// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "drop_in_place", scope: ![[VTABLE_TY1]], {{.*}} baseType: ![[PTR]], size: {{64|32}}, align: {{64|32}})
+// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "size", scope: ![[VTABLE_TY1]], {{.*}} baseType: ![[USIZE]], size: {{64|32}}, align: {{64|32}}, offset: {{64|32}})
+// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "align", scope: ![[VTABLE_TY1]], {{.*}} baseType: ![[USIZE]], size: {{64|32}}, align: {{64|32}}, offset: {{128|64}})
+// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "__method3", scope: ![[VTABLE_TY1]], {{.*}} baseType: ![[PTR]], size: {{64|32}}, align: {{64|32}}, offset: {{192|96}})
+
+// NONMSVC: !DIGlobalVariable(name: "<debug_vtable::Foo as _>::{vtable}"
+// MSVC: !DIGlobalVariable(name: "impl$<debug_vtable::Foo, _>::vtable$"
+
+// NONMSVC: ![[VTABLE_TY2:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "<debug_vtable::Foo as _>::{vtable_type}", {{.*}}, size: {{192|96}}, align: {{64|32}}, flags: DIFlagArtificial, {{.*}}, vtableHolder: ![[FOO_TYPE]],
+// MSVC: ![[VTABLE_TY2:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "impl$<debug_vtable::Foo, _>::vtable_type$", {{.*}}, size: {{192|96}}, align: {{64|32}}, flags: DIFlagArtificial, {{.*}}, vtableHolder: ![[FOO_TYPE]],
+// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "drop_in_place", scope: ![[VTABLE_TY2]], {{.*}}, baseType: ![[PTR]], size: {{64|32}}, align: {{64|32}})
+// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "size", scope: ![[VTABLE_TY2]], {{.*}}, baseType: ![[USIZE]], size: {{64|32}}, align: {{64|32}}, offset: {{64|32}})
+// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "align", scope: ![[VTABLE_TY2]], {{.*}}, baseType: ![[USIZE]], size: {{64|32}}, align: {{64|32}}, offset: {{128|64}})
+
+// NONMSVC: !DIGlobalVariable(name: "<debug_vtable::bar::{closure_env#0} as core::ops::function::FnOnce<(core::option::Option<&dyn core::ops::function::Fn<(), Output=()>>)>>::{vtable}"
+// MSVC: !DIGlobalVariable(name: "impl$<debug_vtable::bar::closure_env$0, core::ops::function::FnOnce<tuple$<enum2$<core::option::Option<ref$<dyn$<core::ops::function::Fn<tuple$<>,assoc$<Output,tuple$<> > > > > > > > > >::vtable$"
+
+// NONMSVC: !DIGlobalVariable(name: "<debug_vtable::generic_closure::{closure_env#0}<bool> as core::ops::function::FnOnce<()>>::{vtable}"
+// MSVC: !DIGlobalVariable(name: "impl$<debug_vtable::generic_closure::closure_env$0<bool>, core::ops::function::FnOnce<tuple$<> > >::vtable$
+
+// NONMSVC: !DIGlobalVariable(name: "<debug_vtable::generic_closure::{closure_env#0}<u32> as core::ops::function::FnOnce<()>>::{vtable}"
+// MSVC: !DIGlobalVariable(name: "impl$<debug_vtable::generic_closure::closure_env$0<u32>, core::ops::function::FnOnce<tuple$<> > >::vtable$
+
+#![crate_type = "lib"]
+
+// Force emission for debuginfo for usize and *const() early..
+pub static mut XYZ: Option<(usize, *const ())> = None;
+
+pub struct Foo;
+
+pub trait SomeTrait {
+    fn method1(&self) -> u32;
+    fn method2(&self) -> u32;
+}
+
+impl SomeTrait for Foo {
+    fn method1(&self) -> u32 {
+        1
+    }
+    fn method2(&self) -> u32 {
+        2
+    }
+}
+
+pub trait SomeTraitWithGenerics<T, U> {
+    fn method1(&self) -> (T, U);
+}
+
+impl SomeTraitWithGenerics<u64, i8> for Foo {
+    fn method1(&self) -> (u64, i8) {
+        (1, 2)
+    }
+}
+
+pub fn foo(x: &Foo) -> (u32, (u64, i8), &dyn Send) {
+    let y: &dyn SomeTrait = x;
+    let z: &dyn SomeTraitWithGenerics<u64, i8> = x;
+    (y.method1(), z.method1(), x as &dyn Send)
+}
+
+// Constructing the debuginfo name for the FnOnce vtable below initially caused an ICE on MSVC
+// because the trait type contains a late bound region that needed to be erased before the type
+// layout for the niche enum `Option<&dyn Fn()>` could be computed.
+pub fn bar() -> Box<dyn FnOnce(Option<&dyn Fn()>)> {
+    Box::new(|_x: Option<&dyn Fn()>| {})
+}
+
+fn generic_closure<T: 'static>(x: T) -> Box<dyn FnOnce() -> T> {
+    Box::new(move || x)
+}
+
+pub fn instantiate_generic_closures() -> (Box<dyn FnOnce() -> u32>, Box<dyn FnOnce() -> bool>) {
+    (generic_closure(1u32), generic_closure(false))
+}
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/debuginfo-generic-closure-env-names.rs b/tests/codegen/debuginfo-generic-closure-env-names.rs
new file mode 100644
index 00000000000..b29f8b4a029
--- /dev/null
+++ b/tests/codegen/debuginfo-generic-closure-env-names.rs
@@ -0,0 +1,89 @@
+// This test checks that we get proper type names for closure environments and
+// async-fn environments in debuginfo, especially making sure that generic arguments
+// of the enclosing functions don't get lost.
+//
+// Unfortunately, the order that debuginfo gets emitted into LLVM IR becomes a bit hard
+// to predict once async fns are involved, so DAG allows any order.
+//
+// Note that the test does not check async-fns when targeting MSVC because debuginfo for
+// those does not follow the enum-fallback encoding yet and thus is incomplete.
+
+// ignore-tidy-linelength
+
+// Use the v0 symbol mangling scheme to codegen order independent of rustc version.
+// Unnamed items like shims are generated in lexicographical order of their symbol name and in the
+// legacy mangling scheme rustc version and generic parameters are both hashed into a single part
+// of the name, thus randomizing item order with respect to rustc version.
+
+// compile-flags: -Cdebuginfo=2 --edition 2021 -Copt-level=0 -Csymbol-mangling-version=v0
+
+// non_generic_closure()
+// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}", scope: ![[non_generic_closure_NAMESPACE:[0-9]+]],
+// MSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "closure_env$0", scope: ![[non_generic_closure_NAMESPACE:[0-9]+]],
+// CHECK: ![[non_generic_closure_NAMESPACE]] = !DINamespace(name: "non_generic_closure"
+
+// CHECK: ![[function_containing_closure_NAMESPACE:[0-9]+]] = !DINamespace(name: "function_containing_closure"
+// CHECK: ![[generic_async_function_NAMESPACE:[0-9]+]] = !DINamespace(name: "generic_async_function"
+// CHECK: ![[generic_async_block_NAMESPACE:[0-9]+]] = !DINamespace(name: "generic_async_block"
+
+// function_containing_closure<u32>()
+// NONMSVC-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}<u32>", scope: ![[function_containing_closure_NAMESPACE]]
+// MSVC-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "closure_env$0<u32>", scope: ![[function_containing_closure_NAMESPACE]]
+
+// generic_async_function<Foo>()
+// NONMSVC-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}<debuginfo_generic_closure_env_names::Foo>", scope: ![[generic_async_function_NAMESPACE]]
+
+// generic_async_function<u32>()
+// NONMSVC-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}<u32>", scope: ![[generic_async_function_NAMESPACE]]
+
+// generic_async_block<Foo>()
+// NONMSVC-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_block_env#0}<debuginfo_generic_closure_env_names::Foo>", scope: ![[generic_async_block_NAMESPACE]]
+
+// generic_async_block<u32>()
+// NONMSVC-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_block_env#0}<u32>", scope: ![[generic_async_block_NAMESPACE]]
+
+// function_containing_closure<Foo>()
+// NONMSVC-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}<debuginfo_generic_closure_env_names::Foo>", scope: ![[function_containing_closure_NAMESPACE]]
+// MSVC-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "closure_env$0<debuginfo_generic_closure_env_names::Foo>", scope: ![[function_containing_closure_NAMESPACE]]
+
+
+#![crate_type = "lib"]
+use std::future::Future;
+
+pub struct Foo;
+
+pub fn non_generic_closure(x: Foo) -> Box<dyn FnOnce() -> Foo> {
+    return Box::new(move || x);
+}
+
+fn function_containing_closure<T: 'static>(x: T) -> impl FnOnce() -> T {
+    // This static only exists to trigger generating the namespace debuginfo for
+    // `function_containing_closure` at a predictable, early point, which makes
+    // writing the FileCheck tests above simpler.
+    static _X: u8 = 0;
+
+    return move || x;
+}
+
+async fn generic_async_function<T: 'static>(x: T) -> T {
+    static _X: u8 = 0; // Same as above
+    x
+}
+
+fn generic_async_block<T: 'static>(x: T) -> impl Future<Output=T> {
+    static _X: u8 = 0; // Same as above
+    async move {
+        x
+    }
+}
+
+pub fn instantiate_generics() {
+    let _closure_u32 = function_containing_closure(7u32);
+    let _closure_foo = function_containing_closure(Foo);
+
+    let _async_fn_u32 = generic_async_function(42u32);
+    let _async_fn_foo = generic_async_function(Foo);
+
+    let _async_block_u32 = generic_async_block(64u32);
+    let _async_block_foo = generic_async_block(Foo);
+}
diff --git a/tests/codegen/deduced-param-attrs.rs b/tests/codegen/deduced-param-attrs.rs
new file mode 100644
index 00000000000..153046eef3c
--- /dev/null
+++ b/tests/codegen/deduced-param-attrs.rs
@@ -0,0 +1,60 @@
+// compile-flags: -O
+
+#![crate_type = "lib"]
+#![allow(incomplete_features)]
+#![feature(unsized_locals, unsized_fn_params)]
+
+use std::cell::Cell;
+use std::hint;
+
+// Check to make sure that we can deduce the `readonly` attribute from function bodies for
+// parameters passed indirectly.
+
+pub struct BigStruct {
+    blah: [i32; 1024],
+}
+
+pub struct BigCellContainer {
+    blah: [Cell<i32>; 1024],
+}
+
+// The by-value parameter for this big struct can be marked readonly.
+//
+// CHECK: @use_big_struct_immutably({{.*}} readonly {{.*}} %big_struct)
+#[no_mangle]
+pub fn use_big_struct_immutably(big_struct: BigStruct) {
+    hint::black_box(&big_struct);
+}
+
+// The by-value parameter for this big struct can't be marked readonly, because we mutate it.
+//
+// CHECK-NOT: @use_big_struct_mutably({{.*}} readonly {{.*}} %big_struct)
+#[no_mangle]
+pub fn use_big_struct_mutably(mut big_struct: BigStruct) {
+    big_struct.blah[987] = 654;
+    hint::black_box(&big_struct);
+}
+
+// The by-value parameter for this big struct can't be marked readonly, because it contains
+// UnsafeCell.
+//
+// CHECK-NOT: @use_big_cell_container({{.*}} readonly {{.*}} %big_cell_container)
+#[no_mangle]
+pub fn use_big_cell_container(big_cell_container: BigCellContainer) {
+    hint::black_box(&big_cell_container);
+}
+
+// Make sure that we don't mistakenly mark a big struct as `readonly` when passed through a generic
+// type parameter if it contains UnsafeCell.
+//
+// CHECK-NOT: @use_something({{.*}} readonly {{.*}} %something)
+#[no_mangle]
+#[inline(never)]
+pub fn use_something<T>(something: T) {
+    hint::black_box(&something);
+}
+
+#[no_mangle]
+pub fn forward_big_cell_container(big_cell_container: BigCellContainer) {
+    use_something(big_cell_container)
+}
diff --git a/tests/codegen/default-requires-uwtable.rs b/tests/codegen/default-requires-uwtable.rs
new file mode 100644
index 00000000000..5d77d3f14bb
--- /dev/null
+++ b/tests/codegen/default-requires-uwtable.rs
@@ -0,0 +1,16 @@
+// revisions: WINDOWS ANDROID
+// compile-flags: -C panic=abort
+// [WINDOWS] compile-flags: --target=x86_64-pc-windows-msvc
+// [WINDOWS] needs-llvm-components: x86
+// [ANDROID] compile-flags: --target=armv7-linux-androideabi
+// [ANDROID] needs-llvm-components: arm
+
+#![feature(no_core, lang_items)]
+#![crate_type = "lib"]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+
+// CHECK: attributes #{{.*}} uwtable
+pub fn foo() {}
diff --git a/tests/codegen/dllimports/auxiliary/dummy.rs b/tests/codegen/dllimports/auxiliary/dummy.rs
new file mode 100644
index 00000000000..113a164f145
--- /dev/null
+++ b/tests/codegen/dllimports/auxiliary/dummy.rs
@@ -0,0 +1,6 @@
+// no-prefer-dynamic
+#![crate_type = "staticlib"]
+
+// Since codegen tests don't actually perform linking, this library doesn't need to export
+// any symbols.  It's here just to satisfy the compiler looking for a .lib file when processing
+// #[link(...)] attributes in wrapper.rs.
diff --git a/tests/codegen/dllimports/auxiliary/wrapper.rs b/tests/codegen/dllimports/auxiliary/wrapper.rs
new file mode 100644
index 00000000000..7aa90920a3e
--- /dev/null
+++ b/tests/codegen/dllimports/auxiliary/wrapper.rs
@@ -0,0 +1,14 @@
+// no-prefer-dynamic
+#![crate_type = "rlib"]
+
+#[link(name = "dummy", kind="dylib")]
+extern "C" {
+    pub fn dylib_func2(x: i32) -> i32;
+    pub static dylib_global2: i32;
+}
+
+#[link(name = "dummy", kind="static")]
+extern "C" {
+    pub fn static_func2(x: i32) -> i32;
+    pub static static_global2: i32;
+}
diff --git a/tests/codegen/dllimports/main.rs b/tests/codegen/dllimports/main.rs
new file mode 100644
index 00000000000..383940e9590
--- /dev/null
+++ b/tests/codegen/dllimports/main.rs
@@ -0,0 +1,43 @@
+ // This test is for *-windows-msvc only.
+// only-windows
+// ignore-gnu
+
+// aux-build:dummy.rs
+// aux-build:wrapper.rs
+
+extern crate wrapper;
+
+// Check that external symbols coming from foreign dylibs are adorned with 'dllimport',
+// whereas symbols coming from foreign staticlibs are not. (RFC-1717)
+
+// CHECK: @dylib_global1 = external dllimport local_unnamed_addr global i32
+// CHECK: @dylib_global2 = external dllimport local_unnamed_addr global i32
+// CHECK: @static_global1 = external local_unnamed_addr global i32
+// CHECK: @static_global2 = external local_unnamed_addr global i32
+
+// CHECK: declare dllimport noundef i32 @dylib_func1(i32 noundef)
+// CHECK: declare dllimport noundef i32 @dylib_func2(i32 noundef)
+// CHECK: declare noundef i32 @static_func1(i32 noundef)
+// CHECK: declare noundef i32 @static_func2(i32 noundef)
+
+#[link(name = "dummy", kind="dylib")]
+extern "C" {
+    pub fn dylib_func1(x: i32) -> i32;
+    pub static dylib_global1: i32;
+}
+
+#[link(name = "dummy", kind="static")]
+extern "C" {
+    pub fn static_func1(x: i32) -> i32;
+    pub static static_global1: i32;
+}
+
+fn main() {
+    unsafe {
+        dylib_func1(dylib_global1);
+        wrapper::dylib_func2(wrapper::dylib_global2);
+
+        static_func1(static_global1);
+        wrapper::static_func2(wrapper::static_global2);
+    }
+}
diff --git a/tests/codegen/drop-in-place-noalias.rs b/tests/codegen/drop-in-place-noalias.rs
new file mode 100644
index 00000000000..725e6fc048d
--- /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
new file mode 100644
index 00000000000..3615ef47b53
--- /dev/null
+++ b/tests/codegen/drop.rs
@@ -0,0 +1,37 @@
+// 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"]
+
+struct SomeUniqueName;
+
+impl Drop for SomeUniqueName {
+    fn drop(&mut self) {
+    }
+}
+
+pub fn possibly_unwinding() {
+}
+
+// CHECK-LABEL: @droppy
+#[no_mangle]
+pub fn droppy() {
+// Check that there are exactly 6 drop calls. The cleanups for the unwinding should be reused, so
+// that's one new drop call per call to possibly_unwinding(), and finally 3 drop calls for the
+// regular function exit. We used to have problems with quadratic growths of drop calls in such
+// functions.
+// FIXME(eddyb) the `void @` forces a match on the instruction, instead of the
+// comment, that's `; call core::ptr::drop_in_place::<drop::SomeUniqueName>`
+// for the `v0` mangling, should switch to matching on that once `legacy` is gone.
+// CHECK-COUNT-6: {{(call|invoke) void @.*}}drop_in_place{{.*}}SomeUniqueName
+// CHECK-NOT: {{(call|invoke) void @.*}}drop_in_place{{.*}}SomeUniqueName
+// The next line checks for the } that ends the function definition
+// CHECK-LABEL: {{^[}]}}
+    let _s = SomeUniqueName;
+    possibly_unwinding();
+    let _s = SomeUniqueName;
+    possibly_unwinding();
+    let _s = SomeUniqueName;
+    possibly_unwinding();
+}
diff --git a/tests/codegen/dst-vtable-align-nonzero.rs b/tests/codegen/dst-vtable-align-nonzero.rs
new file mode 100644
index 00000000000..54f6e7f992f
--- /dev/null
+++ b/tests/codegen/dst-vtable-align-nonzero.rs
@@ -0,0 +1,61 @@
+// compile-flags: -O -Z merge-functions=disabled
+
+#![crate_type = "lib"]
+#![feature(core_intrinsics)]
+
+// This test checks that we annotate alignment loads from vtables with nonzero range metadata,
+// and that this allows LLVM to eliminate redundant `align >= 1` checks.
+
+pub trait Trait {
+    fn f(&self);
+}
+
+pub struct WrapperWithAlign1<T: ?Sized> { x: u8, y: T }
+
+pub struct WrapperWithAlign2<T: ?Sized> { x: u16, y: T }
+
+pub struct Struct<W: ?Sized> {
+    _field: i8,
+    dst: W,
+}
+
+// CHECK-LABEL: @eliminates_runtime_check_when_align_1
+#[no_mangle]
+pub fn eliminates_runtime_check_when_align_1(
+    x: &Struct<WrapperWithAlign1<dyn Trait>>
+) -> &WrapperWithAlign1<dyn Trait> {
+    // CHECK: load [[USIZE:i[0-9]+]], {{.+}} !range [[RANGE_META:![0-9]+]]
+    // CHECK-NOT: llvm.umax
+    // CHECK-NOT: icmp
+    // CHECK-NOT: select
+    // CHECK: ret
+    &x.dst
+}
+
+// CHECK-LABEL: @does_not_eliminate_runtime_check_when_align_2
+#[no_mangle]
+pub fn does_not_eliminate_runtime_check_when_align_2(
+    x: &Struct<WrapperWithAlign2<dyn Trait>>
+) -> &WrapperWithAlign2<dyn Trait> {
+    // CHECK: [[X0:%[0-9]+]] = load [[USIZE]], {{.+}} !range [[RANGE_META]]
+    // CHECK: {{icmp|llvm.umax}}
+    // CHECK: ret
+    &x.dst
+}
+
+// CHECK-LABEL: @align_load_from_align_of_val
+#[no_mangle]
+pub fn align_load_from_align_of_val(x: &dyn Trait) -> usize {
+    // CHECK: {{%[0-9]+}} = load [[USIZE]], {{.+}} !range [[RANGE_META]]
+    core::mem::align_of_val(x)
+}
+
+// CHECK-LABEL: @align_load_from_vtable_align_intrinsic
+#[no_mangle]
+pub unsafe fn align_load_from_vtable_align_intrinsic(x: &dyn Trait) -> usize {
+    let (data, vtable): (*const (), *const ()) = core::mem::transmute(x);
+    // CHECK: {{%[0-9]+}} = load [[USIZE]], {{.+}} !range [[RANGE_META]]
+    core::intrinsics::vtable_align(vtable)
+}
+
+// CHECK: [[RANGE_META]] = !{[[USIZE]] 1, [[USIZE]] 0}
diff --git a/tests/codegen/dst-vtable-size-range.rs b/tests/codegen/dst-vtable-size-range.rs
new file mode 100644
index 00000000000..671c8abdebd
--- /dev/null
+++ b/tests/codegen/dst-vtable-size-range.rs
@@ -0,0 +1,35 @@
+// compile-flags: -O -Z merge-functions=disabled
+
+#![crate_type = "lib"]
+#![feature(core_intrinsics)]
+
+// Check that we annotate size loads from vtables with 0..(isize::MAX + 1) range metadata.
+
+pub trait Trait {
+    fn f(&self);
+}
+
+// Note that rustc uses inclusive bounds, but LLVM uses exclusive bounds for range metadata.
+// CHECK-LABEL: @generate_exclusive_bound
+#[no_mangle]
+pub fn generate_exclusive_bound() -> usize {
+    // CHECK: ret [[USIZE:i[0-9]+]] [[EXCLUSIVE_BOUND:[-0-9]+]]
+    isize::MAX as usize + 1
+}
+
+// CHECK-LABEL: @size_load_from_size_of_val
+#[no_mangle]
+pub fn size_load_from_size_of_val(x: &dyn Trait) -> usize {
+    // CHECK: {{%[0-9]+}} = load [[USIZE]], {{.+}} !range [[RANGE_META:![0-9]+]]
+    core::mem::size_of_val(x)
+}
+
+// CHECK-LABEL: @size_load_from_vtable_size_intrinsic
+#[no_mangle]
+pub unsafe fn size_load_from_vtable_size_intrinsic(x: &dyn Trait) -> usize {
+    let (data, vtable): (*const (), *const ()) = core::mem::transmute(x);
+    // CHECK: {{%[0-9]+}} = load [[USIZE]], {{.+}} !range [[RANGE_META]]
+    core::intrinsics::vtable_size(vtable)
+}
+
+// CHECK: [[RANGE_META]] = !{[[USIZE]] 0, [[USIZE]] [[EXCLUSIVE_BOUND]]}
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-bounds-check-derived-idx.rs b/tests/codegen/enum-bounds-check-derived-idx.rs
new file mode 100644
index 00000000000..aa66c2ed08e
--- /dev/null
+++ b/tests/codegen/enum-bounds-check-derived-idx.rs
@@ -0,0 +1,24 @@
+// This test checks an optimization that is not guaranteed to work. This test case should not block
+// a future LLVM update.
+// compile-flags: -O
+
+#![crate_type = "lib"]
+
+pub enum Bar {
+    A = 1,
+    B = 3,
+}
+
+// CHECK-LABEL: @lookup_inc
+#[no_mangle]
+pub fn lookup_inc(buf: &[u8; 5], f: Bar) -> u8 {
+    // CHECK-NOT: panic_bounds_check
+    buf[f as usize + 1]
+}
+
+// CHECK-LABEL: @lookup_dec
+#[no_mangle]
+pub fn lookup_dec(buf: &[u8; 5], f: Bar) -> u8 {
+    // CHECK-NOT: panic_bounds_check
+    buf[f as usize - 1]
+}
diff --git a/tests/codegen/enum-bounds-check-issue-13926.rs b/tests/codegen/enum-bounds-check-issue-13926.rs
new file mode 100644
index 00000000000..b26945bc549
--- /dev/null
+++ b/tests/codegen/enum-bounds-check-issue-13926.rs
@@ -0,0 +1,18 @@
+// This test checks an optimization that is not guaranteed to work. This test case should not block
+// a future LLVM update.
+// compile-flags: -O
+
+#![crate_type = "lib"]
+
+#[repr(u8)]
+pub enum Exception {
+    Low = 5,
+    High = 10,
+}
+
+// CHECK-LABEL: @access
+#[no_mangle]
+pub fn access(array: &[usize; 12], exc: Exception) -> usize {
+    // CHECK-NOT: panic_bounds_check
+    array[(exc as u8 - 4) as usize]
+}
diff --git a/tests/codegen/enum-bounds-check-issue-82871.rs b/tests/codegen/enum-bounds-check-issue-82871.rs
new file mode 100644
index 00000000000..32fdc4a5f4f
--- /dev/null
+++ b/tests/codegen/enum-bounds-check-issue-82871.rs
@@ -0,0 +1,18 @@
+// compile-flags: -C opt-level=0
+
+#![crate_type = "lib"]
+
+#[repr(C)]
+pub enum E {
+    A,
+}
+
+// CHECK-LABEL: @index
+#[no_mangle]
+pub fn index(x: &[u32; 3], ind: E) -> u32 {
+    // Canary: we should be able to optimize out the bounds check, but we need
+    // to track the range of the discriminant result in order to be able to do that.
+    // oli-obk tried to add that, but that caused miscompilations all over the place.
+    // CHECK: panic_bounds_check
+    x[ind as usize]
+}
diff --git a/tests/codegen/enum-bounds-check.rs b/tests/codegen/enum-bounds-check.rs
new file mode 100644
index 00000000000..17322d5911b
--- /dev/null
+++ b/tests/codegen/enum-bounds-check.rs
@@ -0,0 +1,26 @@
+// compile-flags: -O
+
+#![crate_type = "lib"]
+
+pub enum Foo {
+    A, B
+}
+
+// CHECK-LABEL: @lookup
+#[no_mangle]
+pub fn lookup(buf: &[u8; 2], f: Foo) -> u8 {
+    // CHECK-NOT: panic_bounds_check
+    buf[f as usize]
+}
+
+pub enum Bar {
+    A = 2,
+    B = 3
+}
+
+// CHECK-LABEL: @lookup_unmodified
+#[no_mangle]
+pub fn lookup_unmodified(buf: &[u8; 5], f: Bar) -> u8 {
+    // CHECK-NOT: panic_bounds_check
+    buf[f as usize]
+}
diff --git a/tests/codegen/enum-debug-clike.rs b/tests/codegen/enum-debug-clike.rs
new file mode 100644
index 00000000000..1e369a2c4e6
--- /dev/null
+++ b/tests/codegen/enum-debug-clike.rs
@@ -0,0 +1,23 @@
+// This tests that debug info for "c-like" 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: "E",{{.*}}flags: DIFlagEnumClass,{{.*}}
+// CHECK: {{.*}}DIEnumerator{{.*}}name: "A",{{.*}}value: {{[0-9].*}}
+// CHECK: {{.*}}DIEnumerator{{.*}}name: "B",{{.*}}value: {{[0-9].*}}
+// CHECK: {{.*}}DIEnumerator{{.*}}name: "C",{{.*}}value: {{[0-9].*}}
+
+#![allow(dead_code)]
+#![allow(unused_variables)]
+#![allow(unused_assignments)]
+
+enum E { A, B, C }
+
+pub fn main() {
+    let e = E::C;
+}
diff --git a/tests/codegen/enum-debug-niche-2.rs b/tests/codegen/enum-debug-niche-2.rs
new file mode 100644
index 00000000000..4b607d50574
--- /dev/null
+++ b/tests/codegen/enum-debug-niche-2.rs
@@ -0,0 +1,50 @@
+// This tests that optimized enum debug info accurately reflects the enum layout.
+// This is ignored for the fallback mode on MSVC due to problems with PDB.
+
+//
+// ignore-msvc
+
+// 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: i128 4294967295{{[,)].*}}
+// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "Error",{{.*}}extraData: i128 0{{[,)].*}}
+
+#![feature(never_type)]
+
+#[derive(Copy, Clone)]
+pub struct Entity {
+    private: std::num::NonZeroU32,
+}
+
+#[derive(Copy, Clone, PartialEq, Eq)]
+pub struct Declaration;
+
+impl TypeFamily for Declaration {
+    type Base = Base;
+    type Placeholder = !;
+
+    fn intern_base_data(_: BaseKind<Self>) {}
+}
+
+#[derive(Copy, Clone)]
+pub struct Base;
+
+pub trait TypeFamily: Copy + 'static {
+    type Base: Copy;
+    type Placeholder: Copy;
+
+    fn intern_base_data(_: BaseKind<Self>);
+}
+
+#[derive(Copy, Clone)]
+pub enum BaseKind<F: TypeFamily> {
+    Named(Entity),
+    Placeholder(F::Placeholder),
+    Error,
+}
+
+pub fn main() {
+    let x = BaseKind::Error::<Declaration>;
+    let y = 7;
+}
diff --git a/tests/codegen/enum-debug-niche.rs b/tests/codegen/enum-debug-niche.rs
new file mode 100644
index 00000000000..b718a6854dd
--- /dev/null
+++ b/tests/codegen/enum-debug-niche.rs
@@ -0,0 +1,29 @@
+// This tests that optimized enum debug info accurately reflects the enum layout.
+// 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_variant_part,{{.*}}discriminator:{{.*}}
+// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "A",{{.*}}extraData:{{.*}}
+// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_structure_type,{{.*}}name: "A",{{.*}}
+// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "B",{{.*}}extraData:{{.*}}
+// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_structure_type,{{.*}}name: "B",{{.*}}
+// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "C",{{.*}}extraData:{{.*}}
+// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_structure_type,{{.*}}name: "C",{{.*}}
+// CHECK-NOT: {{.*}}DIDerivedType{{.*}}name: "D",{{.*}}extraData:{{.*}}
+// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "D",{{.*}}
+// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_structure_type,{{.*}}name: "D",{{.*}}
+// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}flags: DIFlagArtificial{{.*}}
+
+#![allow(dead_code)]
+#![allow(unused_variables)]
+#![allow(unused_assignments)]
+
+enum E { A, B, C, D(bool) }
+
+pub fn main() {
+    let e = E::D(true);
+}
diff --git a/tests/codegen/enum-debug-tagged.rs b/tests/codegen/enum-debug-tagged.rs
new file mode 100644
index 00000000000..095c49ac3ac
--- /dev/null
+++ b/tests/codegen/enum-debug-tagged.rs
@@ -0,0 +1,27 @@
+// This tests that debug info for tagged (ordinary) 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_structure_type,{{.*}}name: "E",{{.*}}
+// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_variant_part,{{.*}}discriminator:{{.*}}
+// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "A",{{.*}}extraData:{{.*}}
+// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_structure_type,{{.*}}name: "A",{{.*}}
+// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "__0",{{.*}}
+// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "B",{{.*}}extraData:{{.*}}
+// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_structure_type,{{.*}}name: "B",{{.*}}
+// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "__0",{{.*}}
+// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}flags: DIFlagArtificial{{.*}}
+
+#![allow(dead_code)]
+#![allow(unused_variables)]
+#![allow(unused_assignments)]
+
+enum E { A(u32), B(u32) }
+
+pub fn main() {
+    let e = E::A(23);
+}
diff --git a/tests/codegen/enum-discriminant-value.rs b/tests/codegen/enum-discriminant-value.rs
new file mode 100644
index 00000000000..cc14c212002
--- /dev/null
+++ b/tests/codegen/enum-discriminant-value.rs
@@ -0,0 +1,27 @@
+// Verify that DIEnumerator uses isUnsigned flag when appropriate.
+//
+// compile-flags: -g -C no-prepopulate-passes
+
+#[repr(i64)]
+pub enum I64 {
+    I64Min = i64::MIN,
+    I64Max = i64::MAX,
+}
+
+#[repr(u64)]
+pub enum U64 {
+    U64Min = u64::MIN,
+    U64Max = u64::MAX,
+}
+
+fn main() {
+    let _a = I64::I64Min;
+    let _b = I64::I64Max;
+    let _c = U64::U64Min;
+    let _d = U64::U64Max;
+}
+
+// CHECK: !DIEnumerator(name: "I64Min", value: -9223372036854775808)
+// CHECK: !DIEnumerator(name: "I64Max", value: 9223372036854775807)
+// CHECK: !DIEnumerator(name: "U64Min", value: 0, isUnsigned: true)
+// CHECK: !DIEnumerator(name: "U64Max", value: 18446744073709551615, isUnsigned: true)
diff --git a/tests/codegen/enum-match.rs b/tests/codegen/enum-match.rs
new file mode 100644
index 00000000000..5548cd25147
--- /dev/null
+++ b/tests/codegen/enum-match.rs
@@ -0,0 +1,112 @@
+// compile-flags: -Copt-level=1
+// only-x86_64
+
+#![crate_type = "lib"]
+
+// Check each of the 3 cases for `codegen_get_discr`.
+
+// Case 0: One tagged variant.
+pub enum Enum0 {
+    A(bool),
+    B,
+}
+
+// CHECK: define noundef i8 @match0{{.*}}
+// CHECK-NEXT: start:
+// CHECK-NEXT: %1 = icmp eq i8 %0, 2
+// CHECK-NEXT: %2 = and i8 %0, 1
+// CHECK-NEXT: %_0.0 = select i1 %1, i8 13, i8 %2
+#[no_mangle]
+pub fn match0(e: Enum0) -> u8 {
+    use Enum0::*;
+    match e {
+        A(b) => b as u8,
+        B => 13,
+    }
+}
+
+// Case 1: Niche values are on a boundary for `range`.
+pub enum Enum1 {
+    A(bool),
+    B,
+    C,
+}
+
+// CHECK: define noundef i8 @match1{{.*}}
+// CHECK-NEXT: start:
+// CHECK-NEXT: %1 = add i8 %0, -2
+// CHECK-NEXT: %2 = zext i8 %1 to i64
+// CHECK-NEXT: %3 = icmp ult i8 %1, 2
+// CHECK-NEXT: %4 = add nuw nsw i64 %2, 1
+// CHECK-NEXT: %_2 = select i1 %3, i64 %4, i64 0
+#[no_mangle]
+pub fn match1(e: Enum1) -> u8 {
+    use Enum1::*;
+    match e {
+        A(b) => b as u8,
+        B => 13,
+        C => 100,
+    }
+}
+
+// Case 2: Special cases don't apply.
+pub enum X {
+    _2=2, _3, _4, _5, _6, _7, _8, _9, _10, _11,
+    _12, _13, _14, _15, _16, _17, _18, _19, _20,
+    _21, _22, _23, _24, _25, _26, _27, _28, _29,
+    _30, _31, _32, _33, _34, _35, _36, _37, _38,
+    _39, _40, _41, _42, _43, _44, _45, _46, _47,
+    _48, _49, _50, _51, _52, _53, _54, _55, _56,
+    _57, _58, _59, _60, _61, _62, _63, _64, _65,
+    _66, _67, _68, _69, _70, _71, _72, _73, _74,
+    _75, _76, _77, _78, _79, _80, _81, _82, _83,
+    _84, _85, _86, _87, _88, _89, _90, _91, _92,
+    _93, _94, _95, _96, _97, _98, _99, _100, _101,
+    _102, _103, _104, _105, _106, _107, _108, _109,
+    _110, _111, _112, _113, _114, _115, _116, _117,
+    _118, _119, _120, _121, _122, _123, _124, _125,
+    _126, _127, _128, _129, _130, _131, _132, _133,
+    _134, _135, _136, _137, _138, _139, _140, _141,
+    _142, _143, _144, _145, _146, _147, _148, _149,
+    _150, _151, _152, _153, _154, _155, _156, _157,
+    _158, _159, _160, _161, _162, _163, _164, _165,
+    _166, _167, _168, _169, _170, _171, _172, _173,
+    _174, _175, _176, _177, _178, _179, _180, _181,
+    _182, _183, _184, _185, _186, _187, _188, _189,
+    _190, _191, _192, _193, _194, _195, _196, _197,
+    _198, _199, _200, _201, _202, _203, _204, _205,
+    _206, _207, _208, _209, _210, _211, _212, _213,
+    _214, _215, _216, _217, _218, _219, _220, _221,
+    _222, _223, _224, _225, _226, _227, _228, _229,
+    _230, _231, _232, _233, _234, _235, _236, _237,
+    _238, _239, _240, _241, _242, _243, _244, _245,
+    _246, _247, _248, _249, _250, _251, _252, _253,
+}
+
+pub enum Enum2 {
+    A(X),
+    B,
+    C,
+    D,
+    E,
+}
+
+// CHECK: define noundef i8 @match2{{.*}}
+// CHECK-NEXT: start:
+// CHECK-NEXT: %1 = add i8 %0, 2
+// CHECK-NEXT: %2 = zext i8 %1 to i64
+// CHECK-NEXT: %3 = icmp ult i8 %1, 4
+// CHECK-NEXT: %4 = add nuw nsw i64 %2, 1
+// CHECK-NEXT: %_2 = select i1 %3, i64 %4, i64 0
+// CHECK-NEXT: switch i64 %_2, label {{.*}} [
+#[no_mangle]
+pub fn match2(e: Enum2) -> u8 {
+    use Enum2::*;
+    match e {
+        A(b) => b as u8,
+        B => 13,
+        C => 100,
+        D => 200,
+        E => 250,
+    }
+}
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/export-no-mangle.rs b/tests/codegen/export-no-mangle.rs
new file mode 100644
index 00000000000..a89d48ee153
--- /dev/null
+++ b/tests/codegen/export-no-mangle.rs
@@ -0,0 +1,31 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+mod private {
+    // CHECK: @FOO =
+    #[no_mangle]
+    pub static FOO: u32 = 3;
+
+    // CHECK: @BAR =
+    #[export_name = "BAR"]
+    static BAR: u32 = 3;
+
+    // CHECK: void @a()
+    #[no_mangle]
+    pub extern "C" fn a() {}
+
+    // CHECK: void @b()
+    #[export_name = "b"]
+    extern "C" fn b() {}
+
+    // CHECK: void @c()
+    #[export_name = "c"]
+    #[inline]
+    extern "C" fn c() {}
+
+    // CHECK: void @d()
+    #[export_name = "d"]
+    #[inline(always)]
+    extern "C" fn d() {}
+}
diff --git a/tests/codegen/external-no-mangle-fns.rs b/tests/codegen/external-no-mangle-fns.rs
new file mode 100644
index 00000000000..70349b2ec4f
--- /dev/null
+++ b/tests/codegen/external-no-mangle-fns.rs
@@ -0,0 +1,75 @@
+// compile-flags: -C no-prepopulate-passes
+// `#[no_mangle]`d functions always have external linkage, i.e., no `internal` in their `define`s
+
+#![crate_type = "lib"]
+#![no_std]
+
+// CHECK: define{{( dso_local)?}} void @a()
+#[no_mangle]
+fn a() {}
+
+// CHECK: define{{( dso_local)?}} void @b()
+#[no_mangle]
+pub fn b() {}
+
+mod private {
+    // CHECK: define{{( dso_local)?}} void @c()
+    #[no_mangle]
+    fn c() {}
+
+    // CHECK: define{{( dso_local)?}} void @d()
+    #[no_mangle]
+    pub fn d() {}
+}
+
+const HIDDEN: () = {
+    // CHECK: define{{( dso_local)?}} void @e()
+    #[no_mangle]
+    fn e() {}
+
+    // CHECK: define{{( dso_local)?}} void @f()
+    #[no_mangle]
+    pub fn f() {}
+};
+
+// The surrounding item should not accidentally become external
+// CHECK-LABEL: ; external_no_mangle_fns::x
+// CHECK-NEXT: ; Function Attrs:
+// CHECK-NEXT: define internal
+#[inline(never)]
+fn x() {
+    // CHECK: define{{( dso_local)?}} void @g()
+    #[no_mangle]
+    fn g() {
+        x();
+    }
+
+    // CHECK: define{{( dso_local)?}} void @h()
+    #[no_mangle]
+    pub fn h() {}
+
+    // side effect to keep `x` around
+    unsafe {
+        core::ptr::read_volatile(&42);
+    }
+}
+
+// CHECK: define{{( dso_local)?}} void @i()
+#[no_mangle]
+#[inline]
+fn i() {}
+
+// CHECK: define{{( dso_local)?}} void @j()
+#[no_mangle]
+#[inline]
+pub fn j() {}
+
+// CHECK: define{{( dso_local)?}} void @k()
+#[no_mangle]
+#[inline(always)]
+fn k() {}
+
+// CHECK: define{{( dso_local)?}} void @l()
+#[no_mangle]
+#[inline(always)]
+pub fn l() {}
diff --git a/tests/codegen/external-no-mangle-statics.rs b/tests/codegen/external-no-mangle-statics.rs
new file mode 100644
index 00000000000..48023a2a901
--- /dev/null
+++ b/tests/codegen/external-no-mangle-statics.rs
@@ -0,0 +1,77 @@
+// revisions: lib staticlib
+// ignore-emscripten default visibility is hidden
+// compile-flags: -O
+// [lib] compile-flags: --crate-type lib
+// [staticlib] compile-flags: --crate-type staticlib
+// `#[no_mangle]`d static variables always have external linkage, i.e., no `internal` in their
+// definitions
+
+// CHECK: @A = {{(dso_local )?}}local_unnamed_addr constant
+#[no_mangle]
+static A: u8 = 0;
+
+// CHECK: @B = {{(dso_local )?}}local_unnamed_addr global
+#[no_mangle]
+static mut B: u8 = 0;
+
+// CHECK: @C = {{(dso_local )?}}local_unnamed_addr constant
+#[no_mangle]
+pub static C: u8 = 0;
+
+// CHECK: @D = {{(dso_local )?}}local_unnamed_addr global
+#[no_mangle]
+pub static mut D: u8 = 0;
+
+mod private {
+    // CHECK: @E = {{(dso_local )?}}local_unnamed_addr constant
+    #[no_mangle]
+    static E: u8 = 0;
+
+    // CHECK: @F = {{(dso_local )?}}local_unnamed_addr global
+    #[no_mangle]
+    static mut F: u8 = 0;
+
+    // CHECK: @G = {{(dso_local )?}}local_unnamed_addr constant
+    #[no_mangle]
+    pub static G: u8 = 0;
+
+    // CHECK: @H = {{(dso_local )?}}local_unnamed_addr global
+    #[no_mangle]
+    pub static mut H: u8 = 0;
+}
+
+const HIDDEN: () = {
+    // CHECK: @I = {{(dso_local )?}}local_unnamed_addr constant
+    #[no_mangle]
+    static I: u8 = 0;
+
+    // CHECK: @J = {{(dso_local )?}}local_unnamed_addr global
+    #[no_mangle]
+    static mut J: u8 = 0;
+
+    // CHECK: @K = {{(dso_local )?}}local_unnamed_addr constant
+    #[no_mangle]
+    pub static K: u8 = 0;
+
+    // CHECK: @L = {{(dso_local )?}}local_unnamed_addr global
+    #[no_mangle]
+    pub static mut L: u8 = 0;
+};
+
+fn x() {
+    // CHECK: @M = {{(dso_local )?}}local_unnamed_addr constant
+    #[no_mangle]
+    static M: fn() = x;
+
+    // CHECK: @N = {{(dso_local )?}}local_unnamed_addr global
+    #[no_mangle]
+    static mut N: u8 = 0;
+
+    // CHECK: @O = {{(dso_local )?}}local_unnamed_addr constant
+    #[no_mangle]
+    pub static O: u8 = 0;
+
+    // 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
new file mode 100644
index 00000000000..02f5d545910
--- /dev/null
+++ b/tests/codegen/fastcall-inreg.rs
@@ -0,0 +1,41 @@
+// Checks if the "fastcall" calling convention marks function arguments
+// as "inreg" like the C/C++ compilers for the platforms.
+// x86 only.
+
+// compile-flags: --target i686-unknown-linux-gnu -O -C no-prepopulate-passes
+// needs-llvm-components: x86
+
+#![crate_type = "lib"]
+#![no_core]
+#![feature(no_core, lang_items)]
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+pub mod tests {
+    // CHECK: @f1(i32 inreg noundef %_1, i32 inreg noundef %_2, i32 noundef %_3)
+    #[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)
+    #[no_mangle]
+    pub extern "fastcall" fn f2(_: *const i32, _: *const i32, _: *const i32) {}
+
+    // CHECK: @f3(float noundef %_1, i32 inreg noundef %_2, i32 inreg noundef %_3, i32 noundef %_4)
+    #[no_mangle]
+    pub extern "fastcall" fn f3(_: f32, _: i32, _: i32, _: i32) {}
+
+    // CHECK: @f4(i32 inreg noundef %_1, float noundef %_2, i32 inreg noundef %_3, i32 noundef %_4)
+    #[no_mangle]
+    pub extern "fastcall" fn f4(_: i32, _: f32, _: i32, _: i32) {}
+
+    // CHECK: @f5(i64 noundef %_1, i32 noundef %_2)
+    #[no_mangle]
+    pub extern "fastcall" fn f5(_: i64, _: i32) {}
+
+    // CHECK: @f6(i1 inreg noundef zeroext %_1, i32 inreg noundef %_2, i32 noundef %_3)
+    #[no_mangle]
+    pub extern "fastcall" fn f6(_: bool, _: i32, _: i32) {}
+}
diff --git a/tests/codegen/fatptr.rs b/tests/codegen/fatptr.rs
new file mode 100644
index 00000000000..1c49b5714ef
--- /dev/null
+++ b/tests/codegen/fatptr.rs
@@ -0,0 +1,12 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+pub trait T {}
+
+// CHECK-LABEL: @copy_fat_ptr
+#[no_mangle]
+pub fn copy_fat_ptr(x: &T) {
+// CHECK-NOT: extractvalue
+    let x2 = x;
+}
diff --git a/tests/codegen/fewer-names.rs b/tests/codegen/fewer-names.rs
new file mode 100644
index 00000000000..df1080bff2b
--- /dev/null
+++ b/tests/codegen/fewer-names.rs
@@ -0,0 +1,20 @@
+// no-system-llvm
+// compile-flags: -Coverflow-checks=no -O
+// revisions: YES NO
+// [YES]compile-flags: -Zfewer-names=yes
+// [NO] compile-flags: -Zfewer-names=no
+#![crate_type = "lib"]
+
+#[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
+
+    // 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/ffi-const.rs b/tests/codegen/ffi-const.rs
new file mode 100644
index 00000000000..93720503480
--- /dev/null
+++ b/tests/codegen/ffi-const.rs
@@ -0,0 +1,13 @@
+// compile-flags: -C no-prepopulate-passes
+#![crate_type = "lib"]
+#![feature(ffi_const)]
+
+pub fn bar() { unsafe { foo() } }
+
+extern "C" {
+    // CHECK-LABEL: declare{{.*}}void @foo()
+    // CHECK-SAME: [[ATTRS:#[0-9]+]]
+    // The attribute changed from `readnone` to `memory(none)` with LLVM 16.0.
+    // CHECK-DAG: attributes [[ATTRS]] = { {{.*}}{{readnone|memory\(none\)}}{{.*}} }
+    #[ffi_const] pub fn foo();
+}
diff --git a/tests/codegen/ffi-out-of-bounds-loads.rs b/tests/codegen/ffi-out-of-bounds-loads.rs
new file mode 100644
index 00000000000..099726b2f08
--- /dev/null
+++ b/tests/codegen/ffi-out-of-bounds-loads.rs
@@ -0,0 +1,25 @@
+// Regression test for #29988
+
+// compile-flags: -C no-prepopulate-passes
+// only-x86_64
+// ignore-windows
+
+#[repr(C)]
+struct S {
+    f1: i32,
+    f2: i32,
+    f3: i32,
+}
+
+extern "C" {
+    fn foo(s: S);
+}
+
+fn main() {
+    let s = S { f1: 1, f2: 2, f3: 3 };
+    unsafe {
+        // CHECK: load { i64, i32 }, {{.*}}, align 4
+        // CHECK: call void @foo({ i64, i32 } {{.*}})
+        foo(s);
+    }
+}
diff --git a/tests/codegen/ffi-pure.rs b/tests/codegen/ffi-pure.rs
new file mode 100644
index 00000000000..2ed73581358
--- /dev/null
+++ b/tests/codegen/ffi-pure.rs
@@ -0,0 +1,13 @@
+// compile-flags: -C no-prepopulate-passes
+#![crate_type = "lib"]
+#![feature(ffi_pure)]
+
+pub fn bar() { unsafe { foo() } }
+
+extern "C" {
+    // CHECK-LABEL: declare{{.*}}void @foo()
+    // CHECK-SAME: [[ATTRS:#[0-9]+]]
+    // The attribute changed from `readonly` to `memory(read)` with LLVM 16.0.
+    // CHECK-DAG: attributes [[ATTRS]] = { {{.*}}{{readonly|memory\(read\)}}{{.*}} }
+    #[ffi_pure] pub fn foo();
+}
diff --git a/tests/codegen/ffi-returns-twice.rs b/tests/codegen/ffi-returns-twice.rs
new file mode 100644
index 00000000000..0fbe03f0bb6
--- /dev/null
+++ b/tests/codegen/ffi-returns-twice.rs
@@ -0,0 +1,11 @@
+// compile-flags: -C no-prepopulate-passes
+#![crate_type = "lib"]
+#![feature(ffi_returns_twice)]
+
+pub fn bar() { unsafe { foo() } }
+
+extern "C" {
+    // CHECK: declare{{( dso_local)?}} void @foo(){{.*}}[[ATTRS:#[0-9]+]]
+    // CHECK: attributes [[ATTRS]] = { {{.*}}returns_twice{{.*}} }
+    #[ffi_returns_twice] pub fn foo();
+}
diff --git a/tests/codegen/float_math.rs b/tests/codegen/float_math.rs
new file mode 100644
index 00000000000..592e09452df
--- /dev/null
+++ b/tests/codegen/float_math.rs
@@ -0,0 +1,50 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+#![feature(core_intrinsics)]
+
+use std::intrinsics::{fadd_fast, fsub_fast, fmul_fast, fdiv_fast, frem_fast};
+
+// CHECK-LABEL: @add
+#[no_mangle]
+pub fn add(x: f32, y: f32) -> f32 {
+// CHECK: fadd float
+// CHECK-NOT: fast
+    x + y
+}
+
+// CHECK-LABEL: @addition
+#[no_mangle]
+pub fn addition(x: f32, y: f32) -> f32 {
+// CHECK: fadd fast float
+    unsafe {
+        fadd_fast(x, y)
+    }
+}
+
+// CHECK-LABEL: @subtraction
+#[no_mangle]
+pub fn subtraction(x: f32, y: f32) -> f32 {
+// CHECK: fsub fast float
+    unsafe {
+        fsub_fast(x, y)
+    }
+}
+
+// CHECK-LABEL: @multiplication
+#[no_mangle]
+pub fn multiplication(x: f32, y: f32) -> f32 {
+// CHECK: fmul fast float
+    unsafe {
+        fmul_fast(x, y)
+    }
+}
+
+// CHECK-LABEL: @division
+#[no_mangle]
+pub fn division(x: f32, y: f32) -> f32 {
+// CHECK: fdiv fast float
+    unsafe {
+        fdiv_fast(x, y)
+    }
+}
diff --git a/tests/codegen/fn-impl-trait-self.rs b/tests/codegen/fn-impl-trait-self.rs
new file mode 100644
index 00000000000..0abc8a409ed
--- /dev/null
+++ b/tests/codegen/fn-impl-trait-self.rs
@@ -0,0 +1,16 @@
+// compile-flags: -g
+//
+// CHECK-LABEL: @main
+// MSVC: {{.*}}DIDerivedType(tag: DW_TAG_pointer_type, name: "recursive_type$ (*)()",{{.*}}
+// NONMSVC: {{.*}}DIDerivedType(tag: DW_TAG_pointer_type, name: "fn() -> <recursive_type>",{{.*}}
+//
+// CHECK: {{.*}}DISubroutineType{{.*}}
+// CHECK: {{.*}}DIBasicType(name: "<recur_type>", size: {{32|64}}, encoding: DW_ATE_unsigned)
+
+pub fn foo() -> impl Copy {
+    foo
+}
+
+fn main() {
+    let my_res = foo();
+}
diff --git a/tests/codegen/foo.s b/tests/codegen/foo.s
new file mode 100644
index 00000000000..304d82aa0c6
--- /dev/null
+++ b/tests/codegen/foo.s
@@ -0,0 +1,3 @@
+.global foo
+foo:
+    jmp baz
diff --git a/tests/codegen/force-frame-pointers.rs b/tests/codegen/force-frame-pointers.rs
new file mode 100644
index 00000000000..637c4234654
--- /dev/null
+++ b/tests/codegen/force-frame-pointers.rs
@@ -0,0 +1,6 @@
+// compile-flags: -C no-prepopulate-passes -C force-frame-pointers=y
+
+#![crate_type="lib"]
+
+// CHECK: attributes #{{.*}} "frame-pointer"="all"
+pub fn foo() {}
diff --git a/tests/codegen/force-no-unwind-tables.rs b/tests/codegen/force-no-unwind-tables.rs
new file mode 100644
index 00000000000..3ee23f05eb2
--- /dev/null
+++ b/tests/codegen/force-no-unwind-tables.rs
@@ -0,0 +1,11 @@
+// compile-flags: -C no-prepopulate-passes -C panic=abort -C force-unwind-tables=n
+// ignore-windows
+
+#![crate_type="lib"]
+
+// CHECK-LABEL: define{{.*}}void @foo
+// CHECK-NOT: attributes #{{.*}} uwtable
+#[no_mangle]
+fn foo() {
+    panic!();
+}
diff --git a/tests/codegen/force-unwind-tables.rs b/tests/codegen/force-unwind-tables.rs
new file mode 100644
index 00000000000..4c0a5602c6d
--- /dev/null
+++ b/tests/codegen/force-unwind-tables.rs
@@ -0,0 +1,6 @@
+// compile-flags: -C no-prepopulate-passes -C force-unwind-tables=y
+
+#![crate_type="lib"]
+
+// CHECK: attributes #{{.*}} uwtable
+pub fn foo() {}
diff --git a/tests/codegen/frame-pointer.rs b/tests/codegen/frame-pointer.rs
new file mode 100644
index 00000000000..d8933262e52
--- /dev/null
+++ b/tests/codegen/frame-pointer.rs
@@ -0,0 +1,35 @@
+// compile-flags: --crate-type=rlib -Copt-level=0
+// revisions: aarch64-apple aarch64-linux force x64-apple x64-linux
+// [aarch64-apple] needs-llvm-components: aarch64
+// [aarch64-apple] compile-flags: --target=aarch64-apple-darwin
+// [aarch64-linux] needs-llvm-components: aarch64
+// [aarch64-linux] compile-flags: --target=aarch64-unknown-linux-gnu
+// [force] needs-llvm-components: x86
+// [force] compile-flags: --target=x86_64-unknown-linux-gnu -Cforce-frame-pointers=yes
+// [x64-apple] needs-llvm-components: x86
+// [x64-apple] compile-flags: --target=x86_64-apple-darwin
+// [x64-linux] needs-llvm-components: x86
+// [x64-linux] compile-flags: --target=x86_64-unknown-linux-gnu
+
+#![feature(no_core, lang_items)]
+#![no_core]
+#[lang="sized"]
+trait Sized { }
+#[lang="copy"]
+trait Copy { }
+impl Copy for u32 {}
+
+
+// CHECK: define i32 @peach{{.*}}[[PEACH_ATTRS:\#[0-9]+]] {
+#[no_mangle]
+pub fn peach(x: u32) -> u32 {
+    x
+}
+
+// CHECK: attributes [[PEACH_ATTRS]] = {
+// x64-linux-NOT: {{.*}}"frame-pointer"{{.*}}
+// aarch64-linux-NOT: {{.*}}"frame-pointer"{{.*}}
+// x64-apple-SAME: {{.*}}"frame-pointer"="all"
+// force-SAME: {{.*}}"frame-pointer"="all"
+// aarch64-apple-SAME: {{.*}}"frame-pointer"="non-leaf"
+// CHECK-SAME: }
diff --git a/tests/codegen/function-arguments-noopt.rs b/tests/codegen/function-arguments-noopt.rs
new file mode 100644
index 00000000000..35f31eba3b1
--- /dev/null
+++ b/tests/codegen/function-arguments-noopt.rs
@@ -0,0 +1,69 @@
+// compile-flags: -C opt-level=0 -C no-prepopulate-passes
+
+// This test checks that arguments/returns in opt-level=0 builds,
+// while lacking attributes used for optimization, still have ABI-affecting attributes.
+
+#![crate_type = "lib"]
+#![feature(rustc_attrs)]
+
+pub struct S {
+  _field: [i32; 8],
+}
+
+// CHECK: zeroext i1 @boolean(i1 zeroext %x)
+#[no_mangle]
+pub fn boolean(x: bool) -> bool {
+  x
+}
+
+// CHECK-LABEL: @boolean_call
+#[no_mangle]
+pub fn boolean_call(x: bool, f: fn(bool) -> bool) -> bool {
+// CHECK: call zeroext i1 %f(i1 zeroext %x)
+  f(x)
+}
+
+// CHECK: align 4 {{i32\*|ptr}} @borrow({{i32\*|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)
+#[no_mangle]
+pub fn borrow_mut(x: &mut i32) -> &mut i32 {
+  x
+}
+
+// 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)
+  f(x)
+}
+
+// CHECK: void @struct_({{%S\*|ptr}} sret(%S){{( %_0)?}}, {{%S\*|ptr}} %x)
+#[no_mangle]
+pub fn struct_(x: S) -> S {
+  x
+}
+
+// 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}} %{{.+}})
+  f(x)
+}
+
+// CHECK: { i8, i8 } @enum_(i1 zeroext %x.0, i8 %x.1)
+#[no_mangle]
+pub fn enum_(x: Option<u8>) -> Option<u8> {
+  x
+}
+
+// CHECK-LABEL: @enum_call
+#[no_mangle]
+pub fn enum_call(x: Option<u8>, f: fn(Option<u8>) -> Option<u8>) -> Option<u8> {
+  // CHECK: call { i8, i8 } %f(i1 zeroext %x.0, i8 %x.1)
+  f(x)
+}
diff --git a/tests/codegen/function-arguments.rs b/tests/codegen/function-arguments.rs
new file mode 100644
index 00000000000..ccf4a5de327
--- /dev/null
+++ b/tests/codegen/function-arguments.rs
@@ -0,0 +1,290 @@
+// compile-flags: -O -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+#![feature(dyn_star)]
+
+use std::mem::MaybeUninit;
+use std::num::NonZeroU64;
+use std::marker::PhantomPinned;
+use std::ptr::NonNull;
+
+pub struct S {
+  _field: [i32; 8],
+}
+
+pub struct UnsafeInner {
+  _field: std::cell::UnsafeCell<i16>,
+}
+
+pub struct NotUnpin {
+  _field: i32,
+  _marker: PhantomPinned,
+}
+
+pub enum MyBool {
+  True,
+  False,
+}
+
+// CHECK: noundef zeroext i1 @boolean(i1 noundef zeroext %x)
+#[no_mangle]
+pub fn boolean(x: bool) -> bool {
+  x
+}
+
+// CHECK: i8 @maybeuninit_boolean(i8 %x)
+#[no_mangle]
+pub fn maybeuninit_boolean(x: MaybeUninit<bool>) -> MaybeUninit<bool> {
+  x
+}
+
+// CHECK: noundef zeroext i1 @enum_bool(i1 noundef zeroext %x)
+#[no_mangle]
+pub fn enum_bool(x: MyBool) -> MyBool {
+  x
+}
+
+// CHECK: i8 @maybeuninit_enum_bool(i8 %x)
+#[no_mangle]
+pub fn maybeuninit_enum_bool(x: MaybeUninit<MyBool>) -> MaybeUninit<MyBool> {
+  x
+}
+
+// CHECK: noundef i32 @char(i32 noundef %x)
+#[no_mangle]
+pub fn char(x: char) -> char {
+  x
+}
+
+// CHECK: i32 @maybeuninit_char(i32 %x)
+#[no_mangle]
+pub fn maybeuninit_char(x: MaybeUninit<char>) -> MaybeUninit<char> {
+  x
+}
+
+// CHECK: noundef i64 @int(i64 noundef %x)
+#[no_mangle]
+pub fn int(x: u64) -> u64 {
+  x
+}
+
+// CHECK: noundef i64 @nonzero_int(i64 noundef %x)
+#[no_mangle]
+pub fn nonzero_int(x: NonZeroU64) -> NonZeroU64 {
+  x
+}
+
+// CHECK: noundef i64 @option_nonzero_int(i64 noundef %x)
+#[no_mangle]
+pub fn option_nonzero_int(x: Option<NonZeroU64>) -> Option<NonZeroU64> {
+  x
+}
+
+// CHECK: @readonly_borrow({{i32\*|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()
+#[no_mangle]
+pub fn readonly_borrow_ret() -> &'static i32 {
+  loop {}
+}
+
+// CHECK: @static_borrow({{i32\*|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)
+// 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)
+// 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)
+// ... 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)
+// 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()
+#[no_mangle]
+pub fn mutable_borrow_ret() -> &'static mut i32 {
+  loop {}
+}
+
+#[no_mangle]
+// CHECK: @mutable_notunpin_borrow({{i32\*|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)
+// But `&NotUnpin` behaves perfectly normal.
+#[no_mangle]
+pub fn notunpin_borrow(_: &NotUnpin) {
+}
+
+// CHECK: @indirect_struct({{%S\*|ptr}} noalias nocapture noundef readonly dereferenceable(32) %_1)
+#[no_mangle]
+pub fn indirect_struct(_: S) {
+}
+
+// CHECK: @borrowed_struct({{%S\*|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)
+#[no_mangle]
+pub fn option_borrow(x: Option<&i32>) {
+}
+
+// CHECK: @option_borrow_mut({{i32\*|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)
+#[no_mangle]
+pub fn raw_struct(_: *const S) {
+}
+
+// CHECK: @raw_option_nonnull_struct({{i32\*|ptr}} noundef %_1)
+#[no_mangle]
+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)
+#[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)
+#[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)?}})
+#[no_mangle]
+pub fn struct_return() -> S {
+  S {
+    _field: [0, 0, 0, 0, 0, 0, 0, 0]
+  }
+}
+
+// Hack to get the correct size for the length part in slices
+// CHECK: @helper([[USIZE:i[0-9]+]] noundef %_1)
+#[no_mangle]
+pub fn helper(_: usize) {
+}
+
+// CHECK: @slice({{\[0 x i8\]\*|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)
+// 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)
+// 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)
+#[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)
+// 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)
+// 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)
+#[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)
+#[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)
+#[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)?}})
+#[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)
+#[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)
+#[no_mangle]
+pub fn return_slice(x: &[u16]) -> &[u16] {
+  x
+}
+
+// CHECK: { i16, i16 } @enum_id_1(i16 noundef %x.0, i16 %x.1)
+#[no_mangle]
+pub fn enum_id_1(x: Option<Result<u16, u16>>) -> Option<Result<u16, u16>> {
+  x
+}
+
+// CHECK: { i8, i8 } @enum_id_2(i1 noundef zeroext %x.0, i8 %x.1)
+#[no_mangle]
+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)
+// 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]
+pub fn dyn_star(x: dyn* Drop) -> dyn* Drop {
+  x
+}
diff --git a/tests/codegen/gdb_debug_script_load.rs b/tests/codegen/gdb_debug_script_load.rs
new file mode 100644
index 00000000000..002be8d1b41
--- /dev/null
+++ b/tests/codegen/gdb_debug_script_load.rs
@@ -0,0 +1,17 @@
+//
+// ignore-windows
+// ignore-macos
+// ignore-wasm
+// ignore-emscripten
+
+// compile-flags: -g -C no-prepopulate-passes
+
+#![feature(start)]
+
+// CHECK-LABEL: @main
+// CHECK: load volatile i8, {{.+}} @__rustc_debug_gdb_scripts_section__
+
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
+    return 0;
+}
diff --git a/tests/codegen/generator-debug-msvc.rs b/tests/codegen/generator-debug-msvc.rs
new file mode 100644
index 00000000000..9d70ccdef03
--- /dev/null
+++ b/tests/codegen/generator-debug-msvc.rs
@@ -0,0 +1,59 @@
+// Verify debuginfo for generators:
+//  - Each variant points to the file and line of its yield point
+//  - The discriminants are marked artificial
+//  - Other fields are not marked artificial
+//
+//
+// compile-flags: -C debuginfo=2
+// only-msvc
+
+#![feature(generators, generator_trait)]
+use std::ops::Generator;
+
+fn generator_test() -> impl Generator<Yield = i32, Return = ()> {
+    || {
+        yield 0;
+        let s = String::from("foo");
+        yield 1;
+    }
+}
+
+// FIXME: No way to reliably check the filename.
+
+// CHECK-DAG:  [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "enum2$<generator_debug_msvc::generator_test::generator_env$0>"
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant0", scope: [[GEN]],
+// For brevity, we only check the struct name and members of the last variant.
+// CHECK-SAME: file: [[FILE:![0-9]*]], line: 14,
+// CHECK-NOT:  flags: DIFlagArtificial
+// CHECK-SAME: )
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant1", scope: [[GEN]],
+// CHECK-SAME: file: [[FILE]], line: 18,
+// CHECK-NOT:  flags: DIFlagArtificial
+// CHECK-SAME: )
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant2", scope: [[GEN]],
+// CHECK-SAME: file: [[FILE]], line: 18,
+// CHECK-NOT:  flags: DIFlagArtificial
+// CHECK-SAME: )
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant3", scope: [[GEN]],
+// CHECK-SAME: file: [[FILE]], line: 15,
+// CHECK-NOT:  flags: DIFlagArtificial
+// CHECK-SAME: )
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant4", scope: [[GEN]],
+// CHECK-SAME: file: [[FILE]], line: 17,
+// CHECK-SAME: baseType: [[VARIANT_WRAPPER:![0-9]*]]
+// CHECK-NOT:  flags: DIFlagArtificial
+// CHECK-SAME: )
+// CHECK:      [[VARIANT_WRAPPER]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Variant4", scope: [[GEN]],
+// CHECK:      !DIDerivedType(tag: DW_TAG_member, name: "value", scope: [[VARIANT_WRAPPER]], {{.*}}, baseType: [[VARIANT:![0-9]*]],
+// CHECK:      [[VARIANT]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN]],
+// CHECK-NOT:  flags: DIFlagArtificial
+// CHECK-SAME: )
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[VARIANT]]
+// CHECK-NOT:  flags: DIFlagArtificial
+// CHECK-SAME: )
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "tag", scope: [[GEN]],
+// CHECK-NOT: flags: DIFlagArtificial
+
+fn main() {
+    let _dummy = generator_test();
+}
diff --git a/tests/codegen/generator-debug.rs b/tests/codegen/generator-debug.rs
new file mode 100644
index 00000000000..3ec860f2cbc
--- /dev/null
+++ b/tests/codegen/generator-debug.rs
@@ -0,0 +1,62 @@
+// Verify debuginfo for generators:
+//  - Each variant points to the file and line of its yield point
+//  - The discriminants are marked artificial
+//  - Other fields are not marked artificial
+//
+//
+// compile-flags: -C debuginfo=2 --edition=2018
+// ignore-msvc
+
+#![feature(generators, generator_trait)]
+use std::ops::Generator;
+
+fn generator_test() -> impl Generator<Yield = i32, Return = ()> {
+    || {
+        yield 0;
+        let s = String::from("foo");
+        yield 1;
+    }
+}
+
+// FIXME: No way to reliably check the filename.
+
+// CHECK-DAG:  [[GEN_FN:!.*]] = !DINamespace(name: "generator_test"
+// CHECK-DAG:  [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{generator_env#0}", scope: [[GEN_FN]]
+// CHECK:      [[VARIANT:!.*]] = !DICompositeType(tag: DW_TAG_variant_part, scope: [[GEN]],
+// CHECK-NOT:  flags: DIFlagArtificial
+// CHECK-SAME: discriminator: [[DISC:![0-9]*]]
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "0", scope: [[VARIANT]],
+// CHECK-SAME: file: [[FILE:![0-9]*]], line: 14,
+// CHECK-NOT:  flags: DIFlagArtificial
+// CHECK-SAME: )
+// CHECK:      {{!.*}} = !DICompositeType(tag: DW_TAG_structure_type, name: "Unresumed", scope: [[GEN]],
+// CHECK-NOT:  flags: DIFlagArtificial
+// CHECK-SAME: )
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "1", scope: [[VARIANT]],
+// CHECK-SAME: file: [[FILE]], line: 18,
+// CHECK-NOT:  flags: DIFlagArtificial
+// CHECK-SAME: )
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "2", scope: [[VARIANT]],
+// CHECK-SAME: file: [[FILE]], line: 18,
+// CHECK-NOT:  flags: DIFlagArtificial
+// CHECK-SAME: )
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "3", scope: [[VARIANT]],
+// CHECK-SAME: file: [[FILE]], line: 15,
+// CHECK-NOT:  flags: DIFlagArtificial
+// CHECK-SAME: )
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "4", scope: [[VARIANT]],
+// CHECK-SAME: file: [[FILE]], line: 17,
+// CHECK-NOT:  flags: DIFlagArtificial
+// CHECK-SAME: )
+// CHECK:      [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN]],
+// CHECK-NOT:  flags: DIFlagArtificial
+// CHECK-SAME: )
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[S1]]
+// CHECK-NOT:  flags: DIFlagArtificial
+// CHECK-SAME: )
+// CHECK:      [[DISC]] = !DIDerivedType(tag: DW_TAG_member, name: "__state", scope: [[GEN]],
+// CHECK-SAME: flags: DIFlagArtificial
+
+fn main() {
+    let _dummy = generator_test();
+}
diff --git a/tests/codegen/generic-debug.rs b/tests/codegen/generic-debug.rs
new file mode 100644
index 00000000000..eea16805c59
--- /dev/null
+++ b/tests/codegen/generic-debug.rs
@@ -0,0 +1,17 @@
+// ignore-windows
+
+// compile-flags: -g -C no-prepopulate-passes
+
+// CHECK-LABEL: @main
+// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_structure_type,{{.*}}name: "Generic<i32>",{{.*}}
+// CHECK: {{.*}}DITemplateTypeParameter{{.*}}name: "Type",{{.*}}
+
+#![allow(dead_code)]
+#![allow(unused_variables)]
+#![allow(unused_assignments)]
+
+pub struct Generic<Type>(Type);
+
+fn main () {
+    let generic = Generic(10);
+}
diff --git a/tests/codegen/global_asm.rs b/tests/codegen/global_asm.rs
new file mode 100644
index 00000000000..41a99530ad2
--- /dev/null
+++ b/tests/codegen/global_asm.rs
@@ -0,0 +1,46 @@
+// 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
+// ignore-loongarch64
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+use std::arch::global_asm;
+
+// CHECK-LABEL: foo
+// CHECK: module asm
+// this regex will capture the correct unconditional branch inst.
+// CHECK: module asm "{{[[:space:]]+}}jmp baz"
+global_asm!(
+    r#"
+    .global foo
+foo:
+    jmp baz
+"#
+);
+
+extern "C" {
+    fn foo();
+}
+
+// CHECK-LABEL: @baz
+#[no_mangle]
+pub unsafe extern "C" fn baz() {}
diff --git a/tests/codegen/global_asm_include.rs b/tests/codegen/global_asm_include.rs
new file mode 100644
index 00000000000..e25c164f407
--- /dev/null
+++ b/tests/codegen/global_asm_include.rs
@@ -0,0 +1,39 @@
+// 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
+// ignore-loongarch64
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+use std::arch::global_asm;
+
+// CHECK-LABEL: foo
+// CHECK: module asm
+// CHECK: module asm "{{[[:space:]]+}}jmp baz"
+global_asm!(include_str!("foo.s"));
+
+extern "C" {
+    fn foo();
+}
+
+// CHECK-LABEL: @baz
+#[no_mangle]
+pub unsafe extern "C" fn baz() {}
diff --git a/tests/codegen/global_asm_x2.rs b/tests/codegen/global_asm_x2.rs
new file mode 100644
index 00000000000..71ecef124f1
--- /dev/null
+++ b/tests/codegen/global_asm_x2.rs
@@ -0,0 +1,65 @@
+// 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
+// ignore-loongarch64
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+#![no_std]
+
+use core::arch::global_asm;
+
+// CHECK-LABEL: foo
+// CHECK: module asm
+// CHECK: module asm "{{[[:space:]]+}}jmp baz"
+// any other global_asm will be appended to this first block, so:
+// CHECK-LABEL: bar
+// CHECK: module asm "{{[[:space:]]+}}jmp quux"
+global_asm!(
+    r#"
+    .global foo
+foo:
+    jmp baz
+"#
+);
+
+extern "C" {
+    fn foo();
+}
+
+// CHECK-LABEL: @baz
+#[no_mangle]
+pub unsafe extern "C" fn baz() {}
+
+// no checks here; this has been appended to the first occurrence
+global_asm!(
+    r#"
+    .global bar
+bar:
+    jmp quux
+"#
+);
+
+extern "C" {
+    fn bar();
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn quux() {}
diff --git a/tests/codegen/i686-macosx-deployment-target.rs b/tests/codegen/i686-macosx-deployment-target.rs
new file mode 100644
index 00000000000..17258a264a5
--- /dev/null
+++ b/tests/codegen/i686-macosx-deployment-target.rs
@@ -0,0 +1,27 @@
+//
+// Checks that we correctly modify the target when MACOSX_DEPLOYMENT_TARGET is set.
+// See issue #60235.
+
+// compile-flags: -O --target=i686-apple-darwin --crate-type=rlib
+// needs-llvm-components: x86
+// rustc-env:MACOSX_DEPLOYMENT_TARGET=10.9
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang="sized"]
+trait Sized { }
+#[lang="freeze"]
+trait Freeze { }
+#[lang="copy"]
+trait Copy { }
+
+#[repr(C)]
+pub struct Bool {
+    b: bool,
+}
+
+// CHECK: target triple = "i686-apple-macosx10.9.0"
+#[no_mangle]
+pub extern "C" fn structbool() -> Bool {
+    Bool { b: true }
+}
diff --git a/tests/codegen/i686-no-macosx-deployment-target.rs b/tests/codegen/i686-no-macosx-deployment-target.rs
new file mode 100644
index 00000000000..043040a95e3
--- /dev/null
+++ b/tests/codegen/i686-no-macosx-deployment-target.rs
@@ -0,0 +1,27 @@
+//
+// Checks that we leave the target alone MACOSX_DEPLOYMENT_TARGET is unset.
+// See issue #60235.
+
+// compile-flags: -O --target=i686-apple-darwin --crate-type=rlib
+// needs-llvm-components: x86
+// unset-rustc-env:MACOSX_DEPLOYMENT_TARGET
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang="sized"]
+trait Sized { }
+#[lang="freeze"]
+trait Freeze { }
+#[lang="copy"]
+trait Copy { }
+
+#[repr(C)]
+pub struct Bool {
+    b: bool,
+}
+
+// CHECK: target triple = "i686-apple-macosx10.7.0"
+#[no_mangle]
+pub extern "C" fn structbool() -> Bool {
+    Bool { b: true }
+}
diff --git a/tests/codegen/inherit_overflow.rs b/tests/codegen/inherit_overflow.rs
new file mode 100644
index 00000000000..39909d7abfd
--- /dev/null
+++ b/tests/codegen/inherit_overflow.rs
@@ -0,0 +1,14 @@
+// compile-flags: -Zmir-enable-passes=+Inline,+ConstProp --crate-type lib
+// revisions: ASSERT NOASSERT
+//[ASSERT] compile-flags: -Coverflow-checks=on
+//[NOASSERT] compile-flags: -Coverflow-checks=off
+
+// CHECK-LABEL: define{{.*}} @assertion
+// ASSERT: call void @{{.*4core9panicking5panic}}
+// NOASSERT: ret i8 0
+#[no_mangle]
+pub fn assertion() -> u8 {
+    // Optimized MIR will replace this `CheckedBinaryOp` by `const (0, true)`.
+    // Verify that codegen does or does not emit the panic.
+    <u8 as std::ops::Add>::add(255, 1)
+}
diff --git a/tests/codegen/inline-always-works-always.rs b/tests/codegen/inline-always-works-always.rs
new file mode 100644
index 00000000000..912af782a8f
--- /dev/null
+++ b/tests/codegen/inline-always-works-always.rs
@@ -0,0 +1,21 @@
+// revisions: NO-OPT SIZE-OPT SPEED-OPT
+//[NO-OPT] compile-flags: -Copt-level=0
+//[SIZE-OPT] compile-flags: -Copt-level=s
+//[SPEED-OPT] compile-flags: -Copt-level=3
+
+#![crate_type="rlib"]
+
+#[no_mangle]
+#[inline(always)]
+pub extern "C" fn callee() -> u32 {
+    4 + 4
+}
+
+// CHECK-LABEL: caller
+// SIZE-OPT: ret i32 8
+// SPEED-OPT: ret i32 8
+// NO-OPT: ret i32 8
+#[no_mangle]
+pub extern "C" fn caller() -> u32 {
+    callee()
+}
diff --git a/tests/codegen/inline-debuginfo.rs b/tests/codegen/inline-debuginfo.rs
new file mode 100644
index 00000000000..5b230361f39
--- /dev/null
+++ b/tests/codegen/inline-debuginfo.rs
@@ -0,0 +1,17 @@
+#![crate_type="rlib"]
+// compile-flags: -Copt-level=3 -g
+//
+
+#[no_mangle]
+#[inline(always)]
+pub extern "C" fn callee(x: u32) -> u32 {
+    x + 4
+}
+
+// CHECK-LABEL: caller
+// CHECK: call void @llvm.dbg.value(metadata i32 %y, metadata !{{.*}}, metadata !DIExpression(DW_OP_constu, 3, DW_OP_minus, DW_OP_stack_value)), !dbg [[A:!.*]]
+// CHECK: [[A]] = !DILocation(line: {{.*}}, scope: {{.*}}, inlinedAt: {{.*}})
+#[no_mangle]
+pub extern "C" fn caller(y: u32) -> u32 {
+    callee(y - 3)
+}
diff --git a/tests/codegen/inline-function-args-debug-info.rs b/tests/codegen/inline-function-args-debug-info.rs
new file mode 100644
index 00000000000..e3d8caa49d4
--- /dev/null
+++ b/tests/codegen/inline-function-args-debug-info.rs
@@ -0,0 +1,20 @@
+// This test checks that debug information includes function argument indexes even if the function
+// gets inlined by MIR inlining. Without function argument indexes, `info args` in gdb won't show
+// arguments and their values for the current function.
+
+// compile-flags: -Zinline-mir=yes -Cdebuginfo=2 --edition=2021
+
+#![crate_type = "lib"]
+
+pub fn outer_function(x: usize, y: usize) -> usize {
+    inner_function(x, y) + 1
+}
+
+#[inline]
+fn inner_function(aaaa: usize, bbbb: usize) -> usize {
+    // CHECK: !DILocalVariable(name: "aaaa", arg: 1
+    // CHECK-SAME: line: 14
+    // CHECK: !DILocalVariable(name: "bbbb", arg: 2
+    // CHECK-SAME: line: 14
+    aaaa + bbbb
+}
diff --git a/tests/codegen/inline-hint.rs b/tests/codegen/inline-hint.rs
new file mode 100644
index 00000000000..bb2a8e6a649
--- /dev/null
+++ b/tests/codegen/inline-hint.rs
@@ -0,0 +1,31 @@
+// Checks that closures, constructors, and shims except
+// for a drop glue receive inline hint by default.
+//
+// compile-flags: -Cno-prepopulate-passes -Csymbol-mangling-version=v0 -Zinline-mir=no
+#![crate_type = "lib"]
+
+pub fn f() {
+    let a = A;
+    let b = (0i32, 1i32, 2i32, 3 as *const i32);
+    let c = || {};
+
+    a(String::new(), String::new());
+    b.clone();
+    c();
+}
+
+struct A(String, String);
+
+// CHECK:      ; core::ptr::drop_in_place::<inline_hint::A>
+// CHECK-NEXT: ; Function Attrs:
+// CHECK-NOT:  inlinehint
+// CHECK-SAME: {{$}}
+
+// CHECK:      ; <(i32, i32, i32, *const i{{16|32|64}}) as core::clone::Clone>::clone
+// CHECK-NEXT: ; Function Attrs: inlinehint
+
+// CHECK:      ; inline_hint::f::{closure#0}
+// CHECK-NEXT: ; Function Attrs: inlinehint
+
+// CHECK:      ; inline_hint::A
+// CHECK-NEXT: ; Function Attrs: inlinehint
diff --git a/tests/codegen/instrument-coverage.rs b/tests/codegen/instrument-coverage.rs
new file mode 100644
index 00000000000..78f8875a2d9
--- /dev/null
+++ b/tests/codegen/instrument-coverage.rs
@@ -0,0 +1,17 @@
+// Test that `-Cinstrument-coverage` creates expected __llvm_profile_filename symbol in LLVM IR.
+
+// needs-profiler-support
+// compile-flags: -Cinstrument-coverage
+
+// CHECK: @__llvm_profile_filename = {{.*}}"default_%m_%p.profraw\00"{{.*}}
+
+#![crate_type="lib"]
+
+#[inline(never)]
+fn some_function() {
+
+}
+
+pub fn some_other_function() {
+    some_function();
+}
diff --git a/tests/codegen/instrument-mcount.rs b/tests/codegen/instrument-mcount.rs
new file mode 100644
index 00000000000..b26076e7a7b
--- /dev/null
+++ b/tests/codegen/instrument-mcount.rs
@@ -0,0 +1,7 @@
+//
+// compile-flags: -Z instrument-mcount
+
+#![crate_type = "lib"]
+
+// CHECK: attributes #{{.*}} "frame-pointer"="all" "instrument-function-entry-inlined"="{{.*}}mcount{{.*}}"
+pub fn foo() {}
diff --git a/tests/codegen/instrument-xray/basic.rs b/tests/codegen/instrument-xray/basic.rs
new file mode 100644
index 00000000000..d3e49d53174
--- /dev/null
+++ b/tests/codegen/instrument-xray/basic.rs
@@ -0,0 +1,9 @@
+// Checks that `-Z instrument-xray` produces expected instrumentation.
+//
+// needs-xray
+// compile-flags: -Z instrument-xray=always
+
+#![crate_type = "lib"]
+
+// CHECK: attributes #{{.*}} "function-instrument"="xray-always"
+pub fn function() {}
diff --git a/tests/codegen/instrument-xray/options-combine.rs b/tests/codegen/instrument-xray/options-combine.rs
new file mode 100644
index 00000000000..f7e500b65f6
--- /dev/null
+++ b/tests/codegen/instrument-xray/options-combine.rs
@@ -0,0 +1,12 @@
+// Checks that `-Z instrument-xray` options can be specified multiple times.
+//
+// needs-xray
+// compile-flags: -Z instrument-xray=skip-exit
+// compile-flags: -Z instrument-xray=instruction-threshold=123
+// compile-flags: -Z instrument-xray=instruction-threshold=456
+
+#![crate_type = "lib"]
+
+// CHECK:      attributes #{{.*}} "xray-instruction-threshold"="456" "xray-skip-exit"
+// CHECK-NOT:  attributes #{{.*}} "xray-instruction-threshold"="123"
+pub fn function() {}
diff --git a/tests/codegen/instrument-xray/options-override.rs b/tests/codegen/instrument-xray/options-override.rs
new file mode 100644
index 00000000000..00f81837902
--- /dev/null
+++ b/tests/codegen/instrument-xray/options-override.rs
@@ -0,0 +1,11 @@
+// Checks that the last `-Z instrument-xray` option wins.
+//
+// needs-xray
+// compile-flags: -Z instrument-xray=always
+// compile-flags: -Z instrument-xray=never
+
+#![crate_type = "lib"]
+
+// CHECK:      attributes #{{.*}} "function-instrument"="xray-never"
+// CHECK-NOT:  attributes #{{.*}} "function-instrument"="xray-always"
+pub fn function() {}
diff --git a/tests/codegen/integer-cmp.rs b/tests/codegen/integer-cmp.rs
new file mode 100644
index 00000000000..8ada3cf09d0
--- /dev/null
+++ b/tests/codegen/integer-cmp.rs
@@ -0,0 +1,28 @@
+// This is test for more optimal Ord implementation for integers.
+// See <https://github.com/rust-lang/rust/issues/63758> for more info.
+
+// compile-flags: -C opt-level=3
+
+#![crate_type = "lib"]
+
+use std::cmp::Ordering;
+
+// CHECK-LABEL: @cmp_signed
+#[no_mangle]
+pub fn cmp_signed(a: i64, b: i64) -> Ordering {
+// CHECK: icmp slt
+// CHECK: icmp ne
+// CHECK: zext i1
+// CHECK: select i1
+    a.cmp(&b)
+}
+
+// CHECK-LABEL: @cmp_unsigned
+#[no_mangle]
+pub fn cmp_unsigned(a: u32, b: u32) -> Ordering {
+// CHECK: icmp ult
+// CHECK: icmp ne
+// CHECK: zext i1
+// CHECK: select i1
+    a.cmp(&b)
+}
diff --git a/tests/codegen/integer-overflow.rs b/tests/codegen/integer-overflow.rs
new file mode 100644
index 00000000000..183de56db96
--- /dev/null
+++ b/tests/codegen/integer-overflow.rs
@@ -0,0 +1,26 @@
+// no-system-llvm
+// compile-flags: -O -C overflow-checks=on
+
+#![crate_type = "lib"]
+
+
+pub struct S1<'a> {
+    data: &'a [u8],
+    position: usize,
+}
+
+// CHECK-LABEL: @slice_no_index_order
+#[no_mangle]
+pub fn slice_no_index_order<'a>(s: &'a mut S1, n: usize) -> &'a [u8] {
+    // CHECK-NOT: slice_index_order_fail
+    let d = &s.data[s.position..s.position+n];
+    s.position += n;
+    return d;
+}
+
+// CHECK-LABEL: @test_check
+#[no_mangle]
+pub fn test_check<'a>(s: &'a mut S1, x: usize, y: usize) -> &'a [u8] {
+    // CHECK: slice_index_order_fail
+    &s.data[x..y]
+}
diff --git a/tests/codegen/internalize-closures.rs b/tests/codegen/internalize-closures.rs
new file mode 100644
index 00000000000..ab3dc3fba5e
--- /dev/null
+++ b/tests/codegen/internalize-closures.rs
@@ -0,0 +1,14 @@
+// compile-flags: -C no-prepopulate-passes -Zmir-opt-level=0
+
+pub fn main() {
+
+    // We want to make sure that closures get 'internal' linkage instead of
+    // 'weak_odr' when they are not shared between codegen units
+    // FIXME(eddyb) `legacy` mangling uses `{{closure}}`, while `v0`
+    // uses `{closure#0}`, switch to the latter once `legacy` is gone.
+    // CHECK-LABEL: ; internalize_closures::main::{{.*}}closure
+    // CHECK-NEXT: ; Function Attrs:
+    // CHECK-NEXT: define internal
+    let c = |x:i32| { x + 1 };
+    let _ = c(1);
+}
diff --git a/tests/codegen/intrinsic-no-unnamed-attr.rs b/tests/codegen/intrinsic-no-unnamed-attr.rs
new file mode 100644
index 00000000000..c8a8e0b3e7a
--- /dev/null
+++ b/tests/codegen/intrinsic-no-unnamed-attr.rs
@@ -0,0 +1,12 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![feature(intrinsics)]
+
+extern "rust-intrinsic" {
+    fn sqrtf32(x: f32) -> f32;
+}
+// CHECK: @llvm.sqrt.f32(float) #{{[0-9]*}}
+
+fn main() {
+    unsafe { sqrtf32(0.0f32); }
+}
diff --git a/tests/codegen/intrinsics/const_eval_select.rs b/tests/codegen/intrinsics/const_eval_select.rs
new file mode 100644
index 00000000000..f3877dc6b96
--- /dev/null
+++ b/tests/codegen/intrinsics/const_eval_select.rs
@@ -0,0 +1,18 @@
+// compile-flags: -C no-prepopulate-passes -Copt-level=0
+
+#![crate_type = "lib"]
+#![feature(const_eval_select)]
+#![feature(core_intrinsics)]
+
+use std::intrinsics::const_eval_select;
+
+const fn foo(_: i32) -> i32 { 1 }
+
+#[no_mangle]
+pub fn hi(n: i32) -> i32 { n }
+
+#[no_mangle]
+pub unsafe fn hey() {
+    // CHECK: call i32 @hi(i32
+    const_eval_select((42,), foo, hi);
+}
diff --git a/tests/codegen/intrinsics/exact_div.rs b/tests/codegen/intrinsics/exact_div.rs
new file mode 100644
index 00000000000..68eaa39997a
--- /dev/null
+++ b/tests/codegen/intrinsics/exact_div.rs
@@ -0,0 +1,20 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+#![feature(core_intrinsics)]
+
+use std::intrinsics::exact_div;
+
+// CHECK-LABEL: @exact_sdiv
+#[no_mangle]
+pub unsafe fn exact_sdiv(x: i32, y: i32) -> i32 {
+    // CHECK: sdiv exact
+    exact_div(x, y)
+}
+
+// CHECK-LABEL: @exact_udiv
+#[no_mangle]
+pub unsafe fn exact_udiv(x: u32, y: u32) -> u32 {
+    // CHECK: udiv exact
+    exact_div(x, y)
+}
diff --git a/tests/codegen/intrinsics/likely.rs b/tests/codegen/intrinsics/likely.rs
new file mode 100644
index 00000000000..c5a0185bd48
--- /dev/null
+++ b/tests/codegen/intrinsics/likely.rs
@@ -0,0 +1,30 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+#![feature(core_intrinsics)]
+
+use std::intrinsics::{likely,unlikely};
+
+#[no_mangle]
+pub fn check_likely(x: i32, y: i32) -> Option<i32> {
+    unsafe {
+        // CHECK: call i1 @llvm.expect.i1(i1 %{{.*}}, i1 true)
+        if likely(x == y) {
+            None
+        } else {
+            Some(x + y)
+        }
+    }
+}
+
+#[no_mangle]
+pub fn check_unlikely(x: i32, y: i32) -> Option<i32> {
+    unsafe {
+        // CHECK: call i1 @llvm.expect.i1(i1 %{{.*}}, i1 false)
+        if unlikely(x == y) {
+            None
+        } else {
+            Some(x + y)
+        }
+    }
+}
diff --git a/tests/codegen/intrinsics/mask.rs b/tests/codegen/intrinsics/mask.rs
new file mode 100644
index 00000000000..8f93da2e5da
--- /dev/null
+++ b/tests/codegen/intrinsics/mask.rs
@@ -0,0 +1,12 @@
+// compile-flags: -Copt-level=0
+#![crate_type = "lib"]
+#![feature(core_intrinsics)]
+
+// CHECK-LABEL: @mask_ptr
+// CHECK-SAME: [[WORD:i[0-9]+]] %mask
+#[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)
+    core::intrinsics::ptr_mask(ptr, mask)
+}
diff --git a/tests/codegen/intrinsics/nearby.rs b/tests/codegen/intrinsics/nearby.rs
new file mode 100644
index 00000000000..520fe2f1886
--- /dev/null
+++ b/tests/codegen/intrinsics/nearby.rs
@@ -0,0 +1,18 @@
+#![crate_type = "lib"]
+#![feature(core_intrinsics)]
+
+use std::intrinsics;
+
+// CHECK-LABEL: @nearbyintf32
+#[no_mangle]
+pub unsafe fn nearbyintf32(a: f32) -> f32 {
+    // CHECK: llvm.nearbyint.f32
+    intrinsics::nearbyintf32(a)
+}
+
+// CHECK-LABEL: @nearbyintf64
+#[no_mangle]
+pub unsafe fn nearbyintf64(a: f64) -> f64 {
+    // CHECK: llvm.nearbyint.f64
+    intrinsics::nearbyintf64(a)
+}
diff --git a/tests/codegen/intrinsics/nontemporal.rs b/tests/codegen/intrinsics/nontemporal.rs
new file mode 100644
index 00000000000..d8ee2945266
--- /dev/null
+++ b/tests/codegen/intrinsics/nontemporal.rs
@@ -0,0 +1,13 @@
+// compile-flags: -O
+
+#![feature(core_intrinsics)]
+#![crate_type = "lib"]
+
+#[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
+    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..7fc4f4498d6
--- /dev/null
+++ b/tests/codegen/intrinsics/offset.rs
@@ -0,0 +1,34 @@
+// compile-flags: -O -C no-prepopulate-passes
+// min-llvm-version: 15.0 (because we're using opaque pointers)
+
+#![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/offset_from.rs b/tests/codegen/intrinsics/offset_from.rs
new file mode 100644
index 00000000000..d0de4c8355d
--- /dev/null
+++ b/tests/codegen/intrinsics/offset_from.rs
@@ -0,0 +1,36 @@
+// compile-flags: -C opt-level=1
+// only-64bit (because we're using [ui]size)
+
+#![crate_type = "lib"]
+#![feature(core_intrinsics)]
+
+//! Basic optimizations are enabled because otherwise `x86_64-gnu-nopt` had an alloca.
+//! Uses a type with non-power-of-two size to avoid normalizations to shifts.
+
+use std::intrinsics::*;
+
+type RGB = [u8; 3];
+
+// CHECK-LABEL: @offset_from_odd_size
+#[no_mangle]
+pub unsafe fn offset_from_odd_size(a: *const RGB, b: *const RGB) -> isize {
+    // CHECK: start
+    // CHECK-NEXT: ptrtoint
+    // CHECK-NEXT: ptrtoint
+    // CHECK-NEXT: sub i64
+    // CHECK-NEXT: sdiv exact i64 %{{[0-9]+}}, 3
+    // CHECK-NEXT: ret i64
+    ptr_offset_from(a, b)
+}
+
+// CHECK-LABEL: @offset_from_unsigned_odd_size
+#[no_mangle]
+pub unsafe fn offset_from_unsigned_odd_size(a: *const RGB, b: *const RGB) -> usize {
+    // CHECK: start
+    // CHECK-NEXT: ptrtoint
+    // CHECK-NEXT: ptrtoint
+    // CHECK-NEXT: sub nuw i64
+    // CHECK-NEXT: udiv exact i64 %{{[0-9]+}}, 3
+    // CHECK-NEXT: ret i64
+    ptr_offset_from_unsigned(a, b)
+}
diff --git a/tests/codegen/intrinsics/prefetch.rs b/tests/codegen/intrinsics/prefetch.rs
new file mode 100644
index 00000000000..59d7fa6381b
--- /dev/null
+++ b/tests/codegen/intrinsics/prefetch.rs
@@ -0,0 +1,63 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+#![feature(core_intrinsics)]
+
+use std::intrinsics::{prefetch_read_data, prefetch_write_data,
+                      prefetch_read_instruction, prefetch_write_instruction};
+
+#[no_mangle]
+pub fn check_prefetch_read_data(data: &[i8]) {
+    unsafe {
+        // CHECK: call void @llvm.prefetch{{.*}}({{.*}}, i32 0, i32 0, i32 1)
+        prefetch_read_data(data.as_ptr(), 0);
+        // CHECK: call void @llvm.prefetch{{.*}}({{.*}}, i32 0, i32 1, i32 1)
+        prefetch_read_data(data.as_ptr(), 1);
+        // CHECK: call void @llvm.prefetch{{.*}}({{.*}}, i32 0, i32 2, i32 1)
+        prefetch_read_data(data.as_ptr(), 2);
+        // CHECK: call void @llvm.prefetch{{.*}}({{.*}}, i32 0, i32 3, i32 1)
+        prefetch_read_data(data.as_ptr(), 3);
+    }
+}
+
+#[no_mangle]
+pub fn check_prefetch_write_data(data: &[i8]) {
+    unsafe {
+        // CHECK: call void @llvm.prefetch{{.*}}({{.*}}, i32 1, i32 0, i32 1)
+        prefetch_write_data(data.as_ptr(), 0);
+        // CHECK: call void @llvm.prefetch{{.*}}({{.*}}, i32 1, i32 1, i32 1)
+        prefetch_write_data(data.as_ptr(), 1);
+        // CHECK: call void @llvm.prefetch{{.*}}({{.*}}, i32 1, i32 2, i32 1)
+        prefetch_write_data(data.as_ptr(), 2);
+        // CHECK: call void @llvm.prefetch{{.*}}({{.*}}, i32 1, i32 3, i32 1)
+        prefetch_write_data(data.as_ptr(), 3);
+    }
+}
+
+#[no_mangle]
+pub fn check_prefetch_read_instruction(data: &[i8]) {
+    unsafe {
+        // CHECK: call void @llvm.prefetch{{.*}}({{.*}}, i32 0, i32 0, i32 0)
+        prefetch_read_instruction(data.as_ptr(), 0);
+        // CHECK: call void @llvm.prefetch{{.*}}({{.*}}, i32 0, i32 1, i32 0)
+        prefetch_read_instruction(data.as_ptr(), 1);
+        // CHECK: call void @llvm.prefetch{{.*}}({{.*}}, i32 0, i32 2, i32 0)
+        prefetch_read_instruction(data.as_ptr(), 2);
+        // CHECK: call void @llvm.prefetch{{.*}}({{.*}}, i32 0, i32 3, i32 0)
+        prefetch_read_instruction(data.as_ptr(), 3);
+    }
+}
+
+#[no_mangle]
+pub fn check_prefetch_write_instruction(data: &[i8]) {
+    unsafe {
+        // CHECK: call void @llvm.prefetch{{.*}}({{.*}}, i32 1, i32 0, i32 0)
+        prefetch_write_instruction(data.as_ptr(), 0);
+        // CHECK: call void @llvm.prefetch{{.*}}({{.*}}, i32 1, i32 1, i32 0)
+        prefetch_write_instruction(data.as_ptr(), 1);
+        // CHECK: call void @llvm.prefetch{{.*}}({{.*}}, i32 1, i32 2, i32 0)
+        prefetch_write_instruction(data.as_ptr(), 2);
+        // CHECK: call void @llvm.prefetch{{.*}}({{.*}}, i32 1, i32 3, i32 0)
+        prefetch_write_instruction(data.as_ptr(), 3);
+    }
+}
diff --git a/tests/codegen/intrinsics/transmute-niched.rs b/tests/codegen/intrinsics/transmute-niched.rs
new file mode 100644
index 00000000000..fffc24a1181
--- /dev/null
+++ b/tests/codegen/intrinsics/transmute-niched.rs
@@ -0,0 +1,184 @@
+// 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)
+// min-llvm-version: 15.0 # this test assumes `ptr`s
+
+#![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
new file mode 100644
index 00000000000..168838ef497
--- /dev/null
+++ b/tests/codegen/intrinsics/transmute-x64.rs
@@ -0,0 +1,35 @@
+// 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"]
+
+use std::arch::x86_64::{__m128, __m128i, __m256i};
+use std::mem::transmute;
+
+// CHECK-LABEL: @check_sse_float_to_int(
+#[no_mangle]
+pub unsafe fn check_sse_float_to_int(x: __m128) -> __m128i {
+    // CHECK-NOT: alloca
+    // CHECK: %0 = load <4 x float>, ptr %x, align 16
+    // CHECK: store <4 x float> %0, ptr %_0, align 16
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_sse_pair_to_avx(
+#[no_mangle]
+pub unsafe fn check_sse_pair_to_avx(x: (__m128i, __m128i)) -> __m256i {
+    // CHECK-NOT: alloca
+    // CHECK: %0 = load <4 x i64>, ptr %x, align 16
+    // CHECK: store <4 x i64> %0, ptr %_0, align 32
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_sse_pair_from_avx(
+#[no_mangle]
+pub unsafe fn check_sse_pair_from_avx(x: __m256i) -> (__m128i, __m128i) {
+    // CHECK-NOT: alloca
+    // 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
new file mode 100644
index 00000000000..f8c20960660
--- /dev/null
+++ b/tests/codegen/intrinsics/transmute.rs
@@ -0,0 +1,470 @@
+// 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)]
+#![feature(custom_mir)]
+#![feature(inline_const)]
+#![allow(unreachable_code)]
+
+use std::intrinsics::{transmute, transmute_unchecked};
+use std::mem::MaybeUninit;
+
+// Some of these need custom MIR to not get removed by MIR optimizations.
+use std::intrinsics::mir::*;
+
+pub enum ZstNever {}
+
+#[repr(align(2))]
+pub struct BigNever(ZstNever, u16, ZstNever);
+
+#[repr(align(8))]
+pub struct Scalar64(i64);
+
+#[repr(C, align(4))]
+pub struct Aggregate64(u16, u8, i8, f32);
+
+#[repr(C)]
+pub struct Aggregate8(u8);
+
+// CHECK-LABEL: @check_bigger_size(
+#[no_mangle]
+pub unsafe fn check_bigger_size(x: u16) -> u32 {
+    // CHECK: call void @llvm.trap
+    transmute_unchecked(x)
+}
+
+// CHECK-LABEL: @check_smaller_size(
+#[no_mangle]
+pub unsafe fn check_smaller_size(x: u32) -> u16 {
+    // CHECK: call void @llvm.trap
+    transmute_unchecked(x)
+}
+
+// CHECK-LABEL: @check_smaller_array(
+#[no_mangle]
+pub unsafe fn check_smaller_array(x: [u32; 7]) -> [u32; 3] {
+    // CHECK: call void @llvm.trap
+    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()
+        }
+    }
+}
+
+// CHECK-LABEL: @check_from_empty_array(
+#[no_mangle]
+#[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
+    // CHECK-NOT: trap
+    mir! {
+        {
+            RET = CastTransmute(x);
+            Return()
+        }
+    }
+}
+
+// CHECK-LABEL: @check_to_uninhabited(
+#[no_mangle]
+#[custom_mir(dialect = "runtime", phase = "optimized")]
+pub unsafe fn check_to_uninhabited(x: u16) {
+    // CHECK-NOT: trap
+    // CHECK: call void @llvm.trap
+    // CHECK-NOT: trap
+    mir! {
+        let temp: BigNever;
+        {
+            temp = CastTransmute(x);
+            Return()
+        }
+    }
+}
+
+// CHECK-LABEL: @check_from_uninhabited(
+#[no_mangle]
+#[custom_mir(dialect = "runtime", phase = "optimized")]
+pub unsafe fn check_from_uninhabited(x: BigNever) -> u16 {
+    // CHECK: ret i16 poison
+    mir! {
+        {
+            RET = CastTransmute(x);
+            Return()
+        }
+    }
+}
+
+// CHECK-LABEL: @check_intermediate_passthrough(
+#[no_mangle]
+pub unsafe fn check_intermediate_passthrough(x: u32) -> i32 {
+    // CHECK: start
+    // CHECK: %[[TMP:.+]] = add i32 1, %x
+    // CHECK: %[[RET:.+]] = add i32 %[[TMP]], 1
+    // CHECK: ret i32 %[[RET]]
+    unsafe { transmute::<u32, i32>(1 + x) + 1 }
+}
+
+// CHECK-LABEL: @check_nop_pair(
+#[no_mangle]
+pub unsafe fn check_nop_pair(x: (u8, i8)) -> (i8, u8) {
+    // CHECK-NOT: alloca
+    // 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) }
+}
+
+// CHECK-LABEL: @check_to_newtype(
+#[no_mangle]
+pub unsafe fn check_to_newtype(x: u64) -> Scalar64 {
+    // CHECK-NOT: alloca
+    // CHECK: ret i64 %x
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_from_newtype(
+#[no_mangle]
+pub unsafe fn check_from_newtype(x: Scalar64) -> u64 {
+    // CHECK-NOT: alloca
+    // CHECK: ret i64 %x
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_aggregate_to_bool(
+#[no_mangle]
+pub unsafe fn check_aggregate_to_bool(x: Aggregate8) -> bool {
+    // CHECK: %x = alloca %Aggregate8, align 1
+    // CHECK: %[[BYTE:.+]] = load i8, ptr %x, align 1
+    // CHECK: %[[BOOL:.+]] = trunc i8 %[[BYTE]] to i1
+    // CHECK: ret i1 %[[BOOL]]
+    transmute(x)
+}
+
+// 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: %[[BYTE:.+]] = zext i1 %x to i8
+    // CHECK: store i8 %[[BYTE]], ptr %_0, align 1
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_byte_to_bool(
+#[no_mangle]
+pub unsafe fn check_byte_to_bool(x: u8) -> bool {
+    // CHECK-NOT: alloca
+    // CHECK: %[[R:.+]] = trunc i8 %x to i1
+    // CHECK: ret i1 %[[R]]
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_byte_from_bool(
+#[no_mangle]
+pub unsafe fn check_byte_from_bool(x: bool) -> u8 {
+    // CHECK-NOT: alloca
+    // 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
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_from_pair(
+#[no_mangle]
+pub unsafe fn check_from_pair(x: Option<i32>) -> u64 {
+    // The two arguments are of types that are only 4-aligned, but they're
+    // 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 %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)
+}
+
+// CHECK-LABEL: @check_to_float(
+#[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
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_from_float(
+#[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
+    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
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_from_bytes(
+#[no_mangle]
+pub unsafe fn check_from_bytes(x: [u8; 4]) -> u32 {
+    // CHECK: %x = alloca [4 x i8], align 1
+    // CHECK: %[[VAL:.+]] = load i32, ptr %x, align 1
+    // CHECK: ret i32 %[[VAL]]
+    transmute(x)
+}
+
+// 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: %0 = load i64, ptr %_0, align 4
+    // CHECK: ret i64 %0
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_from_aggregate(
+#[no_mangle]
+pub unsafe fn check_from_aggregate(x: Aggregate64) -> u64 {
+    // CHECK: %x = alloca %Aggregate64, align 4
+    // CHECK: %[[VAL:.+]] = load i64, ptr %x, align 4
+    // CHECK: ret i64 %[[VAL]]
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_long_array_less_aligned(
+#[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: ret void
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_long_array_more_aligned(
+#[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: ret void
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_pair_with_bool(
+#[no_mangle]
+pub unsafe fn check_pair_with_bool(x: (u8, bool)) -> (bool, i8) {
+    // CHECK-NOT: alloca
+    // CHECK: trunc i8 %x.0 to i1
+    // CHECK: zext i1 %x.1 to i8
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_float_to_pointer(
+#[no_mangle]
+pub unsafe fn check_float_to_pointer(x: f64) -> *const () {
+    // CHECK-NOT: alloca
+    // CHECK: %0 = bitcast double %x to i64
+    // CHECK: %_0 = inttoptr i64 %0 to ptr
+    // CHECK: ret ptr %_0
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_float_from_pointer(
+#[no_mangle]
+pub unsafe fn check_float_from_pointer(x: *const ()) -> f64 {
+    // CHECK-NOT: alloca
+    // CHECK: %0 = ptrtoint ptr %x to i64
+    // CHECK: %_0 = bitcast i64 %0 to double
+    // CHECK: ret double %_0
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_array_to_pair(
+#[no_mangle]
+pub unsafe fn check_array_to_pair(x: [u8; 16]) -> (i64, u64) {
+    // CHECK-NOT: alloca
+    // CHECK: %[[FST:.+]] = load i64, ptr %{{.+}}, align 1, !noundef !
+    // CHECK: %[[SND:.+]] = load i64, ptr %{{.+}}, align 1, !noundef !
+    // CHECK: %[[PAIR0:.+]] = insertvalue { i64, i64 } poison, i64 %[[FST]], 0
+    // CHECK: %[[PAIR01:.+]] = insertvalue { i64, i64 } %[[PAIR0]], i64 %[[SND]], 1
+    // CHECK: ret { i64, i64 } %[[PAIR01]]
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_pair_to_array(
+#[no_mangle]
+pub unsafe fn check_pair_to_array(x: (i64, u64)) -> [u8; 16] {
+    // CHECK-NOT: alloca
+    // CHECK: store i64 %x.0, ptr %{{.+}}, align 1
+    // CHECK: store i64 %x.1, ptr %{{.+}}, align 1
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_heterogeneous_integer_pair(
+#[no_mangle]
+pub unsafe fn check_heterogeneous_integer_pair(x: (i32, bool)) -> (bool, u32) {
+    // CHECK: store i32 %x.0
+    // CHECK: %[[WIDER:.+]] = zext i1 %x.1 to i8
+    // CHECK: store i8 %[[WIDER]]
+
+    // CHECK: %[[BYTE:.+]] = load i8
+    // CHECK: trunc i8 %[[BYTE:.+]] to i1
+    // CHECK: load i32
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_heterogeneous_float_pair(
+#[no_mangle]
+pub unsafe fn check_heterogeneous_float_pair(x: (f64, f32)) -> (f32, f64) {
+    // CHECK: store double %x.0
+    // CHECK: store float %x.1
+    // CHECK: %[[A:.+]] = load float
+    // CHECK: %[[B:.+]] = load double
+    // CHECK: %[[P:.+]] = insertvalue { float, double } poison, float %[[A]], 0
+    // CHECK: insertvalue { float, double } %[[P]], double %[[B]], 1
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_issue_110005(
+#[no_mangle]
+pub unsafe fn check_issue_110005(x: (usize, bool)) -> Option<Box<[u8]>> {
+    // CHECK: store i64 %x.0
+    // CHECK: %[[WIDER:.+]] = zext i1 %x.1 to i8
+    // CHECK: store i8 %[[WIDER]]
+    // CHECK: load ptr
+    // CHECK: load i64
+    transmute(x)
+}
+
+// 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.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)
+}
+
+// CHECK-LABEL: @check_issue_109992(
+#[no_mangle]
+#[custom_mir(dialect = "runtime", phase = "optimized")]
+pub unsafe fn check_issue_109992(x: ()) -> [(); 1] {
+    // This uses custom MIR to avoid MIR optimizations having removed ZST ops.
+
+    // CHECK: start
+    // CHECK-NEXT: ret void
+    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()
+        }
+    }
+}
+
+// CHECK-LABEL: @check_maybe_uninit_pair(i16 %x.0, i64 %x.1)
+#[no_mangle]
+pub unsafe fn check_maybe_uninit_pair(
+    x: (MaybeUninit<u16>, MaybeUninit<u64>),
+) -> (MaybeUninit<i64>, MaybeUninit<i16>) {
+    // Thanks to `MaybeUninit` this is actually defined behaviour,
+    // unlike the examples above with pairs of primitives.
+
+    // CHECK: store i16 %x.0
+    // CHECK: store i64 %x.1
+    // CHECK: load i64
+    // CHECK-NOT: noundef
+    // CHECK: load i16
+    // CHECK-NOT: noundef
+    // CHECK: ret { i64, i16 }
+    transmute(x)
+}
+
+#[repr(align(8))]
+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: %0 = load i64, ptr %_0, align 8
+    // CHECK: ret i64 %0
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_from_overalign(
+#[no_mangle]
+pub unsafe fn check_from_overalign(x: HighAlignScalar) -> u64 {
+    // CHECK: %x = alloca %HighAlignScalar, align 8
+    // CHECK: %[[VAL:.+]] = load i64, ptr %x, align 8
+    // CHECK: ret i64 %[[VAL]]
+    transmute(x)
+}
diff --git a/tests/codegen/intrinsics/unchecked_math.rs b/tests/codegen/intrinsics/unchecked_math.rs
new file mode 100644
index 00000000000..419c120ede9
--- /dev/null
+++ b/tests/codegen/intrinsics/unchecked_math.rs
@@ -0,0 +1,46 @@
+#![crate_type = "lib"]
+#![feature(core_intrinsics)]
+
+use std::intrinsics::*;
+
+// CHECK-LABEL: @unchecked_add_signed
+#[no_mangle]
+pub unsafe fn unchecked_add_signed(a: i32, b: i32) -> i32 {
+    // CHECK: add nsw
+    unchecked_add(a, b)
+}
+
+// CHECK-LABEL: @unchecked_add_unsigned
+#[no_mangle]
+pub unsafe fn unchecked_add_unsigned(a: u32, b: u32) -> u32 {
+    // CHECK: add nuw
+    unchecked_add(a, b)
+}
+
+// CHECK-LABEL: @unchecked_sub_signed
+#[no_mangle]
+pub unsafe fn unchecked_sub_signed(a: i32, b: i32) -> i32 {
+    // CHECK: sub nsw
+    unchecked_sub(a, b)
+}
+
+// CHECK-LABEL: @unchecked_sub_unsigned
+#[no_mangle]
+pub unsafe fn unchecked_sub_unsigned(a: u32, b: u32) -> u32 {
+    // CHECK: sub nuw
+    unchecked_sub(a, b)
+}
+
+// CHECK-LABEL: @unchecked_mul_signed
+#[no_mangle]
+pub unsafe fn unchecked_mul_signed(a: i32, b: i32) -> i32 {
+    // CHECK: mul nsw
+    unchecked_mul(a, b)
+}
+
+// CHECK-LABEL: @unchecked_mul_unsigned
+#[no_mangle]
+pub unsafe fn unchecked_mul_unsigned(a: u32, b: u32) -> u32 {
+    // CHECK: mul nuw
+    unchecked_mul(a, b)
+}
diff --git a/tests/codegen/intrinsics/volatile.rs b/tests/codegen/intrinsics/volatile.rs
new file mode 100644
index 00000000000..7980c00e7e7
--- /dev/null
+++ b/tests/codegen/intrinsics/volatile.rs
@@ -0,0 +1,55 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+#![feature(core_intrinsics)]
+
+use std::intrinsics;
+
+// CHECK-LABEL: @volatile_copy_memory
+#[no_mangle]
+pub unsafe fn volatile_copy_memory(a: *mut u8, b: *const u8) {
+    // CHECK: llvm.memmove.{{\w*(.*true)}}
+    intrinsics::volatile_copy_memory(a, b, 1)
+}
+
+// CHECK-LABEL: @volatile_copy_nonoverlapping_memory
+#[no_mangle]
+pub unsafe fn volatile_copy_nonoverlapping_memory(a: *mut u8, b: *const u8) {
+    // CHECK: llvm.memcpy.{{\w*(.*true)}}
+    intrinsics::volatile_copy_nonoverlapping_memory(a, b, 1)
+}
+
+// CHECK-LABEL: @volatile_set_memory
+#[no_mangle]
+pub unsafe fn volatile_set_memory(a: *mut u8, b: u8) {
+    // CHECK: llvm.memset.{{\w*(.*true)}}
+    intrinsics::volatile_set_memory(a, b, 1)
+}
+
+// CHECK-LABEL: @volatile_load
+#[no_mangle]
+pub unsafe fn volatile_load(a: *const u8) -> u8 {
+    // CHECK: load volatile
+    intrinsics::volatile_load(a)
+}
+
+// CHECK-LABEL: @volatile_store
+#[no_mangle]
+pub unsafe fn volatile_store(a: *mut u8, b: u8) {
+    // CHECK: store volatile
+    intrinsics::volatile_store(a, b)
+}
+
+// CHECK-LABEL: @unaligned_volatile_load
+#[no_mangle]
+pub unsafe fn unaligned_volatile_load(a: *const u8) -> u8 {
+    // CHECK: load volatile
+    intrinsics::unaligned_volatile_load(a)
+}
+
+// CHECK-LABEL: @unaligned_volatile_store
+#[no_mangle]
+pub unsafe fn unaligned_volatile_store(a: *mut u8, b: u8) {
+    // CHECK: store volatile
+    intrinsics::unaligned_volatile_store(a, b)
+}
diff --git a/tests/codegen/intrinsics/volatile_order.rs b/tests/codegen/intrinsics/volatile_order.rs
new file mode 100644
index 00000000000..99469831a6c
--- /dev/null
+++ b/tests/codegen/intrinsics/volatile_order.rs
@@ -0,0 +1,18 @@
+#![crate_type = "lib"]
+#![feature(core_intrinsics)]
+
+use std::intrinsics::*;
+
+pub unsafe fn test_volatile_order() {
+    let mut a: Box<u8> = Box::new(0);
+    // CHECK: load volatile
+    let x = volatile_load(&*a);
+    // CHECK: load volatile
+    let x = volatile_load(&*a);
+    // CHECK: store volatile
+    volatile_store(&mut *a, 12);
+    // CHECK: store volatile
+    unaligned_volatile_store(&mut *a, 12);
+    // CHECK: llvm.memset.p0
+    volatile_set_memory(&mut *a, 12, 1)
+}
diff --git a/tests/codegen/issues/auxiliary/static_dllimport_aux.rs b/tests/codegen/issues/auxiliary/static_dllimport_aux.rs
new file mode 100644
index 00000000000..afb0dc42f44
--- /dev/null
+++ b/tests/codegen/issues/auxiliary/static_dllimport_aux.rs
@@ -0,0 +1,13 @@
+use std::sync::atomic::{AtomicPtr, Ordering};
+
+#[inline(always)]
+pub fn memrchr() {
+    fn detect() {}
+
+    static CROSS_CRATE_STATIC_ITEM: AtomicPtr<()> = AtomicPtr::new(detect as *mut ());
+
+    unsafe {
+        let fun = CROSS_CRATE_STATIC_ITEM.load(Ordering::SeqCst);
+        std::mem::transmute::<*mut (), fn()>(fun)()
+    }
+}
diff --git a/tests/codegen/issues/issue-101048.rs b/tests/codegen/issues/issue-101048.rs
new file mode 100644
index 00000000000..efa4db93ec2
--- /dev/null
+++ b/tests/codegen/issues/issue-101048.rs
@@ -0,0 +1,13 @@
+// compile-flags: -O
+// min-llvm-version: 16
+
+#![crate_type = "lib"]
+
+#[no_mangle]
+pub fn all_zero(data: &[u64]) -> bool {
+    // CHECK-LABEL: @all_zero(
+    // CHECK: [[PHI:%.*]] = phi i1
+    // CHECK-NOT: phi i8
+    // CHECK-NOT: zext
+    data.iter().copied().fold(true, |acc, x| acc & (x == 0))
+}
diff --git a/tests/codegen/issues/issue-101082.rs b/tests/codegen/issues/issue-101082.rs
new file mode 100644
index 00000000000..2cbe99942cb
--- /dev/null
+++ b/tests/codegen/issues/issue-101082.rs
@@ -0,0 +1,17 @@
+// compile-flags: -O
+// min-llvm-version: 16
+// ignore-debug: the debug assertions get in the way
+
+#![crate_type = "lib"]
+
+#[no_mangle]
+pub fn test() -> usize {
+    // CHECK-LABEL: @test(
+    // CHECK: ret {{i64|i32}} 165
+    let values = [23, 16, 54, 3, 60, 9];
+    let mut acc = 0;
+    for item in values {
+        acc += item;
+    }
+    acc
+}
diff --git a/tests/codegen/issues/issue-101814.rs b/tests/codegen/issues/issue-101814.rs
new file mode 100644
index 00000000000..13796352c02
--- /dev/null
+++ b/tests/codegen/issues/issue-101814.rs
@@ -0,0 +1,20 @@
+// compile-flags: -O
+// min-llvm-version: 16
+// ignore-debug: the debug assertions get in the way
+
+#![crate_type = "lib"]
+
+#[no_mangle]
+pub fn test(a: [i32; 10]) -> i32 {
+    // CHECK-LABEL: @test(
+    // CHECK: [[L1:%.+]] = load i32
+    // CHECK: [[L2:%.+]] = load i32
+    // CHECK: [[R:%.+]] = add i32 [[L1]], [[L2]]
+    // CHECK: ret i32 [[R]]
+    let mut sum = 0;
+    for v in a.iter().skip(8) {
+        sum += v;
+    }
+
+    sum
+}
diff --git a/tests/codegen/issues/issue-103132.rs b/tests/codegen/issues/issue-103132.rs
new file mode 100644
index 00000000000..cc87d7cd2b9
--- /dev/null
+++ b/tests/codegen/issues/issue-103132.rs
@@ -0,0 +1,16 @@
+// compile-flags: -O -C overflow-checks
+// min-llvm-version: 16
+
+#![crate_type = "lib"]
+
+#[no_mangle]
+pub fn test(arr: &[u8], weight: u32) {
+    // CHECK-LABEL: @test(
+    // CHECK-NOT: panic
+    let weight = weight.min(256 * 256 * 256);
+
+    for x in arr {
+        assert!(weight <= 256 * 256 * 256);
+        let result = *x as u32 * weight;
+    }
+}
diff --git a/tests/codegen/issues/issue-103285-ptr-addr-overflow-check.rs b/tests/codegen/issues/issue-103285-ptr-addr-overflow-check.rs
new file mode 100644
index 00000000000..a3499babea2
--- /dev/null
+++ b/tests/codegen/issues/issue-103285-ptr-addr-overflow-check.rs
@@ -0,0 +1,16 @@
+// compile-flags: -O -C debug-assertions=yes
+
+#![crate_type = "lib"]
+#![feature(strict_provenance)]
+
+#[no_mangle]
+pub fn test(src: *const u8, dst: *const u8) -> usize {
+    // CHECK-LABEL: @test(
+    // CHECK-NOT: panic
+    let src_usize = src.addr();
+    let dst_usize = dst.addr();
+    if src_usize > dst_usize {
+        return src_usize - dst_usize;
+    }
+    return 0;
+}
diff --git a/tests/codegen/issues/issue-103327.rs b/tests/codegen/issues/issue-103327.rs
new file mode 100644
index 00000000000..cee00faccc8
--- /dev/null
+++ b/tests/codegen/issues/issue-103327.rs
@@ -0,0 +1,18 @@
+// compile-flags: -O
+// min-llvm-version: 16
+
+#![crate_type = "lib"]
+
+#[no_mangle]
+pub fn test(a: i32, b: i32) -> bool {
+    // CHECK-LABEL: @test(
+    // CHECK: ret i1 true
+    let c1 = (a >= 0) && (a <= 10);
+    let c2 = (b >= 0) && (b <= 20);
+
+    if c1 & c2 {
+        a + 100 != b
+    } else {
+        true
+    }
+}
diff --git a/tests/codegen/issues/issue-103840.rs b/tests/codegen/issues/issue-103840.rs
new file mode 100644
index 00000000000..da64692d27d
--- /dev/null
+++ b/tests/codegen/issues/issue-103840.rs
@@ -0,0 +1,10 @@
+// compile-flags: -O
+// min-llvm-version: 16.0
+#![crate_type = "lib"]
+
+pub fn foo(t: &mut Vec<usize>) {
+    // CHECK-NOT: __rust_dealloc
+    let mut taken = std::mem::take(t);
+    taken.pop();
+    *t = taken;
+}
diff --git a/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs b/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs
new file mode 100644
index 00000000000..6e0eacfe400
--- /dev/null
+++ b/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs
@@ -0,0 +1,24 @@
+// compile-flags: --crate-type=lib -O -Cdebuginfo=2 -Cno-prepopulate-passes -Zmir-enable-passes=-ScalarReplacementOfAggregates
+// MIR SROA will decompose the closure
+// min-llvm-version: 15.0 # this test uses opaque pointer notation
+#![feature(stmt_expr_attributes)]
+
+pub struct S([usize; 8]);
+
+#[no_mangle]
+pub fn outer_function(x: S, y: S) -> usize {
+    (#[inline(always)]|| {
+        let _z = x;
+        y.0[0]
+    })()
+}
+
+// Check that we do not attempt to load from the spilled arg before it is assigned to
+// when generating debuginfo.
+// CHECK-LABEL: @outer_function
+// CHECK: [[spill:%.*]] = alloca %"[closure@{{.*.rs}}:10:23: 10:25]"
+// CHECK-NOT: [[ptr_tmp:%.*]] = getelementptr inbounds %"[closure@{{.*.rs}}:10:23: 10:25]", ptr [[spill]]
+// CHECK-NOT: [[load:%.*]] = load ptr, ptr
+// CHECK: call void @llvm.lifetime.start{{.*}}({{.*}}, ptr [[spill]])
+// CHECK: [[inner:%.*]] = getelementptr inbounds %"{{.*}}", ptr [[spill]]
+// CHECK: call void @llvm.memcpy{{.*}}(ptr {{align .*}} [[inner]], ptr {{align .*}} %x
diff --git a/tests/codegen/issues/issue-106369.rs b/tests/codegen/issues/issue-106369.rs
new file mode 100644
index 00000000000..3fe7be4f144
--- /dev/null
+++ b/tests/codegen/issues/issue-106369.rs
@@ -0,0 +1,15 @@
+// compile-flags: -O
+// ignore-debug (the extra assertions get in the way)
+
+#![crate_type = "lib"]
+
+// From <https://github.com/rust-lang/rust/issues/106369#issuecomment-1369095304>
+
+// CHECK-LABEL: @issue_106369(
+#[no_mangle]
+pub unsafe fn issue_106369(ptr: *const &i32) -> bool {
+    // CHECK-NOT: icmp
+    // CHECK: ret i1 true
+    // CHECK-NOT: icmp
+    Some(std::ptr::read(ptr)).is_some()
+}
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-13018.rs b/tests/codegen/issues/issue-13018.rs
new file mode 100644
index 00000000000..b70ea1f48c8
--- /dev/null
+++ b/tests/codegen/issues/issue-13018.rs
@@ -0,0 +1,11 @@
+// compile-flags: -O
+
+// A drop([...].clone()) sequence on an Rc should be a no-op
+// In particular, no call to __rust_dealloc should be emitted
+#![crate_type = "lib"]
+use std::rc::Rc;
+
+pub fn foo(t: &Rc<Vec<usize>>) {
+// CHECK-NOT: __rust_dealloc
+    drop(t.clone());
+}
diff --git a/tests/codegen/issues/issue-15953.rs b/tests/codegen/issues/issue-15953.rs
new file mode 100644
index 00000000000..28d28428904
--- /dev/null
+++ b/tests/codegen/issues/issue-15953.rs
@@ -0,0 +1,29 @@
+// Test that llvm generates `memcpy` for moving a value
+// inside a function and moving an argument.
+
+struct Foo {
+    x: Vec<i32>,
+}
+
+#[inline(never)]
+#[no_mangle]
+// CHECK: memcpy
+fn interior(x: Vec<i32>) -> Vec<i32> {
+    let Foo { x } = Foo { x: x };
+    x
+}
+
+#[inline(never)]
+#[no_mangle]
+// CHECK: memcpy
+fn exterior(x: Vec<i32>) -> Vec<i32> {
+    x
+}
+
+fn main() {
+    let x = interior(Vec::new());
+    println!("{:?}", x);
+
+    let x = exterior(Vec::new());
+    println!("{:?}", x);
+}
diff --git a/tests/codegen/issues/issue-27130.rs b/tests/codegen/issues/issue-27130.rs
new file mode 100644
index 00000000000..e5ee94e1f45
--- /dev/null
+++ b/tests/codegen/issues/issue-27130.rs
@@ -0,0 +1,21 @@
+// compile-flags: -O
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @trim_in_place
+#[no_mangle]
+pub fn trim_in_place(a: &mut &[u8]) {
+    while a.first() == Some(&42) {
+        // CHECK-NOT: slice_index_order_fail
+        *a = &a[1..];
+    }
+}
+
+// CHECK-LABEL: @trim_in_place2
+#[no_mangle]
+pub fn trim_in_place2(a: &mut &[u8]) {
+    while let Some(&42) = a.first() {
+        // CHECK-NOT: slice_index_order_fail
+        *a = &a[2..];
+    }
+}
diff --git a/tests/codegen/issues/issue-32031.rs b/tests/codegen/issues/issue-32031.rs
new file mode 100644
index 00000000000..abef92c19b6
--- /dev/null
+++ b/tests/codegen/issues/issue-32031.rs
@@ -0,0 +1,23 @@
+// compile-flags: -C no-prepopulate-passes -Copt-level=0
+
+#![crate_type = "lib"]
+
+#[no_mangle]
+pub struct F32(f32);
+
+// CHECK: define{{.*}}float @add_newtype_f32(float %a, float %b)
+#[inline(never)]
+#[no_mangle]
+pub fn add_newtype_f32(a: F32, b: F32) -> F32 {
+    F32(a.0 + b.0)
+}
+
+#[no_mangle]
+pub struct F64(f64);
+
+// CHECK: define{{.*}}double @add_newtype_f64(double %a, double %b)
+#[inline(never)]
+#[no_mangle]
+pub fn add_newtype_f64(a: F64, b: F64) -> F64 {
+    F64(a.0 + b.0)
+}
diff --git a/tests/codegen/issues/issue-32364.rs b/tests/codegen/issues/issue-32364.rs
new file mode 100644
index 00000000000..85493a4bb73
--- /dev/null
+++ b/tests/codegen/issues/issue-32364.rs
@@ -0,0 +1,18 @@
+// Test that `extern "stdcall"` is properly translated.
+
+// only-x86
+
+// compile-flags: -C no-prepopulate-passes
+
+struct Foo;
+
+impl Foo {
+// CHECK: define internal x86_stdcallcc void @{{.*}}foo{{.*}}()
+    #[inline(never)]
+    pub extern "stdcall" fn foo<T>() {
+    }
+}
+
+fn main() {
+    Foo::foo::<Foo>();
+}
diff --git a/tests/codegen/issues/issue-34634.rs b/tests/codegen/issues/issue-34634.rs
new file mode 100644
index 00000000000..f53fa240cd1
--- /dev/null
+++ b/tests/codegen/issues/issue-34634.rs
@@ -0,0 +1,16 @@
+// Test that `wrapping_div` only checks divisor once.
+// This test checks that there is only a single compare against -1 and -1 is not present as a
+// switch case (the second check present until rustc 1.12).
+// This test also verifies that a single panic call is generated (for the division by zero case).
+
+// compile-flags: -O
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @f
+#[no_mangle]
+pub fn f(x: i32, y: i32) -> i32 {
+    // CHECK-COUNT-1: icmp eq i32 %y, -1
+    // CHECK-COUNT-1: panic
+    // CHECK-NOT: i32 -1, label
+    x.wrapping_div(y)
+}
diff --git a/tests/codegen/issues/issue-34947-pow-i32.rs b/tests/codegen/issues/issue-34947-pow-i32.rs
new file mode 100644
index 00000000000..653da8e8b5f
--- /dev/null
+++ b/tests/codegen/issues/issue-34947-pow-i32.rs
@@ -0,0 +1,13 @@
+// compile-flags: -O
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @issue_34947
+#[no_mangle]
+pub fn issue_34947(x: i32) -> i32 {
+    // CHECK: mul
+    // CHECK-NEXT: mul
+    // CHECK-NEXT: mul
+    // CHECK-NEXT: ret
+    x.pow(5)
+}
diff --git a/tests/codegen/issues/issue-37945.rs b/tests/codegen/issues/issue-37945.rs
new file mode 100644
index 00000000000..4f386d335c7
--- /dev/null
+++ b/tests/codegen/issues/issue-37945.rs
@@ -0,0 +1,35 @@
+// compile-flags: -O -Zmerge-functions=disabled
+// ignore-32bit LLVM has a bug with them
+// ignore-debug
+
+// Check that LLVM understands that `Iter` pointer is not null. Issue #37945.
+
+#![crate_type = "lib"]
+
+use std::slice::Iter;
+
+#[no_mangle]
+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:    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:    ret i1 [[B:%.*]]
+    {xs}.next().is_none()
+}
+
+#[no_mangle]
+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:    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:    ret i1 [[D:%.*]]
+    xs.map(|&x| x).next().is_none()
+}
diff --git a/tests/codegen/issues/issue-44056-macos-tls-align.rs b/tests/codegen/issues/issue-44056-macos-tls-align.rs
new file mode 100644
index 00000000000..1a3923f1bb1
--- /dev/null
+++ b/tests/codegen/issues/issue-44056-macos-tls-align.rs
@@ -0,0 +1,28 @@
+//
+// only-macos
+// no-system-llvm
+// compile-flags: -O
+
+#![crate_type = "rlib"]
+#![feature(thread_local)]
+
+// local_unnamed_addr does not appear when std is built with debug assertions.
+// CHECK: @STATIC_VAR_1 = thread_local {{(local_unnamed_addr )?}}global <{ [32 x i8] }> zeroinitializer, section "__DATA,__thread_bss", align 4
+#[no_mangle]
+#[thread_local]
+static mut STATIC_VAR_1: [u32; 8] = [0; 8];
+
+// CHECK: @STATIC_VAR_2 = thread_local {{(local_unnamed_addr )?}}global <{ [32 x i8] }> <{{[^>]*}}>, section "__DATA,__thread_data", align 4
+#[no_mangle]
+#[thread_local]
+static mut STATIC_VAR_2: [u32; 8] = [4; 8];
+
+#[no_mangle]
+pub unsafe fn f(x: &mut [u32; 8]) {
+    std::mem::swap(x, &mut STATIC_VAR_1)
+}
+
+#[no_mangle]
+pub unsafe fn g(x: &mut [u32; 8]) {
+    std::mem::swap(x, &mut STATIC_VAR_2)
+}
diff --git a/tests/codegen/issues/issue-45222.rs b/tests/codegen/issues/issue-45222.rs
new file mode 100644
index 00000000000..e9b05e648b4
--- /dev/null
+++ b/tests/codegen/issues/issue-45222.rs
@@ -0,0 +1,63 @@
+// compile-flags: -O
+// ignore-debug: the debug assertions get in the way
+
+#![crate_type = "lib"]
+
+// verify that LLVM recognizes a loop involving 0..=n and will const-fold it.
+
+// Example from original issue #45222
+
+fn foo2(n: u64) -> u64 {
+    let mut count = 0;
+    for _ in 0..n {
+        for j in (0..=n).rev() {
+            count += j;
+        }
+    }
+    count
+}
+
+// CHECK-LABEL: @check_foo2
+#[no_mangle]
+pub fn check_foo2() -> u64 {
+    // CHECK: ret i64 500005000000000
+    foo2(100000)
+}
+
+// Simplified example of #45222
+//
+// Temporarily disabled in #68835 to fix a soundness hole.
+//
+// fn triangle_inc(n: u64) -> u64 {
+//     let mut count = 0;
+//     for j in 0 ..= n {
+//         count += j;
+//     }
+//     count
+// }
+//
+// // COMMENTEDCHECK-LABEL: @check_triangle_inc
+// #[no_mangle]
+// pub fn check_triangle_inc() -> u64 {
+//     // COMMENTEDCHECK: ret i64 5000050000
+//     triangle_inc(100000)
+// }
+
+// Demo in #48012
+
+fn foo3r(n: u64) -> u64 {
+    let mut count = 0;
+    (0..n).for_each(|_| {
+        (0..=n).rev().for_each(|j| {
+            count += j;
+        })
+    });
+    count
+}
+
+// CHECK-LABEL: @check_foo3r
+#[no_mangle]
+pub fn check_foo3r() -> u64 {
+    // CHECK: ret i64 500050000000
+    foo3r(10000)
+}
diff --git a/tests/codegen/issues/issue-45466.rs b/tests/codegen/issues/issue-45466.rs
new file mode 100644
index 00000000000..c7954276777
--- /dev/null
+++ b/tests/codegen/issues/issue-45466.rs
@@ -0,0 +1,15 @@
+// compile-flags: -O
+// ignore-debug: the debug assertions get in the way
+
+#![crate_type="rlib"]
+
+// CHECK-LABEL: @memzero
+// CHECK-NOT: store
+// CHECK: call void @llvm.memset
+// CHECK-NOT: store
+#[no_mangle]
+pub fn memzero(data: &mut [u8]) {
+    for i in 0..data.len() {
+        data[i] = 0;
+    }
+}
diff --git a/tests/codegen/issues/issue-45964-bounds-check-slice-pos.rs b/tests/codegen/issues/issue-45964-bounds-check-slice-pos.rs
new file mode 100644
index 00000000000..1daa213fc82
--- /dev/null
+++ b/tests/codegen/issues/issue-45964-bounds-check-slice-pos.rs
@@ -0,0 +1,39 @@
+// This test case checks that slice::{r}position functions do not
+// prevent optimizing away bounds checks
+
+// compile-flags: -O
+// ignore-debug: the debug assertions get in the way
+
+#![crate_type="rlib"]
+
+// CHECK-LABEL: @test
+#[no_mangle]
+pub fn test(y: &[u32], x: &u32, z: &u32) -> bool {
+    let result = match y.iter().position(|a| a == x) {
+        Some(p) => Ok(p),
+        None => Err(()),
+    };
+
+    if let Ok(p) = result {
+        // CHECK-NOT: panic
+        y[p] == *z
+    } else {
+        false
+    }
+}
+
+// CHECK-LABEL: @rtest
+#[no_mangle]
+pub fn rtest(y: &[u32], x: &u32, z: &u32) -> bool {
+    let result = match y.iter().rposition(|a| a == x) {
+        Some(p) => Ok(p),
+        None => Err(()),
+    };
+
+    if let Ok(p) = result {
+        // CHECK-NOT: panic
+        y[p] == *z
+    } else {
+        false
+    }
+}
diff --git a/tests/codegen/issues/issue-47278.rs b/tests/codegen/issues/issue-47278.rs
new file mode 100644
index 00000000000..9076274f45e
--- /dev/null
+++ b/tests/codegen/issues/issue-47278.rs
@@ -0,0 +1,9 @@
+// -C no-prepopulate-passes
+#![crate_type="staticlib"]
+
+#[repr(C)]
+pub struct Foo(u64);
+
+// CHECK: define {{.*}} @foo(
+#[no_mangle]
+pub extern "C" fn foo(_: Foo) -> Foo { loop {} }
diff --git a/tests/codegen/issues/issue-47442.rs b/tests/codegen/issues/issue-47442.rs
new file mode 100644
index 00000000000..6944336d335
--- /dev/null
+++ b/tests/codegen/issues/issue-47442.rs
@@ -0,0 +1,22 @@
+// check that we don't emit unneeded `resume` cleanup blocks for every
+// destructor.
+
+// CHECK-NOT: Unwind
+
+#![feature(test)]
+#![crate_type="rlib"]
+
+extern crate test;
+
+struct Foo {}
+
+impl Drop for Foo {
+    fn drop(&mut self) {
+        test::black_box(());
+    }
+}
+
+#[no_mangle]
+pub fn foo() {
+    let _foo = Foo {};
+}
diff --git a/tests/codegen/issues/issue-56267-2.rs b/tests/codegen/issues/issue-56267-2.rs
new file mode 100644
index 00000000000..4dc9ebfebbc
--- /dev/null
+++ b/tests/codegen/issues/issue-56267-2.rs
@@ -0,0 +1,18 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type="rlib"]
+
+#[allow(dead_code)]
+pub struct Foo<T> {
+    foo: u64,
+    bar: 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
+#[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
new file mode 100644
index 00000000000..7bdd2577998
--- /dev/null
+++ b/tests/codegen/issues/issue-56267.rs
@@ -0,0 +1,18 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type="rlib"]
+
+#[allow(dead_code)]
+pub struct Foo<T> {
+    foo: u64,
+    bar: 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
+#[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
new file mode 100644
index 00000000000..044d721814b
--- /dev/null
+++ b/tests/codegen/issues/issue-56927.rs
@@ -0,0 +1,43 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type="rlib"]
+
+#[repr(align(16))]
+pub struct S {
+    arr: [u32; 4],
+}
+
+// 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
+#[no_mangle]
+pub fn test1(s: &mut S) {
+    s.arr[0] = 0;
+    s.arr[1] = 1;
+    s.arr[2] = 2;
+    s.arr[3] = 3;
+}
+
+// CHECK-LABEL: @test2
+// CHECK: store i32 4, {{i32\*|ptr}} %{{.+}}, align 4
+#[allow(unconditional_panic)]
+#[no_mangle]
+pub fn test2(s: &mut S) {
+    s.arr[usize::MAX / 4 + 1] = 4;
+}
+
+// CHECK-LABEL: @test3
+// CHECK: store i32 5, {{i32\*|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
+#[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
new file mode 100644
index 00000000000..00f8953d949
--- /dev/null
+++ b/tests/codegen/issues/issue-58881.rs
@@ -0,0 +1,21 @@
+// compile-flags: -C no-prepopulate-passes -Copt-level=0
+//
+// only-x86_64
+// ignore-windows
+
+#![crate_type = "lib"]
+
+extern "C" {
+    fn variadic_fn(_: i32, ...);
+}
+
+#[repr(C)]
+struct Foo(u8);
+#[repr(C)]
+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}} {{.*}})
+    variadic_fn(0, Foo(0), Bar(0, 0, 0))
+}
diff --git a/tests/codegen/issues/issue-59352.rs b/tests/codegen/issues/issue-59352.rs
new file mode 100644
index 00000000000..d271fe027e3
--- /dev/null
+++ b/tests/codegen/issues/issue-59352.rs
@@ -0,0 +1,18 @@
+// This test is a mirror of mir-opt/issues/issue-59352.rs. The LLVM inliner doesn't inline
+// `char::method::is_digit()` and `char::method::to_digit()`, probably because of their size.
+//
+// Currently, the MIR optimizer isn't capable of removing the unreachable panic in this test case.
+// Once the optimizer can do that, mir-opt/issues/issue-59352.rs will need to be updated and this
+// test case should be removed as it will become redundant.
+
+// mir-opt-level=3 enables inlining and enables LLVM to optimize away the unreachable panic call.
+// compile-flags: -O -Z mir-opt-level=3
+
+#![crate_type = "rlib"]
+
+// CHECK-LABEL: @num_to_digit
+#[no_mangle]
+pub fn num_to_digit(num: char) -> u32 {
+    // CHECK-NOT: panic
+    if num.is_digit(8) { num.to_digit(8).unwrap() } else { 0 }
+}
diff --git a/tests/codegen/issues/issue-69101-bounds-check.rs b/tests/codegen/issues/issue-69101-bounds-check.rs
new file mode 100644
index 00000000000..a3aca3a2912
--- /dev/null
+++ b/tests/codegen/issues/issue-69101-bounds-check.rs
@@ -0,0 +1,44 @@
+// no-system-llvm
+// compile-flags: -O
+// ignore-debug: the debug assertions get in the way
+#![crate_type = "lib"]
+
+// Make sure no bounds checks are emitted in the loop when upfront slicing
+// ensures that the slices are big enough.
+// In particular, bounds checks were not always optimized out if the upfront
+// check was for a greater len than the loop requires.
+// (i.e. `already_sliced_no_bounds_check` was not always optimized even when
+// `already_sliced_no_bounds_check_exact` was)
+// CHECK-LABEL: @already_sliced_no_bounds_check
+#[no_mangle]
+pub fn already_sliced_no_bounds_check(a: &[u8], b: &[u8], c: &mut [u8]) {
+    // CHECK: slice_end_index_len_fail
+    // CHECK-NOT: panic_bounds_check
+    let _ = (&a[..2048], &b[..2048], &mut c[..2048]);
+    for i in 0..1024 {
+        c[i] = a[i] ^ b[i];
+    }
+}
+
+// CHECK-LABEL: @already_sliced_no_bounds_check_exact
+#[no_mangle]
+pub fn already_sliced_no_bounds_check_exact(a: &[u8], b: &[u8], c: &mut [u8]) {
+    // CHECK: slice_end_index_len_fail
+    // CHECK-NOT: panic_bounds_check
+    let _ = (&a[..1024], &b[..1024], &mut c[..1024]);
+    for i in 0..1024 {
+        c[i] = a[i] ^ b[i];
+    }
+}
+
+// Make sure we're checking for the right thing: there can be a panic if the slice is too small.
+// CHECK-LABEL: @already_sliced_bounds_check
+#[no_mangle]
+pub fn already_sliced_bounds_check(a: &[u8], b: &[u8], c: &mut [u8]) {
+    // CHECK: slice_end_index_len_fail
+    // CHECK: panic_bounds_check
+    let _ = (&a[..1023], &b[..2048], &mut c[..2048]);
+    for i in 0..1024 {
+        c[i] = a[i] ^ b[i];
+    }
+}
diff --git a/tests/codegen/issues/issue-73031.rs b/tests/codegen/issues/issue-73031.rs
new file mode 100644
index 00000000000..a09c4bcfbea
--- /dev/null
+++ b/tests/codegen/issues/issue-73031.rs
@@ -0,0 +1,26 @@
+// compile-flags: -O
+#![crate_type = "lib"]
+
+// Test that LLVM can eliminate the unreachable `All::None` branch.
+
+pub enum All {
+    None,
+    Foo,
+    Bar,
+}
+
+// CHECK-LABEL: @issue_73031
+#[no_mangle]
+pub fn issue_73031(a: &mut All, q: i32) -> i32 {
+    *a = if q == 5 {
+        All::Foo
+    } else {
+        All::Bar
+    };
+    match *a {
+        // CHECK-NOT: panic
+        All::None => panic!(),
+        All::Foo => 1,
+        All::Bar => 2,
+    }
+}
diff --git a/tests/codegen/issues/issue-73258.rs b/tests/codegen/issues/issue-73258.rs
new file mode 100644
index 00000000000..0134f929b29
--- /dev/null
+++ b/tests/codegen/issues/issue-73258.rs
@@ -0,0 +1,38 @@
+// compile-flags: -O
+// ignore-debug (the extra assertions get in the way)
+
+#![crate_type = "lib"]
+
+// Adapted from <https://github.com/rust-lang/rust/issues/73258#issue-637346014>
+
+#[derive(Clone, Copy)]
+#[repr(u8)]
+pub enum Foo {
+    A, B, C, D,
+}
+
+// CHECK-LABEL: @issue_73258(
+#[no_mangle]
+pub unsafe fn issue_73258(ptr: *const Foo) -> Foo {
+    // CHECK-NOT: icmp
+    // CHECK-NOT: call
+    // CHECK-NOT: br
+    // CHECK-NOT: select
+
+    // CHECK: %[[R:.+]] = load i8
+    // CHECK-SAME: !range !
+
+    // CHECK-NOT: icmp
+    // CHECK-NOT: call
+    // CHECK-NOT: br
+    // CHECK-NOT: select
+
+    // CHECK: ret i8 %[[R]]
+
+    // CHECK-NOT: icmp
+    // CHECK-NOT: call
+    // CHECK-NOT: br
+    // CHECK-NOT: select
+    let k: Option<Foo> = Some(ptr.read());
+    return k.unwrap();
+}
diff --git a/tests/codegen/issues/issue-73338-effecient-cmp.rs b/tests/codegen/issues/issue-73338-effecient-cmp.rs
new file mode 100644
index 00000000000..85c2bbfd040
--- /dev/null
+++ b/tests/codegen/issues/issue-73338-effecient-cmp.rs
@@ -0,0 +1,39 @@
+// This test checks that comparison operation
+// generated by #[derive(PartialOrd)]
+// doesn't contain jumps for C enums
+
+// compile-flags: -Copt-level=3
+
+#![crate_type="lib"]
+
+#[repr(u32)]
+#[derive(Copy, Clone, Eq, PartialEq, PartialOrd)]
+pub enum Foo {
+    Zero,
+    One,
+    Two,
+}
+
+#[no_mangle]
+pub fn compare_less(a: Foo, b: Foo)->bool{
+    // CHECK-NOT: br {{.*}}
+    a < b
+}
+
+#[no_mangle]
+pub fn compare_le(a: Foo, b: Foo)->bool{
+    // CHECK-NOT: br {{.*}}
+    a <= b
+}
+
+#[no_mangle]
+pub fn compare_ge(a: Foo, b: Foo)->bool{
+    // CHECK-NOT: br {{.*}}
+    a >= b
+}
+
+#[no_mangle]
+pub fn compare_greater(a: Foo, b: Foo)->bool{
+    // CHECK-NOT: br {{.*}}
+    a > b
+}
diff --git a/tests/codegen/issues/issue-73396-bounds-check-after-position.rs b/tests/codegen/issues/issue-73396-bounds-check-after-position.rs
new file mode 100644
index 00000000000..2d779788791
--- /dev/null
+++ b/tests/codegen/issues/issue-73396-bounds-check-after-position.rs
@@ -0,0 +1,95 @@
+// compile-flags: -O
+// ignore-debug: the debug assertions get in the way
+#![crate_type = "lib"]
+
+// Make sure no bounds checks are emitted when slicing or indexing
+// with an index from `position()` or `rposition()`.
+
+// CHECK-LABEL: @position_slice_to_no_bounds_check
+#[no_mangle]
+pub fn position_slice_to_no_bounds_check(s: &[u8]) -> &[u8] {
+    // CHECK-NOT: panic
+    // 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 {
+        s
+    }
+}
+
+// CHECK-LABEL: @position_slice_from_no_bounds_check
+#[no_mangle]
+pub fn position_slice_from_no_bounds_check(s: &[u8]) -> &[u8] {
+    // CHECK-NOT: panic
+    // 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 {
+        s
+    }
+}
+
+// CHECK-LABEL: @position_index_no_bounds_check
+#[no_mangle]
+pub fn position_index_no_bounds_check(s: &[u8]) -> u8 {
+    // CHECK-NOT: panic
+    // 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 {
+        42
+    }
+}
+// CHECK-LABEL: @rposition_slice_to_no_bounds_check
+#[no_mangle]
+pub fn rposition_slice_to_no_bounds_check(s: &[u8]) -> &[u8] {
+    // CHECK-NOT: panic
+    // 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 {
+        s
+    }
+}
+
+// CHECK-LABEL: @rposition_slice_from_no_bounds_check
+#[no_mangle]
+pub fn rposition_slice_from_no_bounds_check(s: &[u8]) -> &[u8] {
+    // CHECK-NOT: panic
+    // 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 {
+        s
+    }
+}
+
+// CHECK-LABEL: @rposition_index_no_bounds_check
+#[no_mangle]
+pub fn rposition_index_no_bounds_check(s: &[u8]) -> u8 {
+    // CHECK-NOT: panic
+    // 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 {
+        42
+    }
+}
diff --git a/tests/codegen/issues/issue-73827-bounds-check-index-in-subexpr.rs b/tests/codegen/issues/issue-73827-bounds-check-index-in-subexpr.rs
new file mode 100644
index 00000000000..1ad05906e21
--- /dev/null
+++ b/tests/codegen/issues/issue-73827-bounds-check-index-in-subexpr.rs
@@ -0,0 +1,17 @@
+// This test checks that bounds checks are elided when
+// index is part of a (x | y) < C style condition
+
+// compile-flags: -O
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @get
+#[no_mangle]
+pub fn get(array: &[u8; 8], x: usize, y: usize) -> u8 {
+    if x > 7 || y > 7 {
+        0
+    } else {
+        // CHECK-NOT: panic_bounds_check
+        array[y]
+    }
+}
diff --git a/tests/codegen/issues/issue-75525-bounds-checks.rs b/tests/codegen/issues/issue-75525-bounds-checks.rs
new file mode 100644
index 00000000000..2d363d8f73b
--- /dev/null
+++ b/tests/codegen/issues/issue-75525-bounds-checks.rs
@@ -0,0 +1,26 @@
+// Regression test for #75525, verifies that no bounds checks are generated.
+
+// compile-flags: -O
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @f0
+// CHECK-NOT: panic
+#[no_mangle]
+pub fn f0(idx: usize, buf: &[u8; 10]) -> u8 {
+    if idx < 8 { buf[idx + 1] } else { 0 }
+}
+
+// CHECK-LABEL: @f1
+// CHECK-NOT: panic
+#[no_mangle]
+pub fn f1(idx: usize, buf: &[u8; 10]) -> u8 {
+    if idx > 5 && idx < 8 { buf[idx - 1] } else { 0 }
+}
+
+// CHECK-LABEL: @f2
+// CHECK-NOT: panic
+#[no_mangle]
+pub fn f2(idx: usize, buf: &[u8; 10]) -> u8 {
+    if idx > 5 && idx < 8 { buf[idx] } else { 0 }
+}
diff --git a/tests/codegen/issues/issue-75546.rs b/tests/codegen/issues/issue-75546.rs
new file mode 100644
index 00000000000..470a9e04096
--- /dev/null
+++ b/tests/codegen/issues/issue-75546.rs
@@ -0,0 +1,15 @@
+// compile-flags: -O
+#![crate_type = "lib"]
+
+// Test that LLVM can eliminate the impossible `i == 0` check.
+
+// CHECK-LABEL: @issue_75546
+#[no_mangle]
+pub fn issue_75546() {
+    let mut i = 1u32;
+    while i < u32::MAX {
+        // CHECK-NOT: panic
+        if i == 0 { panic!(); }
+        i += 1;
+    }
+}
diff --git a/tests/codegen/issues/issue-75659.rs b/tests/codegen/issues/issue-75659.rs
new file mode 100644
index 00000000000..9394868c08d
--- /dev/null
+++ b/tests/codegen/issues/issue-75659.rs
@@ -0,0 +1,63 @@
+// This test checks that the call to memchr/slice_contains is optimized away
+// when searching in small slices.
+
+// compile-flags: -O -Zinline-mir=false
+// only-x86_64
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @foo1
+#[no_mangle]
+pub fn foo1(x: u8, data: &[u8; 1]) -> bool {
+    // CHECK-NOT: memchr
+    // CHECK-NOT: slice_contains
+    data.contains(&x)
+}
+
+// CHECK-LABEL: @foo2
+#[no_mangle]
+pub fn foo2(x: u8, data: &[u8; 2]) -> bool {
+    // CHECK-NOT: memchr
+    // CHECK-NOT: slice_contains
+    data.contains(&x)
+}
+
+// CHECK-LABEL: @foo3
+#[no_mangle]
+pub fn foo3(x: u8, data: &[u8; 3]) -> bool {
+    // CHECK-NOT: memchr
+    // CHECK-NOT: slice_contains
+    data.contains(&x)
+}
+
+// CHECK-LABEL: @foo4
+#[no_mangle]
+pub fn foo4(x: u8, data: &[u8; 4]) -> bool {
+    // CHECK-NOT: memchr
+    // CHECK-NOT: slice_contains
+    data.contains(&x)
+}
+
+// CHECK-LABEL: @foo8
+#[no_mangle]
+pub fn foo8(x: u8, data: &[u8; 8]) -> bool {
+    // CHECK-NOT: memchr
+    // CHECK-NOT: slice_contains
+    data.contains(&x)
+}
+
+// CHECK-LABEL: @foo8_i8
+#[no_mangle]
+pub fn foo8_i8(x: i8, data: &[i8; 8]) -> bool {
+    // CHECK-NOT: memchr
+    // CHECK-NOT: slice_contains
+    !data.contains(&x)
+}
+
+// Check that the general case isn't inlined
+// CHECK-LABEL: @foo80
+#[no_mangle]
+pub fn foo80(x: u8, data: &[u8; 80]) -> bool {
+    // CHECK: call core::slice::memchr
+    data.contains(&x)
+}
diff --git a/tests/codegen/issues/issue-75978.rs b/tests/codegen/issues/issue-75978.rs
new file mode 100644
index 00000000000..f335e92c3dc
--- /dev/null
+++ b/tests/codegen/issues/issue-75978.rs
@@ -0,0 +1,19 @@
+// compile-flags: -O
+// min-llvm-version: 16
+
+#![crate_type = "lib"]
+
+#[no_mangle]
+pub fn test() -> u32 {
+    // CHECK-LABEL: @test(
+    // CHECK: ret i32 13
+    let s = [1, 2, 3, 4, 5, 6, 7];
+
+    let mut iter = s.iter();
+    let mut sum = 0;
+    while let Some(_) = iter.next() {
+        sum += iter.next().map_or(1, |&x| x)
+    }
+
+    sum
+}
diff --git a/tests/codegen/issues/issue-77812.rs b/tests/codegen/issues/issue-77812.rs
new file mode 100644
index 00000000000..4cc82414546
--- /dev/null
+++ b/tests/codegen/issues/issue-77812.rs
@@ -0,0 +1,32 @@
+// compile-flags: -O
+#![crate_type = "lib"]
+
+// Test that LLVM can eliminate the unreachable `Variant::Zero` branch.
+
+#[derive(Copy, Clone, Eq, PartialEq)]
+pub enum Variant {
+    Zero,
+    One,
+    Two,
+}
+
+extern {
+    fn exf1();
+    fn exf2();
+}
+
+pub static mut GLOBAL: Variant = Variant::Zero;
+
+// CHECK-LABEL: @issue_77812
+#[no_mangle]
+pub unsafe fn issue_77812() {
+    let g = GLOBAL;
+    if g != Variant::Zero {
+        match g {
+            Variant::One => exf1(),
+            Variant::Two => exf2(),
+            // CHECK-NOT: panic
+            Variant::Zero => panic!(),
+        }
+    }
+}
diff --git a/tests/codegen/issues/issue-81408-dllimport-thinlto-windows.rs b/tests/codegen/issues/issue-81408-dllimport-thinlto-windows.rs
new file mode 100644
index 00000000000..0b6ab4f7ecb
--- /dev/null
+++ b/tests/codegen/issues/issue-81408-dllimport-thinlto-windows.rs
@@ -0,0 +1,15 @@
+// compile-flags: -O -C lto=thin -C prefer-dynamic=no
+// only-windows
+// aux-build:static_dllimport_aux.rs
+
+// Test that on Windows, when performing ThinLTO, we do not mark cross-crate static items with
+// dllimport because lld does not fix the symbol names for us.
+
+extern crate static_dllimport_aux;
+
+// CHECK-LABEL: @{{.+}}CROSS_CRATE_STATIC_ITEM{{.+}} =
+// CHECK-SAME: external local_unnamed_addr global %"{{.+}}AtomicPtr
+
+pub fn main() {
+    static_dllimport_aux::memrchr();
+}
diff --git a/tests/codegen/issues/issue-84268.rs b/tests/codegen/issues/issue-84268.rs
new file mode 100644
index 00000000000..7ca19544700
--- /dev/null
+++ b/tests/codegen/issues/issue-84268.rs
@@ -0,0 +1,23 @@
+// compile-flags: -O --crate-type=rlib
+#![feature(platform_intrinsics, repr_simd)]
+
+extern "platform-intrinsic" {
+    fn simd_fabs<T>(x: T) -> T;
+    fn simd_eq<T, U>(x: T, y: T) -> U;
+}
+
+#[repr(simd)]
+pub struct V([f32; 4]);
+
+#[repr(simd)]
+pub struct M([i32; 4]);
+
+#[no_mangle]
+// CHECK-LABEL: @is_infinite
+pub fn is_infinite(v: V) -> M {
+    // CHECK: fabs
+    // CHECK: cmp oeq
+    unsafe {
+        simd_eq(simd_fabs(v), V([f32::INFINITY; 4]))
+    }
+}
diff --git a/tests/codegen/issues/issue-85872-multiple-reverse.rs b/tests/codegen/issues/issue-85872-multiple-reverse.rs
new file mode 100644
index 00000000000..591a1aca747
--- /dev/null
+++ b/tests/codegen/issues/issue-85872-multiple-reverse.rs
@@ -0,0 +1,20 @@
+// min-llvm-version: 15.0.0
+// compile-flags: -O
+
+#![crate_type = "lib"]
+
+#[no_mangle]
+pub fn u16_be_to_arch(mut data: [u8; 2]) -> [u8; 2] {
+    // CHECK-LABEL: @u16_be_to_arch
+    // CHECK: @llvm.bswap.i16
+    data.reverse();
+    data
+}
+
+#[no_mangle]
+pub fn u32_be_to_arch(mut data: [u8; 4]) -> [u8; 4] {
+    // CHECK-LABEL: @u32_be_to_arch
+    // CHECK: @llvm.bswap.i32
+    data.reverse();
+    data
+}
diff --git a/tests/codegen/issues/issue-86106.rs b/tests/codegen/issues/issue-86106.rs
new file mode 100644
index 00000000000..be5034dcfbd
--- /dev/null
+++ b/tests/codegen/issues/issue-86106.rs
@@ -0,0 +1,51 @@
+// 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()`
+// produce the identical code.
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: define {{(dso_local )?}}void @string_new
+#[no_mangle]
+pub fn string_new() -> String {
+    // CHECK: store ptr inttoptr
+    // CHECK-NEXT: getelementptr
+    // CHECK-NEXT: call void @llvm.memset
+    // CHECK-NEXT: ret void
+    String::new()
+}
+
+// CHECK-LABEL: define {{(dso_local )?}}void @empty_to_string
+#[no_mangle]
+pub fn empty_to_string() -> String {
+    // CHECK: store ptr inttoptr
+    // CHECK-NEXT: getelementptr
+    // CHECK-NEXT: call void @llvm.memset
+    // CHECK-NEXT: ret void
+    "".to_string()
+}
+
+// The below two functions ensure that both `vec![]` and `vec![].clone()`
+// produce the identical code.
+
+// CHECK-LABEL: @empty_vec
+#[no_mangle]
+pub fn empty_vec() -> Vec<u8> {
+    // CHECK: store ptr inttoptr
+    // CHECK-NEXT: getelementptr
+    // CHECK-NEXT: call void @llvm.memset
+    // CHECK-NEXT: ret void
+    vec![]
+}
+
+// CHECK-LABEL: @empty_vec_clone
+#[no_mangle]
+pub fn empty_vec_clone() -> Vec<u8> {
+    // CHECK: store ptr inttoptr
+    // CHECK-NEXT: getelementptr
+    // 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
new file mode 100644
index 00000000000..28bfcce0d7b
--- /dev/null
+++ b/tests/codegen/issues/issue-96274.rs
@@ -0,0 +1,17 @@
+// min-llvm-version: 15.0
+// compile-flags: -O
+
+#![crate_type = "lib"]
+#![feature(inline_const)]
+
+use std::mem::MaybeUninit;
+
+pub fn maybe_uninit() -> [MaybeUninit<u8>; 3000] {
+    // CHECK-NOT: memset
+    [MaybeUninit::uninit(); 3000]
+}
+
+pub fn maybe_uninit_const<T>() -> [MaybeUninit<T>; 8192] {
+    // CHECK-NOT: memset
+    [const { MaybeUninit::uninit() }; 8192]
+}
diff --git a/tests/codegen/issues/issue-96497-slice-size-nowrap.rs b/tests/codegen/issues/issue-96497-slice-size-nowrap.rs
new file mode 100644
index 00000000000..0413ed6b26f
--- /dev/null
+++ b/tests/codegen/issues/issue-96497-slice-size-nowrap.rs
@@ -0,0 +1,29 @@
+// This test case checks that LLVM is aware that computing the size of a slice cannot wrap.
+// The possibility of wrapping results in an additional branch when dropping boxed slices
+// 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"]
+
+// CHECK-LABEL: @simple_size_of_nowrap
+#[no_mangle]
+pub fn simple_size_of_nowrap(x: &[u32]) -> usize {
+    // Make sure the shift used to compute the size has a nowrap flag.
+
+    // CHECK: [[A:%.*]] = shl nsw {{.*}}, 2
+    // CHECK-NEXT: ret {{.*}} [[A]]
+    core::mem::size_of_val(x)
+}
+
+// CHECK-LABEL: @drop_write
+#[no_mangle]
+pub fn drop_write(mut x: Box<[u32]>) {
+    // Check that this write is optimized out.
+    // This depends on the size calculation not wrapping,
+    // since otherwise LLVM can't tell that the memory is always deallocated if the slice len > 0.
+
+    // CHECK-NOT: store i32 42
+    x[1] = 42;
+}
diff --git a/tests/codegen/issues/issue-98156-const-arg-temp-lifetime.rs b/tests/codegen/issues/issue-98156-const-arg-temp-lifetime.rs
new file mode 100644
index 00000000000..12ace5fff6b
--- /dev/null
+++ b/tests/codegen/issues/issue-98156-const-arg-temp-lifetime.rs
@@ -0,0 +1,27 @@
+// This test checks that temporaries for indirectly-passed arguments get lifetime markers.
+
+// compile-flags: -O -C no-prepopulate-passes -Zmir-opt-level=0
+
+#![crate_type = "lib"]
+
+extern "Rust" {
+    fn f(x: [u8; 1024]);
+}
+
+const A: [u8; 1024] = [0; 1024];
+
+// CHECK-LABEL: @const_arg_indirect
+#[no_mangle]
+pub unsafe fn const_arg_indirect() {
+    // Ensure that the live ranges for the two argument temporaries don't overlap.
+
+    // CHECK: call void @llvm.lifetime.start
+    // CHECK: call void @f
+    // CHECK: call void @llvm.lifetime.end
+    // CHECK: call void @llvm.lifetime.start
+    // CHECK: call void @f
+    // CHECK: call void @llvm.lifetime.end
+
+    f(A);
+    f(A);
+}
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
new file mode 100644
index 00000000000..7da29cd7952
--- /dev/null
+++ b/tests/codegen/issues/issue-98294-get-mut-copy-from-slice-opt.rs
@@ -0,0 +1,19 @@
+// min-llvm-version: 15.0.0
+// ignore-debug: The debug assertions get in the way
+// compile-flags: -O
+
+#![crate_type = "lib"]
+
+// There should be no calls to panic / len_mismatch_fail.
+
+#[no_mangle]
+pub fn test(a: &mut [u8], offset: usize, bytes: &[u8]) {
+    // CHECK-LABEL: @test(
+    // CHECK-NOT: call
+    // CHECK: call void @llvm.memcpy
+    // CHECK-NOT: call
+    // CHECK: }
+    if let Some(dst) = a.get_mut(offset..offset + bytes.len()) {
+        dst.copy_from_slice(bytes);
+    }
+}
diff --git a/tests/codegen/issues/issue-99960.rs b/tests/codegen/issues/issue-99960.rs
new file mode 100644
index 00000000000..e9c9367fa64
--- /dev/null
+++ b/tests/codegen/issues/issue-99960.rs
@@ -0,0 +1,15 @@
+// compile-flags: -O
+// min-llvm-version: 16
+
+#![crate_type = "lib"]
+
+#[no_mangle]
+pub fn test(dividend: i64, divisor: i64) -> Option<i64> {
+    // CHECK-LABEL: @test(
+    // CHECK-NOT: panic
+    if dividend > i64::min_value() && divisor != 0 {
+        Some(dividend / divisor)
+    } else {
+        None
+    }
+}
diff --git a/tests/codegen/iter-repeat-n-trivial-drop.rs b/tests/codegen/iter-repeat-n-trivial-drop.rs
new file mode 100644
index 00000000000..24059f190ac
--- /dev/null
+++ b/tests/codegen/iter-repeat-n-trivial-drop.rs
@@ -0,0 +1,56 @@
+// compile-flags: -O
+// only-x86_64
+// ignore-debug: the debug assertions get in the way
+
+#![crate_type = "lib"]
+#![feature(iter_repeat_n)]
+
+#[derive(Clone)]
+pub struct NotCopy(u16);
+
+impl Drop for NotCopy {
+    fn drop(&mut self) {}
+}
+
+// For a type where `Drop::drop` doesn't do anything observable and a clone is the
+// same as a move, make sure that the extra case for the last item disappears.
+
+#[no_mangle]
+// CHECK-LABEL: @iter_repeat_n_next
+pub fn iter_repeat_n_next(it: &mut std::iter::RepeatN<NotCopy>) -> Option<NotCopy> {
+    // CHECK-NEXT: start:
+    // CHECK-NOT: br
+    // CHECK: %[[COUNT:.+]] = load i64
+    // CHECK-NEXT: %[[COUNT_ZERO:.+]] = icmp eq i64 %[[COUNT]], 0
+    // CHECK-NEXT: br i1 %[[COUNT_ZERO]], label %[[EMPTY:.+]], label %[[NOT_EMPTY:.+]]
+
+    // CHECK: [[NOT_EMPTY]]:
+    // CHECK-NEXT: %[[DEC:.+]] = add i64 %[[COUNT]], -1
+    // CHECK-NEXT: store i64 %[[DEC]]
+    // CHECK-NOT: br
+    // CHECK: %[[VAL:.+]] = load i16
+    // CHECK-NEXT: br label %[[EMPTY]]
+
+    // CHECK: [[EMPTY]]:
+    // CHECK-NOT: br
+    // CHECK: phi i16 [ undef, %start ], [ %[[VAL]], %[[NOT_EMPTY]] ]
+    // CHECK-NOT: br
+    // CHECK: ret
+
+    it.next()
+}
+
+// And as a result, using the iterator can optimize without special cases for
+// the last iteration, like `memset`ing all the items in one call.
+
+#[no_mangle]
+// CHECK-LABEL: @vec_extend_via_iter_repeat_n
+pub fn vec_extend_via_iter_repeat_n() -> Vec<u8> {
+    // CHECK: %[[ADDR:.+]] = tail call noundef dereferenceable_or_null(1234) ptr @__rust_alloc(i64 noundef 1234, i64 noundef 1)
+    // CHECK: tail call void @llvm.memset.p0.i64(ptr noundef nonnull align 1 dereferenceable(1234) %[[ADDR]], i8 42, i64 1234,
+
+    let n = 1234_usize;
+    let mut v = Vec::with_capacity(n);
+    v.extend(std::iter::repeat_n(42_u8, n));
+    v
+}
diff --git a/tests/codegen/layout-size-checks.rs b/tests/codegen/layout-size-checks.rs
new file mode 100644
index 00000000000..d067cc10a94
--- /dev/null
+++ b/tests/codegen/layout-size-checks.rs
@@ -0,0 +1,31 @@
+// compile-flags: -O
+// only-x86_64
+// ignore-debug: the debug assertions get in the way
+
+#![crate_type = "lib"]
+
+use std::alloc::Layout;
+
+type RGB48 = [u16; 3];
+
+// CHECK-LABEL: @layout_array_rgb48
+#[no_mangle]
+pub fn layout_array_rgb48(n: usize) -> Layout {
+    // CHECK-NOT: llvm.umul.with.overflow.i64
+    // CHECK: icmp ugt i64 %n, 1537228672809129301
+    // CHECK-NOT: llvm.umul.with.overflow.i64
+    // CHECK: mul nuw nsw i64 %n, 6
+    // CHECK-NOT: llvm.umul.with.overflow.i64
+    Layout::array::<RGB48>(n).unwrap()
+}
+
+// CHECK-LABEL: @layout_array_i32
+#[no_mangle]
+pub fn layout_array_i32(n: usize) -> Layout {
+    // CHECK-NOT: llvm.umul.with.overflow.i64
+    // CHECK: icmp ugt i64 %n, 2305843009213693951
+    // CHECK-NOT: llvm.umul.with.overflow.i64
+    // CHECK: shl nuw nsw i64 %n, 2
+    // CHECK-NOT: llvm.umul.with.overflow.i64
+    Layout::array::<i32>(n).unwrap()
+}
diff --git a/tests/codegen/lifetime_start_end.rs b/tests/codegen/lifetime_start_end.rs
new file mode 100644
index 00000000000..471a0b8cedd
--- /dev/null
+++ b/tests/codegen/lifetime_start_end.rs
@@ -0,0 +1,34 @@
+// compile-flags: -O -C no-prepopulate-passes -Zmir-opt-level=0
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @test
+#[no_mangle]
+pub fn test() {
+    let a = 0u8;
+    &a; // keep variable in an alloca
+
+// CHECK: call void @llvm.lifetime.start{{.*}}(i{{[0-9 ]+}}, {{i8\*|ptr}} %a)
+
+    {
+        let b = &Some(a);
+        &b; // keep variable in an alloca
+
+// CHECK: call void @llvm.lifetime.start{{.*}}(i{{[0-9 ]+}}, {{.*}})
+
+// CHECK: call void @llvm.lifetime.start{{.*}}(i{{[0-9 ]+}}, {{.*}})
+
+// CHECK: call void @llvm.lifetime.end{{.*}}(i{{[0-9 ]+}}, {{.*}})
+
+// CHECK: call void @llvm.lifetime.end{{.*}}(i{{[0-9 ]+}}, {{.*}})
+    }
+
+    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.end{{.*}}(i{{[0-9 ]+}}, {{i8\*|ptr}} %c)
+
+// CHECK: call void @llvm.lifetime.end{{.*}}(i{{[0-9 ]+}}, {{i8\*|ptr}} %a)
+}
diff --git a/tests/codegen/link-dead-code.rs b/tests/codegen/link-dead-code.rs
new file mode 100644
index 00000000000..de5a237c5f8
--- /dev/null
+++ b/tests/codegen/link-dead-code.rs
@@ -0,0 +1,22 @@
+// compile-flags:-Clink-dead-code
+
+#![crate_type = "rlib"]
+
+// This test makes sure that, when -Clink-dead-code is specified, we generate
+// code for functions that would otherwise be skipped.
+
+// CHECK-LABEL: ; link_dead_code::const_fn
+// CHECK-NEXT: ; Function Attrs:
+// CHECK-NEXT: define hidden
+const fn const_fn() -> i32 { 1 }
+
+// CHECK-LABEL: ; link_dead_code::inline_fn
+// CHECK-NEXT: ; Function Attrs:
+// CHECK-NEXT: define hidden
+#[inline]
+fn inline_fn() -> i32 { 2 }
+
+// CHECK-LABEL: ; link_dead_code::private_fn
+// CHECK-NEXT: ; Function Attrs:
+// CHECK-NEXT: define hidden
+fn private_fn() -> i32 { 3 }
diff --git a/tests/codegen/link_section.rs b/tests/codegen/link_section.rs
new file mode 100644
index 00000000000..2b26b604ad3
--- /dev/null
+++ b/tests/codegen/link_section.rs
@@ -0,0 +1,35 @@
+// ignore-emscripten default visibility is hidden
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+// 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")]
+pub static VAR1: u32 = 1;
+
+#[no_mangle]
+#[link_section = ".test_one"]
+#[cfg(target_endian = "big")]
+pub static VAR1: u32 = 0x01000000;
+
+pub enum E {
+    A(u32),
+    B(f32)
+}
+
+// CHECK: @VAR2 = {{(dso_local )?}}constant {{.*}}, section ".test_two"
+#[no_mangle]
+#[link_section = ".test_two"]
+pub static VAR2: E = E::A(666);
+
+// CHECK: @VAR3 = {{(dso_local )?}}constant {{.*}}, section ".test_three"
+#[no_mangle]
+#[link_section = ".test_three"]
+pub static VAR3: E = E::B(1.);
+
+// CHECK: define {{(dso_local )?}}void @fn1() {{.*}} section ".test_four" {
+#[no_mangle]
+#[link_section = ".test_four"]
+pub fn fn1() {}
diff --git a/tests/codegen/loads.rs b/tests/codegen/loads.rs
new file mode 100644
index 00000000000..f29a26596bf
--- /dev/null
+++ b/tests/codegen/loads.rs
@@ -0,0 +1,152 @@
+// compile-flags: -C no-prepopulate-passes -Zmir-opt-level=0
+
+#![crate_type = "lib"]
+
+use std::mem::MaybeUninit;
+use std::num::NonZeroU16;
+
+pub struct Bytes {
+    a: u8,
+    b: u8,
+    c: u8,
+    d: u8,
+}
+
+#[derive(Copy, Clone)]
+pub enum MyBool {
+    True,
+    False,
+}
+
+#[repr(align(16))]
+pub struct Align16(u128);
+
+// CHECK: @ptr_alignment_helper({{.*}}align [[PTR_ALIGNMENT:[0-9]+]]
+#[no_mangle]
+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]+}}
+    *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]+}}
+    *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]+}}
+    *x
+}
+
+// CHECK-LABEL: @load_raw_pointer
+#[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]+]]{{$}}
+    *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]+}}
+    *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]+}}
+    *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{{$}}
+    *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]+}}
+    *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{{$}}
+    *x
+}
+
+// CHECK-LABEL: @load_int
+#[no_mangle]
+pub fn load_int(x: &u16) -> u16 {
+    // CHECK: load i16, {{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]+}}
+    *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]]{{$}}
+    *x
+}
+
+// CHECK-LABEL: @borrow
+#[no_mangle]
+pub fn borrow(x: &i32) -> &i32 {
+    // CHECK: load {{i32\*|ptr}}, {{i32\*\*|ptr}} %x{{.*}}, !nonnull
+    &x; // keep variable in an alloca
+    x
+}
+
+// CHECK-LABEL: @_box
+#[no_mangle]
+pub fn _box(x: Box<i32>) -> i32 {
+    // CHECK: load {{i32\*|ptr}}, {{i32\*\*|ptr}} %x{{.*}}, align [[PTR_ALIGNMENT]]
+    *x
+}
+
+// CHECK-LABEL: small_array_alignment
+// The array is loaded as i32, but its alignment is lower, go with 1 byte to avoid target
+// 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: ret i32 [[VAR]]
+    x
+}
+
+// CHECK-LABEL: small_struct_alignment
+// The struct is loaded as i32, but its alignment is lower, go with 1 byte to avoid target
+// dependent alignment
+#[no_mangle]
+pub fn small_struct_alignment(x: Bytes) -> Bytes {
+    // CHECK: [[VAR:%[0-9]+]] = load i32, {{i32\*|ptr}} %{{.*}}, align 1
+    // CHECK: ret i32 [[VAR]]
+    x
+}
+
+// CHECK-DAG: ![[BOOL_RANGE]] = !{i8 0, i8 2}
+// CHECK-DAG: ![[NONZEROU16_RANGE]] = !{i16 1, i16 0}
+// CHECK-DAG: ![[ALIGN_4_META]] = !{i64 4}
+// CHECK-DAG: ![[ALIGN_16_META]] = !{i64 16}
diff --git a/tests/codegen/local-generics-in-exe-internalized.rs b/tests/codegen/local-generics-in-exe-internalized.rs
new file mode 100644
index 00000000000..449c5ca75fc
--- /dev/null
+++ b/tests/codegen/local-generics-in-exe-internalized.rs
@@ -0,0 +1,14 @@
+// compile-flags: -C no-prepopulate-passes -Zshare-generics=yes -Zinline-mir=no
+
+// Check that local generics are internalized if they are in the same CGU
+
+// CHECK-LABEL: ; local_generics_in_exe_internalized::foo
+// CHECK-NEXT: ; Function Attrs:
+// CHECK-NEXT: define internal
+pub fn foo<T>(x: T, y: T) -> (T, T) {
+    (x, y)
+}
+
+fn main() {
+    let _ = foo(0u8, 1u8);
+}
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/lto-removes-invokes.rs b/tests/codegen/lto-removes-invokes.rs
new file mode 100644
index 00000000000..3979a97dc01
--- /dev/null
+++ b/tests/codegen/lto-removes-invokes.rs
@@ -0,0 +1,21 @@
+// compile-flags: -C lto -C panic=abort -O
+// no-prefer-dynamic
+
+fn main() {
+    foo();
+}
+
+#[no_mangle]
+#[inline(never)]
+fn foo() {
+    let _a = Box::new(3);
+    bar();
+// CHECK-LABEL: define dso_local void @foo
+// CHECK: call void @bar
+}
+
+#[inline(never)]
+#[no_mangle]
+fn bar() {
+    println!("hello!");
+}
diff --git a/tests/codegen/mainsubprogram.rs b/tests/codegen/mainsubprogram.rs
new file mode 100644
index 00000000000..790db33437b
--- /dev/null
+++ b/tests/codegen/mainsubprogram.rs
@@ -0,0 +1,13 @@
+// This test depends on a patch that was committed to upstream LLVM
+// before 4.0, formerly backported to the Rust LLVM fork.
+
+// ignore-windows
+// ignore-macos
+
+// compile-flags: -g -C no-prepopulate-passes
+
+// CHECK-LABEL: @main
+// CHECK: {{.*}}DISubprogram{{.*}}name: "main",{{.*}}DI{{(SP)?}}FlagMainSubprogram{{.*}}
+
+pub fn main() {
+}
diff --git a/tests/codegen/mainsubprogramstart.rs b/tests/codegen/mainsubprogramstart.rs
new file mode 100644
index 00000000000..d4de9f59ac2
--- /dev/null
+++ b/tests/codegen/mainsubprogramstart.rs
@@ -0,0 +1,14 @@
+// ignore-windows
+// ignore-macos
+
+// compile-flags: -g -C no-prepopulate-passes
+
+#![feature(start)]
+
+// CHECK-LABEL: @main
+// CHECK: {{.*}}DISubprogram{{.*}}name: "start",{{.*}}DI{{(SP)?}}FlagMainSubprogram{{.*}}
+
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
+    return 0;
+}
diff --git a/tests/codegen/match-optimized.rs b/tests/codegen/match-optimized.rs
new file mode 100644
index 00000000000..59e6eeb7c5d
--- /dev/null
+++ b/tests/codegen/match-optimized.rs
@@ -0,0 +1,60 @@
+// compile-flags: -C no-prepopulate-passes -O
+
+#![crate_type = "lib"]
+
+pub enum E {
+    A,
+    B,
+    C,
+}
+
+// CHECK-LABEL: @exhaustive_match
+#[no_mangle]
+pub fn exhaustive_match(e: E) -> u8 {
+// CHECK: switch{{.*}}, label %[[OTHERWISE:[a-zA-Z0-9_]+]] [
+// CHECK-NEXT: i[[TY:[0-9]+]] [[DISCR:[0-9]+]], label %[[A:[a-zA-Z0-9_]+]]
+// CHECK-NEXT: i[[TY:[0-9]+]] [[DISCR:[0-9]+]], label %[[B:[a-zA-Z0-9_]+]]
+// CHECK-NEXT: i[[TY:[0-9]+]] [[DISCR:[0-9]+]], label %[[C:[a-zA-Z0-9_]+]]
+// CHECK-NEXT: ]
+// CHECK: [[OTHERWISE]]:
+// CHECK-NEXT: unreachable
+//
+// CHECK: [[A]]:
+// CHECK-NEXT: store i8 0, {{i8\*|ptr}} %_0, align 1
+// CHECK-NEXT: br label %[[EXIT:[a-zA-Z0-9_]+]]
+// CHECK: [[B]]:
+// CHECK-NEXT: store i8 1, {{i8\*|ptr}} %_0, align 1
+// CHECK-NEXT: br label %[[EXIT]]
+// CHECK: [[C]]:
+// CHECK-NEXT: store i8 2, {{i8\*|ptr}} %_0, align 1
+// CHECK-NEXT: br label %[[EXIT]]
+    match e {
+        E::A => 0,
+        E::B => 1,
+        E::C => 2,
+    }
+}
+
+#[repr(u16)]
+pub enum E2 {
+    A = 13,
+    B = 42,
+}
+
+// For optimized code we produce a switch with an unreachable target as the `otherwise` so LLVM
+// knows the possible values. Compare with `tests/codegen/match-unoptimized.rs`.
+
+// CHECK-LABEL: @exhaustive_match_2
+#[no_mangle]
+pub fn exhaustive_match_2(e: E2) -> u8 {
+    // CHECK: switch i16 %{{.+}}, label %[[UNREACH:.+]] [
+    // CHECK-NEXT: i16 13,
+    // CHECK-NEXT: i16 42,
+    // CHECK-NEXT: ]
+    // CHECK: [[UNREACH]]:
+    // CHECK-NEXT: unreachable
+    match e {
+        E2::A => 0,
+        E2::B => 1,
+    }
+}
diff --git a/tests/codegen/match-optimizes-away.rs b/tests/codegen/match-optimizes-away.rs
new file mode 100644
index 00000000000..8f66c518ccf
--- /dev/null
+++ b/tests/codegen/match-optimizes-away.rs
@@ -0,0 +1,34 @@
+//
+// no-system-llvm
+// compile-flags: -O
+#![crate_type="lib"]
+
+pub enum Three { A, B, C }
+
+#[repr(u16)]
+pub enum Four { A, B, C, D }
+
+#[no_mangle]
+pub fn three_valued(x: Three) -> Three {
+    // CHECK-LABEL: @three_valued
+    // CHECK-NEXT: {{^.*:$}}
+    // CHECK-NEXT: ret i8 %0
+    match x {
+        Three::A => Three::A,
+        Three::B => Three::B,
+        Three::C => Three::C,
+    }
+}
+
+#[no_mangle]
+pub fn four_valued(x: Four) -> Four {
+    // CHECK-LABEL: @four_valued
+    // CHECK-NEXT: {{^.*:$}}
+    // CHECK-NEXT: ret i16 %0
+    match x {
+        Four::A => Four::A,
+        Four::B => Four::B,
+        Four::C => Four::C,
+        Four::D => Four::D,
+    }
+}
diff --git a/tests/codegen/match-unoptimized.rs b/tests/codegen/match-unoptimized.rs
new file mode 100644
index 00000000000..78ea4f9b409
--- /dev/null
+++ b/tests/codegen/match-unoptimized.rs
@@ -0,0 +1,23 @@
+// compile-flags: -C no-prepopulate-passes -Copt-level=0
+
+#![crate_type = "lib"]
+
+#[repr(u16)]
+pub enum E2 {
+    A = 13,
+    B = 42,
+}
+
+// For unoptimized code we produce a `br` instead of a `switch`. Compare with
+// `tests/codegen/match-optimized.rs`
+
+// CHECK-LABEL: @exhaustive_match_2
+#[no_mangle]
+pub fn exhaustive_match_2(e: E2) -> u8 {
+    // CHECK: %[[CMP:.+]] = icmp eq i16 %{{.+}}, 13
+    // CHECK-NEXT: br i1 %[[CMP:.+]],
+    match e {
+        E2::A => 0,
+        E2::B => 1,
+    }
+}
diff --git a/tests/codegen/mem-replace-big-type.rs b/tests/codegen/mem-replace-big-type.rs
new file mode 100644
index 00000000000..55c2741faaf
--- /dev/null
+++ b/tests/codegen/mem-replace-big-type.rs
@@ -0,0 +1,33 @@
+// 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"]
+
+#[repr(C, align(8))]
+pub struct Big([u64; 7]);
+pub fn replace_big(dst: &mut Big, src: Big) -> Big {
+    // 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)
+}
+
+// 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 large type, we expect exactly three `memcpy`s
+// CHECK-LABEL: define internal void @{{.+}}mem{{.+}}replace{{.+}}sret(%Big)
+// CHECK-NOT: call void @llvm.memcpy
+// CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 8 %result, {{i8\*|ptr}} align 8 %dest, i{{.*}} 56, i1 false)
+// CHECK-NOT: call void @llvm.memcpy
+// CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 8 %dest, {{i8\*|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-simple-type.rs b/tests/codegen/mem-replace-simple-type.rs
new file mode 100644
index 00000000000..5c4acf813ea
--- /dev/null
+++ b/tests/codegen/mem-replace-simple-type.rs
@@ -0,0 +1,45 @@
+// compile-flags: -O -C no-prepopulate-passes
+// min-llvm-version: 15.0 (for opaque pointers)
+// 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/merge-functions.rs b/tests/codegen/merge-functions.rs
new file mode 100644
index 00000000000..d6caeeee896
--- /dev/null
+++ b/tests/codegen/merge-functions.rs
@@ -0,0 +1,16 @@
+// revisions: O Os
+//[Os] compile-flags: -Copt-level=s
+//[O] compile-flags: -O
+#![crate_type = "lib"]
+
+// CHECK: @func{{2|1}} = {{.*}}alias{{.*}}@func{{1|2}}
+
+#[no_mangle]
+pub fn func1(c: char) -> bool {
+    c == 's' || c == 'm' || c == 'h' || c == 'd' || c == 'w'
+}
+
+#[no_mangle]
+pub fn func2(c: char) -> bool {
+    matches!(c, 's' | 'm' | 'h' | 'd' | 'w')
+}
diff --git a/tests/codegen/mir-inlined-line-numbers.rs b/tests/codegen/mir-inlined-line-numbers.rs
new file mode 100644
index 00000000000..d13527b9521
--- /dev/null
+++ b/tests/codegen/mir-inlined-line-numbers.rs
@@ -0,0 +1,25 @@
+// compile-flags: -O -g
+
+#![crate_type = "lib"]
+
+#[inline(always)]
+fn foo() {
+    bar();
+}
+
+#[inline(never)]
+#[no_mangle]
+fn bar() {
+    panic!();
+}
+
+#[no_mangle]
+pub fn example() {
+    foo();
+}
+
+// CHECK-LABEL: @example
+// 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/mir_zst_stores.rs b/tests/codegen/mir_zst_stores.rs
new file mode 100644
index 00000000000..17e7ba3093b
--- /dev/null
+++ b/tests/codegen/mir_zst_stores.rs
@@ -0,0 +1,17 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+use std::marker::PhantomData;
+
+#[derive(Copy, Clone)]
+struct Zst { phantom: PhantomData<Zst> }
+
+// CHECK-LABEL: @mir
+// CHECK-NOT: store{{.*}}undef
+#[no_mangle]
+pub fn mir() {
+    let x = Zst { phantom: PhantomData };
+    let y = (x, 0);
+    drop(y);
+    drop((0, x));
+}
diff --git a/tests/codegen/move-operands.rs b/tests/codegen/move-operands.rs
new file mode 100644
index 00000000000..1d8209e8ea5
--- /dev/null
+++ b/tests/codegen/move-operands.rs
@@ -0,0 +1,12 @@
+// compile-flags: -C no-prepopulate-passes -Zmir-enable-passes=+DestinationPropagation,-CopyProp
+
+#![crate_type = "lib"]
+
+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)
+    b(a, a)
+}
diff --git a/tests/codegen/naked-functions.rs b/tests/codegen/naked-functions.rs
new file mode 100644
index 00000000000..e05bbc26e83
--- /dev/null
+++ b/tests/codegen/naked-functions.rs
@@ -0,0 +1,32 @@
+// compile-flags: -C no-prepopulate-passes -Copt-level=0
+// needs-asm-support
+// only-x86_64
+
+#![crate_type = "lib"]
+#![feature(naked_functions)]
+use std::arch::asm;
+
+// CHECK: Function Attrs: naked
+// CHECK-NEXT: define{{.*}}void @naked_empty()
+#[no_mangle]
+#[naked]
+pub unsafe extern "C" fn naked_empty() {
+    // CHECK-NEXT: {{.+}}:
+    // CHECK-NEXT: call void asm
+    // CHECK-NEXT: unreachable
+    asm!("ret",
+         options(noreturn));
+}
+
+// CHECK: Function Attrs: naked
+// CHECK-NEXT: define{{.*}}i{{[0-9]+}} @naked_with_args_and_return(i64 %a, i64 %b)
+#[no_mangle]
+#[naked]
+pub unsafe extern "C" fn naked_with_args_and_return(a: isize, b: isize) -> isize {
+    // CHECK-NEXT: {{.+}}:
+    // CHECK-NEXT: call void asm
+    // CHECK-NEXT: unreachable
+    asm!("lea rax, [rdi + rsi]",
+         "ret",
+         options(noreturn));
+}
diff --git a/tests/codegen/naked-nocoverage.rs b/tests/codegen/naked-nocoverage.rs
new file mode 100644
index 00000000000..3c755e49c6d
--- /dev/null
+++ b/tests/codegen/naked-nocoverage.rs
@@ -0,0 +1,19 @@
+// Checks that naked functions are not instrumented by -Cinstrument-coverage.
+// Regression test for issue #105170.
+//
+// needs-asm-support
+// needs-profiler-support
+// compile-flags: -Cinstrument-coverage
+#![crate_type = "lib"]
+#![feature(naked_functions)]
+use std::arch::asm;
+
+#[naked]
+#[no_mangle]
+pub unsafe extern "C" fn f() {
+    // CHECK:       define {{(dso_local )?}}void @f()
+    // CHECK-NEXT:  start:
+    // CHECK-NEXT:    call void asm
+    // CHECK-NEXT:    unreachable
+    asm!("", options(noreturn));
+}
diff --git a/tests/codegen/naked-noinline.rs b/tests/codegen/naked-noinline.rs
new file mode 100644
index 00000000000..5cfb500c0ef
--- /dev/null
+++ b/tests/codegen/naked-noinline.rs
@@ -0,0 +1,31 @@
+// Checks that naked functions are never inlined.
+// compile-flags: -O -Zmir-opt-level=3
+// needs-asm-support
+// ignore-wasm32
+#![crate_type = "lib"]
+#![feature(naked_functions)]
+
+use std::arch::asm;
+
+#[naked]
+#[no_mangle]
+pub unsafe extern "C" fn f() {
+    // Check that f has naked and noinline attributes.
+    //
+    // CHECK:       define {{(dso_local )?}}void @f() unnamed_addr [[ATTR:#[0-9]+]]
+    // CHECK-NEXT:  start:
+    // CHECK-NEXT:    call void asm
+    asm!("", options(noreturn));
+}
+
+#[no_mangle]
+pub unsafe fn g() {
+    // Check that call to f is not inlined.
+    //
+    // CHECK-LABEL: define {{(dso_local )?}}void @g()
+    // CHECK-NEXT:  start:
+    // CHECK-NEXT:    call void @f()
+    f();
+}
+
+// CHECK: attributes [[ATTR]] = { naked{{.*}}noinline{{.*}} }
diff --git a/tests/codegen/no-assumes-on-casts.rs b/tests/codegen/no-assumes-on-casts.rs
new file mode 100644
index 00000000000..b5cfa2775ab
--- /dev/null
+++ b/tests/codegen/no-assumes-on-casts.rs
@@ -0,0 +1,19 @@
+#![crate_type = "lib"]
+
+// compile-flags: -Cno-prepopulate-passes
+
+// CHECK-LABEL: fna
+#[no_mangle]
+pub fn fna(a: i16) -> i32 {
+    a as i32
+// CHECK-NOT: assume
+// CHECK: sext
+}
+
+// CHECK-LABEL: fnb
+#[no_mangle]
+pub fn fnb(a: u16) -> u32 {
+    a as u32
+// CHECK-NOT: assume
+// CHECK: zext
+}
diff --git a/tests/codegen/no-dllimport-w-cross-lang-lto.rs b/tests/codegen/no-dllimport-w-cross-lang-lto.rs
new file mode 100644
index 00000000000..33fc2bc1540
--- /dev/null
+++ b/tests/codegen/no-dllimport-w-cross-lang-lto.rs
@@ -0,0 +1,13 @@
+// This test makes sure that functions get annotated with the proper
+// "target-cpu" attribute in LLVM.
+
+// no-prefer-dynamic
+// only-msvc
+// compile-flags: -C linker-plugin-lto
+
+#![crate_type = "rlib"]
+
+// CHECK-NOT: @{{.*}}__imp_{{.*}}GLOBAL{{.*}} = global i8*
+
+pub static GLOBAL: u32 = 0;
+pub static mut GLOBAL2: u32 = 0;
diff --git a/tests/codegen/no-jump-tables.rs b/tests/codegen/no-jump-tables.rs
new file mode 100644
index 00000000000..8e2cb47566e
--- /dev/null
+++ b/tests/codegen/no-jump-tables.rs
@@ -0,0 +1,22 @@
+// Test that the `no-jump-tables` function attribute are (not) emitted when
+// the `-Zno-jump-tables` flag is (not) set.
+
+// revisions: unset set
+// needs-llvm-components: x86
+// compile-flags: --target x86_64-unknown-linux-gnu
+// [set] compile-flags: -Zno-jump-tables
+
+#![crate_type = "lib"]
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+
+#[no_mangle]
+pub fn foo() {
+    // CHECK: @foo() unnamed_addr #0
+
+    // unset-NOT: attributes #0 = { {{.*}}"no-jump-tables"="true"{{.*}} }
+    // set: attributes #0 = { {{.*}}"no-jump-tables"="true"{{.*}} }
+}
diff --git a/tests/codegen/no-plt.rs b/tests/codegen/no-plt.rs
new file mode 100644
index 00000000000..b36e9ae88f4
--- /dev/null
+++ b/tests/codegen/no-plt.rs
@@ -0,0 +1,17 @@
+// compile-flags: -C relocation-model=pic -Z plt=no
+
+#![crate_type = "lib"]
+
+// We need a function which is normally called through the PLT.
+extern "C" {
+    // CHECK: Function Attrs:{{.*}}nonlazybind
+    fn getenv(name: *const u8) -> *mut u8;
+}
+
+// Ensure the function gets referenced.
+pub unsafe fn call_through_plt() -> *mut u8 {
+    getenv(b"\0".as_ptr())
+}
+
+// Ensure intrinsics also skip the PLT
+// CHECK: !"RtLibUseGOT"
diff --git a/tests/codegen/noalias-box-off.rs b/tests/codegen/noalias-box-off.rs
new file mode 100644
index 00000000000..c82c53b2a48
--- /dev/null
+++ b/tests/codegen/noalias-box-off.rs
@@ -0,0 +1,11 @@
+// compile-flags: -O -Z box-noalias=no
+
+#![crate_type = "lib"]
+
+// 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(foo: Box<u8>) {
+    drop(foo);
+}
diff --git a/tests/codegen/noalias-box.rs b/tests/codegen/noalias-box.rs
new file mode 100644
index 00000000000..a3d1f093d8b
--- /dev/null
+++ b/tests/codegen/noalias-box.rs
@@ -0,0 +1,8 @@
+// compile-flags: -O
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @box_should_have_noalias_by_default(
+// CHECK: noalias
+#[no_mangle]
+pub fn box_should_have_noalias_by_default(_b: Box<u8>) {}
diff --git a/tests/codegen/noalias-flag.rs b/tests/codegen/noalias-flag.rs
new file mode 100644
index 00000000000..a9ec61e286d
--- /dev/null
+++ b/tests/codegen/noalias-flag.rs
@@ -0,0 +1,23 @@
+// compile-flags: -O -Zmutable-noalias=no
+
+#![crate_type = "lib"]
+
+// `-Zmutable-noalias=no` should disable noalias on mut refs...
+
+// CHECK-LABEL: @test_mut_ref(
+// CHECK-NOT: noalias
+// CHECK-SAME: %x
+#[no_mangle]
+pub fn test_mut_ref(x: &mut i32) -> &mut i32 {
+    x
+}
+
+// ...but not on shared refs
+
+// CHECK-LABEL: @test_ref(
+// CHECK-SAME: noalias
+// CHECK-SAME: %x
+#[no_mangle]
+pub fn test_ref(x: &i32) -> &i32 {
+    x
+}
diff --git a/tests/codegen/noalias-refcell.rs b/tests/codegen/noalias-refcell.rs
new file mode 100644
index 00000000000..dba73937abf
--- /dev/null
+++ b/tests/codegen/noalias-refcell.rs
@@ -0,0 +1,14 @@
+// compile-flags: -O -C no-prepopulate-passes -Z mutable-noalias=yes
+
+#![crate_type = "lib"]
+
+use std::cell::{Ref, RefCell, RefMut};
+
+// Make sure that none of the arguments get a `noalias` attribute, because
+// the `RefCell` might alias writes after either `Ref`/`RefMut` is dropped.
+
+// CHECK-LABEL: @maybe_aliased(
+// CHECK-NOT: noalias
+// CHECK-SAME: %_refcell
+#[no_mangle]
+pub unsafe fn maybe_aliased(_: Ref<'_, i32>, _: RefMut<'_, i32>, _refcell: &RefCell<i32>) {}
diff --git a/tests/codegen/noalias-rwlockreadguard.rs b/tests/codegen/noalias-rwlockreadguard.rs
new file mode 100644
index 00000000000..7f7b46c85a8
--- /dev/null
+++ b/tests/codegen/noalias-rwlockreadguard.rs
@@ -0,0 +1,14 @@
+// compile-flags: -O -C no-prepopulate-passes -Z mutable-noalias=yes
+
+#![crate_type = "lib"]
+
+use std::sync::{RwLock, RwLockReadGuard};
+
+// Make sure that `RwLockReadGuard` does not get a `noalias` attribute, because
+// the `RwLock` might alias writes after it is dropped.
+
+// CHECK-LABEL: @maybe_aliased(
+// CHECK-NOT: noalias
+// CHECK-SAME: %_data
+#[no_mangle]
+pub unsafe fn maybe_aliased(_: RwLockReadGuard<'_, i32>, _data: &RwLock<i32>) {}
diff --git a/tests/codegen/noalias-unpin.rs b/tests/codegen/noalias-unpin.rs
new file mode 100644
index 00000000000..8ca9b98eee2
--- /dev/null
+++ b/tests/codegen/noalias-unpin.rs
@@ -0,0 +1,15 @@
+// compile-flags: -O -Z mutable-noalias=yes
+
+#![crate_type = "lib"]
+
+pub struct SelfRef {
+    self_ref: *mut SelfRef,
+    _pin: std::marker::PhantomPinned
+}
+
+// CHECK-LABEL: @test_self_ref(
+// CHECK-NOT: noalias
+#[no_mangle]
+pub unsafe fn test_self_ref(s: &mut SelfRef) {
+    (*s.self_ref).self_ref = std::ptr::null_mut();
+}
diff --git a/tests/codegen/non-terminate/infinite-loop-1.rs b/tests/codegen/non-terminate/infinite-loop-1.rs
new file mode 100644
index 00000000000..fa9c66b47c0
--- /dev/null
+++ b/tests/codegen/non-terminate/infinite-loop-1.rs
@@ -0,0 +1,17 @@
+// compile-flags: -C opt-level=3
+
+#![crate_type = "lib"]
+
+fn infinite_loop() -> u8 {
+    loop {}
+}
+
+// CHECK-LABEL: @test
+#[no_mangle]
+fn test() -> u8 {
+    // CHECK-NOT: unreachable
+    // CHECK: br label %{{.+}}
+    // CHECK-NOT: unreachable
+    let x = infinite_loop();
+    x
+}
diff --git a/tests/codegen/non-terminate/infinite-loop-2.rs b/tests/codegen/non-terminate/infinite-loop-2.rs
new file mode 100644
index 00000000000..81d62ab33d7
--- /dev/null
+++ b/tests/codegen/non-terminate/infinite-loop-2.rs
@@ -0,0 +1,19 @@
+// compile-flags: -C opt-level=3
+
+#![crate_type = "lib"]
+
+fn infinite_loop() -> u8 {
+    let i = 2;
+    while i > 1 {}
+    1
+}
+
+// CHECK-LABEL: @test
+#[no_mangle]
+fn test() -> u8 {
+    // CHECK-NOT: unreachable
+    // CHECK: br label %{{.+}}
+    // CHECK-NOT: unreachable
+    let x = infinite_loop();
+    x
+}
diff --git a/tests/codegen/non-terminate/infinite-recursion.rs b/tests/codegen/non-terminate/infinite-recursion.rs
new file mode 100644
index 00000000000..6d1f2d4bf8f
--- /dev/null
+++ b/tests/codegen/non-terminate/infinite-recursion.rs
@@ -0,0 +1,14 @@
+// compile-flags: -C opt-level=3
+
+#![crate_type = "lib"]
+
+#![allow(unconditional_recursion)]
+
+// CHECK-LABEL: @infinite_recursion
+#[no_mangle]
+fn infinite_recursion() -> u8 {
+    // CHECK-NOT: ret i8 undef
+    // CHECK: br label %{{.+}}
+    // CHECK-NOT: ret i8 undef
+    infinite_recursion()
+}
diff --git a/tests/codegen/non-terminate/nonempty-infinite-loop.rs b/tests/codegen/non-terminate/nonempty-infinite-loop.rs
new file mode 100644
index 00000000000..5e25e04fc24
--- /dev/null
+++ b/tests/codegen/non-terminate/nonempty-infinite-loop.rs
@@ -0,0 +1,28 @@
+// compile-flags: -C opt-level=3
+
+#![crate_type = "lib"]
+
+// Verify that we don't miscompile this even if rustc didn't apply the trivial loop detection to
+// insert the sideeffect intrinsic.
+
+fn infinite_loop() -> u8 {
+    let mut x = 0;
+    // CHECK-NOT: sideeffect
+    loop {
+        if x == 42 {
+            x = 0;
+        } else {
+            x = 42;
+        }
+    }
+}
+
+// CHECK-LABEL: @test
+#[no_mangle]
+fn test() -> u8 {
+    // CHECK-NOT: unreachable
+    // CHECK: br label %{{.+}}
+    // CHECK-NOT: unreachable
+    let x = infinite_loop();
+    x
+}
diff --git a/tests/codegen/noreturn-uninhabited.rs b/tests/codegen/noreturn-uninhabited.rs
new file mode 100644
index 00000000000..49f93cf62c7
--- /dev/null
+++ b/tests/codegen/noreturn-uninhabited.rs
@@ -0,0 +1,31 @@
+// compile-flags: -g -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+#[derive(Clone, Copy)]
+pub enum EmptyEnum {}
+
+#[no_mangle]
+pub fn empty(x: &EmptyEnum) -> EmptyEnum {
+    // CHECK: @empty({{.*}}) unnamed_addr #0
+    // CHECK-NOT: ret void
+    // CHECK: call void @llvm.trap()
+    // CHECK: unreachable
+    *x
+}
+
+pub struct Foo(String, EmptyEnum);
+
+#[no_mangle]
+pub fn foo(x: String, y: &EmptyEnum) -> Foo {
+    // CHECK: @foo({{.*}}) unnamed_addr #0
+    // CHECK-NOT: ret %Foo
+    // CHECK: call void @llvm.trap()
+    // CHECK: unreachable
+    Foo(x, *y)
+}
+
+// CHECK: attributes #0 = {{{.*}} noreturn {{.*}}}
+
+// CHECK: DISubprogram(name: "empty", {{.*}} DIFlagNoReturn
+// CHECK: DISubprogram(name: "foo", {{.*}} DIFlagNoReturn
diff --git a/tests/codegen/noreturnflag.rs b/tests/codegen/noreturnflag.rs
new file mode 100644
index 00000000000..95c100571ce
--- /dev/null
+++ b/tests/codegen/noreturnflag.rs
@@ -0,0 +1,22 @@
+// compile-flags: -g -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+#[no_mangle]
+pub fn foo() -> ! {
+// CHECK: @foo() unnamed_addr #0
+    loop {}
+}
+
+pub enum EmptyEnum {}
+
+#[no_mangle]
+pub fn bar() -> EmptyEnum {
+// CHECK: @bar() unnamed_addr #0
+    loop {}
+}
+
+// CHECK: attributes #0 = {{{.*}} noreturn {{.*}}}
+
+// CHECK: DISubprogram(name: "foo", {{.*}} DIFlagNoReturn
+// CHECK: DISubprogram(name: "bar", {{.*}} DIFlagNoReturn
diff --git a/tests/codegen/nounwind.rs b/tests/codegen/nounwind.rs
new file mode 100644
index 00000000000..f639c60b893
--- /dev/null
+++ b/tests/codegen/nounwind.rs
@@ -0,0 +1,16 @@
+// aux-build:nounwind.rs
+// compile-flags: -C no-prepopulate-passes -C panic=abort -C metadata=a
+// ignore-windows
+// ignore-android
+
+#![crate_type = "lib"]
+
+extern crate nounwind;
+
+#[no_mangle]
+pub fn foo() {
+    nounwind::bar();
+// CHECK: @foo() unnamed_addr #0
+// CHECK: @bar() unnamed_addr #0
+// CHECK: attributes #0 = { {{.*}}nounwind{{.*}} }
+}
diff --git a/tests/codegen/nrvo.rs b/tests/codegen/nrvo.rs
new file mode 100644
index 00000000000..b2ae99f3761
--- /dev/null
+++ b/tests/codegen/nrvo.rs
@@ -0,0 +1,17 @@
+// compile-flags: -O
+
+#![crate_type = "lib"]
+
+// Ensure that we do not call `memcpy` for the following function.
+// `memset` and `init` should be called directly on the return pointer.
+#[no_mangle]
+pub fn nrvo(init: fn(&mut [u8; 4096])) -> [u8; 4096] {
+    // CHECK-LABEL: nrvo
+    // CHECK: @llvm.memset
+    // FIXME: turn on nrvo then check-not: @llvm.memcpy
+    // CHECK: ret
+    // CHECK-EMPTY
+    let mut buf = [0; 4096];
+    init(&mut buf);
+    buf
+}
diff --git a/tests/codegen/optimize-attr-1.rs b/tests/codegen/optimize-attr-1.rs
new file mode 100644
index 00000000000..d95ba853030
--- /dev/null
+++ b/tests/codegen/optimize-attr-1.rs
@@ -0,0 +1,47 @@
+// revisions: NO-OPT SIZE-OPT SPEED-OPT
+//[NO-OPT] compile-flags: -Copt-level=0 -Ccodegen-units=1
+//[SIZE-OPT] compile-flags: -Copt-level=s -Ccodegen-units=1
+//[SPEED-OPT] compile-flags: -Copt-level=3 -Ccodegen-units=1
+
+#![feature(optimize_attribute)]
+#![crate_type="rlib"]
+
+// CHECK-LABEL: define{{.*}}i32 @nothing
+// CHECK-SAME: [[NOTHING_ATTRS:#[0-9]+]]
+// SIZE-OPT: ret i32 4
+// SPEED-OPT: ret i32 4
+#[no_mangle]
+pub fn nothing() -> i32 {
+    2 + 2
+}
+
+// CHECK-LABEL: define{{.*}}i32 @size
+// CHECK-SAME: [[SIZE_ATTRS:#[0-9]+]]
+// SIZE-OPT: ret i32 6
+// SPEED-OPT: ret i32 6
+#[optimize(size)]
+#[no_mangle]
+pub fn size() -> i32 {
+    3 + 3
+}
+
+// CHECK-LABEL: define{{.*}}i32 @speed
+// NO-OPT-SAME: [[NOTHING_ATTRS]]
+// SPEED-OPT-SAME: [[NOTHING_ATTRS]]
+// SIZE-OPT-SAME: [[SPEED_ATTRS:#[0-9]+]]
+// SIZE-OPT: ret i32 8
+// SPEED-OPT: ret i32 8
+#[optimize(speed)]
+#[no_mangle]
+pub fn speed() -> i32 {
+    4 + 4
+}
+
+// NO-OPT-DAG: attributes [[SIZE_ATTRS]] = {{.*}}minsize{{.*}}optsize{{.*}}
+// SPEED-OPT-DAG: attributes [[SIZE_ATTRS]] = {{.*}}minsize{{.*}}optsize{{.*}}
+// SIZE-OPT-DAG: attributes [[NOTHING_ATTRS]] = {{.*}}optsize{{.*}}
+// SIZE-OPT-DAG: attributes [[SIZE_ATTRS]] = {{.*}}minsize{{.*}}optsize{{.*}}
+
+// SIZE-OPT: attributes [[SPEED_ATTRS]]
+// SIZE-OPT-NOT: minsize
+// SIZE-OPT-NOT: optsize
diff --git a/tests/codegen/option-as-slice.rs b/tests/codegen/option-as-slice.rs
new file mode 100644
index 00000000000..1edd9ba9f7d
--- /dev/null
+++ b/tests/codegen/option-as-slice.rs
@@ -0,0 +1,38 @@
+// compile-flags: -O -Z randomize-layout=no
+// only-x86_64
+// ignore-llvm-version: 16.0.0
+// ^ needs https://reviews.llvm.org/D146149 in 16.0.1
+
+#![crate_type = "lib"]
+#![feature(option_as_slice)]
+
+extern crate core;
+
+use core::num::NonZeroU64;
+use core::option::Option;
+
+// CHECK-LABEL: @u64_opt_as_slice
+#[no_mangle]
+pub fn u64_opt_as_slice(o: &Option<u64>) -> &[u64] {
+    // CHECK-NOT: select
+    // CHECK-NOT: br
+    // CHECK-NOT: switch
+    // CHECK-NOT: icmp
+    o.as_slice()
+}
+
+// CHECK-LABEL: @nonzero_u64_opt_as_slice
+#[no_mangle]
+pub fn nonzero_u64_opt_as_slice(o: &Option<NonZeroU64>) -> &[NonZeroU64] {
+    // CHECK-NOT: select
+    // CHECK-NOT: br
+    // CHECK-NOT: switch
+    // CHECK-NOT: icmp
+    // CHECK: %[[NZ:.+]] = icmp ne i64 %{{.+}}, 0
+    // CHECK-NEXT: zext i1 %[[NZ]] to i64
+    // CHECK-NOT: select
+    // CHECK-NOT: br
+    // CHECK-NOT: switch
+    // CHECK-NOT: icmp
+    o.as_slice()
+}
diff --git a/tests/codegen/option-nonzero-eq.rs b/tests/codegen/option-nonzero-eq.rs
new file mode 100644
index 00000000000..a394695f3bd
--- /dev/null
+++ b/tests/codegen/option-nonzero-eq.rs
@@ -0,0 +1,38 @@
+// compile-flags: -O -Zmerge-functions=disabled
+
+#![crate_type = "lib"]
+
+extern crate core;
+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 {
+    // CHECK: start:
+    // CHECK-NEXT: icmp eq i32
+    // CHECK-NEXT: ret i1
+    l == r
+}
+
+// CHECK-lABEL: @non_zero_signed_eq
+#[no_mangle]
+pub fn non_zero_signed_eq(l: Option<NonZeroI64>, r: Option<NonZeroI64>) -> bool {
+    // CHECK: start:
+    // CHECK-NEXT: icmp eq i64
+    // CHECK-NEXT: ret i1
+    l == r
+}
+
+// CHECK-lABEL: @non_null_eq
+#[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
+}
diff --git a/tests/codegen/packed.rs b/tests/codegen/packed.rs
new file mode 100644
index 00000000000..fd63b4f0acd
--- /dev/null
+++ b/tests/codegen/packed.rs
@@ -0,0 +1,153 @@
+//
+// compile-flags: -O -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+#[repr(packed)]
+pub struct Packed1 {
+    dealign: u8,
+    data: u32
+}
+
+#[repr(packed(2))]
+pub struct Packed2 {
+    dealign: u8,
+    data: u32
+}
+
+// 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
+    let result = pkd.data;
+    pkd.data = 42;
+    result
+}
+
+// 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
+    let result = pkd.data;
+    pkd.data = 42;
+    result
+}
+
+pub struct Array([i32; 8]);
+#[repr(packed)]
+pub struct BigPacked1 {
+    dealign: u8,
+    data: Array
+}
+
+#[repr(packed(2))]
+pub struct BigPacked2 {
+    dealign: u8,
+    data: Array
+}
+
+// CHECK-LABEL: @call_pkd1
+#[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 that calls whose destination is a field of a packed struct
+    // go through an alloca rather than calling the function with an
+    // unaligned destination.
+    BigPacked1 { dealign: 0, data: f() }
+}
+
+// CHECK-LABEL: @call_pkd2
+#[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 that calls whose destination is a field of a packed struct
+    // go through an alloca rather than calling the function with an
+    // unaligned destination.
+    BigPacked2 { dealign: 0, data: f() }
+}
+
+// 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
+#[no_mangle]
+pub fn write_packed_array1(p: &mut BigPacked1) {
+    p.data.0[0] = 0;
+    p.data.0[1] = 1;
+    p.data.0[2] = 2;
+}
+
+// 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
+#[no_mangle]
+pub fn write_packed_array2(p: &mut BigPacked2) {
+    p.data.0[0] = 0;
+    p.data.0[1] = 1;
+    p.data.0[2] = 2;
+}
+
+// CHECK-LABEL: @repeat_packed_array1
+// CHECK: store i32 42, {{i32\*|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
+#[no_mangle]
+pub fn repeat_packed_array2(p: &mut BigPacked2) {
+    p.data.0 = [42; 8];
+}
+
+#[repr(packed)]
+#[derive(Copy, Clone)]
+pub struct Packed1Pair(u8, u32);
+
+#[repr(packed(2))]
+#[derive(Copy, Clone)]
+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)
+    *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)
+    *pair2 = *pair1;
+}
+
+#[repr(packed)]
+#[derive(Copy, Clone)]
+pub struct Packed1NestedPair((u32, u32));
+
+#[repr(packed(2))]
+#[derive(Copy, Clone)]
+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)
+    *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)
+    *pair2 = *pair1;
+}
diff --git a/tests/codegen/panic-abort-windows.rs b/tests/codegen/panic-abort-windows.rs
new file mode 100644
index 00000000000..2ee29762dcd
--- /dev/null
+++ b/tests/codegen/panic-abort-windows.rs
@@ -0,0 +1,18 @@
+// This test is for *-windows only.
+// only-windows
+
+// compile-flags: -C no-prepopulate-passes -C panic=abort -O
+
+#![crate_type = "lib"]
+
+// CHECK: Function Attrs: nounwind uwtable
+// CHECK-NEXT: define void @normal_uwtable()
+#[no_mangle]
+pub fn normal_uwtable() {
+}
+
+// CHECK: Function Attrs: nounwind uwtable
+// CHECK-NEXT: define void @extern_uwtable()
+#[no_mangle]
+pub extern fn extern_uwtable() {
+}
diff --git a/tests/codegen/panic-in-drop-abort.rs b/tests/codegen/panic-in-drop-abort.rs
new file mode 100644
index 00000000000..7a84484c419
--- /dev/null
+++ b/tests/codegen/panic-in-drop-abort.rs
@@ -0,0 +1,57 @@
+// compile-flags: -Z panic-in-drop=abort -O
+// ignore-msvc
+
+// Ensure that unwinding code paths are eliminated from the output after
+// optimization.
+
+// This test uses ignore-msvc, because the expected optimization does not happen on targets using
+// SEH exceptions with the new LLVM pass manager anymore, see
+// https://github.com/llvm/llvm-project/issues/51311.
+
+// CHECK-NOT: {{(call|invoke).*}}should_not_appear_in_output
+
+#![crate_type = "lib"]
+use std::any::Any;
+use std::mem::forget;
+
+pub struct ExternDrop;
+impl Drop for ExternDrop {
+    #[inline(always)]
+    fn drop(&mut self) {
+        // This call may potentially unwind.
+        extern "Rust" {
+            fn extern_drop();
+        }
+        unsafe {
+            extern_drop();
+        }
+    }
+}
+
+struct AssertNeverDrop;
+impl Drop for AssertNeverDrop {
+    #[inline(always)]
+    fn drop(&mut self) {
+        // This call should be optimized away as unreachable.
+        extern "C" {
+            fn should_not_appear_in_output();
+        }
+        unsafe {
+            should_not_appear_in_output();
+        }
+    }
+}
+
+#[no_mangle]
+pub fn normal_drop(x: ExternDrop) {
+    let guard = AssertNeverDrop;
+    drop(x);
+    forget(guard);
+}
+
+#[no_mangle]
+pub fn indirect_drop(x: Box<dyn Any>) {
+    let guard = AssertNeverDrop;
+    drop(x);
+    forget(guard);
+}
diff --git a/tests/codegen/panic-unwind-default-uwtable.rs b/tests/codegen/panic-unwind-default-uwtable.rs
new file mode 100644
index 00000000000..4c85008cf35
--- /dev/null
+++ b/tests/codegen/panic-unwind-default-uwtable.rs
@@ -0,0 +1,6 @@
+// compile-flags: -C panic=unwind -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+// CHECK: attributes #{{.*}} uwtable
+pub fn foo() {}
diff --git a/tests/codegen/personality_lifetimes.rs b/tests/codegen/personality_lifetimes.rs
new file mode 100644
index 00000000000..9ff7a9b3e88
--- /dev/null
+++ b/tests/codegen/personality_lifetimes.rs
@@ -0,0 +1,33 @@
+// ignore-msvc
+// ignore-wasm32-bare compiled with panic=abort by default
+// needs-unwind
+
+// compile-flags: -O -C no-prepopulate-passes
+
+#![crate_type="lib"]
+
+struct S;
+
+impl Drop for S {
+    fn drop(&mut self) {
+    }
+}
+
+fn might_unwind() {
+}
+
+// CHECK-LABEL: @test
+#[no_mangle]
+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-LABEL: cleanup:
+    // CHECK: call void @llvm.lifetime.start.{{.*}}({{.*}})
+    // CHECK-LABEL: cleanup1:
+    // CHECK: call void @llvm.lifetime.start.{{.*}}({{.*}})
+    might_unwind();
+    let _t = S;
+    might_unwind();
+}
diff --git a/tests/codegen/pgo-counter-bias.rs b/tests/codegen/pgo-counter-bias.rs
new file mode 100644
index 00000000000..28caa7f4aa3
--- /dev/null
+++ b/tests/codegen/pgo-counter-bias.rs
@@ -0,0 +1,10 @@
+// Test that __llvm_profile_counter_bias does not get internalized by lto.
+
+// ignore-macos -runtime-counter-relocation not honored on Mach-O
+// compile-flags: -Cprofile-generate -Cllvm-args=-runtime-counter-relocation -Clto=fat
+// needs-profiler-support
+// no-prefer-dynamic
+
+// CHECK: @__llvm_profile_counter_bias = {{.*}}global
+
+pub fn main() {}
diff --git a/tests/codegen/pgo-instrumentation.rs b/tests/codegen/pgo-instrumentation.rs
new file mode 100644
index 00000000000..05c2d2fc0d8
--- /dev/null
+++ b/tests/codegen/pgo-instrumentation.rs
@@ -0,0 +1,22 @@
+// Test that `-Cprofile-generate` creates expected instrumentation artifacts in LLVM IR.
+
+// needs-profiler-support
+// compile-flags: -Cprofile-generate -Ccodegen-units=1
+
+// CHECK: @__llvm_profile_raw_version =
+// CHECK-DAG: @__profc_{{.*}}pgo_instrumentation{{.*}}some_function{{.*}} = {{.*}}global
+// CHECK-DAG: @__profd_{{.*}}pgo_instrumentation{{.*}}some_function{{.*}} = {{.*}}global
+// CHECK-DAG: @__profc_{{.*}}pgo_instrumentation{{.*}}some_other_function{{.*}} = {{.*}}global
+// CHECK-DAG: @__profd_{{.*}}pgo_instrumentation{{.*}}some_other_function{{.*}} = {{.*}}global
+// CHECK: @__llvm_profile_filename = {{.*}}"default_%m.profraw\00"{{.*}}
+
+#![crate_type="lib"]
+
+#[inline(never)]
+fn some_function() {
+
+}
+
+pub fn some_other_function() {
+    some_function();
+}
diff --git a/tests/codegen/pic-relocation-model.rs b/tests/codegen/pic-relocation-model.rs
new file mode 100644
index 00000000000..518e949ffe3
--- /dev/null
+++ b/tests/codegen/pic-relocation-model.rs
@@ -0,0 +1,19 @@
+// compile-flags: -C relocation-model=pic -Copt-level=0
+
+#![crate_type = "rlib"]
+
+// CHECK: define i8 @call_foreign_fn()
+#[no_mangle]
+pub fn call_foreign_fn() -> u8 {
+    unsafe {
+        foreign_fn()
+    }
+}
+
+// (Allow but do not require `zeroext` here, because it is not worth effort to
+// spell out which targets have it and which ones do not; see rust#97800.)
+
+// CHECK: declare{{( zeroext)?}} i8 @foreign_fn()
+extern "C" {fn foreign_fn() -> u8;}
+
+// CHECK: !{i32 {{[78]}}, !"PIC Level", i32 2}
diff --git a/tests/codegen/pie-relocation-model.rs b/tests/codegen/pie-relocation-model.rs
new file mode 100644
index 00000000000..941cca922bd
--- /dev/null
+++ b/tests/codegen/pie-relocation-model.rs
@@ -0,0 +1,22 @@
+// compile-flags: -C relocation-model=pie -Copt-level=0
+// only-x86_64-unknown-linux-gnu
+
+#![crate_type = "rlib"]
+
+// With PIE we know local functions cannot be interpositioned, we can mark them
+// as dso_local.
+// CHECK: define dso_local i8 @call_foreign_fn()
+#[no_mangle]
+pub fn call_foreign_fn() -> u8 {
+    unsafe {
+        foreign_fn()
+    }
+}
+
+// External functions are still marked as non-dso_local, since we don't know if the symbol
+// is defined in the binary or in the shared library.
+// CHECK: declare zeroext i8 @foreign_fn()
+extern "C" {fn foreign_fn() -> u8;}
+
+// CHECK: !{i32 {{[78]}}, !"PIC Level", i32 2}
+// CHECK: !{i32 7, !"PIE Level", i32 2}
diff --git a/tests/codegen/ptr-read-metadata.rs b/tests/codegen/ptr-read-metadata.rs
new file mode 100644
index 00000000000..73d1db6df27
--- /dev/null
+++ b/tests/codegen/ptr-read-metadata.rs
@@ -0,0 +1,96 @@
+// compile-flags: -O -Z merge-functions=disabled
+// no-system-llvm
+// ignore-debug (the extra assertions get in the way)
+
+#![crate_type = "lib"]
+
+// Ensure that various forms of reading pointers correctly annotate the `load`s
+// with `!noundef` and `!range` metadata to enable extra optimization.
+
+use std::mem::MaybeUninit;
+
+// CHECK-LABEL: define {{(dso_local )?}}noundef i8 @copy_byte(
+#[no_mangle]
+pub unsafe fn copy_byte(p: *const u8) -> u8 {
+    // CHECK-NOT: load
+    // CHECK: load i8, ptr %p, align 1
+    // CHECK-SAME: !noundef !
+    // CHECK-NOT: load
+    *p
+}
+
+// CHECK-LABEL: define {{(dso_local )?}}noundef i8 @read_byte(
+#[no_mangle]
+pub unsafe fn read_byte(p: *const u8) -> u8 {
+    // CHECK-NOT: load
+    // CHECK: load i8, ptr %p, align 1
+    // CHECK-SAME: !noundef !
+    // CHECK-NOT: load
+    p.read()
+}
+
+// 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
+    // CHECK: load i8, ptr %p, align 1
+    // CHECK-NOT: noundef
+    // CHECK-NOT: load
+    p.read()
+}
+
+// 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
+    // CHECK: load i8, ptr %p, align 1
+    // CHECK-SAME: !noundef !
+    // CHECK-NOT: load
+    p.assume_init_read()
+}
+
+// CHECK-LABEL: define {{(dso_local )?}}noundef i32 @copy_char(
+#[no_mangle]
+pub unsafe fn copy_char(p: *const char) -> char {
+    // CHECK-NOT: load
+    // CHECK: load i32, ptr %p
+    // CHECK-SAME: !range ![[RANGE:[0-9]+]]
+    // CHECK-SAME: !noundef !
+    // CHECK-NOT: load
+    *p
+}
+
+// CHECK-LABEL: define {{(dso_local )?}}noundef i32 @read_char(
+#[no_mangle]
+pub unsafe fn read_char(p: *const char) -> char {
+    // CHECK-NOT: load
+    // CHECK: load i32, ptr %p
+    // CHECK-SAME: !range ![[RANGE]]
+    // CHECK-SAME: !noundef !
+    // CHECK-NOT: load
+    p.read()
+}
+
+// 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
+    // CHECK: load i32, ptr %p
+    // CHECK-NOT: range
+    // CHECK-NOT: noundef
+    // CHECK-NOT: load
+    p.read()
+}
+
+// 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
+    // CHECK: load i32, ptr %p
+    // CHECK-SAME: !range ![[RANGE]]
+    // CHECK-SAME: !noundef !
+    // CHECK-NOT: load
+    p.assume_init_read()
+}
+
+// CHECK: ![[RANGE]] = !{i32 0, i32 1114112}
diff --git a/tests/codegen/refs.rs b/tests/codegen/refs.rs
new file mode 100644
index 00000000000..a5289766711
--- /dev/null
+++ b/tests/codegen/refs.rs
@@ -0,0 +1,23 @@
+// compile-flags: -C no-prepopulate-passes -Zmir-opt-level=0 -Copt-level=0
+
+#![crate_type = "lib"]
+
+// Hack to get the correct size for the length part in slices
+// CHECK: @helper([[USIZE:i[0-9]+]] %_1)
+#[no_mangle]
+pub fn helper(_: usize) {
+}
+
+// CHECK-LABEL: @ref_dst
+#[no_mangle]
+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: store [[USIZE]] %s.1, {{.*}} [[X1]]
+
+    let x = &*s;
+    &x; // keep variable in an alloca
+}
diff --git a/tests/codegen/remap_path_prefix/aux_mod.rs b/tests/codegen/remap_path_prefix/aux_mod.rs
new file mode 100644
index 00000000000..44cc4bb722d
--- /dev/null
+++ b/tests/codegen/remap_path_prefix/aux_mod.rs
@@ -0,0 +1,6 @@
+// ignore-test: this is not a test
+
+#[inline]
+pub fn some_aux_mod_function() -> i32 {
+    1234
+}
diff --git a/tests/codegen/remap_path_prefix/auxiliary/remap_path_prefix_aux.rs b/tests/codegen/remap_path_prefix/auxiliary/remap_path_prefix_aux.rs
new file mode 100644
index 00000000000..887915955b5
--- /dev/null
+++ b/tests/codegen/remap_path_prefix/auxiliary/remap_path_prefix_aux.rs
@@ -0,0 +1,8 @@
+//
+
+// compile-flags: -g  --remap-path-prefix={{cwd}}=/the/aux-cwd --remap-path-prefix={{src-base}}/remap_path_prefix/auxiliary=/the/aux-src
+
+#[inline]
+pub fn some_aux_function() -> i32 {
+    1234
+}
diff --git a/tests/codegen/remap_path_prefix/auxiliary/xcrate-generic.rs b/tests/codegen/remap_path_prefix/auxiliary/xcrate-generic.rs
new file mode 100644
index 00000000000..15bd0f17421
--- /dev/null
+++ b/tests/codegen/remap_path_prefix/auxiliary/xcrate-generic.rs
@@ -0,0 +1,8 @@
+//
+// compile-flags: -g  --remap-path-prefix={{cwd}}=/the/aux-cwd --remap-path-prefix={{src-base}}/remap_path_prefix/auxiliary=/the/aux-src
+
+#![crate_type = "lib"]
+
+pub fn foo<T: Default>() -> T {
+    T::default()
+}
diff --git a/tests/codegen/remap_path_prefix/issue-73167-remap-std.rs b/tests/codegen/remap_path_prefix/issue-73167-remap-std.rs
new file mode 100644
index 00000000000..b66abc6bedf
--- /dev/null
+++ b/tests/codegen/remap_path_prefix/issue-73167-remap-std.rs
@@ -0,0 +1,15 @@
+// ignore-windows
+
+// compile-flags: -g  -C no-prepopulate-passes -Z simulate-remapped-rust-src-base=/rustc/xyz
+
+// Here we check that importing std will not cause real path to std source files
+// to leak. If rustc was compiled with remap-debuginfo = true, this should be
+// true automatically. If paths to std library hasn't been remapped, we use the
+// above simulate-remapped-rust-src-base option to do it temporarily
+
+// CHECK: !DIFile(filename: "{{/rustc/.*/library/std/src/panic.rs}}"
+fn main() {
+    std::thread::spawn(|| {
+        println!("hello");
+    });
+}
diff --git a/tests/codegen/remap_path_prefix/main.rs b/tests/codegen/remap_path_prefix/main.rs
new file mode 100644
index 00000000000..f1e1dd69b96
--- /dev/null
+++ b/tests/codegen/remap_path_prefix/main.rs
@@ -0,0 +1,28 @@
+// ignore-windows
+//
+
+// compile-flags: -g  -C no-prepopulate-passes --remap-path-prefix={{cwd}}=/the/cwd --remap-path-prefix={{src-base}}=/the/src -Zinline-mir=no
+// aux-build:remap_path_prefix_aux.rs
+
+extern crate remap_path_prefix_aux;
+
+// Here we check that submodules and include files are found using the path without
+// remapping. This test requires that rustc is called with an absolute path.
+mod aux_mod;
+include!("aux_mod.rs");
+
+// Here we check that the expansion of the file!() macro is mapped.
+// CHECK: @alloc_5761061597a97f66e13ef2ff92712c4b = private unnamed_addr constant <{ [34 x i8] }> <{ [34 x i8] c"/the/src/remap_path_prefix/main.rs" }>
+pub static FILE_PATH: &'static str = file!();
+
+fn main() {
+    remap_path_prefix_aux::some_aux_function();
+    aux_mod::some_aux_mod_function();
+    some_aux_mod_function();
+}
+
+// Here we check that local debuginfo is mapped correctly.
+// CHECK: !DIFile(filename: "/the/src/remap_path_prefix/main.rs", directory: ""
+
+// And here that debuginfo from other crates are expanded to absolute paths.
+// CHECK: !DIFile(filename: "/the/aux-src/remap_path_prefix_aux.rs", directory: ""
diff --git a/tests/codegen/remap_path_prefix/xcrate-generic.rs b/tests/codegen/remap_path_prefix/xcrate-generic.rs
new file mode 100644
index 00000000000..399deec1fc9
--- /dev/null
+++ b/tests/codegen/remap_path_prefix/xcrate-generic.rs
@@ -0,0 +1,14 @@
+// ignore-windows
+// compile-flags: -g -C metadata=foo -C no-prepopulate-passes
+// aux-build:xcrate-generic.rs
+
+#![crate_type = "lib"]
+
+extern crate xcrate_generic;
+
+pub fn foo() {
+    println!("{}", xcrate_generic::foo::<u32>());
+}
+
+// Here we check that local debuginfo is mapped correctly.
+// CHECK: !DIFile(filename: "/the/aux-src/xcrate-generic.rs", directory: ""
diff --git a/tests/codegen/repeat-trusted-len.rs b/tests/codegen/repeat-trusted-len.rs
new file mode 100644
index 00000000000..d06978f2435
--- /dev/null
+++ b/tests/codegen/repeat-trusted-len.rs
@@ -0,0 +1,20 @@
+// compile-flags: -O
+//
+
+#![crate_type = "lib"]
+
+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{{.*}} %{{.*}}, 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{{.*}} %{{.*}}, 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
new file mode 100644
index 00000000000..ba3ba272efb
--- /dev/null
+++ b/tests/codegen/repr-transparent-aggregates-1.rs
@@ -0,0 +1,89 @@
+// 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
+// ignore-loongarch64
+// ignore-wasm32-bare
+// 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
new file mode 100644
index 00000000000..a7bde2d05c3
--- /dev/null
+++ b/tests/codegen/repr-transparent-aggregates-2.rs
@@ -0,0 +1,90 @@
+// 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
+// ignore-loongarch64
+// 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-aggregates-3.rs b/tests/codegen/repr-transparent-aggregates-3.rs
new file mode 100644
index 00000000000..0db17e6b13a
--- /dev/null
+++ b/tests/codegen/repr-transparent-aggregates-3.rs
@@ -0,0 +1,79 @@
+// compile-flags: -C no-prepopulate-passes
+//
+
+// only-mips64
+// 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* [[BIGS_RET_ATTRS1:.*]] sret(%BigS) [[BIGS_RET_ATTRS2:.*]], [8 x i64]
+#[no_mangle]
+pub extern fn test_BigS(_: BigS) -> BigS { loop {} }
+
+// CHECK: define void @test_TsBigS(%TsBigS* [[BIGS_RET_ATTRS1]] sret(%TsBigS) [[BIGS_RET_ATTRS2]], [8 x i64]
+#[no_mangle]
+pub extern fn test_TsBigS(_: TsBigS) -> TsBigS { loop {} }
+
+// CHECK: define void @test_TuBigS(%TuBigS* [[BIGS_RET_ATTRS1]] sret(%TuBigS) [[BIGS_RET_ATTRS2]], [8 x i64]
+#[no_mangle]
+pub extern fn test_TuBigS(_: TuBigS) -> TuBigS { loop {} }
+
+// CHECK: define void @test_TeBigS(%"TeBigS::Variant"* [[BIGS_RET_ATTRS1]] sret(%"TeBigS::Variant") [[BIGS_RET_ATTRS2]], [8 x i64]
+#[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* [[BIGU_RET_ATTRS1:.*]] sret(%BigU) [[BIGU_RET_ATTRS2:.*]], [8 x i64]
+#[no_mangle]
+pub extern fn test_BigU(_: BigU) -> BigU { loop {} }
+
+// CHECK: define void @test_TsBigU(%TsBigU* [[BIGU_RET_ATTRS1]] sret(%TsBigU) [[BIGU_RET_ATTRS2]], [8 x i64]
+#[no_mangle]
+pub extern fn test_TsBigU(_: TsBigU) -> TsBigU { loop {} }
+
+// CHECK: define void @test_TuBigU(%TuBigU* [[BIGU_RET_ATTRS1]] sret(%TuBigU) [[BIGU_RET_ATTRS2]], [8 x i64]
+#[no_mangle]
+pub extern fn test_TuBigU(_: TuBigU) -> TuBigU { loop {} }
+
+// CHECK: define void @test_TeBigU(%"TeBigU::Variant"* [[BIGU_RET_ATTRS1]] sret(%"TeBigU::Variant") [[BIGU_RET_ATTRS2]], [8 x i64]
+#[no_mangle]
+pub extern fn test_TeBigU(_: TeBigU) -> TeBigU { loop {} }
diff --git a/tests/codegen/repr-transparent-sysv64.rs b/tests/codegen/repr-transparent-sysv64.rs
new file mode 100644
index 00000000000..886b0dd9e7b
--- /dev/null
+++ b/tests/codegen/repr-transparent-sysv64.rs
@@ -0,0 +1,28 @@
+// only-x86_64
+
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type="lib"]
+
+#[repr(C)]
+pub struct Rgb8 { r: u8, g: u8, b: u8 }
+
+#[repr(transparent)]
+pub struct Rgb8Wrap(Rgb8);
+
+// CHECK: i24 @test_Rgb8Wrap(i24{{( %0)?}})
+#[no_mangle]
+pub extern "sysv64" fn test_Rgb8Wrap(_: Rgb8Wrap) -> Rgb8Wrap { loop {} }
+
+#[repr(C)]
+pub union FloatBits {
+    float: f32,
+    bits: u32,
+}
+
+#[repr(transparent)]
+pub struct SmallUnion(FloatBits);
+
+// CHECK: i32 @test_SmallUnion(i32{{( %0)?}})
+#[no_mangle]
+pub extern "sysv64" fn test_SmallUnion(_: SmallUnion) -> SmallUnion { loop {} }
diff --git a/tests/codegen/repr-transparent.rs b/tests/codegen/repr-transparent.rs
new file mode 100644
index 00000000000..759ddea67a5
--- /dev/null
+++ b/tests/codegen/repr-transparent.rs
@@ -0,0 +1,171 @@
+// 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
+
+#![crate_type="lib"]
+#![feature(repr_simd, transparent_unions)]
+
+use std::marker::PhantomData;
+
+#[derive(Copy, Clone)]
+pub struct Zst1;
+#[derive(Copy, Clone)]
+pub struct Zst2(());
+
+#[derive(Copy, Clone)]
+#[repr(transparent)]
+pub struct F32(f32);
+
+// CHECK: define{{.*}}float @test_F32(float noundef %_1)
+#[no_mangle]
+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)
+#[no_mangle]
+pub extern "C" fn test_Ptr(_: Ptr) -> Ptr { loop {} }
+
+#[repr(transparent)]
+pub struct WithZst(u64, Zst1);
+
+// CHECK: define{{.*}}i64 @test_WithZst(i64 noundef %_1)
+#[no_mangle]
+pub extern "C" fn test_WithZst(_: WithZst) -> WithZst { loop {} }
+
+#[repr(transparent)]
+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)
+#[no_mangle]
+pub extern "C" fn test_WithZeroSizedArray(_: WithZeroSizedArray) -> WithZeroSizedArray { loop {} }
+
+#[repr(transparent)]
+pub struct Generic<T>(T);
+
+// CHECK: define{{.*}}double @test_Generic(double noundef %_1)
+#[no_mangle]
+pub extern "C" fn test_Generic(_: Generic<f64>) -> Generic<f64> { loop {} }
+
+#[repr(transparent)]
+pub struct GenericPlusZst<T>(T, Zst2);
+
+#[repr(u8)]
+pub enum Bool { True, False, FileNotFound }
+
+// CHECK: define{{( dso_local)?}} noundef{{( zeroext)?}} i8 @test_Gpz(i8 noundef{{( zeroext)?}} %_1)
+#[no_mangle]
+pub extern "C" fn test_Gpz(_: GenericPlusZst<Bool>) -> GenericPlusZst<Bool> { loop {} }
+
+#[repr(transparent)]
+pub struct LifetimePhantom<'a, T: 'a>(*const T, PhantomData<&'a T>);
+
+// CHECK: define{{.*}}{{i16\*|ptr}} @test_LifetimePhantom({{i16\*|ptr}} noundef %_1)
+#[no_mangle]
+pub extern "C" fn test_LifetimePhantom(_: LifetimePhantom<i16>) -> LifetimePhantom<i16> { loop {} }
+
+// This works despite current alignment resrictions because PhantomData is always align(1)
+#[repr(transparent)]
+pub struct UnitPhantom<T, U> { val: T, unit: PhantomData<U> }
+
+pub struct Px;
+
+// CHECK: define{{.*}}float @test_UnitPhantom(float noundef %_1)
+#[no_mangle]
+pub extern "C" fn test_UnitPhantom(_: UnitPhantom<f32, Px>) -> UnitPhantom<f32, Px> { loop {} }
+
+#[repr(transparent)]
+pub struct TwoZsts(Zst1, i8, Zst2);
+
+// CHECK: define{{( dso_local)?}} noundef{{( signext)?}} i8 @test_TwoZsts(i8 noundef{{( signext)?}} %_1)
+#[no_mangle]
+pub extern "C" fn test_TwoZsts(_: TwoZsts) -> TwoZsts { loop {} }
+
+#[repr(transparent)]
+pub struct Nested1(Zst2, Generic<f64>);
+
+// CHECK: define{{.*}}double @test_Nested1(double noundef %_1)
+#[no_mangle]
+pub extern "C" fn test_Nested1(_: Nested1) -> Nested1 { loop {} }
+
+#[repr(transparent)]
+pub struct Nested2(Nested1, Zst1);
+
+// CHECK: define{{.*}}double @test_Nested2(double noundef %_1)
+#[no_mangle]
+pub extern "C" fn test_Nested2(_: Nested2) -> Nested2 { loop {} }
+
+#[repr(simd)]
+struct f32x4(f32, f32, f32, f32);
+
+#[repr(transparent)]
+pub struct Vector(f32x4);
+
+// CHECK: define{{.*}}<4 x float> @test_Vector(<4 x float> %_1)
+#[no_mangle]
+pub extern "C" fn test_Vector(_: Vector) -> Vector { loop {} }
+
+trait Mirror { type It: ?Sized; }
+impl<T: ?Sized> Mirror for T { type It = Self; }
+
+#[repr(transparent)]
+pub struct StructWithProjection(<f32 as Mirror>::It);
+
+// CHECK: define{{.*}}float @test_Projection(float noundef %_1)
+#[no_mangle]
+pub extern "C" fn test_Projection(_: StructWithProjection) -> StructWithProjection { loop {} }
+
+#[repr(transparent)]
+pub enum EnumF32 {
+    Variant(F32)
+}
+
+// CHECK: define{{.*}}float @test_EnumF32(float noundef %_1)
+#[no_mangle]
+pub extern "C" fn test_EnumF32(_: EnumF32) -> EnumF32 { loop {} }
+
+#[repr(transparent)]
+pub enum EnumF32WithZsts {
+    Variant(Zst1, F32, Zst2)
+}
+
+// CHECK: define{{.*}}float @test_EnumF32WithZsts(float noundef %_1)
+#[no_mangle]
+pub extern "C" fn test_EnumF32WithZsts(_: EnumF32WithZsts) -> EnumF32WithZsts { loop {} }
+
+#[repr(transparent)]
+pub union UnionF32 {
+    field: F32,
+}
+
+// CHECK: define{{.*}} float @test_UnionF32(float %_1)
+#[no_mangle]
+pub extern "C" fn test_UnionF32(_: UnionF32) -> UnionF32 { loop {} }
+
+#[repr(transparent)]
+pub union UnionF32WithZsts {
+    zst1: Zst1,
+    field: F32,
+    zst2: Zst2,
+}
+
+// CHECK: define{{.*}}float @test_UnionF32WithZsts(float %_1)
+#[no_mangle]
+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-
+// 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.
+//
+// You may be wondering why we don't just compare the return types and argument types for equality
+// with FileCheck regex captures. Well, rustc doesn't perform newtype unwrapping on newtypes
+// containing aggregates. This is OK on all ABIs we support, but because LLVM has not gotten rid of
+// pointee types yet, the IR function signature will be syntactically different (%Foo* vs
+// %FooWrapper*).
diff --git a/tests/codegen/riscv-abi/call-llvm-intrinsics.rs b/tests/codegen/riscv-abi/call-llvm-intrinsics.rs
new file mode 100644
index 00000000000..31a88f2c0a9
--- /dev/null
+++ b/tests/codegen/riscv-abi/call-llvm-intrinsics.rs
@@ -0,0 +1,30 @@
+// compile-flags: -C no-prepopulate-passes
+
+// only-riscv64
+
+#![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, float* %{{.}}, align 4
+        // CHECK: call float @llvm.sqrt.f32(float %{{.}}
+        sqrt(4.0);
+    }
+}
diff --git a/tests/codegen/riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs b/tests/codegen/riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs
new file mode 100644
index 00000000000..ec18fa9a328
--- /dev/null
+++ b/tests/codegen/riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs
@@ -0,0 +1,189 @@
+// compile-flags: --target riscv64gc-unknown-linux-gnu -O -C no-prepopulate-passes
+// needs-llvm-components: riscv
+
+#![crate_type = "lib"]
+#![no_core]
+#![feature(no_core, lang_items)]
+#![allow(improper_ctypes)]
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+impl Copy for bool {}
+impl Copy for i8 {}
+impl Copy for u8 {}
+impl Copy for i32 {}
+impl Copy for i64 {}
+impl Copy for u64 {}
+impl Copy for f32 {}
+impl Copy for f64 {}
+
+// CHECK: define void @f_void()
+#[no_mangle]
+pub extern "C" fn f_void() {}
+
+// CHECK: define noundef zeroext i1 @f_scalar_0(i1 noundef zeroext %a)
+#[no_mangle]
+pub extern "C" fn f_scalar_0(a: bool) -> bool {
+    a
+}
+
+// CHECK: define noundef signext i8 @f_scalar_1(i8 noundef signext %x)
+#[no_mangle]
+pub extern "C" fn f_scalar_1(x: i8) -> i8 {
+    x
+}
+
+// CHECK: define noundef zeroext i8 @f_scalar_2(i8 noundef zeroext %x)
+#[no_mangle]
+pub extern "C" fn f_scalar_2(x: u8) -> u8 {
+    x
+}
+
+// CHECK: define noundef signext i32 @f_scalar_3(i32 noundef signext %x)
+#[no_mangle]
+pub extern "C" fn f_scalar_3(x: i32) -> u32 {
+    x as u32
+}
+
+// CHECK: define noundef i64 @f_scalar_4(i64 noundef %x)
+#[no_mangle]
+pub extern "C" fn f_scalar_4(x: i64) -> i64 {
+    x
+}
+
+// CHECK: define float @f_fp_scalar_1(float %0)
+#[no_mangle]
+pub extern "C" fn f_fp_scalar_1(x: f32) -> f32 {
+    x
+}
+// CHECK: define double @f_fp_scalar_2(double %0)
+#[no_mangle]
+pub extern "C" fn f_fp_scalar_2(x: f64) -> f64 {
+    x
+}
+
+#[repr(C)]
+pub struct Empty {}
+
+// CHECK: define void @f_agg_empty_struct()
+#[no_mangle]
+pub extern "C" fn f_agg_empty_struct(e: Empty) -> Empty {
+    e
+}
+
+#[repr(C)]
+pub struct Tiny {
+    a: u16,
+    b: u16,
+    c: u16,
+    d: u16,
+}
+
+// CHECK: define void @f_agg_tiny(i64 %0)
+#[no_mangle]
+pub extern "C" fn f_agg_tiny(mut e: Tiny) {
+}
+
+// CHECK: define i64 @f_agg_tiny_ret()
+#[no_mangle]
+pub extern "C" fn f_agg_tiny_ret() -> Tiny {
+    Tiny { a: 1, b: 2, c: 3, d: 4 }
+}
+
+#[repr(C)]
+pub struct Small {
+    a: i64,
+    b: *mut i64,
+}
+
+// CHECK: define void @f_agg_small([2 x i64] %0)
+#[no_mangle]
+pub extern "C" fn f_agg_small(mut x: Small) {
+}
+
+// CHECK: define [2 x i64] @f_agg_small_ret()
+#[no_mangle]
+pub extern "C" fn f_agg_small_ret() -> Small {
+    Small { a: 1, b: 0 as *mut _ }
+}
+
+#[repr(C)]
+pub struct SmallAligned {
+    a: i128,
+}
+
+// CHECK: define void @f_agg_small_aligned(i128 %0)
+#[no_mangle]
+pub extern "C" fn f_agg_small_aligned(mut x: SmallAligned) {
+}
+
+#[repr(C)]
+pub struct Large {
+    a: i64,
+    b: i64,
+    c: i64,
+    d: i64,
+}
+
+// CHECK: define void @f_agg_large({{%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)
+#[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)
+#[no_mangle]
+pub extern "C" fn f_scalar_stack_1(
+    a: Tiny,
+    b: Small,
+    c: SmallAligned,
+    d: Large,
+    e: u8,
+    f: i8,
+    g: u8,
+    h: i8,
+) {
+}
+
+// CHECK: define void @f_scalar_stack_2({{%Large\*|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,
+    b: SmallAligned,
+    c: SmallAligned,
+    d: u64,
+    e: u8,
+    f: i8,
+    g: u8,
+) -> Large {
+    Large { a: a as i64, b: e as i64, c: f as i64, d: g as i64 }
+}
+
+extern "C" {
+    fn f_va_callee(_: i32, ...) -> i32;
+}
+
+#[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}} {{.*}})
+    f_va_callee(
+        1,
+        2i32,
+        3i64,
+        4.0f64,
+        5.0f64,
+        Tiny { a: 1, b: 2, c: 3, d: 4 },
+        Small { a: 10, b: 0 as *mut _ },
+        SmallAligned { a: 11 },
+        Large { a: 12, b: 13, c: 14, d: 15 },
+    );
+    // CHECK: call noundef signext i32 (i32, ...) @f_va_callee(i32 noundef signext 1, i32 noundef signext 2, i32 noundef signext 3, i32 noundef signext 4, i128 {{.*}}, i32 noundef signext 6, i32 noundef signext 7, i32 noundef 8, i32 noundef 9)
+    f_va_callee(1, 2i32, 3i32, 4i32, SmallAligned { a: 5 }, 6i32, 7i32, 8i32, 9i32);
+}
diff --git a/tests/codegen/riscv-abi/riscv64-lp64d-abi.rs b/tests/codegen/riscv-abi/riscv64-lp64d-abi.rs
new file mode 100644
index 00000000000..1555acadfbc
--- /dev/null
+++ b/tests/codegen/riscv-abi/riscv64-lp64d-abi.rs
@@ -0,0 +1,293 @@
+//
+// compile-flags: -C no-prepopulate-passes
+// only-riscv64
+// 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 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 signext %a, i32 signext %b, i32 signext %c, i32 signext %d, i32 signext %e, i32 signext %f, i32 signext %g, i32 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(%IntDoubleInt* {{.*}}%a)
+#[no_mangle]
+pub extern "C" fn f_int_double_int_s_arg(a: IntDoubleInt) {}
+
+// CHECK: define void @f_ret_int_double_int_s(%IntDoubleInt* {{.*}}sret
+#[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/riscv-abi/riscv64-lp64f-lp64d-abi.rs b/tests/codegen/riscv-abi/riscv64-lp64f-lp64d-abi.rs
new file mode 100644
index 00000000000..f08fabed421
--- /dev/null
+++ b/tests/codegen/riscv-abi/riscv64-lp64f-lp64d-abi.rs
@@ -0,0 +1,277 @@
+//
+// compile-flags: -C no-prepopulate-passes
+// only-riscv64
+// only-linux
+#![crate_type = "lib"]
+
+// CHECK: define void @f_fpr_tracking(float %0, float %1, float %2, float %3, float %4, float %5, float %6, float %7, i8 zeroext %i)
+#[no_mangle]
+pub extern "C" fn f_fpr_tracking(
+    a: f32,
+    b: f32,
+    c: f32,
+    d: f32,
+    e: f32,
+    f: f32,
+    g: f32,
+    h: f32,
+    i: u8,
+) {
+}
+
+#[repr(C)]
+pub struct Float {
+    f: f32,
+}
+
+#[repr(C)]
+pub struct FloatFloat {
+    f: f32,
+    g: f32,
+}
+
+// CHECK: define void @f_float_s_arg(float %0)
+#[no_mangle]
+pub extern "C" fn f_float_s_arg(a: Float) {}
+
+// CHECK: define float @f_ret_float_s()
+#[no_mangle]
+pub extern "C" fn f_ret_float_s() -> Float {
+    Float { f: 1. }
+}
+
+// CHECK: define void @f_float_float_s_arg({ float, float } %0)
+#[no_mangle]
+pub extern "C" fn f_float_float_s_arg(a: FloatFloat) {}
+
+// CHECK: define { float, float } @f_ret_float_float_s()
+#[no_mangle]
+pub extern "C" fn f_ret_float_float_s() -> FloatFloat {
+    FloatFloat { f: 1., g: 2. }
+}
+
+// CHECK: define void @f_float_float_s_arg_insufficient_fprs(float %0, float %1, float %2, float %3, float %4, float %5, float %6, i64 %7)
+#[no_mangle]
+pub extern "C" fn f_float_float_s_arg_insufficient_fprs(
+    a: f32,
+    b: f32,
+    c: f32,
+    d: f32,
+    e: f32,
+    f: f32,
+    g: f32,
+    h: FloatFloat,
+) {
+}
+
+#[repr(C)]
+pub struct FloatInt8 {
+    f: f32,
+    i: i8,
+}
+
+#[repr(C)]
+pub struct FloatUInt8 {
+    f: f32,
+    i: u8,
+}
+
+#[repr(C)]
+pub struct FloatInt32 {
+    f: f32,
+    i: i32,
+}
+
+#[repr(C)]
+pub struct FloatInt64 {
+    f: f32,
+    i: i64,
+}
+
+// CHECK: define void @f_float_int8_s_arg({ float, i8 } %0)
+#[no_mangle]
+pub extern "C" fn f_float_int8_s_arg(a: FloatInt8) {}
+
+// CHECK: define { float, i8 } @f_ret_float_int8_s()
+#[no_mangle]
+pub extern "C" fn f_ret_float_int8_s() -> FloatInt8 {
+    FloatInt8 { f: 1., i: 2 }
+}
+
+// CHECK: define void @f_float_int32_s_arg({ float, i32 } %0)
+#[no_mangle]
+pub extern "C" fn f_float_int32_s_arg(a: FloatInt32) {}
+
+// CHECK: define { float, i32 } @f_ret_float_int32_s()
+#[no_mangle]
+pub extern "C" fn f_ret_float_int32_s() -> FloatInt32 {
+    FloatInt32 { f: 1., i: 2 }
+}
+
+// CHECK: define void @f_float_uint8_s_arg({ float, i8 } %0)
+#[no_mangle]
+pub extern "C" fn f_float_uint8_s_arg(a: FloatUInt8) {}
+
+// CHECK: define { float, i8 } @f_ret_float_uint8_s()
+#[no_mangle]
+pub extern "C" fn f_ret_float_uint8_s() -> FloatUInt8 {
+    FloatUInt8 { f: 1., i: 2 }
+}
+
+// CHECK: define void @f_float_int64_s_arg({ float, i64 } %0)
+#[no_mangle]
+pub extern "C" fn f_float_int64_s_arg(a: FloatInt64) {}
+
+// CHECK: define { float, i64 } @f_ret_float_int64_s()
+#[no_mangle]
+pub extern "C" fn f_ret_float_int64_s() -> FloatInt64 {
+    FloatInt64 { f: 1., i: 2 }
+}
+
+// CHECK: define void @f_float_int8_s_arg_insufficient_gprs(i32 signext %a, i32 signext %b, i32 signext %c, i32 signext %d, i32 signext %e, i32 signext %f, i32 signext %g, i32 signext %h, i64 %0)
+#[no_mangle]
+pub extern "C" fn f_float_int8_s_arg_insufficient_gprs(
+    a: i32,
+    b: i32,
+    c: i32,
+    d: i32,
+    e: i32,
+    f: i32,
+    g: i32,
+    h: i32,
+    i: FloatInt8,
+) {
+}
+
+// CHECK: define void @f_struct_float_int8_insufficient_fprs(float %0, float %1, float %2,  float %3, float %4, float %5, float %6, float %7, i64 %8)
+#[no_mangle]
+pub extern "C" fn f_struct_float_int8_insufficient_fprs(
+    a: f32,
+    b: f32,
+    c: f32,
+    d: f32,
+    e: f32,
+    f: f32,
+    g: f32,
+    h: f32,
+    i: FloatInt8,
+) {
+}
+
+#[repr(C)]
+pub struct FloatArr1 {
+    a: [f32; 1],
+}
+
+// CHECK: define void @f_floatarr1_s_arg(float %0)
+#[no_mangle]
+pub extern "C" fn f_floatarr1_s_arg(a: FloatArr1) {}
+
+// CHECK: define float @f_ret_floatarr1_s()
+#[no_mangle]
+pub extern "C" fn f_ret_floatarr1_s() -> FloatArr1 {
+    FloatArr1 { a: [1.] }
+}
+
+#[repr(C)]
+pub struct FloatArr2 {
+    a: [f32; 2],
+}
+
+// CHECK: define void @f_floatarr2_s_arg({ float, float } %0)
+#[no_mangle]
+pub extern "C" fn f_floatarr2_s_arg(a: FloatArr2) {}
+
+// CHECK: define { float, float } @f_ret_floatarr2_s()
+#[no_mangle]
+pub extern "C" fn f_ret_floatarr2_s() -> FloatArr2 {
+    FloatArr2 { a: [1., 2.] }
+}
+
+#[repr(C)]
+pub struct Tricky1 {
+    f: [f32; 1],
+}
+
+#[repr(C)]
+pub struct FloatArr2Tricky1 {
+    g: [Tricky1; 2],
+}
+
+// CHECK: define void @f_floatarr2_tricky1_s_arg({ float, float } %0)
+#[no_mangle]
+pub extern "C" fn f_floatarr2_tricky1_s_arg(a: FloatArr2Tricky1) {}
+
+// CHECK: define { float, float } @f_ret_floatarr2_tricky1_s()
+#[no_mangle]
+pub extern "C" fn f_ret_floatarr2_tricky1_s() -> FloatArr2Tricky1 {
+    FloatArr2Tricky1 { g: [Tricky1 { f: [1.] }, Tricky1 { f: [2.] }] }
+}
+
+#[repr(C)]
+pub struct EmptyStruct {}
+
+#[repr(C)]
+pub struct FloatArr2Tricky2 {
+    s: EmptyStruct,
+    g: [Tricky1; 2],
+}
+
+// CHECK: define void @f_floatarr2_tricky2_s_arg({ float, float } %0)
+#[no_mangle]
+pub extern "C" fn f_floatarr2_tricky2_s_arg(a: FloatArr2Tricky2) {}
+
+// CHECK: define { float, float } @f_ret_floatarr2_tricky2_s()
+#[no_mangle]
+pub extern "C" fn f_ret_floatarr2_tricky2_s() -> FloatArr2Tricky2 {
+    FloatArr2Tricky2 { s: EmptyStruct {}, g: [Tricky1 { f: [1.] }, Tricky1 { f: [2.] }] }
+}
+
+#[repr(C)]
+pub struct IntFloatInt {
+    a: i32,
+    b: f32,
+    c: i32,
+}
+
+// CHECK: define void @f_int_float_int_s_arg([2 x i64] %0)
+#[no_mangle]
+pub extern "C" fn f_int_float_int_s_arg(a: IntFloatInt) {}
+
+// CHECK: define [2 x i64] @f_ret_int_float_int_s()
+#[no_mangle]
+pub extern "C" fn f_ret_int_float_int_s() -> IntFloatInt {
+    IntFloatInt { a: 1, b: 2., c: 3 }
+}
+
+#[repr(C)]
+pub struct CharCharFloat {
+    a: u8,
+    b: u8,
+    c: f32,
+}
+
+// CHECK: define void @f_char_char_float_s_arg(i64 %0)
+#[no_mangle]
+pub extern "C" fn f_char_char_float_s_arg(a: CharCharFloat) {}
+
+// CHECK: define i64 @f_ret_char_char_float_s()
+#[no_mangle]
+pub extern "C" fn f_ret_char_char_float_s() -> CharCharFloat {
+    CharCharFloat { a: 1, b: 2, c: 3. }
+}
+
+#[repr(C)]
+pub union FloatU {
+    a: f32,
+}
+
+// CHECK: define void @f_float_u_arg(i64 %0)
+#[no_mangle]
+pub extern "C" fn f_float_u_arg(a: FloatU) {}
+
+// CHECK: define i64 @f_ret_float_u()
+#[no_mangle]
+pub extern "C" fn f_ret_float_u() -> FloatU {
+    unsafe { FloatU { a: 1. } }
+}
diff --git a/tests/codegen/sanitizer-cfi-add-canonical-jump-tables-flag.rs b/tests/codegen/sanitizer-cfi-add-canonical-jump-tables-flag.rs
new file mode 100644
index 00000000000..1ee8bdfc3ab
--- /dev/null
+++ b/tests/codegen/sanitizer-cfi-add-canonical-jump-tables-flag.rs
@@ -0,0 +1,11 @@
+// Verifies that "CFI Canonical Jump Tables" 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, !"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
new file mode 100644
index 00000000000..cea6aac8b8b
--- /dev/null
+++ b/tests/codegen/sanitizer-cfi-emit-type-checks.rs
@@ -0,0 +1,19 @@
+// Verifies that pointer type membership tests for indirect calls are emitted.
+//
+// needs-sanitizer-cfi
+// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Copt-level=0
+
+#![crate_type="lib"]
+
+pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
+    // 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:       type_test.fail:
+    // CHECK-NEXT:  call void @llvm.trap()
+    // CHECK-NEXT:  unreachable
+    f(arg)
+}
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
new file mode 100644
index 00000000000..63e63c5d4aa
--- /dev/null
+++ b/tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs
@@ -0,0 +1,604 @@
+// Verifies that type metadata identifiers for functions are emitted correctly.
+//
+// needs-sanitizer-cfi
+// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi
+
+#![crate_type="lib"]
+#![allow(dead_code)]
+#![allow(incomplete_features)]
+#![allow(unused_must_use)]
+#![feature(adt_const_params, extern_types, inline_const, type_alias_impl_trait)]
+
+extern crate core;
+use core::ffi::*;
+use std::marker::PhantomData;
+
+// User-defined type (structure)
+pub struct Struct1<T> {
+    member1: T,
+}
+
+// User-defined type (enum)
+pub enum Enum1<T> {
+    Variant1(T),
+}
+
+// User-defined type (union)
+pub union Union1<T> {
+    member1: std::mem::ManuallyDrop<T>,
+}
+
+// Extern type
+extern {
+    pub type type1;
+}
+
+// Trait
+pub trait Trait1<T> {
+    fn foo(&self) { }
+}
+
+// Trait implementation
+impl<T> Trait1<T> for i32 {
+    fn foo(&self) { }
+}
+
+// Trait implementation
+impl<T, U> Trait1<T> for Struct1<U> {
+    fn foo(&self) { }
+}
+
+// impl Trait type aliases for helping with defining other types (see below)
+pub type Type1 = impl Send;
+pub type Type2 = impl Send;
+pub type Type3 = impl Send;
+pub type Type4 = impl Send;
+pub type Type5 = impl Send;
+pub type Type6 = impl Send;
+pub type Type7 = impl Send;
+pub type Type8 = impl Send;
+pub type Type9 = impl Send;
+pub type Type10 = impl Send;
+pub type Type11 = impl Send;
+
+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;
+
+    // Constructor
+    pub struct Foo(i32);
+    let _: Type2 = Foo;
+
+    // Type in extern path
+    extern {
+        fn foo();
+    }
+    let _: Type3 = foo;
+
+    // Type in closure path
+    || {
+        pub struct Foo;
+        let _: Type4 = Foo;
+    };
+
+    // Type in const path
+    const {
+        pub struct Foo;
+        fn foo() -> Type5 { Foo }
+    };
+
+    // Type in impl path
+    impl<T> Struct1<T> {
+        fn foo(&self) { }
+    }
+    let _: Type6 = <Struct1<i32>>::foo;
+
+    // Trait method
+    let _: Type7 = <dyn Trait1<i32>>::foo;
+
+    // Trait method
+    let _: Type8 = <i32 as Trait1<i32>>::foo;
+
+    // Trait method
+    let _: Type9 = <Struct1<i32> as Trait1<i32>>::foo;
+
+    // Const generics
+    pub struct Qux<T, const N: usize>([T; N]);
+    let _: Type10 = Qux([0; 32]);
+
+    // Lifetimes/regions
+    pub struct Quux<'a>(&'a i32);
+    pub struct Quuux<'a, 'b>(&'a i32, &'b Quux<'b>);
+    let _: Type11 = Quuux;
+}
+
+// Helper type to make Type12 have an unique id
+struct Foo(i32);
+
+// repr(transparent) user-defined type
+#[repr(transparent)]
+pub struct Type12 {
+    member1: (),
+    member2: PhantomData<i32>,
+    member3: Foo,
+}
+
+// Self-referencing repr(transparent) user-defined type
+#[repr(transparent)]
+pub struct Type13<'a> {
+    member1: (),
+    member2: PhantomData<i32>,
+    member3: &'a Type13<'a>,
+}
+
+// Helper type to make Type14 have an unique id
+pub struct Bar;
+
+// repr(transparent) user-defined generic type
+#[repr(transparent)]
+pub struct Type14<T>(T);
+
+pub fn foo0(_: ()) { }
+// 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]+]] !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]+]] !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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo9(_: bool) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo11(_: bool, _: bool, _: bool) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo13(_: i8, _: i8) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo15(_: i16) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo17(_: i16, _: i16, _: i16) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo19(_: i32, _: i32) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo21(_: i64) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo23(_: i64, _: i64, _: i64) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo25(_: i128, _: i128) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo27(_: isize) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo29(_: isize, _: isize, _: isize) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo31(_: u8, _: u8) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo33(_: u16) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo35(_: u16, _: u16, _: u16) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo37(_: u32, _: u32) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo39(_: u64) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo41(_: u64, _: u64, _: u64) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo43(_: u128, _: u128) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo45(_: usize) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo47(_: usize, _: usize, _: usize) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo49(_: f32, _: f32) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo51(_: f64) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo53(_: f64, _: f64, _: f64) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo55(_: char, _: char) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo57(_: &str) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo59(_: &str, _: &str, _: &str) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo61(_: (i32, i32), _: (i32, i32)) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo63(_: [i32; 32]) { }
+// 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]+]] !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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo66(_: &[i32]) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo68(_: &[i32], _: &[i32], _: &[i32]) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo70(_: &Struct1::<i32>, _: &Struct1::<i32>) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo72(_: &Enum1::<i32>) { }
+// 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]+]] !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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo75(_: &Union1::<i32>) { }
+// 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]+]] !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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo78(_: *mut type1) { }
+// 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]+]] !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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo81(_: &mut i32) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo83(_: &mut i32, _: &i32, _: &i32) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo85(_: &i32, _: &mut i32) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo87(_: *mut i32) { }
+// 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]+]] !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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo90(_: *const i32) { }
+// 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]+]] !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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo93(_: fn(i32) -> i32) { }
+// 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]+]] !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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo96(_: &dyn Fn(i32) -> i32) { }
+// 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]+]] !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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo99(_: &dyn FnMut(i32) -> i32) { }
+// 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]+]] !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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo102(_: &dyn FnOnce(i32) -> i32) { }
+// 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]+]] !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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo105(_: &dyn Send) { }
+// 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]+]] !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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo108(_: Type1) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo110(_: Type1, _: Type1, _: Type1) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo112(_: Type2, _: Type2) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo114(_: Type3) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo116(_: Type3, _: Type3, _: Type3) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo118(_: Type4, _: Type4) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo120(_: Type5) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo122(_: Type5, _: Type5, _: Type5) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo124(_: Type6, _: Type6) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo126(_: Type7) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo128(_: Type7, _: Type7, _: Type7) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo130(_: Type8, _: Type8) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo132(_: Type9) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo134(_: Type9, _: Type9, _: Type9) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo136(_: Type10, _: Type10) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo138(_: Type11) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo140(_: Type11, _: Type11, _: Type11) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo142(_: Type12, _: Type12) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo144(_: Type13) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo146(_: Type13, _: Type13, _: Type13) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo148(_: Type14<Bar>, _: Type14<Bar>) { }
+// 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]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+
+// CHECK: ![[TYPE0]] = !{i64 0, !"_ZTSFvvE"}
+// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvvvE"}
+// CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFvvvvE"}
+// CHECK: ![[TYPE3]] = !{i64 0, !"_ZTSFvPvE"}
+// CHECK: ![[TYPE4]] = !{i64 0, !"_ZTSFvPvS_E"}
+// CHECK: ![[TYPE5]] = !{i64 0, !"_ZTSFvPvS_S_E"}
+// CHECK: ![[TYPE6]] = !{i64 0, !"_ZTSFvPKvE"}
+// CHECK: ![[TYPE7]] = !{i64 0, !"_ZTSFvPKvS0_E"}
+// CHECK: ![[TYPE8]] = !{i64 0, !"_ZTSFvPKvS0_S0_E"}
+// CHECK: ![[TYPE9]] = !{i64 0, !"_ZTSFvbE"}
+// CHECK: ![[TYPE10]] = !{i64 0, !"_ZTSFvbbE"}
+// CHECK: ![[TYPE11]] = !{i64 0, !"_ZTSFvbbbE"}
+// CHECK: ![[TYPE12]] = !{i64 0, !"_ZTSFvu2i8E"}
+// CHECK: ![[TYPE13]] = !{i64 0, !"_ZTSFvu2i8S_E"}
+// CHECK: ![[TYPE14]] = !{i64 0, !"_ZTSFvu2i8S_S_E"}
+// CHECK: ![[TYPE15]] = !{i64 0, !"_ZTSFvu3i16E"}
+// CHECK: ![[TYPE16]] = !{i64 0, !"_ZTSFvu3i16S_E"}
+// CHECK: ![[TYPE17]] = !{i64 0, !"_ZTSFvu3i16S_S_E"}
+// CHECK: ![[TYPE18]] = !{i64 0, !"_ZTSFvu3i32E"}
+// CHECK: ![[TYPE19]] = !{i64 0, !"_ZTSFvu3i32S_E"}
+// CHECK: ![[TYPE20]] = !{i64 0, !"_ZTSFvu3i32S_S_E"}
+// CHECK: ![[TYPE21]] = !{i64 0, !"_ZTSFvu3i64E"}
+// CHECK: ![[TYPE22]] = !{i64 0, !"_ZTSFvu3i64S_E"}
+// CHECK: ![[TYPE23]] = !{i64 0, !"_ZTSFvu3i64S_S_E"}
+// CHECK: ![[TYPE24]] = !{i64 0, !"_ZTSFvu4i128E"}
+// CHECK: ![[TYPE25]] = !{i64 0, !"_ZTSFvu4i128S_E"}
+// CHECK: ![[TYPE26]] = !{i64 0, !"_ZTSFvu4i128S_S_E"}
+// CHECK: ![[TYPE27]] = !{i64 0, !"_ZTSFvu5isizeE"}
+// CHECK: ![[TYPE28]] = !{i64 0, !"_ZTSFvu5isizeS_E"}
+// CHECK: ![[TYPE29]] = !{i64 0, !"_ZTSFvu5isizeS_S_E"}
+// CHECK: ![[TYPE30]] = !{i64 0, !"_ZTSFvu2u8E"}
+// CHECK: ![[TYPE31]] = !{i64 0, !"_ZTSFvu2u8S_E"}
+// CHECK: ![[TYPE32]] = !{i64 0, !"_ZTSFvu2u8S_S_E"}
+// CHECK: ![[TYPE33]] = !{i64 0, !"_ZTSFvu3u16E"}
+// CHECK: ![[TYPE34]] = !{i64 0, !"_ZTSFvu3u16S_E"}
+// CHECK: ![[TYPE35]] = !{i64 0, !"_ZTSFvu3u16S_S_E"}
+// CHECK: ![[TYPE36]] = !{i64 0, !"_ZTSFvu3u32E"}
+// CHECK: ![[TYPE37]] = !{i64 0, !"_ZTSFvu3u32S_E"}
+// CHECK: ![[TYPE38]] = !{i64 0, !"_ZTSFvu3u32S_S_E"}
+// CHECK: ![[TYPE39]] = !{i64 0, !"_ZTSFvu3u64E"}
+// CHECK: ![[TYPE40]] = !{i64 0, !"_ZTSFvu3u64S_E"}
+// CHECK: ![[TYPE41]] = !{i64 0, !"_ZTSFvu3u64S_S_E"}
+// CHECK: ![[TYPE42]] = !{i64 0, !"_ZTSFvu4u128E"}
+// CHECK: ![[TYPE43]] = !{i64 0, !"_ZTSFvu4u128S_E"}
+// CHECK: ![[TYPE44]] = !{i64 0, !"_ZTSFvu4u128S_S_E"}
+// CHECK: ![[TYPE45]] = !{i64 0, !"_ZTSFvu5usizeE"}
+// CHECK: ![[TYPE46]] = !{i64 0, !"_ZTSFvu5usizeS_E"}
+// CHECK: ![[TYPE47]] = !{i64 0, !"_ZTSFvu5usizeS_S_E"}
+// CHECK: ![[TYPE48]] = !{i64 0, !"_ZTSFvu3f32E"}
+// CHECK: ![[TYPE49]] = !{i64 0, !"_ZTSFvu3f32S_E"}
+// CHECK: ![[TYPE50]] = !{i64 0, !"_ZTSFvu3f32S_S_E"}
+// CHECK: ![[TYPE51]] = !{i64 0, !"_ZTSFvu3f64E"}
+// CHECK: ![[TYPE52]] = !{i64 0, !"_ZTSFvu3f64S_E"}
+// CHECK: ![[TYPE53]] = !{i64 0, !"_ZTSFvu3f64S_S_E"}
+// CHECK: ![[TYPE54]] = !{i64 0, !"_ZTSFvu4charE"}
+// CHECK: ![[TYPE55]] = !{i64 0, !"_ZTSFvu4charS_E"}
+// CHECK: ![[TYPE56]] = !{i64 0, !"_ZTSFvu4charS_S_E"}
+// CHECK: ![[TYPE57]] = !{i64 0, !"_ZTSFvu3refIu3strEE"}
+// CHECK: ![[TYPE58]] = !{i64 0, !"_ZTSFvu3refIu3strES0_E"}
+// CHECK: ![[TYPE59]] = !{i64 0, !"_ZTSFvu3refIu3strES0_S0_E"}
+// CHECK: ![[TYPE60]] = !{i64 0, !"_ZTSFvu5tupleIu3i32S_EE"}
+// CHECK: ![[TYPE61]] = !{i64 0, !"_ZTSFvu5tupleIu3i32S_ES0_E"}
+// CHECK: ![[TYPE62]] = !{i64 0, !"_ZTSFvu5tupleIu3i32S_ES0_S0_E"}
+// CHECK: ![[TYPE63]] = !{i64 0, !"_ZTSFvA32u3i32E"}
+// CHECK: ![[TYPE64]] = !{i64 0, !"_ZTSFvA32u3i32S0_E"}
+// CHECK: ![[TYPE65]] = !{i64 0, !"_ZTSFvA32u3i32S0_S0_E"}
+// CHECK: ![[TYPE66]] = !{i64 0, !"_ZTSFvu3refIu5sliceIu3i32EEE"}
+// CHECK: ![[TYPE67]] = !{i64 0, !"_ZTSFvu3refIu5sliceIu3i32EES1_E"}
+// CHECK: ![[TYPE68]] = !{i64 0, !"_ZTSFvu3refIu5sliceIu3i32EES1_S1_E"}
+// CHECK: ![[TYPE69]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi7Struct1Iu3i32EEE"}
+// CHECK: ![[TYPE70]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi7Struct1Iu3i32EES1_E"}
+// CHECK: ![[TYPE71]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi7Struct1Iu3i32EES1_S1_E"}
+// CHECK: ![[TYPE72]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi5Enum1Iu3i32EEE"}
+// CHECK: ![[TYPE73]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi5Enum1Iu3i32EES1_E"}
+// CHECK: ![[TYPE74]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi5Enum1Iu3i32EES1_S1_E"}
+// CHECK: ![[TYPE75]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Union1Iu3i32EEE"}
+// CHECK: ![[TYPE76]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Union1Iu3i32EES1_E"}
+// CHECK: ![[TYPE77]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Union1Iu3i32EES1_S1_E"}
+// CHECK: ![[TYPE78]] = !{i64 0, !"_ZTSFvP5type1E"}
+// CHECK: ![[TYPE79]] = !{i64 0, !"_ZTSFvP5type1S0_E"}
+// CHECK: ![[TYPE80]] = !{i64 0, !"_ZTSFvP5type1S0_S0_E"}
+// CHECK: ![[TYPE81]] = !{i64 0, !"_ZTSFvU3mutu3refIu3i32EE"}
+// CHECK: ![[TYPE82]] = !{i64 0, !"_ZTSFvU3mutu3refIu3i32ES0_E"}
+// CHECK: ![[TYPE83]] = !{i64 0, !"_ZTSFvU3mutu3refIu3i32ES0_S0_E"}
+// CHECK: ![[TYPE84]] = !{i64 0, !"_ZTSFvu3refIu3i32EE"}
+// CHECK: ![[TYPE85]] = !{i64 0, !"_ZTSFvu3refIu3i32EU3mutS0_E"}
+// CHECK: ![[TYPE86]] = !{i64 0, !"_ZTSFvu3refIu3i32EU3mutS0_S1_E"}
+// CHECK: ![[TYPE87]] = !{i64 0, !"_ZTSFvPu3i32E"}
+// CHECK: ![[TYPE88]] = !{i64 0, !"_ZTSFvPu3i32PKS_E"}
+// CHECK: ![[TYPE89]] = !{i64 0, !"_ZTSFvPu3i32PKS_S2_E"}
+// CHECK: ![[TYPE90]] = !{i64 0, !"_ZTSFvPKu3i32E"}
+// CHECK: ![[TYPE91]] = !{i64 0, !"_ZTSFvPKu3i32PS_E"}
+// CHECK: ![[TYPE92]] = !{i64 0, !"_ZTSFvPKu3i32PS_S2_E"}
+// 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:]]+}}_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"}
+// CHECK: ![[TYPE108]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NCNvC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3fn111{{[{}][{}]}}closure{{[}][}]}}Iu2i8PFvvEvEE"}
+// CHECK: ![[TYPE109]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NCNvC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3fn111{{[{}][{}]}}closure{{[}][}]}}Iu2i8PFvvEvES1_E"}
+// CHECK: ![[TYPE110]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NCNvC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3fn111{{[{}][{}]}}closure{{[}][}]}}Iu2i8PFvvEvES1_S1_E"}
+// CHECK: ![[TYPE111]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NcNtNvC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3fn13Foo15{{[{}][{}]}}constructor{{[}][}]}}E"}
+// CHECK: ![[TYPE112]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NcNtNvC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3fn13Foo15{{[{}][{}]}}constructor{{[}][}]}}S_E"}
+// CHECK: ![[TYPE113]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NcNtNvC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3fn13Foo15{{[{}][{}]}}constructor{{[}][}]}}S_S_E"}
+// CHECK: ![[TYPE114]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNFNvC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3fn110{{[{}][{}]}}extern{{[}][}]}}3fooE"}
+// CHECK: ![[TYPE115]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNFNvC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3fn110{{[{}][{}]}}extern{{[}][}]}}3fooS_E"}
+// CHECK: ![[TYPE116]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNFNvC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3fn110{{[{}][{}]}}extern{{[}][}]}}3fooS_S_E"}
+// CHECK: ![[TYPE117]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3fn1s0_11{{[{}][{}]}}closure{{[}][}]}}3FooE"}
+// CHECK: ![[TYPE118]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3fn1s0_11{{[{}][{}]}}closure{{[}][}]}}3FooS_E"}
+// CHECK: ![[TYPE119]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3fn1s0_11{{[{}][{}]}}closure{{[}][}]}}3FooS_S_E"}
+// CHECK: ![[TYPE120]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3fn112{{[{}][{}]}}constant{{[}][}]}}3FooE"}
+// CHECK: ![[TYPE121]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3fn112{{[{}][{}]}}constant{{[}][}]}}3FooS_E"}
+// CHECK: ![[TYPE122]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3fn112{{[{}][{}]}}constant{{[}][}]}}3FooS_S_E"}
+// 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_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"}
+// CHECK: ![[TYPE132]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi7Struct1Iu3i32ES_EE"}
+// CHECK: ![[TYPE133]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi7Struct1Iu3i32ES_ES1_E"}
+// CHECK: ![[TYPE134]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi7Struct1Iu3i32ES_ES1_S1_E"}
+// CHECK: ![[TYPE135]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNvC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3fn13QuxIu3i32Lu5usize32EEE"}
+// CHECK: ![[TYPE136]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNvC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3fn13QuxIu3i32Lu5usize32EES2_E"}
+// CHECK: ![[TYPE137]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNvC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3fn13QuxIu3i32Lu5usize32EES2_S2_E"}
+// CHECK: ![[TYPE138]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NcNtNvC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3fn15Quuux15{{[{}][{}]}}constructor{{[}][}]}}Iu6regionS_EE"}
+// CHECK: ![[TYPE139]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NcNtNvC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3fn15Quuux15{{[{}][{}]}}constructor{{[}][}]}}Iu6regionS_ES0_E"}
+// CHECK: ![[TYPE140]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NcNtNvC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3fn15Quuux15{{[{}][{}]}}constructor{{[}][}]}}Iu6regionS_ES0_S0_E"}
+// CHECK: ![[TYPE141]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3FooE"}
+// CHECK: ![[TYPE142]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3FooS_E"}
+// CHECK: ![[TYPE143]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3FooS_S_E"}
+// 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"}
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
new file mode 100644
index 00000000000..f9fd816dedb
--- /dev/null
+++ b/tests/codegen/sanitizer-cfi-emit-type-metadata-itanium-cxx-abi.rs
@@ -0,0 +1,31 @@
+// Verifies that type metadata for functions are emitted.
+//
+// needs-sanitizer-cfi
+// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi
+
+#![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]+}} !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]+]] !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]+]] !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)
+}
+
+// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFu3i32PFS_S_ES_E"}
+// CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFu3i32PFS_S_S_ES_S_E"}
+// CHECK: ![[TYPE3]] = !{i64 0, !"_ZTSFu3i32PFS_S_S_S_ES_S_S_E"}
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..0f79adab7bd
--- /dev/null
+++ b/tests/codegen/sanitizer-cfi-emit-type-metadata-trait-objects.rs
@@ -0,0 +1,120 @@
+// 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 fn foo1(a: &dyn Trait1) {
+    a.foo();
+    // CHECK-LABEL: define{{.*}}4foo1{{.*}}!type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test({{i8\*|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({{i8\*|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({{i8\*|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({{i8\*|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({{i8\*|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({{i8\*|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({{i8\*|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({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE4:[[: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]]"}
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-kasan-emits-instrumentation.rs b/tests/codegen/sanitizer-kasan-emits-instrumentation.rs
new file mode 100644
index 00000000000..d6e3f2719df
--- /dev/null
+++ b/tests/codegen/sanitizer-kasan-emits-instrumentation.rs
@@ -0,0 +1,47 @@
+// Verifies that `-Zsanitizer=kernel-address` emits sanitizer instrumentation.
+
+// compile-flags: -Zsanitizer=kernel-address
+// revisions: aarch64 riscv64imac riscv64gc x86_64
+//[aarch64] compile-flags: --target aarch64-unknown-none
+//[aarch64] needs-llvm-components: aarch64
+//[riscv64imac] compile-flags: --target riscv64imac-unknown-none-elf
+//[riscv64imac] needs-llvm-components: riscv
+//[riscv64imac] min-llvm-version: 16
+//[riscv64gc] compile-flags: --target riscv64gc-unknown-none-elf
+//[riscv64gc] needs-llvm-components: riscv
+//[riscv64gc] min-llvm-version: 16
+//[x86_64] compile-flags: --target x86_64-unknown-none
+//[x86_64] needs-llvm-components: x86
+
+#![crate_type = "rlib"]
+#![feature(no_core, no_sanitize, lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+
+#[lang = "copy"]
+trait Copy {}
+
+impl Copy for u8 {}
+
+// CHECK-LABEL: ; sanitizer_kasan_emits_instrumentation::unsanitized
+// CHECK-NEXT:  ; Function Attrs:
+// CHECK-NOT:   sanitize_address
+// CHECK:       start:
+// CHECK-NOT:   call void @__asan_report_load
+// CHECK:       }
+#[no_sanitize(address)]
+pub fn unsanitized(b: &mut u8) -> u8 {
+    *b
+}
+
+// CHECK-LABEL: ; sanitizer_kasan_emits_instrumentation::sanitized
+// CHECK-NEXT:  ; Function Attrs:
+// CHECK:       sanitize_address
+// CHECK:       start:
+// CHECK:       call void @__asan_report_load
+// CHECK:       }
+pub fn sanitized(b: &mut u8) -> u8 {
+    *b
+}
diff --git a/tests/codegen/sanitizer-kcfi-add-kcfi-flag.rs b/tests/codegen/sanitizer-kcfi-add-kcfi-flag.rs
new file mode 100644
index 00000000000..c2eb852aec3
--- /dev/null
+++ b/tests/codegen/sanitizer-kcfi-add-kcfi-flag.rs
@@ -0,0 +1,11 @@
+// Verifies that "kcfi" module flag is added.
+//
+// needs-sanitizer-kcfi
+// compile-flags: -Ctarget-feature=-crt-static -Zsanitizer=kcfi
+
+#![crate_type="lib"]
+
+pub fn foo() {
+}
+
+// CHECK: !{{[0-9]+}} = !{i32 4, !"kcfi", i32 1}
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
new file mode 100644
index 00000000000..83cda0ef136
--- /dev/null
+++ b/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi.rs
@@ -0,0 +1,44 @@
+// Verifies that 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 -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
+    // 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 {{(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 {{(noundef )*}}i32 %f(i32 {{(noundef )*}}%arg1, i32 {{(noundef )*}}%arg2, i32 {{(noundef )*}}%arg3){{.*}}[ "kcfi"(i32 1248878270) ]
+    f(arg1, arg2, arg3)
+}
+
+// CHECK: ![[TYPE1]] = !{i32 653723426}
+// CHECK: ![[TYPE2]] = !{i32 412174924}
+// CHECK: ![[TYPE3]] = !{i32 -636668840}
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..004a67e7df2
--- /dev/null
+++ b/tests/codegen/sanitizer-kcfi-emit-type-metadata-trait-objects.rs
@@ -0,0 +1,144 @@
+// 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 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|%Type3\*}} 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|%Type3\*}} 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|i32\*}} %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}, {{\{\}\*|ptr|%Type4\*}} 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|i32\*}} %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}, {{\{\}\*|ptr|%Type4\*}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE4:[[:print:]]+]]) ]
+}
+
+// CHECK: !{{[0-9]+}} = !{i32 [[TYPE1]]}
+// CHECK: !{{[0-9]+}} = !{i32 [[TYPE2]]}
+// CHECK: !{{[0-9]+}} = !{i32 [[TYPE3]]}
+// CHECK: !{{[0-9]+}} = !{i32 [[TYPE4]]}
diff --git a/tests/codegen/sanitizer-memory-track-orgins.rs b/tests/codegen/sanitizer-memory-track-orgins.rs
new file mode 100644
index 00000000000..4bd50508d15
--- /dev/null
+++ b/tests/codegen/sanitizer-memory-track-orgins.rs
@@ -0,0 +1,30 @@
+// Verifies that MemorySanitizer track-origins level can be controlled
+// with -Zsanitizer-memory-track-origins option.
+//
+// needs-sanitizer-memory
+// revisions:MSAN-0 MSAN-1 MSAN-2 MSAN-1-LTO MSAN-2-LTO
+//
+//[MSAN-0] compile-flags: -Zsanitizer=memory
+//[MSAN-1] compile-flags: -Zsanitizer=memory -Zsanitizer-memory-track-origins=1
+//[MSAN-2] compile-flags: -Zsanitizer=memory -Zsanitizer-memory-track-origins
+//[MSAN-1-LTO] compile-flags: -Zsanitizer=memory -Zsanitizer-memory-track-origins=1 -C lto=fat
+//[MSAN-2-LTO] compile-flags: -Zsanitizer=memory -Zsanitizer-memory-track-origins -C lto=fat
+
+#![crate_type="lib"]
+
+// MSAN-0-NOT: @__msan_track_origins
+// MSAN-1:     @__msan_track_origins = weak_odr {{.*}}constant i32 1
+// MSAN-2:     @__msan_track_origins = weak_odr {{.*}}constant i32 2
+// MSAN-1-LTO: @__msan_track_origins = weak_odr {{.*}}constant i32 1
+// MSAN-2-LTO: @__msan_track_origins = weak_odr {{.*}}constant i32 2
+//
+// MSAN-0-LABEL: define void @copy(
+// MSAN-1-LABEL: define void @copy(
+// MSAN-2-LABEL: define void @copy(
+#[no_mangle]
+pub fn copy(dst: &mut i32, src: &i32) {
+    // MSAN-0-NOT: call i32 @__msan_chain_origin(
+    // MSAN-1-NOT: call i32 @__msan_chain_origin(
+    // MSAN-2:     call i32 @__msan_chain_origin(
+    *dst = *src;
+}
diff --git a/tests/codegen/sanitizer-no-sanitize-inlining.rs b/tests/codegen/sanitizer-no-sanitize-inlining.rs
new file mode 100644
index 00000000000..f4af60baefe
--- /dev/null
+++ b/tests/codegen/sanitizer-no-sanitize-inlining.rs
@@ -0,0 +1,30 @@
+// Verifies that no_sanitize attribute prevents inlining when
+// given sanitizer is enabled, but has no effect on inlining otherwise.
+//
+// needs-sanitizer-address
+// needs-sanitizer-leak
+// revisions: ASAN LSAN
+//[ASAN] compile-flags: -Zsanitizer=address -C opt-level=3 -Z mir-opt-level=4
+//[LSAN] compile-flags: -Zsanitizer=leak    -C opt-level=3 -Z mir-opt-level=4
+
+#![crate_type="lib"]
+#![feature(no_sanitize)]
+
+// ASAN-LABEL: define void @test
+// ASAN:         call {{.*}} @random_inline
+// ASAN:       }
+//
+// LSAN-LABEL: define void @test
+// LSAN-NO:      call
+// LSAN:       }
+#[no_mangle]
+pub fn test(n: &mut u32) {
+    random_inline(n);
+}
+
+#[no_sanitize(address)]
+#[inline]
+#[no_mangle]
+pub fn random_inline(n: &mut u32) {
+    *n = 42;
+}
diff --git a/tests/codegen/sanitizer-no-sanitize.rs b/tests/codegen/sanitizer-no-sanitize.rs
new file mode 100644
index 00000000000..fb9d249da03
--- /dev/null
+++ b/tests/codegen/sanitizer-no-sanitize.rs
@@ -0,0 +1,29 @@
+// Verifies that no_sanitize attribute can be used to
+// selectively disable sanitizer instrumentation.
+//
+// needs-sanitizer-address
+// compile-flags: -Zsanitizer=address
+
+#![crate_type="lib"]
+#![feature(no_sanitize)]
+
+// CHECK-LABEL: ; sanitizer_no_sanitize::unsanitized
+// CHECK-NEXT:  ; Function Attrs:
+// CHECK-NOT:   sanitize_address
+// CHECK:       start:
+// CHECK-NOT:   call void @__asan_report_load
+// CHECK:       }
+#[no_sanitize(address)]
+pub fn unsanitized(b: &mut u8) -> u8 {
+    *b
+}
+
+// CHECK-LABEL: ; sanitizer_no_sanitize::sanitized
+// CHECK-NEXT:  ; Function Attrs:
+// CHECK:       sanitize_address
+// CHECK:       start:
+// CHECK:       call void @__asan_report_load
+// CHECK:       }
+pub fn sanitized(b: &mut u8) -> u8 {
+    *b
+}
diff --git a/tests/codegen/sanitizer-recover.rs b/tests/codegen/sanitizer-recover.rs
new file mode 100644
index 00000000000..7b00fcf8e1b
--- /dev/null
+++ b/tests/codegen/sanitizer-recover.rs
@@ -0,0 +1,49 @@
+// Verifies that AddressSanitizer and MemorySanitizer
+// recovery mode can be enabled with -Zsanitizer-recover.
+//
+// needs-sanitizer-address
+// needs-sanitizer-memory
+// revisions:ASAN ASAN-RECOVER MSAN MSAN-RECOVER MSAN-RECOVER-LTO
+// no-prefer-dynamic
+//
+//[ASAN]             compile-flags: -Zsanitizer=address -Copt-level=0
+//[ASAN-RECOVER]     compile-flags: -Zsanitizer=address -Zsanitizer-recover=address -Copt-level=0
+//[MSAN]             compile-flags: -Zsanitizer=memory
+//[MSAN-RECOVER]     compile-flags: -Zsanitizer=memory  -Zsanitizer-recover=memory
+//[MSAN-RECOVER-LTO] compile-flags: -Zsanitizer=memory  -Zsanitizer-recover=memory -C lto=fat
+//
+// MSAN-NOT:         @__msan_keep_going
+// MSAN-RECOVER:     @__msan_keep_going = weak_odr {{.*}}constant i32 1
+// MSAN-RECOVER-LTO: @__msan_keep_going = weak_odr {{.*}}constant i32 1
+
+// ASAN-LABEL: define dso_local i32 @penguin(
+// ASAN:         call void @__asan_report_load4(i64 %0)
+// ASAN:         unreachable
+// ASAN:       }
+//
+// ASAN-RECOVER-LABEL: define dso_local i32 @penguin(
+// ASAN-RECOVER:         call void @__asan_report_load4_noabort(
+// ASAN-RECOVER-NOT:     unreachable
+// ASAN:               }
+//
+// MSAN-LABEL: define dso_local noundef i32 @penguin(
+// MSAN:         call void @__msan_warning{{(_with_origin_noreturn\(i32 0\)|_noreturn\(\))}}
+// MSAN:         unreachable
+// MSAN:       }
+//
+// MSAN-RECOVER-LABEL: define dso_local noundef i32 @penguin(
+// MSAN-RECOVER:         call void @__msan_warning{{(_with_origin\(i32 0\)|\(\))}}
+// MSAN-RECOVER-NOT:     unreachable
+// MSAN-RECOVER:       }
+//
+// MSAN-RECOVER-LTO-LABEL: define dso_local noundef i32 @penguin(
+// MSAN-RECOVER-LTO:          call void @__msan_warning{{(_with_origin\(i32 0\)|\(\))}}
+// MSAN-RECOVER-LTO-NOT:      unreachable
+// MSAN-RECOVER-LTO:       }
+//
+#[no_mangle]
+pub fn penguin(p: &mut i32) -> i32 {
+    *p
+}
+
+fn main() {}
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/sanitizer_memtag_attr_check.rs b/tests/codegen/sanitizer_memtag_attr_check.rs
new file mode 100644
index 00000000000..2fd362656d4
--- /dev/null
+++ b/tests/codegen/sanitizer_memtag_attr_check.rs
@@ -0,0 +1,12 @@
+// This tests that the sanitize_memtag attribute is
+// applied when enabling the memtag sanitizer.
+//
+// needs-sanitizer-memtag
+// compile-flags: -Zsanitizer=memtag -Ctarget-feature=+mte
+
+#![crate_type = "lib"]
+
+// CHECK: ; Function Attrs:{{.*}}sanitize_memtag
+pub fn tagged() {}
+
+// CHECK: attributes #0 = {{.*}}sanitize_memtag
diff --git a/tests/codegen/sanitizer_scs_attr_check.rs b/tests/codegen/sanitizer_scs_attr_check.rs
new file mode 100644
index 00000000000..a885d911717
--- /dev/null
+++ b/tests/codegen/sanitizer_scs_attr_check.rs
@@ -0,0 +1,17 @@
+// This tests that the shadowcallstack attribute is
+// applied when enabling the shadow-call-stack sanitizer.
+//
+// needs-sanitizer-shadow-call-stack
+// compile-flags: -Zsanitizer=shadow-call-stack
+
+#![crate_type = "lib"]
+#![feature(no_sanitize)]
+
+// CHECK: ; sanitizer_scs_attr_check::scs
+// CHECK-NEXT: ; Function Attrs:{{.*}}shadowcallstack
+pub fn scs() {}
+
+// CHECK: ; sanitizer_scs_attr_check::no_scs
+// CHECK-NOT: ; Function Attrs:{{.*}}shadowcallstack
+#[no_sanitize(shadow_call_stack)]
+pub fn no_scs() {}
diff --git a/tests/codegen/scalar-pair-bool.rs b/tests/codegen/scalar-pair-bool.rs
new file mode 100644
index 00000000000..8e8365b6a67
--- /dev/null
+++ b/tests/codegen/scalar-pair-bool.rs
@@ -0,0 +1,45 @@
+// compile-flags: -O
+
+#![crate_type = "lib"]
+
+// CHECK: define{{.*}}{ i8, i8 } @pair_bool_bool(i1 noundef zeroext %pair.0, i1 noundef zeroext %pair.1)
+#[no_mangle]
+pub fn pair_bool_bool(pair: (bool, bool)) -> (bool, bool) {
+    pair
+}
+
+// CHECK: define{{.*}}{ i8, i32 } @pair_bool_i32(i1 noundef zeroext %pair.0, i32 noundef %pair.1)
+#[no_mangle]
+pub fn pair_bool_i32(pair: (bool, i32)) -> (bool, i32) {
+    pair
+}
+
+// CHECK: define{{.*}}{ i32, i8 } @pair_i32_bool(i32 noundef %pair.0, i1 noundef zeroext %pair.1)
+#[no_mangle]
+pub fn pair_i32_bool(pair: (i32, bool)) -> (i32, bool) {
+    pair
+}
+
+// CHECK: define{{.*}}{ i8, i8 } @pair_and_or(i1 noundef zeroext %_1.0, i1 noundef zeroext %_1.1)
+#[no_mangle]
+pub fn pair_and_or((a, b): (bool, bool)) -> (bool, bool) {
+    // Make sure it can operate directly on the unpacked args
+    // (but it might not be using simple and/or instructions)
+    // CHECK-DAG: %_1.0
+    // CHECK-DAG: %_1.1
+    (a && b, a || b)
+}
+
+// CHECK: define{{.*}}void @pair_branches(i1 noundef zeroext %_1.0, i1 noundef zeroext %_1.1)
+#[no_mangle]
+pub fn pair_branches((a, b): (bool, bool)) {
+    // Make sure it can branch directly on the unpacked bool args
+    // CHECK: br i1 %_1.0
+    if a {
+        println!("Hello!");
+    }
+    // CHECK: br i1 %_1.1
+    if b {
+        println!("Goodbye!");
+    }
+}
diff --git a/tests/codegen/set-discriminant-invalid.rs b/tests/codegen/set-discriminant-invalid.rs
new file mode 100644
index 00000000000..bccb9e4c758
--- /dev/null
+++ b/tests/codegen/set-discriminant-invalid.rs
@@ -0,0 +1,43 @@
+// compile-flags: -C opt-level=0
+#![crate_type = "lib"]
+
+pub enum ApiError {}
+#[allow(dead_code)]
+pub struct TokioError {
+    b: bool,
+}
+pub enum Error {
+    Api {
+        source: ApiError,
+    },
+    Ethereum,
+    Tokio {
+        source: TokioError,
+    },
+}
+struct Api;
+impl IntoError<Error> for Api
+{
+    type Source = ApiError;
+    // CHECK-LABEL: @into_error
+    // CHECK: llvm.trap()
+    // Also check the next two instructions to make sure we do not match against `trap`
+    // elsewhere in the code.
+    // CHECK-NEXT: load
+    // CHECK-NEXT: ret
+    #[no_mangle]
+    fn into_error(self, error: Self::Source) -> Error {
+        Error::Api {
+            source: error,
+        }
+    }
+}
+
+pub trait IntoError<E>
+{
+    /// The underlying error
+    type Source;
+
+    /// Combine the information to produce the error
+    fn into_error(self, source: Self::Source) -> E;
+}
diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-abs.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-abs.rs
new file mode 100644
index 00000000000..e7bb2327a6e
--- /dev/null
+++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-abs.rs
@@ -0,0 +1,92 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x2(pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x4(pub f32, pub f32, pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x8(pub f32, pub f32, pub f32, pub f32,
+                 pub f32, pub f32, pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x16(pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32);
+
+extern "platform-intrinsic" {
+    fn simd_fabs<T>(x: T) -> T;
+}
+
+// CHECK-LABEL: @fabs_32x2
+#[no_mangle]
+pub unsafe fn fabs_32x2(a: f32x2) -> f32x2 {
+    // CHECK: call <2 x float> @llvm.fabs.v2f32
+    simd_fabs(a)
+}
+
+// CHECK-LABEL: @fabs_32x4
+#[no_mangle]
+pub unsafe fn fabs_32x4(a: f32x4) -> f32x4 {
+    // CHECK: call <4 x float> @llvm.fabs.v4f32
+    simd_fabs(a)
+}
+
+// CHECK-LABEL: @fabs_32x8
+#[no_mangle]
+pub unsafe fn fabs_32x8(a: f32x8) -> f32x8 {
+    // CHECK: call <8 x float> @llvm.fabs.v8f32
+    simd_fabs(a)
+}
+
+// CHECK-LABEL: @fabs_32x16
+#[no_mangle]
+pub unsafe fn fabs_32x16(a: f32x16) -> f32x16 {
+    // CHECK: call <16 x float> @llvm.fabs.v16f32
+    simd_fabs(a)
+}
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x2(pub f64, pub f64);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x4(pub f64, pub f64, pub f64, pub f64);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x8(pub f64, pub f64, pub f64, pub f64,
+                 pub f64, pub f64, pub f64, pub f64);
+
+// CHECK-LABEL: @fabs_64x4
+#[no_mangle]
+pub unsafe fn fabs_64x4(a: f64x4) -> f64x4 {
+    // CHECK: call <4 x double> @llvm.fabs.v4f64
+    simd_fabs(a)
+}
+
+// CHECK-LABEL: @fabs_64x2
+#[no_mangle]
+pub unsafe fn fabs_64x2(a: f64x2) -> f64x2 {
+    // CHECK: call <2 x double> @llvm.fabs.v2f64
+    simd_fabs(a)
+}
+
+// CHECK-LABEL: @fabs_64x8
+#[no_mangle]
+pub unsafe fn fabs_64x8(a: f64x8) -> f64x8 {
+    // CHECK: call <8 x double> @llvm.fabs.v8f64
+    simd_fabs(a)
+}
diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-ceil.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-ceil.rs
new file mode 100644
index 00000000000..e33482d7556
--- /dev/null
+++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-ceil.rs
@@ -0,0 +1,92 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x2(pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x4(pub f32, pub f32, pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x8(pub f32, pub f32, pub f32, pub f32,
+                 pub f32, pub f32, pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x16(pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32);
+
+extern "platform-intrinsic" {
+    fn simd_ceil<T>(x: T) -> T;
+}
+
+// CHECK-LABEL: @ceil_32x2
+#[no_mangle]
+pub unsafe fn ceil_32x2(a: f32x2) -> f32x2 {
+    // CHECK: call <2 x float> @llvm.ceil.v2f32
+    simd_ceil(a)
+}
+
+// CHECK-LABEL: @ceil_32x4
+#[no_mangle]
+pub unsafe fn ceil_32x4(a: f32x4) -> f32x4 {
+    // CHECK: call <4 x float> @llvm.ceil.v4f32
+    simd_ceil(a)
+}
+
+// CHECK-LABEL: @ceil_32x8
+#[no_mangle]
+pub unsafe fn ceil_32x8(a: f32x8) -> f32x8 {
+    // CHECK: call <8 x float> @llvm.ceil.v8f32
+    simd_ceil(a)
+}
+
+// CHECK-LABEL: @ceil_32x16
+#[no_mangle]
+pub unsafe fn ceil_32x16(a: f32x16) -> f32x16 {
+    // CHECK: call <16 x float> @llvm.ceil.v16f32
+    simd_ceil(a)
+}
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x2(pub f64, pub f64);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x4(pub f64, pub f64, pub f64, pub f64);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x8(pub f64, pub f64, pub f64, pub f64,
+                 pub f64, pub f64, pub f64, pub f64);
+
+// CHECK-LABEL: @ceil_64x4
+#[no_mangle]
+pub unsafe fn ceil_64x4(a: f64x4) -> f64x4 {
+    // CHECK: call <4 x double> @llvm.ceil.v4f64
+    simd_ceil(a)
+}
+
+// CHECK-LABEL: @ceil_64x2
+#[no_mangle]
+pub unsafe fn ceil_64x2(a: f64x2) -> f64x2 {
+    // CHECK: call <2 x double> @llvm.ceil.v2f64
+    simd_ceil(a)
+}
+
+// CHECK-LABEL: @ceil_64x8
+#[no_mangle]
+pub unsafe fn ceil_64x8(a: f64x8) -> f64x8 {
+    // CHECK: call <8 x double> @llvm.ceil.v8f64
+    simd_ceil(a)
+}
diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-cos.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-cos.rs
new file mode 100644
index 00000000000..0f52952bc0c
--- /dev/null
+++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-cos.rs
@@ -0,0 +1,92 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x2(pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x4(pub f32, pub f32, pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x8(pub f32, pub f32, pub f32, pub f32,
+                 pub f32, pub f32, pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x16(pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32);
+
+extern "platform-intrinsic" {
+    fn simd_fcos<T>(x: T) -> T;
+}
+
+// CHECK-LABEL: @fcos_32x2
+#[no_mangle]
+pub unsafe fn fcos_32x2(a: f32x2) -> f32x2 {
+    // CHECK: call <2 x float> @llvm.cos.v2f32
+    simd_fcos(a)
+}
+
+// CHECK-LABEL: @fcos_32x4
+#[no_mangle]
+pub unsafe fn fcos_32x4(a: f32x4) -> f32x4 {
+    // CHECK: call <4 x float> @llvm.cos.v4f32
+    simd_fcos(a)
+}
+
+// CHECK-LABEL: @fcos_32x8
+#[no_mangle]
+pub unsafe fn fcos_32x8(a: f32x8) -> f32x8 {
+    // CHECK: call <8 x float> @llvm.cos.v8f32
+    simd_fcos(a)
+}
+
+// CHECK-LABEL: @fcos_32x16
+#[no_mangle]
+pub unsafe fn fcos_32x16(a: f32x16) -> f32x16 {
+    // CHECK: call <16 x float> @llvm.cos.v16f32
+    simd_fcos(a)
+}
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x2(pub f64, pub f64);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x4(pub f64, pub f64, pub f64, pub f64);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x8(pub f64, pub f64, pub f64, pub f64,
+                 pub f64, pub f64, pub f64, pub f64);
+
+// CHECK-LABEL: @fcos_64x4
+#[no_mangle]
+pub unsafe fn fcos_64x4(a: f64x4) -> f64x4 {
+    // CHECK: call <4 x double> @llvm.cos.v4f64
+    simd_fcos(a)
+}
+
+// CHECK-LABEL: @fcos_64x2
+#[no_mangle]
+pub unsafe fn fcos_64x2(a: f64x2) -> f64x2 {
+    // CHECK: call <2 x double> @llvm.cos.v2f64
+    simd_fcos(a)
+}
+
+// CHECK-LABEL: @fcos_64x8
+#[no_mangle]
+pub unsafe fn fcos_64x8(a: f64x8) -> f64x8 {
+    // CHECK: call <8 x double> @llvm.cos.v8f64
+    simd_fcos(a)
+}
diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-exp.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-exp.rs
new file mode 100644
index 00000000000..1154acf6924
--- /dev/null
+++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-exp.rs
@@ -0,0 +1,92 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x2(pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x4(pub f32, pub f32, pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x8(pub f32, pub f32, pub f32, pub f32,
+                 pub f32, pub f32, pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x16(pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32);
+
+extern "platform-intrinsic" {
+    fn simd_fexp<T>(x: T) -> T;
+}
+
+// CHECK-LABEL: @exp_32x2
+#[no_mangle]
+pub unsafe fn exp_32x2(a: f32x2) -> f32x2 {
+    // CHECK: call <2 x float> @llvm.exp.v2f32
+    simd_fexp(a)
+}
+
+// CHECK-LABEL: @exp_32x4
+#[no_mangle]
+pub unsafe fn exp_32x4(a: f32x4) -> f32x4 {
+    // CHECK: call <4 x float> @llvm.exp.v4f32
+    simd_fexp(a)
+}
+
+// CHECK-LABEL: @exp_32x8
+#[no_mangle]
+pub unsafe fn exp_32x8(a: f32x8) -> f32x8 {
+    // CHECK: call <8 x float> @llvm.exp.v8f32
+    simd_fexp(a)
+}
+
+// CHECK-LABEL: @exp_32x16
+#[no_mangle]
+pub unsafe fn exp_32x16(a: f32x16) -> f32x16 {
+    // CHECK: call <16 x float> @llvm.exp.v16f32
+    simd_fexp(a)
+}
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x2(pub f64, pub f64);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x4(pub f64, pub f64, pub f64, pub f64);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x8(pub f64, pub f64, pub f64, pub f64,
+                 pub f64, pub f64, pub f64, pub f64);
+
+// CHECK-LABEL: @exp_64x4
+#[no_mangle]
+pub unsafe fn exp_64x4(a: f64x4) -> f64x4 {
+    // CHECK: call <4 x double> @llvm.exp.v4f64
+    simd_fexp(a)
+}
+
+// CHECK-LABEL: @exp_64x2
+#[no_mangle]
+pub unsafe fn exp_64x2(a: f64x2) -> f64x2 {
+    // CHECK: call <2 x double> @llvm.exp.v2f64
+    simd_fexp(a)
+}
+
+// CHECK-LABEL: @exp_64x8
+#[no_mangle]
+pub unsafe fn exp_64x8(a: f64x8) -> f64x8 {
+    // CHECK: call <8 x double> @llvm.exp.v8f64
+    simd_fexp(a)
+}
diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-exp2.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-exp2.rs
new file mode 100644
index 00000000000..929dc9ac8df
--- /dev/null
+++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-exp2.rs
@@ -0,0 +1,92 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x2(pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x4(pub f32, pub f32, pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x8(pub f32, pub f32, pub f32, pub f32,
+                 pub f32, pub f32, pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x16(pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32);
+
+extern "platform-intrinsic" {
+    fn simd_fexp2<T>(x: T) -> T;
+}
+
+// CHECK-LABEL: @exp2_32x2
+#[no_mangle]
+pub unsafe fn exp2_32x2(a: f32x2) -> f32x2 {
+    // CHECK: call <2 x float> @llvm.exp2.v2f32
+    simd_fexp2(a)
+}
+
+// CHECK-LABEL: @exp2_32x4
+#[no_mangle]
+pub unsafe fn exp2_32x4(a: f32x4) -> f32x4 {
+    // CHECK: call <4 x float> @llvm.exp2.v4f32
+    simd_fexp2(a)
+}
+
+// CHECK-LABEL: @exp2_32x8
+#[no_mangle]
+pub unsafe fn exp2_32x8(a: f32x8) -> f32x8 {
+    // CHECK: call <8 x float> @llvm.exp2.v8f32
+    simd_fexp2(a)
+}
+
+// CHECK-LABEL: @exp2_32x16
+#[no_mangle]
+pub unsafe fn exp2_32x16(a: f32x16) -> f32x16 {
+    // CHECK: call <16 x float> @llvm.exp2.v16f32
+    simd_fexp2(a)
+}
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x2(pub f64, pub f64);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x4(pub f64, pub f64, pub f64, pub f64);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x8(pub f64, pub f64, pub f64, pub f64,
+                 pub f64, pub f64, pub f64, pub f64);
+
+// CHECK-LABEL: @exp2_64x4
+#[no_mangle]
+pub unsafe fn exp2_64x4(a: f64x4) -> f64x4 {
+    // CHECK: call <4 x double> @llvm.exp2.v4f64
+    simd_fexp2(a)
+}
+
+// CHECK-LABEL: @exp2_64x2
+#[no_mangle]
+pub unsafe fn exp2_64x2(a: f64x2) -> f64x2 {
+    // CHECK: call <2 x double> @llvm.exp2.v2f64
+    simd_fexp2(a)
+}
+
+// CHECK-LABEL: @exp2_64x8
+#[no_mangle]
+pub unsafe fn exp2_64x8(a: f64x8) -> f64x8 {
+    // CHECK: call <8 x double> @llvm.exp2.v8f64
+    simd_fexp2(a)
+}
diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-floor.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-floor.rs
new file mode 100644
index 00000000000..56ca644f6bd
--- /dev/null
+++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-floor.rs
@@ -0,0 +1,92 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x2(pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x4(pub f32, pub f32, pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x8(pub f32, pub f32, pub f32, pub f32,
+                 pub f32, pub f32, pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x16(pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32);
+
+extern "platform-intrinsic" {
+    fn simd_floor<T>(x: T) -> T;
+}
+
+// CHECK-LABEL: @floor_32x2
+#[no_mangle]
+pub unsafe fn floor_32x2(a: f32x2) -> f32x2 {
+    // CHECK: call <2 x float> @llvm.floor.v2f32
+    simd_floor(a)
+}
+
+// CHECK-LABEL: @floor_32x4
+#[no_mangle]
+pub unsafe fn floor_32x4(a: f32x4) -> f32x4 {
+    // CHECK: call <4 x float> @llvm.floor.v4f32
+    simd_floor(a)
+}
+
+// CHECK-LABEL: @floor_32x8
+#[no_mangle]
+pub unsafe fn floor_32x8(a: f32x8) -> f32x8 {
+    // CHECK: call <8 x float> @llvm.floor.v8f32
+    simd_floor(a)
+}
+
+// CHECK-LABEL: @floor_32x16
+#[no_mangle]
+pub unsafe fn floor_32x16(a: f32x16) -> f32x16 {
+    // CHECK: call <16 x float> @llvm.floor.v16f32
+    simd_floor(a)
+}
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x2(pub f64, pub f64);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x4(pub f64, pub f64, pub f64, pub f64);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x8(pub f64, pub f64, pub f64, pub f64,
+                 pub f64, pub f64, pub f64, pub f64);
+
+// CHECK-LABEL: @floor_64x4
+#[no_mangle]
+pub unsafe fn floor_64x4(a: f64x4) -> f64x4 {
+    // CHECK: call <4 x double> @llvm.floor.v4f64
+    simd_floor(a)
+}
+
+// CHECK-LABEL: @floor_64x2
+#[no_mangle]
+pub unsafe fn floor_64x2(a: f64x2) -> f64x2 {
+    // CHECK: call <2 x double> @llvm.floor.v2f64
+    simd_floor(a)
+}
+
+// CHECK-LABEL: @floor_64x8
+#[no_mangle]
+pub unsafe fn floor_64x8(a: f64x8) -> f64x8 {
+    // CHECK: call <8 x double> @llvm.floor.v8f64
+    simd_floor(a)
+}
diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-fma.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-fma.rs
new file mode 100644
index 00000000000..fd65cb72baa
--- /dev/null
+++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-fma.rs
@@ -0,0 +1,92 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x2(pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x4(pub f32, pub f32, pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x8(pub f32, pub f32, pub f32, pub f32,
+                 pub f32, pub f32, pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x16(pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32);
+
+extern "platform-intrinsic" {
+    fn simd_fma<T>(x: T, b: T, c: T) -> T;
+}
+
+// CHECK-LABEL: @fma_32x2
+#[no_mangle]
+pub unsafe fn fma_32x2(a: f32x2, b: f32x2, c: f32x2) -> f32x2 {
+    // CHECK: call <2 x float> @llvm.fma.v2f32
+    simd_fma(a, b, c)
+}
+
+// CHECK-LABEL: @fma_32x4
+#[no_mangle]
+pub unsafe fn fma_32x4(a: f32x4, b: f32x4, c: f32x4) -> f32x4 {
+    // CHECK: call <4 x float> @llvm.fma.v4f32
+    simd_fma(a, b, c)
+}
+
+// CHECK-LABEL: @fma_32x8
+#[no_mangle]
+pub unsafe fn fma_32x8(a: f32x8, b: f32x8, c: f32x8) -> f32x8 {
+    // CHECK: call <8 x float> @llvm.fma.v8f32
+    simd_fma(a, b, c)
+}
+
+// CHECK-LABEL: @fma_32x16
+#[no_mangle]
+pub unsafe fn fma_32x16(a: f32x16, b: f32x16, c: f32x16) -> f32x16 {
+    // CHECK: call <16 x float> @llvm.fma.v16f32
+    simd_fma(a, b, c)
+}
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x2(pub f64, pub f64);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x4(pub f64, pub f64, pub f64, pub f64);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x8(pub f64, pub f64, pub f64, pub f64,
+                 pub f64, pub f64, pub f64, pub f64);
+
+// CHECK-LABEL: @fma_64x4
+#[no_mangle]
+pub unsafe fn fma_64x4(a: f64x4, b: f64x4, c: f64x4) -> f64x4 {
+    // CHECK: call <4 x double> @llvm.fma.v4f64
+    simd_fma(a, b, c)
+}
+
+// CHECK-LABEL: @fma_64x2
+#[no_mangle]
+pub unsafe fn fma_64x2(a: f64x2, b: f64x2, c: f64x2) -> f64x2 {
+    // CHECK: call <2 x double> @llvm.fma.v2f64
+    simd_fma(a, b, c)
+}
+
+// CHECK-LABEL: @fma_64x8
+#[no_mangle]
+pub unsafe fn fma_64x8(a: f64x8, b: f64x8, c: f64x8) -> f64x8 {
+    // CHECK: call <8 x double> @llvm.fma.v8f64
+    simd_fma(a, b, c)
+}
diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-fsqrt.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-fsqrt.rs
new file mode 100644
index 00000000000..adc1919256e
--- /dev/null
+++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-fsqrt.rs
@@ -0,0 +1,92 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x2(pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x4(pub f32, pub f32, pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x8(pub f32, pub f32, pub f32, pub f32,
+                 pub f32, pub f32, pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x16(pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32);
+
+extern "platform-intrinsic" {
+    fn simd_fsqrt<T>(x: T) -> T;
+}
+
+// CHECK-LABEL: @fsqrt_32x2
+#[no_mangle]
+pub unsafe fn fsqrt_32x2(a: f32x2) -> f32x2 {
+    // CHECK: call <2 x float> @llvm.sqrt.v2f32
+    simd_fsqrt(a)
+}
+
+// CHECK-LABEL: @fsqrt_32x4
+#[no_mangle]
+pub unsafe fn fsqrt_32x4(a: f32x4) -> f32x4 {
+    // CHECK: call <4 x float> @llvm.sqrt.v4f32
+    simd_fsqrt(a)
+}
+
+// CHECK-LABEL: @fsqrt_32x8
+#[no_mangle]
+pub unsafe fn fsqrt_32x8(a: f32x8) -> f32x8 {
+    // CHECK: call <8 x float> @llvm.sqrt.v8f32
+    simd_fsqrt(a)
+}
+
+// CHECK-LABEL: @fsqrt_32x16
+#[no_mangle]
+pub unsafe fn fsqrt_32x16(a: f32x16) -> f32x16 {
+    // CHECK: call <16 x float> @llvm.sqrt.v16f32
+    simd_fsqrt(a)
+}
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x2(pub f64, pub f64);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x4(pub f64, pub f64, pub f64, pub f64);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x8(pub f64, pub f64, pub f64, pub f64,
+                 pub f64, pub f64, pub f64, pub f64);
+
+// CHECK-LABEL: @fsqrt_64x4
+#[no_mangle]
+pub unsafe fn fsqrt_64x4(a: f64x4) -> f64x4 {
+    // CHECK: call <4 x double> @llvm.sqrt.v4f64
+    simd_fsqrt(a)
+}
+
+// CHECK-LABEL: @fsqrt_64x2
+#[no_mangle]
+pub unsafe fn fsqrt_64x2(a: f64x2) -> f64x2 {
+    // CHECK: call <2 x double> @llvm.sqrt.v2f64
+    simd_fsqrt(a)
+}
+
+// CHECK-LABEL: @fsqrt_64x8
+#[no_mangle]
+pub unsafe fn fsqrt_64x8(a: f64x8) -> f64x8 {
+    // CHECK: call <8 x double> @llvm.sqrt.v8f64
+    simd_fsqrt(a)
+}
diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-log.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-log.rs
new file mode 100644
index 00000000000..c072519c0d6
--- /dev/null
+++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-log.rs
@@ -0,0 +1,92 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x2(pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x4(pub f32, pub f32, pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x8(pub f32, pub f32, pub f32, pub f32,
+                 pub f32, pub f32, pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x16(pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32);
+
+extern "platform-intrinsic" {
+    fn simd_flog<T>(x: T) -> T;
+}
+
+// CHECK-LABEL: @log_32x2
+#[no_mangle]
+pub unsafe fn log_32x2(a: f32x2) -> f32x2 {
+    // CHECK: call <2 x float> @llvm.log.v2f32
+    simd_flog(a)
+}
+
+// CHECK-LABEL: @log_32x4
+#[no_mangle]
+pub unsafe fn log_32x4(a: f32x4) -> f32x4 {
+    // CHECK: call <4 x float> @llvm.log.v4f32
+    simd_flog(a)
+}
+
+// CHECK-LABEL: @log_32x8
+#[no_mangle]
+pub unsafe fn log_32x8(a: f32x8) -> f32x8 {
+    // CHECK: call <8 x float> @llvm.log.v8f32
+    simd_flog(a)
+}
+
+// CHECK-LABEL: @log_32x16
+#[no_mangle]
+pub unsafe fn log_32x16(a: f32x16) -> f32x16 {
+    // CHECK: call <16 x float> @llvm.log.v16f32
+    simd_flog(a)
+}
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x2(pub f64, pub f64);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x4(pub f64, pub f64, pub f64, pub f64);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x8(pub f64, pub f64, pub f64, pub f64,
+                 pub f64, pub f64, pub f64, pub f64);
+
+// CHECK-LABEL: @log_64x4
+#[no_mangle]
+pub unsafe fn log_64x4(a: f64x4) -> f64x4 {
+    // CHECK: call <4 x double> @llvm.log.v4f64
+    simd_flog(a)
+}
+
+// CHECK-LABEL: @log_64x2
+#[no_mangle]
+pub unsafe fn log_64x2(a: f64x2) -> f64x2 {
+    // CHECK: call <2 x double> @llvm.log.v2f64
+    simd_flog(a)
+}
+
+// CHECK-LABEL: @log_64x8
+#[no_mangle]
+pub unsafe fn log_64x8(a: f64x8) -> f64x8 {
+    // CHECK: call <8 x double> @llvm.log.v8f64
+    simd_flog(a)
+}
diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-log10.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-log10.rs
new file mode 100644
index 00000000000..5fd64899507
--- /dev/null
+++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-log10.rs
@@ -0,0 +1,92 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x2(pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x4(pub f32, pub f32, pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x8(pub f32, pub f32, pub f32, pub f32,
+                 pub f32, pub f32, pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x16(pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32);
+
+extern "platform-intrinsic" {
+    fn simd_flog10<T>(x: T) -> T;
+}
+
+// CHECK-LABEL: @log10_32x2
+#[no_mangle]
+pub unsafe fn log10_32x2(a: f32x2) -> f32x2 {
+    // CHECK: call <2 x float> @llvm.log10.v2f32
+    simd_flog10(a)
+}
+
+// CHECK-LABEL: @log10_32x4
+#[no_mangle]
+pub unsafe fn log10_32x4(a: f32x4) -> f32x4 {
+    // CHECK: call <4 x float> @llvm.log10.v4f32
+    simd_flog10(a)
+}
+
+// CHECK-LABEL: @log10_32x8
+#[no_mangle]
+pub unsafe fn log10_32x8(a: f32x8) -> f32x8 {
+    // CHECK: call <8 x float> @llvm.log10.v8f32
+    simd_flog10(a)
+}
+
+// CHECK-LABEL: @log10_32x16
+#[no_mangle]
+pub unsafe fn log10_32x16(a: f32x16) -> f32x16 {
+    // CHECK: call <16 x float> @llvm.log10.v16f32
+    simd_flog10(a)
+}
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x2(pub f64, pub f64);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x4(pub f64, pub f64, pub f64, pub f64);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x8(pub f64, pub f64, pub f64, pub f64,
+                 pub f64, pub f64, pub f64, pub f64);
+
+// CHECK-LABEL: @log10_64x4
+#[no_mangle]
+pub unsafe fn log10_64x4(a: f64x4) -> f64x4 {
+    // CHECK: call <4 x double> @llvm.log10.v4f64
+    simd_flog10(a)
+}
+
+// CHECK-LABEL: @log10_64x2
+#[no_mangle]
+pub unsafe fn log10_64x2(a: f64x2) -> f64x2 {
+    // CHECK: call <2 x double> @llvm.log10.v2f64
+    simd_flog10(a)
+}
+
+// CHECK-LABEL: @log10_64x8
+#[no_mangle]
+pub unsafe fn log10_64x8(a: f64x8) -> f64x8 {
+    // CHECK: call <8 x double> @llvm.log10.v8f64
+    simd_flog10(a)
+}
diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-log2.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-log2.rs
new file mode 100644
index 00000000000..35175f0ca57
--- /dev/null
+++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-log2.rs
@@ -0,0 +1,92 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x2(pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x4(pub f32, pub f32, pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x8(pub f32, pub f32, pub f32, pub f32,
+                 pub f32, pub f32, pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x16(pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32);
+
+extern "platform-intrinsic" {
+    fn simd_flog2<T>(x: T) -> T;
+}
+
+// CHECK-LABEL: @log2_32x2
+#[no_mangle]
+pub unsafe fn log2_32x2(a: f32x2) -> f32x2 {
+    // CHECK: call <2 x float> @llvm.log2.v2f32
+    simd_flog2(a)
+}
+
+// CHECK-LABEL: @log2_32x4
+#[no_mangle]
+pub unsafe fn log2_32x4(a: f32x4) -> f32x4 {
+    // CHECK: call <4 x float> @llvm.log2.v4f32
+    simd_flog2(a)
+}
+
+// CHECK-LABEL: @log2_32x8
+#[no_mangle]
+pub unsafe fn log2_32x8(a: f32x8) -> f32x8 {
+    // CHECK: call <8 x float> @llvm.log2.v8f32
+    simd_flog2(a)
+}
+
+// CHECK-LABEL: @log2_32x16
+#[no_mangle]
+pub unsafe fn log2_32x16(a: f32x16) -> f32x16 {
+    // CHECK: call <16 x float> @llvm.log2.v16f32
+    simd_flog2(a)
+}
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x2(pub f64, pub f64);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x4(pub f64, pub f64, pub f64, pub f64);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x8(pub f64, pub f64, pub f64, pub f64,
+                 pub f64, pub f64, pub f64, pub f64);
+
+// CHECK-LABEL: @log2_64x4
+#[no_mangle]
+pub unsafe fn log2_64x4(a: f64x4) -> f64x4 {
+    // CHECK: call <4 x double> @llvm.log2.v4f64
+    simd_flog2(a)
+}
+
+// CHECK-LABEL: @log2_64x2
+#[no_mangle]
+pub unsafe fn log2_64x2(a: f64x2) -> f64x2 {
+    // CHECK: call <2 x double> @llvm.log2.v2f64
+    simd_flog2(a)
+}
+
+// CHECK-LABEL: @log2_64x8
+#[no_mangle]
+pub unsafe fn log2_64x8(a: f64x8) -> f64x8 {
+    // CHECK: call <8 x double> @llvm.log2.v8f64
+    simd_flog2(a)
+}
diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-minmax.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-minmax.rs
new file mode 100644
index 00000000000..4e0abed78cd
--- /dev/null
+++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-minmax.rs
@@ -0,0 +1,29 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x4(pub f32, pub f32, pub f32, pub f32);
+
+extern "platform-intrinsic" {
+    fn simd_fmin<T>(x: T, y: T) -> T;
+    fn simd_fmax<T>(x: T, y: T) -> T;
+}
+
+// CHECK-LABEL: @fmin
+#[no_mangle]
+pub unsafe fn fmin(a: f32x4, b: f32x4) -> f32x4 {
+    // CHECK: call <4 x float> @llvm.minnum.v4f32
+    simd_fmin(a, b)
+}
+
+// CHECK-LABEL: @fmax
+#[no_mangle]
+pub unsafe fn fmax(a: f32x4, b: f32x4) -> f32x4 {
+    // CHECK: call <4 x float> @llvm.maxnum.v4f32
+    simd_fmax(a, b)
+}
diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-pow.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-pow.rs
new file mode 100644
index 00000000000..3b8d611ab67
--- /dev/null
+++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-pow.rs
@@ -0,0 +1,92 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x2(pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x4(pub f32, pub f32, pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x8(pub f32, pub f32, pub f32, pub f32,
+                 pub f32, pub f32, pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x16(pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32);
+
+extern "platform-intrinsic" {
+    fn simd_fpow<T>(x: T, b: T) -> T;
+}
+
+// CHECK-LABEL: @fpow_32x2
+#[no_mangle]
+pub unsafe fn fpow_32x2(a: f32x2, b: f32x2) -> f32x2 {
+    // CHECK: call <2 x float> @llvm.pow.v2f32
+    simd_fpow(a, b)
+}
+
+// CHECK-LABEL: @fpow_32x4
+#[no_mangle]
+pub unsafe fn fpow_32x4(a: f32x4, b: f32x4) -> f32x4 {
+    // CHECK: call <4 x float> @llvm.pow.v4f32
+    simd_fpow(a, b)
+}
+
+// CHECK-LABEL: @fpow_32x8
+#[no_mangle]
+pub unsafe fn fpow_32x8(a: f32x8, b: f32x8) -> f32x8 {
+    // CHECK: call <8 x float> @llvm.pow.v8f32
+    simd_fpow(a, b)
+}
+
+// CHECK-LABEL: @fpow_32x16
+#[no_mangle]
+pub unsafe fn fpow_32x16(a: f32x16, b: f32x16) -> f32x16 {
+    // CHECK: call <16 x float> @llvm.pow.v16f32
+    simd_fpow(a, b)
+}
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x2(pub f64, pub f64);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x4(pub f64, pub f64, pub f64, pub f64);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x8(pub f64, pub f64, pub f64, pub f64,
+                 pub f64, pub f64, pub f64, pub f64);
+
+// CHECK-LABEL: @fpow_64x4
+#[no_mangle]
+pub unsafe fn fpow_64x4(a: f64x4, b: f64x4) -> f64x4 {
+    // CHECK: call <4 x double> @llvm.pow.v4f64
+    simd_fpow(a, b)
+}
+
+// CHECK-LABEL: @fpow_64x2
+#[no_mangle]
+pub unsafe fn fpow_64x2(a: f64x2, b: f64x2) -> f64x2 {
+    // CHECK: call <2 x double> @llvm.pow.v2f64
+    simd_fpow(a, b)
+}
+
+// CHECK-LABEL: @fpow_64x8
+#[no_mangle]
+pub unsafe fn fpow_64x8(a: f64x8, b: f64x8) -> f64x8 {
+    // CHECK: call <8 x double> @llvm.pow.v8f64
+    simd_fpow(a, b)
+}
diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-powi.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-powi.rs
new file mode 100644
index 00000000000..e80c50c1076
--- /dev/null
+++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-powi.rs
@@ -0,0 +1,92 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x2(pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x4(pub f32, pub f32, pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x8(pub f32, pub f32, pub f32, pub f32,
+                 pub f32, pub f32, pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x16(pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32);
+
+extern "platform-intrinsic" {
+    fn simd_fpowi<T>(x: T, b: i32) -> T;
+}
+
+// CHECK-LABEL: @fpowi_32x2
+#[no_mangle]
+pub unsafe fn fpowi_32x2(a: f32x2, b: i32) -> f32x2 {
+    // CHECK: call <2 x float> @llvm.powi.v2f32
+    simd_fpowi(a, b)
+}
+
+// CHECK-LABEL: @fpowi_32x4
+#[no_mangle]
+pub unsafe fn fpowi_32x4(a: f32x4, b: i32) -> f32x4 {
+    // CHECK: call <4 x float> @llvm.powi.v4f32
+    simd_fpowi(a, b)
+}
+
+// CHECK-LABEL: @fpowi_32x8
+#[no_mangle]
+pub unsafe fn fpowi_32x8(a: f32x8, b: i32) -> f32x8 {
+    // CHECK: call <8 x float> @llvm.powi.v8f32
+    simd_fpowi(a, b)
+}
+
+// CHECK-LABEL: @fpowi_32x16
+#[no_mangle]
+pub unsafe fn fpowi_32x16(a: f32x16, b: i32) -> f32x16 {
+    // CHECK: call <16 x float> @llvm.powi.v16f32
+    simd_fpowi(a, b)
+}
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x2(pub f64, pub f64);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x4(pub f64, pub f64, pub f64, pub f64);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x8(pub f64, pub f64, pub f64, pub f64,
+                 pub f64, pub f64, pub f64, pub f64);
+
+// CHECK-LABEL: @fpowi_64x4
+#[no_mangle]
+pub unsafe fn fpowi_64x4(a: f64x4, b: i32) -> f64x4 {
+    // CHECK: call <4 x double> @llvm.powi.v4f64
+    simd_fpowi(a, b)
+}
+
+// CHECK-LABEL: @fpowi_64x2
+#[no_mangle]
+pub unsafe fn fpowi_64x2(a: f64x2, b: i32) -> f64x2 {
+    // CHECK: call <2 x double> @llvm.powi.v2f64
+    simd_fpowi(a, b)
+}
+
+// CHECK-LABEL: @fpowi_64x8
+#[no_mangle]
+pub unsafe fn fpowi_64x8(a: f64x8, b: i32) -> f64x8 {
+    // CHECK: call <8 x double> @llvm.powi.v8f64
+    simd_fpowi(a, b)
+}
diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-sin.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-sin.rs
new file mode 100644
index 00000000000..9e3fab49aff
--- /dev/null
+++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-sin.rs
@@ -0,0 +1,92 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x2(pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x4(pub f32, pub f32, pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x8(pub f32, pub f32, pub f32, pub f32,
+                 pub f32, pub f32, pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x16(pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32,
+                  pub f32, pub f32, pub f32, pub f32);
+
+extern "platform-intrinsic" {
+    fn simd_fsin<T>(x: T) -> T;
+}
+
+// CHECK-LABEL: @fsin_32x2
+#[no_mangle]
+pub unsafe fn fsin_32x2(a: f32x2) -> f32x2 {
+    // CHECK: call <2 x float> @llvm.sin.v2f32
+    simd_fsin(a)
+}
+
+// CHECK-LABEL: @fsin_32x4
+#[no_mangle]
+pub unsafe fn fsin_32x4(a: f32x4) -> f32x4 {
+    // CHECK: call <4 x float> @llvm.sin.v4f32
+    simd_fsin(a)
+}
+
+// CHECK-LABEL: @fsin_32x8
+#[no_mangle]
+pub unsafe fn fsin_32x8(a: f32x8) -> f32x8 {
+    // CHECK: call <8 x float> @llvm.sin.v8f32
+    simd_fsin(a)
+}
+
+// CHECK-LABEL: @fsin_32x16
+#[no_mangle]
+pub unsafe fn fsin_32x16(a: f32x16) -> f32x16 {
+    // CHECK: call <16 x float> @llvm.sin.v16f32
+    simd_fsin(a)
+}
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x2(pub f64, pub f64);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x4(pub f64, pub f64, pub f64, pub f64);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f64x8(pub f64, pub f64, pub f64, pub f64,
+                 pub f64, pub f64, pub f64, pub f64);
+
+// CHECK-LABEL: @fsin_64x4
+#[no_mangle]
+pub unsafe fn fsin_64x4(a: f64x4) -> f64x4 {
+    // CHECK: call <4 x double> @llvm.sin.v4f64
+    simd_fsin(a)
+}
+
+// CHECK-LABEL: @fsin_64x2
+#[no_mangle]
+pub unsafe fn fsin_64x2(a: f64x2) -> f64x2 {
+    // CHECK: call <2 x double> @llvm.sin.v2f64
+    simd_fsin(a)
+}
+
+// CHECK-LABEL: @fsin_64x8
+#[no_mangle]
+pub unsafe fn fsin_64x8(a: f64x8) -> f64x8 {
+    // CHECK: call <8 x double> @llvm.sin.v8f64
+    simd_fsin(a)
+}
diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs
new file mode 100644
index 00000000000..0bcfacec6d7
--- /dev/null
+++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs
@@ -0,0 +1,692 @@
+// compile-flags: -C no-prepopulate-passes
+//
+
+#![crate_type = "lib"]
+
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+#![deny(unused)]
+
+// signed integer types
+
+#[repr(simd)] #[derive(Copy, Clone)] pub struct i8x2(i8, i8);
+#[repr(simd)] #[derive(Copy, Clone)] pub struct i8x4(i8, i8, i8, i8);
+#[repr(simd)] #[derive(Copy, Clone)] pub struct i8x8(
+    i8, i8, i8, i8, i8, i8, i8, i8,
+);
+#[repr(simd)] #[derive(Copy, Clone)] pub struct i8x16(
+    i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8,
+);
+#[repr(simd)] #[derive(Copy, Clone)] pub struct i8x32(
+    i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8,
+    i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8,
+);
+#[repr(simd)] #[derive(Copy, Clone)] pub struct i8x64(
+    i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8,
+    i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8,
+    i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8,
+    i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8,
+);
+
+#[repr(simd)] #[derive(Copy, Clone)] pub struct i16x2(i16, i16);
+#[repr(simd)] #[derive(Copy, Clone)] pub struct i16x4(i16, i16, i16, i16);
+#[repr(simd)] #[derive(Copy, Clone)] pub struct i16x8(
+    i16, i16, i16, i16, i16, i16, i16, i16,
+);
+#[repr(simd)] #[derive(Copy, Clone)] pub struct i16x16(
+    i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16,
+);
+#[repr(simd)] #[derive(Copy, Clone)] pub struct i16x32(
+    i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16,
+    i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16,
+);
+
+#[repr(simd)] #[derive(Copy, Clone)] pub struct i32x2(i32, i32);
+#[repr(simd)] #[derive(Copy, Clone)] pub struct i32x4(i32, i32, i32, i32);
+#[repr(simd)] #[derive(Copy, Clone)] pub struct i32x8(
+    i32, i32, i32, i32, i32, i32, i32, i32,
+);
+#[repr(simd)] #[derive(Copy, Clone)] pub struct i32x16(
+    i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32,
+);
+
+#[repr(simd)] #[derive(Copy, Clone)] pub struct i64x2(i64, i64);
+#[repr(simd)] #[derive(Copy, Clone)] pub struct i64x4(i64, i64, i64, i64);
+#[repr(simd)] #[derive(Copy, Clone)] pub struct i64x8(
+    i64, i64, i64, i64, i64, i64, i64, i64,
+);
+
+#[repr(simd)] #[derive(Copy, Clone)] pub struct i128x2(i128, i128);
+#[repr(simd)] #[derive(Copy, Clone)] pub struct i128x4(i128, i128, i128, i128);
+
+// unsigned integer types
+
+#[repr(simd)] #[derive(Copy, Clone)] pub struct u8x2(u8, u8);
+#[repr(simd)] #[derive(Copy, Clone)] pub struct u8x4(u8, u8, u8, u8);
+#[repr(simd)] #[derive(Copy, Clone)] pub struct u8x8(
+    u8, u8, u8, u8, u8, u8, u8, u8,
+);
+#[repr(simd)] #[derive(Copy, Clone)] pub struct u8x16(
+    u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8,
+);
+#[repr(simd)] #[derive(Copy, Clone)] pub struct u8x32(
+    u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8,
+    u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8,
+);
+#[repr(simd)] #[derive(Copy, Clone)] pub struct u8x64(
+    u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8,
+    u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8,
+    u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8,
+    u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8,
+);
+
+#[repr(simd)] #[derive(Copy, Clone)] pub struct u16x2(u16, u16);
+#[repr(simd)] #[derive(Copy, Clone)] pub struct u16x4(u16, u16, u16, u16);
+#[repr(simd)] #[derive(Copy, Clone)] pub struct u16x8(
+    u16, u16, u16, u16, u16, u16, u16, u16,
+);
+#[repr(simd)] #[derive(Copy, Clone)] pub struct u16x16(
+    u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16,
+);
+#[repr(simd)] #[derive(Copy, Clone)] pub struct u16x32(
+    u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16,
+    u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16,
+);
+
+#[repr(simd)] #[derive(Copy, Clone)] pub struct u32x2(u32, u32);
+#[repr(simd)] #[derive(Copy, Clone)] pub struct u32x4(u32, u32, u32, u32);
+#[repr(simd)] #[derive(Copy, Clone)] pub struct u32x8(
+    u32, u32, u32, u32, u32, u32, u32, u32,
+);
+#[repr(simd)] #[derive(Copy, Clone)] pub struct u32x16(
+    u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32,
+);
+
+#[repr(simd)] #[derive(Copy, Clone)] pub struct u64x2(u64, u64);
+#[repr(simd)] #[derive(Copy, Clone)] pub struct u64x4(u64, u64, u64, u64);
+#[repr(simd)] #[derive(Copy, Clone)] pub struct u64x8(
+    u64, u64, u64, u64, u64, u64, u64, u64,
+);
+
+#[repr(simd)] #[derive(Copy, Clone)] pub struct u128x2(u128, u128);
+#[repr(simd)] #[derive(Copy, Clone)] pub struct u128x4(u128, u128, u128, u128);
+
+extern "platform-intrinsic" {
+    fn simd_saturating_add<T>(x: T, y: T) -> T;
+    fn simd_saturating_sub<T>(x: T, y: T) -> T;
+}
+
+// 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 `%0` a vector loaded from that pointer.
+// This is controlled by the target spec option `simd_types_indirect`.
+// 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|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|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|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|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|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|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|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|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|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|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|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|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|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|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|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|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|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|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|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|0}}, <4 x i128> %{{y|1}})
+    simd_saturating_add(x, y)
+}
+
+
+
+// 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|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|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|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|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|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|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|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|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|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|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|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|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|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|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|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|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|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|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|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|0}}, <4 x i128> %{{y|1}})
+    simd_saturating_add(x, y)
+}
+
+
+
+
+
+// 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|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|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|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|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|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|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|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|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|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|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|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|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|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|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|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|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|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|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|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|0}}, <4 x i128> %{{y|1}})
+    simd_saturating_sub(x, y)
+}
+
+
+
+// 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|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|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|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|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|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|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|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|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|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|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|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|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|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|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|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|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|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|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|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|0}}, <4 x i128> %{{y|1}})
+    simd_saturating_sub(x, y)
+}
diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-bitmask.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-bitmask.rs
new file mode 100644
index 00000000000..ea24569bd10
--- /dev/null
+++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-bitmask.rs
@@ -0,0 +1,63 @@
+// compile-flags: -C no-prepopulate-passes
+//
+
+#![crate_type = "lib"]
+
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct u32x2(u32, u32);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct i32x2(i32, i32);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct i8x16(
+    i8, i8, i8, i8, i8, i8, i8, i8,
+    i8, i8, i8, i8, i8, i8, i8, i8,
+);
+
+
+extern "platform-intrinsic" {
+    fn simd_bitmask<T, U>(x: T) -> U;
+}
+
+// NOTE(eddyb) `%{{x|1}}` 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.
+// This is controlled by the target spec option `simd_types_indirect`.
+
+// CHECK-LABEL: @bitmask_int
+#[no_mangle]
+pub unsafe fn bitmask_int(x: i32x2) -> u8 {
+    // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> %{{x|1}}, <i32 31, i32 31>
+    // CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1>
+    // CHECK: [[C:%[0-9]+]] = bitcast <2 x i1> [[B]] to i2
+    // CHECK: %{{[0-9]+}} = zext i2 [[C]] to i8
+    simd_bitmask(x)
+}
+
+// CHECK-LABEL: @bitmask_uint
+#[no_mangle]
+pub unsafe fn bitmask_uint(x: u32x2) -> u8 {
+    // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> %{{x|1}}, <i32 31, i32 31>
+    // CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1>
+    // CHECK: [[C:%[0-9]+]] = bitcast <2 x i1> [[B]] to i2
+    // CHECK: %{{[0-9]+}} = zext i2 [[C]] to i8
+    simd_bitmask(x)
+}
+
+// CHECK-LABEL: @bitmask_int16
+#[no_mangle]
+pub unsafe fn bitmask_int16(x: i8x16) -> u16 {
+    // CHECK: [[A:%[0-9]+]] = lshr <16 x i8> %{{x|1|2}}, <i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7>
+    // CHECK: [[B:%[0-9]+]] = trunc <16 x i8> [[A]] to <16 x i1>
+    // CHECK: %{{[0-9]+}} = bitcast <16 x i1> [[B]] to i16
+    // CHECK-NOT: zext
+    simd_bitmask(x)
+}
diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs
new file mode 100644
index 00000000000..a5d2509d000
--- /dev/null
+++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs
@@ -0,0 +1,47 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+#![feature(repr_simd, platform_intrinsics, min_const_generics)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct M(pub f32, pub f32, pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct S<const N: usize>([f32; N]);
+
+extern "platform-intrinsic" {
+    fn simd_extract<T, U>(x: T, idx: u32) -> U;
+    fn simd_insert<T, U>(x: T, idx: u32, b: U) -> T;
+}
+
+// CHECK-LABEL: @extract_m
+#[no_mangle]
+pub unsafe fn extract_m(v: M, i: u32) -> f32  {
+    // CHECK: extractelement <4 x float> %{{v|1|2}}, i32 %i
+    simd_extract(v, i)
+}
+
+// CHECK-LABEL: @extract_s
+#[no_mangle]
+pub unsafe fn extract_s(v: S<4>, i: u32) -> f32  {
+    // CHECK: extractelement <4 x float> %{{v|1|2}}, i32 %i
+    simd_extract(v, i)
+}
+
+// CHECK-LABEL: @insert_m
+#[no_mangle]
+pub unsafe fn insert_m(v: M, i: u32, j: f32) -> M  {
+    // 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|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
new file mode 100644
index 00000000000..cacc32f2f1b
--- /dev/null
+++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-gather.rs
@@ -0,0 +1,36 @@
+//
+
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct Vec2<T>(pub T, pub T);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct Vec4<T>(pub T, pub T, pub T, pub T);
+
+extern "platform-intrinsic" {
+    fn simd_gather<T, P, M>(value: T, pointers: P, mask: M) -> T;
+}
+
+// CHECK-LABEL: @gather_f32x2
+#[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> {{.*}})
+    simd_gather(values, pointers, mask)
+}
+
+// CHECK-LABEL: @gather_pf32x2
+#[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}}> {{.*}})
+    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
new file mode 100644
index 00000000000..94ecaf6096d
--- /dev/null
+++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-scatter.rs
@@ -0,0 +1,37 @@
+//
+
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct Vec2<T>(pub T, pub T);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct Vec4<T>(pub T, pub T, pub T, pub T);
+
+extern "platform-intrinsic" {
+    fn simd_scatter<T, P, M>(value: T, pointers: P, mask: M);
+}
+
+// CHECK-LABEL: @scatter_f32x2
+#[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> {{.*}})
+    simd_scatter(values, pointers, mask)
+}
+
+
+// CHECK-LABEL: @scatter_pf32x2
+#[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> {{.*}})
+    simd_scatter(values, pointers, mask)
+}
diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-select.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-select.rs
new file mode 100644
index 00000000000..03bb2265526
--- /dev/null
+++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-select.rs
@@ -0,0 +1,37 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+#![feature(repr_simd, platform_intrinsics)]
+#[allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x4(pub f32, pub f32, pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct f32x8(f32, f32, f32, f32, f32, f32, f32, f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct b8x4(pub i8, pub i8, pub i8, pub i8);
+
+extern "platform-intrinsic" {
+    fn simd_select<T, U>(x: T, a: U, b: U) -> U;
+    fn simd_select_bitmask<T, U>(x: T, a: U, b: U) -> U;
+}
+
+// CHECK-LABEL: @select
+#[no_mangle]
+pub unsafe fn select(m: b8x4, a: f32x4, b: f32x4) -> f32x4 {
+    // CHECK: select <4 x i1>
+    simd_select(m, a, b)
+}
+
+// CHECK-LABEL: @select_bitmask
+#[no_mangle]
+pub unsafe fn select_bitmask(m: i8, a: f32x8, b: f32x8) -> f32x8 {
+    // CHECK: select <8 x i1>
+    simd_select_bitmask(m, a, b)
+}
diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs
new file mode 100644
index 00000000000..3a0e37de2f3
--- /dev/null
+++ b/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs
@@ -0,0 +1,82 @@
+//
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+#![allow(non_camel_case_types)]
+#![feature(repr_simd, platform_intrinsics)]
+#![feature(inline_const)]
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct S<const N: usize>([f32; N]);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct T([f32; 4]);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct U(f32, f32, f32, f32);
+
+// CHECK-LABEL: @array_align(
+#[no_mangle]
+pub fn array_align() -> usize {
+    // CHECK: ret [[USIZE:i[0-9]+]] [[ARRAY_ALIGN:[0-9]+]]
+    const { std::mem::align_of::<f32>() }
+}
+
+// CHECK-LABEL: @vector_align(
+#[no_mangle]
+pub fn vector_align() -> usize {
+    // CHECK: ret [[USIZE]] [[VECTOR_ALIGN:[0-9]+]]
+    const { std::mem::align_of::<U>() }
+}
+
+// CHECK-LABEL: @build_array_s
+#[no_mangle]
+pub fn build_array_s(x: [f32; 4]) -> S<4> {
+    // CHECK: call void @llvm.memcpy.{{.+}}({{.*}} align [[VECTOR_ALIGN]] {{.*}} align [[ARRAY_ALIGN]] {{.*}}, [[USIZE]] 16, i1 false)
+    S::<4>(x)
+}
+
+// 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]]
+    unsafe { std::mem::transmute(x) }
+}
+
+// CHECK-LABEL: @build_array_t
+#[no_mangle]
+pub fn build_array_t(x: [f32; 4]) -> T {
+    // CHECK: call void @llvm.memcpy.{{.+}}({{.*}} align [[VECTOR_ALIGN]] {{.*}} align [[ARRAY_ALIGN]] {{.*}}, [[USIZE]] 16, i1 false)
+    T(x)
+}
+
+// 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]]
+    unsafe { std::mem::transmute(x) }
+}
+
+// CHECK-LABEL: @build_array_u
+#[no_mangle]
+pub fn build_array_u(x: [f32; 4]) -> U {
+    // CHECK: store float %a, {{.+}}, align [[VECTOR_ALIGN]]
+    // CHECK: store float %b, {{.+}}, align [[ARRAY_ALIGN]]
+    // CHECK: store float %c, {{.+}}, align
+    // CHECK: store float %d, {{.+}}, align [[ARRAY_ALIGN]]
+    let [a, b, c, d] = x;
+    U(a, b, c, d)
+}
+
+// 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]]
+    unsafe { std::mem::transmute(x) }
+}
diff --git a/tests/codegen/simd-wide-sum.rs b/tests/codegen/simd-wide-sum.rs
new file mode 100644
index 00000000000..db2aa20bde7
--- /dev/null
+++ b/tests/codegen/simd-wide-sum.rs
@@ -0,0 +1,55 @@
+// compile-flags: -C opt-level=3 -Z merge-functions=disabled --edition=2021
+// only-x86_64
+// ignore-debug: the debug assertions get in the way
+
+#![crate_type = "lib"]
+#![feature(portable_simd)]
+
+use std::simd::{Simd, SimdUint};
+const N: usize = 8;
+
+#[no_mangle]
+// CHECK-LABEL: @wider_reduce_simd
+pub fn wider_reduce_simd(x: Simd<u8, N>) -> u16 {
+    // CHECK: zext <8 x i8>
+    // CHECK-SAME: to <8 x i16>
+    // CHECK: call i16 @llvm.vector.reduce.add.v8i16(<8 x i16>
+    let x: Simd<u16, N> = x.cast();
+    x.reduce_sum()
+}
+
+#[no_mangle]
+// CHECK-LABEL: @wider_reduce_loop
+pub fn wider_reduce_loop(x: Simd<u8, N>) -> u16 {
+    // CHECK: zext <8 x i8>
+    // CHECK-SAME: to <8 x i16>
+    // CHECK: call i16 @llvm.vector.reduce.add.v8i16(<8 x i16>
+    let mut sum = 0_u16;
+    for i in 0..N {
+        sum += u16::from(x[i]);
+    }
+    sum
+}
+
+#[no_mangle]
+// CHECK-LABEL: @wider_reduce_iter
+pub fn wider_reduce_iter(x: Simd<u8, N>) -> u16 {
+    // CHECK: zext <8 x i8>
+    // CHECK-SAME: to <8 x i16>
+    // CHECK: call i16 @llvm.vector.reduce.add.v8i16(<8 x i16>
+    x.as_array().iter().copied().map(u16::from).sum()
+}
+
+// This iterator one is the most interesting, as it's the one
+// which used to not auto-vectorize due to a suboptimality in the
+// `<array::IntoIter as Iterator>::fold` implementation.
+
+#[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>
+    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
new file mode 100644
index 00000000000..74d7edc70d7
--- /dev/null
+++ b/tests/codegen/simd_arith_offset.rs
@@ -0,0 +1,26 @@
+// compile-flags: -C no-prepopulate-passes
+// only-64bit (because the LLVM type of i64 for usize shows up)
+//
+
+#![crate_type = "lib"]
+#![feature(repr_simd, platform_intrinsics)]
+
+extern "platform-intrinsic" {
+    pub(crate) fn simd_arith_offset<T, U>(ptrs: T, offsets: U) -> T;
+}
+
+/// A vector of *const T.
+#[derive(Debug, Copy, Clone)]
+#[repr(simd)]
+pub struct SimdConstPtr<T, const LANES: usize>([*const T; LANES]);
+
+#[derive(Debug, Copy, Clone)]
+#[repr(simd)]
+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}}> %0, <8 x i64> %1
+    unsafe { simd_arith_offset(ptrs, offsets) }
+}
diff --git a/tests/codegen/slice-as_chunks.rs b/tests/codegen/slice-as_chunks.rs
new file mode 100644
index 00000000000..48e3f73fc86
--- /dev/null
+++ b/tests/codegen/slice-as_chunks.rs
@@ -0,0 +1,33 @@
+// no-system-llvm
+// compile-flags: -O
+// only-64bit (because the LLVM type of i64 for usize shows up)
+// ignore-debug: the debug assertions get in the way
+
+#![crate_type = "lib"]
+#![feature(slice_as_chunks)]
+
+// CHECK-LABEL: @chunks4
+#[no_mangle]
+pub fn chunks4(x: &[u8]) -> &[[u8; 4]] {
+    // CHECK-NEXT: start:
+    // CHECK-NEXT: lshr i64 %x.1, 2
+    // CHECK-NOT: shl
+    // CHECK-NOT: mul
+    // CHECK-NOT: udiv
+    // CHECK-NOT: urem
+    // CHECK: ret
+    x.as_chunks().0
+}
+
+// CHECK-LABEL: @chunks4_with_remainder
+#[no_mangle]
+pub fn chunks4_with_remainder(x: &[u8]) -> (&[[u8; 4]], &[u8]) {
+    // CHECK: and i64 %x.1, -4
+    // CHECK: and i64 %x.1, 3
+    // CHECK: lshr exact
+    // CHECK-NOT: mul
+    // CHECK-NOT: udiv
+    // CHECK-NOT: urem
+    // CHECK: ret
+    x.as_chunks()
+}
diff --git a/tests/codegen/slice-indexing.rs b/tests/codegen/slice-indexing.rs
new file mode 100644
index 00000000000..c40d59fb0cf
--- /dev/null
+++ b/tests/codegen/slice-indexing.rs
@@ -0,0 +1,35 @@
+// compile-flags: -O
+// only-64bit (because the LLVM type of i64 for usize shows up)
+// ignore-debug: the debug assertions get in the way
+
+#![crate_type = "lib"]
+
+use std::ops::Range;
+
+// CHECK-LABEL: @index_by_range(
+#[no_mangle]
+pub fn index_by_range(x: &[u16], r: Range<usize>) -> &[u16] {
+    // CHECK: sub nuw i64
+    &x[r]
+}
+
+// CHECK-LABEL: @get_unchecked_by_range(
+#[no_mangle]
+pub unsafe fn get_unchecked_by_range(x: &[u16], r: Range<usize>) -> &[u16] {
+    // CHECK: sub nuw i64
+    x.get_unchecked(r)
+}
+
+// CHECK-LABEL: @index_mut_by_range(
+#[no_mangle]
+pub fn index_mut_by_range(x: &mut [i32], r: Range<usize>) -> &mut [i32] {
+    // CHECK: sub nuw i64
+    &mut x[r]
+}
+
+// CHECK-LABEL: @get_unchecked_mut_by_range(
+#[no_mangle]
+pub unsafe fn get_unchecked_mut_by_range(x: &mut [i32], r: Range<usize>) -> &mut [i32] {
+    // CHECK: sub nuw i64
+    x.get_unchecked_mut(r)
+}
diff --git a/tests/codegen/slice-init.rs b/tests/codegen/slice-init.rs
new file mode 100644
index 00000000000..794b773a776
--- /dev/null
+++ b/tests/codegen/slice-init.rs
@@ -0,0 +1,64 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @zero_sized_elem
+#[no_mangle]
+pub fn zero_sized_elem() {
+    // CHECK-NOT: br label %repeat_loop_header{{.*}}
+    // CHECK-NOT: call void @llvm.memset.p0
+    let x = [(); 4];
+    drop(&x);
+}
+
+// CHECK-LABEL: @zero_len_array
+#[no_mangle]
+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);
+}
+
+// CHECK-LABEL: @byte_array
+#[no_mangle]
+pub fn byte_array() {
+    // CHECK: call void @llvm.memset.{{.+}}({{i8\*|ptr}} {{.*}}, i8 7, i{{[0-9]+}} 4
+    // CHECK-NOT: br label %repeat_loop_header{{.*}}
+    let x = [7u8; 4];
+    drop(&x);
+}
+
+#[allow(dead_code)]
+#[derive(Copy, Clone)]
+enum Init {
+    Loop,
+    Memset,
+}
+
+// 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-NOT: br label %repeat_loop_header{{.*}}
+    let x = [Init::Memset; 4];
+    drop(&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-NOT: br label %repeat_loop_header{{.*}}
+    let x = [0u32; 4];
+    drop(&x);
+}
+
+// CHECK-LABEL: @nonzero_integer_array
+#[no_mangle]
+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);
+}
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
new file mode 100644
index 00000000000..69f78cea564
--- /dev/null
+++ b/tests/codegen/slice-iter-len-eq-zero.rs
@@ -0,0 +1,28 @@
+// no-system-llvm
+// compile-flags: -O
+// ignore-debug: the debug assertions add extra comparisons
+#![crate_type = "lib"]
+
+type Demo = [u8; 3];
+
+// CHECK-LABEL: @slice_iter_len_eq_zero
+#[no_mangle]
+pub fn slice_iter_len_eq_zero(y: std::slice::Iter<'_, Demo>) -> bool {
+    // CHECK-NOT: sub
+    // CHECK: %_0 = icmp eq {{i8\*|ptr}} {{%1|%0}}, {{%1|%0}}
+    // CHECK: ret i1 %_0
+    y.len() == 0
+}
+
+// CHECK-LABEL: @array_into_iter_len_eq_zero
+#[no_mangle]
+pub fn array_into_iter_len_eq_zero(y: std::array::IntoIter<Demo, 123>) -> bool {
+    // This should be able to just check that the indexes are equal, and not
+    // need any subtractions or comparisons to handle `start > end`.
+
+    // CHECK-NOT: icmp
+    // CHECK-NOT: sub
+    // 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..997bdaf5636
--- /dev/null
+++ b/tests/codegen/slice-iter-nonnull.rs
@@ -0,0 +1,77 @@
+// no-system-llvm
+// compile-flags: -O
+// ignore-debug (these add extra checks that make it hard to verify)
+#![crate_type = "lib"]
+
+// 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.
+
+// 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()
+}
diff --git a/tests/codegen/slice-position-bounds-check.rs b/tests/codegen/slice-position-bounds-check.rs
new file mode 100644
index 00000000000..b494f42b296
--- /dev/null
+++ b/tests/codegen/slice-position-bounds-check.rs
@@ -0,0 +1,32 @@
+// no-system-llvm
+// compile-flags: -O -C panic=abort
+#![crate_type = "lib"]
+
+fn search<T: Ord + Eq>(arr: &mut [T], a: &T) -> Result<usize, ()> {
+    match arr.iter().position(|x| x == a) {
+        Some(p) => {
+            Ok(p)
+        },
+        None => Err(()),
+    }
+}
+
+// CHECK-LABEL: @position_no_bounds_check
+#[no_mangle]
+pub fn position_no_bounds_check(y: &mut [u32], x: &u32, z: &u32) -> bool {
+    // This contains "call assume" so we cannot just rule out all calls
+    // CHECK-NOT: panic_bounds_check
+    if let Ok(p) = search(y, x) {
+      y[p] == *z
+    } else {
+      false
+    }
+}
+
+// just to make sure that panicking really emits "panic_bounds_check" somewhere in the IR
+// CHECK-LABEL: @test_check
+#[no_mangle]
+pub fn test_check(y: &[i32]) -> i32 {
+    // CHECK: panic_bounds_check
+    y[12]
+}
diff --git a/tests/codegen/slice-ref-equality.rs b/tests/codegen/slice-ref-equality.rs
new file mode 100644
index 00000000000..8f0adab35e7
--- /dev/null
+++ b/tests/codegen/slice-ref-equality.rs
@@ -0,0 +1,92 @@
+// compile-flags: -O -Zmerge-functions=disabled
+// ignore-debug (the extra assertions get in the way)
+
+#![crate_type = "lib"]
+
+use std::num::{NonZeroI16, NonZeroU32};
+
+// #71602 reported a simple array comparison just generating a loop.
+// This was originally fixed by ensuring it generates a single bcmp,
+// but we now generate it as a load+icmp instead. `is_zero_slice` was
+// tweaked to still test the case of comparison against a slice,
+// and `is_zero_array` tests the new array-specific behaviour.
+// The optimization was then extended to short slice-to-array comparisons,
+// so the first test here now has a long slice to still get the bcmp.
+
+// CHECK-LABEL: @is_zero_slice_long
+#[no_mangle]
+pub fn is_zero_slice_long(data: &[u8; 456]) -> bool {
+    // CHECK: %[[BCMP:.+]] = tail call i32 @{{bcmp|memcmp}}({{.+}})
+    // CHECK-NEXT: %[[EQ:.+]] = icmp eq i32 %[[BCMP]], 0
+    // CHECK-NEXT: ret i1 %[[EQ]]
+    &data[..] == [0; 456]
+}
+
+// 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-NEXT: %[[EQ:.+]] = icmp eq i32 %[[LOAD]], 0
+    // CHECK-NEXT: ret i1 %[[EQ]]
+    &data[..] == [0; 4]
+}
+
+// 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-NEXT: %[[EQ:.+]] = icmp eq i32 %[[LOAD]], 0
+    // CHECK-NEXT: ret i1 %[[EQ]]
+    *data == [0; 4]
+}
+
+// The following test the extra specializations to make sure that slice
+// 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
+#[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-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
+#[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-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
+#[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-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
+#[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-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]])
+    x == y
+}
diff --git a/tests/codegen/slice-reverse.rs b/tests/codegen/slice-reverse.rs
new file mode 100644
index 00000000000..e50b22f3ac4
--- /dev/null
+++ b/tests/codegen/slice-reverse.rs
@@ -0,0 +1,27 @@
+// compile-flags: -O
+// only-x86_64
+// ignore-debug: the debug assertions in from_raw_parts get in the way
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @slice_reverse_u8
+#[no_mangle]
+pub fn slice_reverse_u8(slice: &mut [u8]) {
+    // CHECK-NOT: panic_bounds_check
+    // CHECK-NOT: slice_end_index_len_fail
+    // CHECK: shufflevector <{{[0-9]+}} x i8>
+    // CHECK-NOT: panic_bounds_check
+    // CHECK-NOT: slice_end_index_len_fail
+    slice.reverse();
+}
+
+// CHECK-LABEL: @slice_reverse_i32
+#[no_mangle]
+pub fn slice_reverse_i32(slice: &mut [i32]) {
+    // CHECK-NOT: panic_bounds_check
+    // CHECK-NOT: slice_end_index_len_fail
+    // CHECK: shufflevector <{{[0-9]+}} x i32>
+    // CHECK-NOT: panic_bounds_check
+    // CHECK-NOT: slice_end_index_len_fail
+    slice.reverse();
+}
diff --git a/tests/codegen/slice-windows-no-bounds-check.rs b/tests/codegen/slice-windows-no-bounds-check.rs
new file mode 100644
index 00000000000..4f5f4425c27
--- /dev/null
+++ b/tests/codegen/slice-windows-no-bounds-check.rs
@@ -0,0 +1,35 @@
+#![crate_type = "lib"]
+
+// compile-flags: -O
+
+use std::slice::Windows;
+
+// CHECK-LABEL: @naive_string_search
+#[no_mangle]
+pub fn naive_string_search(haystack: &str, needle: &str) -> Option<usize> {
+    if needle.is_empty() {
+        return Some(0);
+    }
+    // CHECK-NOT: panic
+    // CHECK-NOT: fail
+    haystack
+        .as_bytes()
+        .windows(needle.len())
+        .position(|sub| sub == needle.as_bytes())
+}
+
+// CHECK-LABEL: @next
+#[no_mangle]
+pub fn next<'a>(w: &mut Windows<'a, u32>) -> Option<&'a [u32]> {
+    // CHECK-NOT: panic
+    // CHECK-NOT: fail
+    w.next()
+}
+
+// CHECK-LABEL: @next_back
+#[no_mangle]
+pub fn next_back<'a>(w: &mut Windows<'a, u32>) -> Option<&'a [u32]> {
+    // CHECK-NOT: panic
+    // CHECK-NOT: fail
+    w.next_back()
+}
diff --git a/tests/codegen/slice_as_from_ptr_range.rs b/tests/codegen/slice_as_from_ptr_range.rs
new file mode 100644
index 00000000000..0e3fefd9728
--- /dev/null
+++ b/tests/codegen/slice_as_from_ptr_range.rs
@@ -0,0 +1,23 @@
+// 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)]
+
+// This is intentionally using a non-power-of-two array length,
+// as that's where the optimization differences show up
+
+// CHECK-LABEL: @flatten_via_ptr_range
+#[no_mangle]
+pub fn flatten_via_ptr_range(slice_of_arrays: &[[i32; 13]]) -> &[i32] {
+    // CHECK-NOT: lshr
+    // CHECK-NOT: udiv
+    // CHECK: mul nuw nsw i64 %{{.+}}, 13
+    // CHECK-NOT: lshr
+    // CHECK-NOT: udiv
+    let r = slice_of_arrays.as_ptr_range();
+    let r = r.start.cast()..r.end.cast();
+    unsafe { core::slice::from_ptr_range(r) }
+}
diff --git a/tests/codegen/some-abis-do-extend-params-to-32-bits.rs b/tests/codegen/some-abis-do-extend-params-to-32-bits.rs
new file mode 100644
index 00000000000..9f2d9d06524
--- /dev/null
+++ b/tests/codegen/some-abis-do-extend-params-to-32-bits.rs
@@ -0,0 +1,204 @@
+// compile-flags: -Cno-prepopulate-passes -Copt-level=0
+
+// revisions:x86_64 i686 aarch64-apple aarch64-windows aarch64-linux arm riscv
+
+//[x86_64] compile-flags: --target x86_64-unknown-uefi
+//[x86_64] needs-llvm-components: x86
+//[i686] compile-flags: --target i686-unknown-linux-musl
+//[i686] needs-llvm-components: x86
+//[aarch64-windows] compile-flags: --target aarch64-pc-windows-msvc
+//[aarch64-windows] needs-llvm-components: aarch64
+//[aarch64-linux] compile-flags: --target aarch64-unknown-linux-gnu
+//[aarch64-linux] needs-llvm-components: aarch64
+//[aarch64-apple] compile-flags: --target aarch64-apple-darwin
+//[aarch64-apple] needs-llvm-components: aarch64
+//[arm] compile-flags: --target armv7r-none-eabi
+//[arm] needs-llvm-components: arm
+//[riscv] compile-flags: --target riscv64gc-unknown-none-elf
+//[riscv] needs-llvm-components: riscv
+
+// See bottom of file for a corresponding C source file that is meant to yield
+// equivalent declarations.
+#![feature(no_core, lang_items)]
+#![crate_type = "lib"]
+#![no_std]
+#![no_core]
+
+#[lang="sized"] trait Sized { }
+#[lang="freeze"] trait Freeze { }
+#[lang="copy"] trait Copy { }
+
+// The patterns in this file are written in the style of a table to make the
+// uniformities and distinctions more apparent.
+//
+//                  ZERO/SIGN-EXTENDING TO 32 BITS            NON-EXTENDING
+//                  ==============================  =======================
+// x86_64:          void @c_arg_u8(i8 zeroext %_a)
+// i686:            void @c_arg_u8(i8 zeroext %_a)
+// aarch64-apple:   void @c_arg_u8(i8 zeroext %_a)
+// aarch64-windows:                                  void @c_arg_u8(i8 %_a)
+// aarch64-linux:                                    void @c_arg_u8(i8 %_a)
+// arm:             void @c_arg_u8(i8 zeroext %_a)
+// riscv:           void @c_arg_u8(i8 zeroext %_a)
+#[no_mangle] pub extern "C" fn c_arg_u8(_a: u8) { }
+
+// x86_64:          void @c_arg_u16(i16 zeroext %_a)
+// i686:            void @c_arg_u16(i16 zeroext %_a)
+// aarch64-apple:   void @c_arg_u16(i16 zeroext %_a)
+// aarch64-windows:                                 void @c_arg_u16(i16 %_a)
+// aarch64-linux:                                   void @c_arg_u16(i16 %_a)
+// arm:             void @c_arg_u16(i16 zeroext %_a)
+// riscv:           void @c_arg_u16(i16 zeroext %_a)
+#[no_mangle] pub extern "C" fn c_arg_u16(_a: u16) { }
+
+// x86_64:          void @c_arg_u32(i32 %_a)
+// i686:            void @c_arg_u32(i32 %_a)
+// aarch64-apple:   void @c_arg_u32(i32 %_a)
+// aarch64-windows:                                 void @c_arg_u32(i32 %_a)
+// aarch64-linux:                                   void @c_arg_u32(i32 %_a)
+// arm:             void @c_arg_u32(i32 %_a)
+// riscv:           void @c_arg_u32(i32 signext %_a)
+#[no_mangle] pub extern "C" fn c_arg_u32(_a: u32) { }
+
+// x86_64:          void @c_arg_u64(i64 %_a)
+// i686:            void @c_arg_u64(i64 %_a)
+// aarch64-apple:   void @c_arg_u64(i64 %_a)
+// aarch64-windows:                                 void @c_arg_u64(i64 %_a)
+// aarch64-linux:                                   void @c_arg_u64(i64 %_a)
+// arm:             void @c_arg_u64(i64 %_a)
+// riscv:           void @c_arg_u64(i64 %_a)
+#[no_mangle] pub extern "C" fn c_arg_u64(_a: u64) { }
+
+// x86_64:          void @c_arg_i8(i8 signext %_a)
+// i686:            void @c_arg_i8(i8 signext %_a)
+// aarch64-apple:   void @c_arg_i8(i8 signext %_a)
+// aarch64-windows:                                  void @c_arg_i8(i8 %_a)
+// aarch64-linux:                                    void @c_arg_i8(i8 %_a)
+// arm:             void @c_arg_i8(i8 signext %_a)
+// riscv:           void @c_arg_i8(i8 signext %_a)
+#[no_mangle] pub extern "C" fn c_arg_i8(_a: i8) { }
+
+// x86_64:          void @c_arg_i16(i16 signext %_a)
+// i686:            void @c_arg_i16(i16 signext %_a)
+// aarch64-apple:   void @c_arg_i16(i16 signext %_a)
+// aarch64-windows:                                 void @c_arg_i16(i16 %_a)
+// aarch64-linux:                                   void @c_arg_i16(i16 %_a)
+// arm:             void @c_arg_i16(i16 signext %_a)
+// riscv:           void @c_arg_i16(i16 signext %_a)
+#[no_mangle] pub extern "C" fn c_arg_i16(_a: i16) { }
+
+// x86_64:          void @c_arg_i32(i32 %_a)
+// i686:            void @c_arg_i32(i32 %_a)
+// aarch64-apple:   void @c_arg_i32(i32 %_a)
+// aarch64-windows:                                 void @c_arg_i32(i32 %_a)
+// aarch64-linux:                                   void @c_arg_i32(i32 %_a)
+// arm:             void @c_arg_i32(i32 %_a)
+// riscv:           void @c_arg_i32(i32 signext %_a)
+#[no_mangle] pub extern "C" fn c_arg_i32(_a: i32) { }
+
+// x86_64:          void @c_arg_i64(i64 %_a)
+// i686:            void @c_arg_i64(i64 %_a)
+// aarch64-apple:   void @c_arg_i64(i64 %_a)
+// aarch64-windows:                                 void @c_arg_i64(i64 %_a)
+// aarch64-linux:                                   void @c_arg_i64(i64 %_a)
+// arm:             void @c_arg_i64(i64 %_a)
+// riscv:           void @c_arg_i64(i64 %_a)
+#[no_mangle] pub extern "C" fn c_arg_i64(_a: i64) { }
+
+// x86_64:          zeroext i8 @c_ret_u8()
+// i686:            zeroext i8 @c_ret_u8()
+// aarch64-apple:   zeroext i8 @c_ret_u8()
+// aarch64-windows:                                 i8 @c_ret_u8()
+// aarch64-linux:                                   i8 @c_ret_u8()
+// arm:             zeroext i8 @c_ret_u8()
+// riscv:           zeroext i8 @c_ret_u8()
+#[no_mangle] pub extern "C" fn c_ret_u8() -> u8 { 0 }
+
+// x86_64:          zeroext i16 @c_ret_u16()
+// i686:            zeroext i16 @c_ret_u16()
+// aarch64-apple:   zeroext i16 @c_ret_u16()
+// aarch64-windows:                                 i16 @c_ret_u16()
+// aarch64-linux:                                   i16 @c_ret_u16()
+// arm:             zeroext i16 @c_ret_u16()
+// riscv:           zeroext i16 @c_ret_u16()
+#[no_mangle] pub extern "C" fn c_ret_u16() -> u16 { 0 }
+
+// x86_64:          i32 @c_ret_u32()
+// i686:            i32 @c_ret_u32()
+// aarch64-apple:   i32 @c_ret_u32()
+// aarch64-windows:                                 i32 @c_ret_u32()
+// aarch64-linux:                                   i32 @c_ret_u32()
+// arm:             i32 @c_ret_u32()
+// riscv:           signext i32 @c_ret_u32()
+#[no_mangle] pub extern "C" fn c_ret_u32() -> u32 { 0 }
+
+// x86_64:          i64 @c_ret_u64()
+// i686:            i64 @c_ret_u64()
+// aarch64-apple:   i64 @c_ret_u64()
+// aarch64-windows:                                 i64 @c_ret_u64()
+// aarch64-linux:                                   i64 @c_ret_u64()
+// arm:             i64 @c_ret_u64()
+// riscv:           i64 @c_ret_u64()
+#[no_mangle] pub extern "C" fn c_ret_u64() -> u64 { 0 }
+
+// x86_64:          signext i8 @c_ret_i8()
+// i686:            signext i8 @c_ret_i8()
+// aarch64-apple:   signext i8 @c_ret_i8()
+// aarch64-windows:                                 i8 @c_ret_i8()
+// aarch64-linux:                                   i8 @c_ret_i8()
+// arm:             signext i8 @c_ret_i8()
+// riscv:           signext i8 @c_ret_i8()
+#[no_mangle] pub extern "C" fn c_ret_i8() -> i8 { 0 }
+
+// x86_64:          signext i16 @c_ret_i16()
+// i686:            signext i16 @c_ret_i16()
+// aarch64-apple:   signext i16 @c_ret_i16()
+// aarch64-windows:                                 i16 @c_ret_i16()
+// aarch64-linux:                                   i16 @c_ret_i16()
+// arm:             signext i16 @c_ret_i16()
+// riscv:           signext i16 @c_ret_i16()
+#[no_mangle] pub extern "C" fn c_ret_i16() -> i16 { 0 }
+
+// x86_64:          i32 @c_ret_i32()
+// i686:            i32 @c_ret_i32()
+// aarch64-apple:   i32 @c_ret_i32()
+// aarch64-windows:                                 i32 @c_ret_i32()
+// aarch64-linux:                                   i32 @c_ret_i32()
+// arm:             i32 @c_ret_i32()
+// riscv:           signext i32 @c_ret_i32()
+#[no_mangle] pub extern "C" fn c_ret_i32() -> i32 { 0 }
+
+// x86_64:          i64 @c_ret_i64()
+// i686:            i64 @c_ret_i64()
+// aarch64-apple:   i64 @c_ret_i64()
+// aarch64-windows:                                 i64 @c_ret_i64()
+// aarch64-linux:                                   i64 @c_ret_i64()
+// arm:             i64 @c_ret_i64()
+// riscv:           i64 @c_ret_i64()
+#[no_mangle] pub extern "C" fn c_ret_i64() -> i64 { 0 }
+
+const C_SOURCE_FILE: &'static str = r##"
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+
+void c_arg_u8(uint8_t _a) { }
+void c_arg_u16(uint16_t _a) { }
+void c_arg_u32(uint32_t _a) { }
+void c_arg_u64(uint64_t _a) { }
+
+void c_arg_i8(int8_t _a) { }
+void c_arg_i16(int16_t _a) { }
+void c_arg_i32(int32_t _a) { }
+void c_arg_i64(int64_t _a) { }
+
+uint8_t  c_ret_u8()  { return 0; }
+uint16_t c_ret_u16() { return 0; }
+uint32_t c_ret_u32() { return 0; }
+uint64_t c_ret_u64() { return 0; }
+
+int8_t   c_ret_i8()  { return 0; }
+int16_t  c_ret_i16() { return 0; }
+int32_t  c_ret_i32() { return 0; }
+int64_t  c_ret_i64() { return 0; }
+"##;
diff --git a/tests/codegen/some-global-nonnull.rs b/tests/codegen/some-global-nonnull.rs
new file mode 100644
index 00000000000..59c47de4129
--- /dev/null
+++ b/tests/codegen/some-global-nonnull.rs
@@ -0,0 +1,25 @@
+// compile-flags: -O
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @test
+// CHECK-NEXT: start:
+// CHECK-NEXT: tail call void @ext_fn0()
+#[no_mangle]
+pub fn test() {
+    test_inner(Some(inner0));
+}
+
+fn test_inner(f_maybe: Option<fn()>) {
+    if let Some(f) = f_maybe {
+        f();
+    }
+}
+
+fn inner0() {
+    unsafe { ext_fn0() };
+}
+
+extern "C" {
+    fn ext_fn0();
+}
diff --git a/tests/codegen/sparc-struct-abi.rs b/tests/codegen/sparc-struct-abi.rs
new file mode 100644
index 00000000000..e8816e4f303
--- /dev/null
+++ b/tests/codegen/sparc-struct-abi.rs
@@ -0,0 +1,103 @@
+// Checks that we correctly codegen extern "C" functions returning structs.
+// See issues #52638 and #86163.
+
+// compile-flags: -O --target=sparc64-unknown-linux-gnu --crate-type=rlib
+// needs-llvm-components: sparc
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang="sized"]
+trait Sized { }
+#[lang="freeze"]
+trait Freeze { }
+#[lang="copy"]
+trait Copy { }
+
+#[repr(C)]
+pub struct Bool {
+    b: bool,
+}
+
+// CHECK: define i64 @structbool()
+// CHECK-NEXT: start:
+// CHECK-NEXT: ret i64 72057594037927936
+#[no_mangle]
+pub extern "C" fn structbool() -> Bool {
+    Bool { b: true }
+}
+
+
+#[repr(C)]
+pub struct BoolFloat {
+    b: bool,
+    f: f32,
+}
+
+// CHECK: define inreg { i32, float } @structboolfloat()
+// CHECK-NEXT: start:
+// CHECK-NEXT: ret { i32, float } { i32 16777216, float 0x40091EB860000000 }
+#[no_mangle]
+pub extern "C" fn structboolfloat() -> BoolFloat {
+    BoolFloat { b: true, f: 3.14 }
+}
+
+// CHECK: define void @structboolfloat_input({ i32, float } inreg %0)
+// CHECK-NEXT: start:
+#[no_mangle]
+pub extern "C" fn structboolfloat_input(a: BoolFloat) { }
+
+
+#[repr(C)]
+pub struct ShortDouble {
+    s: i16,
+    d: f64,
+}
+
+// CHECK: define { i64, double } @structshortdouble()
+// CHECK-NEXT: start:
+// CHECK-NEXT: ret { i64, double } { i64 34621422135410688, double 3.140000e+00 }
+#[no_mangle]
+pub extern "C" fn structshortdouble() -> ShortDouble {
+    ShortDouble { s: 123, d: 3.14 }
+}
+
+// CHECK: define void @structshortdouble_input({ i64, double } %0)
+// CHECK-NEXT: start:
+#[no_mangle]
+pub extern "C" fn structshortdouble_input(a: ShortDouble) { }
+
+
+#[repr(C)]
+pub struct FloatLongFloat {
+    f: f32,
+    i: i64,
+    g: f32,
+}
+
+// CHECK: define inreg { float, i32, i64, float, i32 } @structfloatlongfloat()
+// CHECK-NEXT: start:
+// CHECK-NEXT: ret { float, i32, i64, float, i32 } { float 0x3FB99999A0000000, i32 undef, i64 123, float 0x40091EB860000000, i32 undef }
+#[no_mangle]
+pub extern "C" fn structfloatlongfloat() -> FloatLongFloat {
+    FloatLongFloat { f: 0.1, i: 123, g: 3.14 }
+}
+
+#[repr(C)]
+pub struct FloatFloat {
+    f: f32,
+    g: f32,
+}
+
+#[repr(C)]
+pub struct NestedStructs {
+    a: FloatFloat,
+    b: FloatFloat,
+}
+
+// CHECK: define inreg { float, float, float, float } @structnestestructs()
+// CHECK-NEXT: start:
+// CHECK-NEXT: ret { float, float, float, float } { float 0x3FB99999A0000000, float 0x3FF19999A0000000, float 0x40019999A0000000, float 0x400A666660000000 }
+#[no_mangle]
+pub extern "C" fn structnestestructs() -> NestedStructs {
+    NestedStructs { a: FloatFloat { f: 0.1, g: 1.1 }, b: FloatFloat { f: 2.2, g: 3.3 } }
+}
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/src-hash-algorithm/src-hash-algorithm-md5.rs b/tests/codegen/src-hash-algorithm/src-hash-algorithm-md5.rs
new file mode 100644
index 00000000000..64be1127786
--- /dev/null
+++ b/tests/codegen/src-hash-algorithm/src-hash-algorithm-md5.rs
@@ -0,0 +1,6 @@
+// compile-flags: -g -Z src-hash-algorithm=md5
+
+#![crate_type = "lib"]
+
+pub fn test() {}
+// CHECK: checksumkind: CSK_MD5
diff --git a/tests/codegen/src-hash-algorithm/src-hash-algorithm-sha1.rs b/tests/codegen/src-hash-algorithm/src-hash-algorithm-sha1.rs
new file mode 100644
index 00000000000..54e07152142
--- /dev/null
+++ b/tests/codegen/src-hash-algorithm/src-hash-algorithm-sha1.rs
@@ -0,0 +1,6 @@
+// compile-flags: -g -Z src-hash-algorithm=sha1
+
+#![crate_type = "lib"]
+
+pub fn test() {}
+// CHECK: checksumkind: CSK_SHA1
diff --git a/tests/codegen/src-hash-algorithm/src-hash-algorithm-sha256.rs b/tests/codegen/src-hash-algorithm/src-hash-algorithm-sha256.rs
new file mode 100644
index 00000000000..dc7db8e2372
--- /dev/null
+++ b/tests/codegen/src-hash-algorithm/src-hash-algorithm-sha256.rs
@@ -0,0 +1,6 @@
+// compile-flags: -g -Z src-hash-algorithm=sha256
+
+#![crate_type = "lib"]
+
+pub fn test() {}
+// CHECK: checksumkind: CSK_SHA256
diff --git a/tests/codegen/sse42-implies-crc32.rs b/tests/codegen/sse42-implies-crc32.rs
new file mode 100644
index 00000000000..56079d32a8d
--- /dev/null
+++ b/tests/codegen/sse42-implies-crc32.rs
@@ -0,0 +1,15 @@
+// only-x86_64
+// compile-flags: -Copt-level=3
+
+#![crate_type = "lib"]
+
+#[cfg(target_arch = "x86_64")]
+#[target_feature(enable = "sse4.2")]
+#[no_mangle]
+pub unsafe fn crc32sse(v: u8) -> u32 {
+    use std::arch::x86_64::*;
+    let out = !0u32;
+    _mm_crc32_u8(out, v)
+}
+
+// CHECK: attributes #0 {{.*"target-features"="\+sse4.2,\+crc32"}}
diff --git a/tests/codegen/stack-probes-call.rs b/tests/codegen/stack-probes-call.rs
new file mode 100644
index 00000000000..a18fd41c28c
--- /dev/null
+++ b/tests/codegen/stack-probes-call.rs
@@ -0,0 +1,24 @@
+// Check the "probe-stack" attribute for targets with `StackProbeType::Call`,
+// or `StackProbeType::InlineOrCall` when running on older LLVM.
+
+// compile-flags: -C no-prepopulate-passes
+// revisions: i686 x86_64
+//[i686] compile-flags: --target i686-unknown-linux-gnu
+//[i686] needs-llvm-components: x86
+//[i686] ignore-llvm-version: 16 - 99
+//[x86_64] compile-flags: --target x86_64-unknown-linux-gnu
+//[x86_64] needs-llvm-components: x86
+//[x86_64] ignore-llvm-version: 16 - 99
+
+#![crate_type = "rlib"]
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+
+#[no_mangle]
+pub fn foo() {
+// CHECK: @foo() unnamed_addr #0
+// CHECK: attributes #0 = { {{.*}}"probe-stack"="__rust_probestack"{{.*}} }
+}
diff --git a/tests/codegen/stack-probes-inline.rs b/tests/codegen/stack-probes-inline.rs
new file mode 100644
index 00000000000..a6b781de531
--- /dev/null
+++ b/tests/codegen/stack-probes-inline.rs
@@ -0,0 +1,32 @@
+// Check the "probe-stack" attribute for targets with `StackProbeType::Inline`,
+// or `StackProbeType::InlineOrCall` when running on newer LLVM.
+
+// compile-flags: -C no-prepopulate-passes
+// revisions: powerpc powerpc64 powerpc64le s390x i686 x86_64
+//[powerpc] compile-flags: --target powerpc-unknown-linux-gnu
+//[powerpc] needs-llvm-components: powerpc
+//[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu
+//[powerpc64] needs-llvm-components: powerpc
+//[powerpc64le] compile-flags: --target powerpc64le-unknown-linux-gnu
+//[powerpc64le] needs-llvm-components: powerpc
+//[s390x] compile-flags: --target s390x-unknown-linux-gnu
+//[s390x] needs-llvm-components: systemz
+//[i686] compile-flags: --target i686-unknown-linux-gnu
+//[i686] needs-llvm-components: x86
+//[i686] min-llvm-version: 16
+//[x86_64] compile-flags: --target x86_64-unknown-linux-gnu
+//[x86_64] needs-llvm-components: x86
+//[x86_64] min-llvm-version: 16
+
+#![crate_type = "rlib"]
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+
+#[no_mangle]
+pub fn foo() {
+// CHECK: @foo() unnamed_addr #0
+// CHECK: attributes #0 = { {{.*}}"probe-stack"="inline-asm"{{.*}} }
+}
diff --git a/tests/codegen/stack-protector.rs b/tests/codegen/stack-protector.rs
new file mode 100644
index 00000000000..a680789af15
--- /dev/null
+++ b/tests/codegen/stack-protector.rs
@@ -0,0 +1,34 @@
+// revisions: all strong basic none
+// ignore-nvptx64 stack protector not supported
+// [all] compile-flags: -Z stack-protector=all
+// [strong] compile-flags: -Z stack-protector=strong
+// [basic] compile-flags: -Z stack-protector=basic
+
+#![crate_type = "lib"]
+
+#[no_mangle]
+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 {{.*}} }
+
+    // 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 {{.*}} }
+
+    // none-NOT: attributes #0 = { {{.*}}sspreq {{.*}} }
+    // none-NOT: attributes #0 = { {{.*}}sspstrong {{.*}} }
+    // none-NOT: attributes #0 = { {{.*}}ssp {{.*}} }
+}
diff --git a/tests/codegen/static-relocation-model-msvc.rs b/tests/codegen/static-relocation-model-msvc.rs
new file mode 100644
index 00000000000..735ef7081c9
--- /dev/null
+++ b/tests/codegen/static-relocation-model-msvc.rs
@@ -0,0 +1,26 @@
+// Verify linkage of external symbols in the static relocation model on MSVC.
+//
+// compile-flags: -O -C relocation-model=static
+// aux-build: extern_decl.rs
+// only-x86_64-pc-windows-msvc
+
+#![crate_type = "rlib"]
+
+extern crate extern_decl;
+
+// The `extern_decl` definitions are imported from a statically linked rust
+// crate, thus they are expected to be marked `dso_local` without `dllimport`.
+//
+// The `access_extern()` symbol is from this compilation unit, thus we expect
+// it to be marked `dso_local` as well, given the static relocation model.
+//
+// CHECK: @extern_static = external dso_local local_unnamed_addr global i8
+// CHECK: define dso_local noundef i8 @access_extern() {{.*}}
+// CHECK: declare dso_local noundef i8 @extern_fn() {{.*}}
+
+#[no_mangle]
+pub fn access_extern() -> u8 {
+    unsafe {
+        extern_decl::extern_fn() + extern_decl::extern_static
+    }
+}
diff --git a/tests/codegen/staticlib-external-inline-fns.rs b/tests/codegen/staticlib-external-inline-fns.rs
new file mode 100644
index 00000000000..432c063e826
--- /dev/null
+++ b/tests/codegen/staticlib-external-inline-fns.rs
@@ -0,0 +1,43 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "staticlib"]
+
+// CHECK: define{{.*}}void @a()
+#[no_mangle]
+#[inline]
+pub extern "C" fn a() {}
+
+// CHECK: define{{.*}}void @b()
+#[export_name = "b"]
+#[inline]
+pub extern "C" fn b() {}
+
+// CHECK: define{{.*}}void @c()
+#[no_mangle]
+#[inline]
+extern "C" fn c() {}
+
+// CHECK: define{{.*}}void @d()
+#[export_name = "d"]
+#[inline]
+extern "C" fn d() {}
+
+// CHECK: define{{.*}}void @e()
+#[no_mangle]
+#[inline(always)]
+pub extern "C" fn e() {}
+
+// CHECK: define{{.*}}void @f()
+#[export_name = "f"]
+#[inline(always)]
+pub extern "C" fn f() {}
+
+// CHECK: define{{.*}}void @g()
+#[no_mangle]
+#[inline(always)]
+extern "C" fn g() {}
+
+// CHECK: define{{.*}}void @h()
+#[export_name = "h"]
+#[inline(always)]
+extern "C" fn h() {}
diff --git a/tests/codegen/stores.rs b/tests/codegen/stores.rs
new file mode 100644
index 00000000000..837256e5369
--- /dev/null
+++ b/tests/codegen/stores.rs
@@ -0,0 +1,35 @@
+// compile-flags: -C no-prepopulate-passes
+//
+
+#![crate_type = "lib"]
+
+pub struct Bytes {
+  a: u8,
+  b: u8,
+  c: u8,
+  d: u8,
+}
+
+// CHECK-LABEL: small_array_alignment
+// The array is stored as i32, but its alignment is lower, go with 1 byte to avoid target
+// dependent alignment
+#[no_mangle]
+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)
+    *x = y;
+}
+
+// CHECK-LABEL: small_struct_alignment
+// The struct is stored as i32, but its alignment is lower, go with 1 byte to avoid target
+// dependent alignment
+#[no_mangle]
+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)
+    *x = y;
+}
diff --git a/tests/codegen/swap-large-types.rs b/tests/codegen/swap-large-types.rs
new file mode 100644
index 00000000000..4a68403578d
--- /dev/null
+++ b/tests/codegen/swap-large-types.rs
@@ -0,0 +1,91 @@
+// compile-flags: -O
+// only-x86_64
+// ignore-debug: the debug assertions get in the way
+
+#![crate_type = "lib"]
+
+use std::mem::swap;
+use std::ptr::{read, copy_nonoverlapping, write};
+
+type KeccakBuffer = [[u64; 5]; 5];
+
+// A basic read+copy+write swap implementation ends up copying one of the values
+// to stack for large types, which is completely unnecessary as the lack of
+// overlap means we can just do whatever fits in registers at a time.
+
+// CHECK-LABEL: @swap_basic
+#[no_mangle]
+pub fn swap_basic(x: &mut KeccakBuffer, y: &mut KeccakBuffer) {
+// CHECK: alloca [5 x [5 x i64]]
+
+    // SAFETY: exclusive references are always valid to read/write,
+    // are non-overlapping, and nothing here panics so it's drop-safe.
+    unsafe {
+        let z = read(x);
+        copy_nonoverlapping(y, x, 1);
+        write(y, z);
+    }
+}
+
+// This test verifies that the library does something smarter, and thus
+// doesn't need any scratch space on the stack.
+
+// CHECK-LABEL: @swap_std
+#[no_mangle]
+pub fn swap_std(x: &mut KeccakBuffer, y: &mut KeccakBuffer) {
+// CHECK-NOT: alloca
+// CHECK: load <{{[0-9]+}} x i64>
+// CHECK: store <{{[0-9]+}} x i64>
+    swap(x, y)
+}
+
+// Verify that types with usize alignment are swapped via vectored usizes,
+// not falling back to byte-level code.
+
+// CHECK-LABEL: @swap_slice
+#[no_mangle]
+pub fn swap_slice(x: &mut [KeccakBuffer], y: &mut [KeccakBuffer]) {
+// CHECK-NOT: alloca
+// CHECK: load <{{[0-9]+}} x i64>
+// CHECK: store <{{[0-9]+}} x i64>
+    if x.len() == y.len() {
+        x.swap_with_slice(y);
+    }
+}
+
+// But for a large align-1 type, vectorized byte copying is what we want.
+
+type OneKilobyteBuffer = [u8; 1024];
+
+// CHECK-LABEL: @swap_1kb_slices
+#[no_mangle]
+pub fn swap_1kb_slices(x: &mut [OneKilobyteBuffer], y: &mut [OneKilobyteBuffer]) {
+// CHECK-NOT: alloca
+// CHECK: load <{{[0-9]+}} x i8>
+// CHECK: store <{{[0-9]+}} x i8>
+    if x.len() == y.len() {
+        x.swap_with_slice(y);
+    }
+}
+
+// This verifies that the 2×read + 2×write optimizes to just 3 memcpys
+// for an unusual type like this.  It's not clear whether we should do anything
+// smarter in Rust for these, so for now it's fine to leave these up to the backend.
+// That's not as bad as it might seem, as for example, LLVM will lower the
+// memcpys below to VMOVAPS on YMMs if one enables the AVX target feature.
+// Eventually we'll be able to pass `align_of::<T>` to a const generic and
+// thus pick a smarter chunk size ourselves without huge code duplication.
+
+#[repr(align(64))]
+pub struct BigButHighlyAligned([u8; 64 * 3]);
+
+// CHECK-LABEL: @swap_big_aligned
+#[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-NOT: call void @llvm.memcpy
+    swap(x, y)
+}
diff --git a/tests/codegen/swap-simd-types.rs b/tests/codegen/swap-simd-types.rs
new file mode 100644
index 00000000000..3472a42b0e6
--- /dev/null
+++ b/tests/codegen/swap-simd-types.rs
@@ -0,0 +1,41 @@
+// compile-flags: -O -C target-feature=+avx
+// only-x86_64
+// ignore-debug: the debug assertions get in the way
+
+#![crate_type = "lib"]
+
+use std::mem::swap;
+
+// SIMD types are highly-aligned already, so make sure the swap code leaves their
+// types alone and doesn't pessimize them (such as by swapping them as `usize`s).
+extern crate core;
+use core::arch::x86_64::__m256;
+
+// CHECK-LABEL: @swap_single_m256
+#[no_mangle]
+pub fn swap_single_m256(x: &mut __m256, y: &mut __m256) {
+// CHECK-NOT: alloca
+// CHECK: load <8 x float>{{.+}}align 32
+// CHECK: store <8 x float>{{.+}}align 32
+    swap(x, y)
+}
+
+// CHECK-LABEL: @swap_m256_slice
+#[no_mangle]
+pub fn swap_m256_slice(x: &mut [__m256], y: &mut [__m256]) {
+// CHECK-NOT: alloca
+// CHECK: load <8 x float>{{.+}}align 32
+// CHECK: store <8 x float>{{.+}}align 32
+    if x.len() == y.len() {
+        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
new file mode 100644
index 00000000000..419645a3fc6
--- /dev/null
+++ b/tests/codegen/swap-small-types.rs
@@ -0,0 +1,78 @@
+// compile-flags: -O -Z merge-functions=disabled
+// only-x86_64
+// ignore-debug: the debug assertions get in the way
+
+#![crate_type = "lib"]
+
+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) {
+    // 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)
+}
+
+// LLVM doesn't vectorize a loop over 3-byte elements,
+// so we chunk it down to bytes and loop over those instead.
+type RGB24 = [u8; 3];
+
+// CHECK-LABEL: @swap_rgb24_slices
+#[no_mangle]
+pub fn swap_rgb24_slices(x: &mut [RGB24], y: &mut [RGB24]) {
+// CHECK-NOT: alloca
+// CHECK: load <{{[0-9]+}} x i8>
+// CHECK: store <{{[0-9]+}} x i8>
+    if x.len() == y.len() {
+        x.swap_with_slice(y);
+    }
+}
+
+// This one has a power-of-two size, so we iterate over it directly
+type RGBA32 = [u8; 4];
+
+// CHECK-LABEL: @swap_rgba32_slices
+#[no_mangle]
+pub fn swap_rgba32_slices(x: &mut [RGBA32], y: &mut [RGBA32]) {
+// CHECK-NOT: alloca
+// CHECK: load <{{[0-9]+}} x i32>
+// CHECK: store <{{[0-9]+}} x i32>
+    if x.len() == y.len() {
+        x.swap_with_slice(y);
+    }
+}
+
+// Strings have a non-power-of-two size, but have pointer alignment,
+// so we swap usizes instead of dropping all the way down to bytes.
+const _: () = assert!(!std::mem::size_of::<String>().is_power_of_two());
+
+// CHECK-LABEL: @swap_string_slices
+#[no_mangle]
+pub fn swap_string_slices(x: &mut [String], y: &mut [String]) {
+// CHECK-NOT: alloca
+// CHECK: load <{{[0-9]+}} x i64>
+// CHECK: store <{{[0-9]+}} x i64>
+    if x.len() == y.len() {
+        x.swap_with_slice(y);
+    }
+}
diff --git a/tests/codegen/target-cpu-on-functions.rs b/tests/codegen/target-cpu-on-functions.rs
new file mode 100644
index 00000000000..c043eceb5cd
--- /dev/null
+++ b/tests/codegen/target-cpu-on-functions.rs
@@ -0,0 +1,21 @@
+// This test makes sure that functions get annotated with the proper
+// "target-cpu" attribute in LLVM.
+
+// no-prefer-dynamic
+//
+// compile-flags: -C no-prepopulate-passes -C panic=abort -C linker-plugin-lto -Cpasses=name-anon-globals
+
+#![crate_type = "staticlib"]
+
+// CHECK-LABEL: define {{.*}} @exported() {{.*}} #0
+#[no_mangle]
+pub extern "C" fn exported() {
+    not_exported();
+}
+
+// CHECK-LABEL: ; target_cpu_on_functions::not_exported
+// CHECK-NEXT: ; Function Attrs:
+// CHECK-NEXT: define {{.*}}() {{.*}} #0
+fn not_exported() {}
+
+// CHECK: attributes #0 = {{.*}} "target-cpu"="{{.*}}"
diff --git a/tests/codegen/target-feature-overrides.rs b/tests/codegen/target-feature-overrides.rs
new file mode 100644
index 00000000000..1bebf66f0df
--- /dev/null
+++ b/tests/codegen/target-feature-overrides.rs
@@ -0,0 +1,47 @@
+// revisions: COMPAT INCOMPAT
+// needs-llvm-components: x86
+// compile-flags: --target=x86_64-unknown-linux-gnu -Copt-level=3
+// [COMPAT] compile-flags: -Ctarget-feature=+avx2,+avx
+// [INCOMPAT] compile-flags: -Ctarget-feature=-avx2,-avx
+
+// See also tests/assembly/target-feature-multiple.rs
+#![feature(no_core, lang_items)]
+#![crate_type = "lib"]
+#![no_core]
+
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+extern "C" {
+    fn peach() -> u32;
+}
+
+#[inline]
+#[target_feature(enable = "avx")]
+#[no_mangle]
+pub unsafe fn apple() -> u32 {
+// CHECK-LABEL: @apple()
+// CHECK-SAME: [[APPLEATTRS:#[0-9]+]] {
+// CHECK: {{.*}}call{{.*}}@peach
+    peach()
+}
+
+// target features same as global
+#[no_mangle]
+pub unsafe fn banana() -> u32 {
+// CHECK-LABEL: @banana()
+// CHECK-SAME: [[BANANAATTRS:#[0-9]+]] {
+// COMPAT: {{.*}}call{{.*}}@peach
+// INCOMPAT: {{.*}}call{{.*}}@apple
+    apple() // Compatible for inline in COMPAT revision and can't be inlined in INCOMPAT
+}
+
+// CHECK: attributes [[APPLEATTRS]]
+// COMPAT-SAME: "target-features"="+avx2,+avx,+avx"
+// INCOMPAT-SAME: "target-features"="-avx2,-avx,+avx"
+// CHECK: attributes [[BANANAATTRS]]
+// COMPAT-SAME: "target-features"="+avx2,+avx"
+// INCOMPAT-SAME: "target-features"="-avx2,-avx"
diff --git a/tests/codegen/thread-local.rs b/tests/codegen/thread-local.rs
new file mode 100644
index 00000000000..caf0366d2c1
--- /dev/null
+++ b/tests/codegen/thread-local.rs
@@ -0,0 +1,50 @@
+// compile-flags: -O
+// aux-build:thread_local_aux.rs
+// ignore-windows FIXME(#84933)
+// ignore-wasm globals are used instead of thread locals
+// ignore-emscripten globals are used instead of thread locals
+// ignore-android does not use #[thread_local]
+// ignore-nto does not use #[thread_local]
+
+#![crate_type = "lib"]
+
+extern crate thread_local_aux as aux;
+
+use std::cell::Cell;
+
+thread_local!(static A: Cell<u32> = const { Cell::new(1) });
+
+// CHECK: [[TLS_AUX:@.+]] = external thread_local local_unnamed_addr global i64
+// CHECK: [[TLS:@.+]] = internal thread_local unnamed_addr global
+
+// CHECK-LABEL: @get
+#[no_mangle]
+fn get() -> u32 {
+    // CHECK: [[RET_0:%.+]] = load i32, {{.*}}[[TLS]]{{.*}}
+    // CHECK-NEXT: ret i32 [[RET_0]]
+    A.with(|a| a.get())
+}
+
+// CHECK-LABEL: @set
+#[no_mangle]
+fn set(v: u32) {
+    // CHECK: store i32 %0, {{.*}}[[TLS]]{{.*}}
+    // CHECK-NEXT: ret void
+    A.with(|a| a.set(v))
+}
+
+// CHECK-LABEL: @get_aux
+#[no_mangle]
+fn get_aux() -> u64 {
+    // CHECK: [[RET_1:%.+]] = load i64, {{.*}}[[TLS_AUX]]
+    // CHECK-NEXT: ret i64 [[RET_1]]
+    aux::A.with(|a| a.get())
+}
+
+// CHECK-LABEL: @set_aux
+#[no_mangle]
+fn set_aux(v: u64) {
+    // CHECK: store i64 %0, {{.*}}[[TLS_AUX]]
+    // CHECK-NEXT: ret void
+    aux::A.with(|a| a.set(v))
+}
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/to_vec.rs b/tests/codegen/to_vec.rs
new file mode 100644
index 00000000000..60dc4efcb62
--- /dev/null
+++ b/tests/codegen/to_vec.rs
@@ -0,0 +1,10 @@
+// compile-flags: -O
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @copy_to_vec
+#[no_mangle]
+fn copy_to_vec(s: &[u64]) -> Vec<u64> {
+  s.to_vec()
+  // CHECK: call void @llvm.memcpy
+}
diff --git a/tests/codegen/transmute-optimized.rs b/tests/codegen/transmute-optimized.rs
new file mode 100644
index 00000000000..461dd550cd7
--- /dev/null
+++ b/tests/codegen/transmute-optimized.rs
@@ -0,0 +1,109 @@
+// compile-flags: -O -Z merge-functions=disabled
+// min-llvm-version: 15.0 # this test uses `ptr`s
+// 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
new file mode 100644
index 00000000000..293b0d664f6
--- /dev/null
+++ b/tests/codegen/transmute-scalar.rs
@@ -0,0 +1,58 @@
+// compile-flags: -C opt-level=0 -C no-prepopulate-passes
+// min-llvm-version: 15.0 # this test assumes `ptr`s and thus no `pointercast`s
+
+#![crate_type = "lib"]
+
+// With opaque ptrs in LLVM, `transmute` can load/store any `alloca` as any type,
+// without needing to pointercast, and SRoA will turn that into a `bitcast`.
+// Thus memory-to-memory transmutes don't need to generate them ourselves.
+
+// 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 %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 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{{.*}}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 %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 %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]] %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_identity.rs b/tests/codegen/try_identity.rs
new file mode 100644
index 00000000000..92be90014ff
--- /dev/null
+++ b/tests/codegen/try_identity.rs
@@ -0,0 +1,34 @@
+// compile-flags: -C no-prepopulate-passes -O -Z mir-opt-level=3 -Zunsound-mir-opts
+
+// Ensure that `x?` has no overhead on `Result<T, E>` due to identity `match`es in lowering.
+// This requires inlining to trigger the MIR optimizations in `SimplifyArmIdentity`.
+
+#![crate_type = "lib"]
+
+type R = Result<u64, i32>;
+
+// This was written to the `?` from `try_trait`, but `try_trait_v2` uses a different structure,
+// so the relevant desugar is copied inline in order to keep the test testing the same thing.
+// FIXME(#85133): while this might be useful for `r#try!`, it would be nice to have a MIR
+// optimization that picks up the `?` desugaring, as `SimplifyArmIdentity` does not.
+#[no_mangle]
+pub fn try_identity(x: R) -> R {
+// CHECK: start:
+// FIXME(JakobDegen): Broken by deaggregation change CHECK-NOT\: br {{.*}}
+// CHECK ret void
+    let y = match into_result(x) {
+        Err(e) => return from_error(From::from(e)),
+        Ok(v) => v,
+    };
+    Ok(y)
+}
+
+#[inline]
+fn into_result<T, E>(r: Result<T, E>) -> Result<T, E> {
+    r
+}
+
+#[inline]
+fn from_error<T, E>(e: E) -> Result<T, E> {
+    Err(e)
+}
diff --git a/tests/codegen/try_question_mark_nop.rs b/tests/codegen/try_question_mark_nop.rs
new file mode 100644
index 00000000000..d239387768e
--- /dev/null
+++ b/tests/codegen/try_question_mark_nop.rs
@@ -0,0 +1,54 @@
+// min-llvm-version: 15.0
+// compile-flags: -O -Z merge-functions=disabled --edition=2021
+// only-x86_64
+
+#![crate_type = "lib"]
+#![feature(try_blocks)]
+
+// These are now NOPs in LLVM 15, presumably thanks to nikic's change mentioned in
+// <https://github.com/rust-lang/rust/issues/85133#issuecomment-1072168354>.
+// Unfortunately, as of 2022-08-17 they're not yet nops for `u64`s nor `Option`.
+
+use std::ops::ControlFlow::{self, Continue, Break};
+
+// CHECK-LABEL: @result_nop_match_32
+#[no_mangle]
+pub fn result_nop_match_32(x: Result<i32, u32>) -> Result<i32, u32> {
+    // CHECK: start
+    // CHECK-NEXT: ret i64 %0
+    match x {
+        Ok(x) => Ok(x),
+        Err(x) => Err(x),
+    }
+}
+
+// CHECK-LABEL: @result_nop_traits_32
+#[no_mangle]
+pub fn result_nop_traits_32(x: Result<i32, u32>) -> Result<i32, u32> {
+    // CHECK: start
+    // CHECK-NEXT: ret i64 %0
+    try {
+        x?
+    }
+}
+
+// CHECK-LABEL: @control_flow_nop_match_32
+#[no_mangle]
+pub fn control_flow_nop_match_32(x: ControlFlow<i32, u32>) -> ControlFlow<i32, u32> {
+    // CHECK: start
+    // CHECK-NEXT: ret i64 %0
+    match x {
+        Continue(x) => Continue(x),
+        Break(x) => Break(x),
+    }
+}
+
+// CHECK-LABEL: @control_flow_nop_traits_32
+#[no_mangle]
+pub fn control_flow_nop_traits_32(x: ControlFlow<i32, u32>) -> ControlFlow<i32, u32> {
+    // CHECK: start
+    // CHECK-NEXT: ret i64 %0
+    try {
+        x?
+    }
+}
diff --git a/tests/codegen/tune-cpu-on-functions.rs b/tests/codegen/tune-cpu-on-functions.rs
new file mode 100644
index 00000000000..ed8dc0e9383
--- /dev/null
+++ b/tests/codegen/tune-cpu-on-functions.rs
@@ -0,0 +1,21 @@
+// This test makes sure that functions get annotated with the proper
+// "tune-cpu" attribute in LLVM.
+
+// no-prefer-dynamic
+//
+// compile-flags: -C no-prepopulate-passes -C panic=abort -C linker-plugin-lto -Cpasses=name-anon-globals -Z tune-cpu=generic
+
+#![crate_type = "staticlib"]
+
+// CHECK-LABEL: define {{.*}} @exported() {{.*}} #0
+#[no_mangle]
+pub extern fn exported() {
+    not_exported();
+}
+
+// CHECK-LABEL: ; tune_cpu_on_functions::not_exported
+// CHECK-NEXT: ; Function Attrs:
+// CHECK-NEXT: define {{.*}}() {{.*}} #0
+fn not_exported() {}
+
+// CHECK: attributes #0 = {{.*}} "tune-cpu"="{{.*}}"
diff --git a/tests/codegen/tuple-layout-opt.rs b/tests/codegen/tuple-layout-opt.rs
new file mode 100644
index 00000000000..309fe1d5ec9
--- /dev/null
+++ b/tests/codegen/tuple-layout-opt.rs
@@ -0,0 +1,36 @@
+// ignore-emscripten
+// compile-flags: -C no-prepopulate-passes -Copt-level=0
+
+// Test that tuples get optimized layout, in particular with a ZST in the last field (#63244)
+
+#![crate_type="lib"]
+
+type ScalarZstLast = (u128, ());
+// CHECK: define {{(dso_local )?}}i128 @test_ScalarZstLast(i128 %_1)
+#[no_mangle]
+pub fn test_ScalarZstLast(_: ScalarZstLast) -> ScalarZstLast { loop {} }
+
+type ScalarZstFirst = ((), u128);
+// CHECK: define {{(dso_local )?}}i128 @test_ScalarZstFirst(i128 %_1)
+#[no_mangle]
+pub fn test_ScalarZstFirst(_: ScalarZstFirst) -> ScalarZstFirst { loop {} }
+
+type ScalarPairZstLast = (u8, u128, ());
+// 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 {{(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 {{(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 {{(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-float-casts.rs b/tests/codegen/unchecked-float-casts.rs
new file mode 100644
index 00000000000..4e3bfcd4397
--- /dev/null
+++ b/tests/codegen/unchecked-float-casts.rs
@@ -0,0 +1,36 @@
+// This file tests that we don't generate any code for saturation when using the
+// unchecked intrinsics.
+
+// compile-flags: -C opt-level=3
+// ignore-wasm32 the wasm target is tested in `wasm_casts_*`
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @f32_to_u32
+#[no_mangle]
+pub fn f32_to_u32(x: f32) -> u32 {
+    // CHECK: fptoui
+    // CHECK-NOT: fcmp
+    // CHECK-NOT: icmp
+    // CHECK-NOT: select
+    unsafe { x.to_int_unchecked() }
+}
+
+// CHECK-LABEL: @f32_to_i32
+#[no_mangle]
+pub fn f32_to_i32(x: f32) -> i32 {
+    // CHECK: fptosi
+    // CHECK-NOT: fcmp
+    // CHECK-NOT: icmp
+    // CHECK-NOT: select
+    unsafe { x.to_int_unchecked() }
+}
+
+#[no_mangle]
+pub fn f64_to_u16(x: f64) -> u16 {
+    // CHECK: fptoui
+    // CHECK-NOT: fcmp
+    // CHECK-NOT: icmp
+    // CHECK-NOT: select
+    unsafe { x.to_int_unchecked() }
+}
diff --git a/tests/codegen/unchecked_shifts.rs b/tests/codegen/unchecked_shifts.rs
new file mode 100644
index 00000000000..0924dda08ee
--- /dev/null
+++ b/tests/codegen/unchecked_shifts.rs
@@ -0,0 +1,70 @@
+// 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"]
+#![feature(unchecked_math)]
+
+// 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
+    a.unchecked_shl(b)
+}
+
+// CHECK-LABEL: @unchecked_shl_unsigned_smaller
+#[no_mangle]
+pub unsafe fn unchecked_shl_unsigned_smaller(a: u16, b: u32) -> u16 {
+    // This uses -DAG to avoid failing on irrelevant reorderings,
+    // like emitting the truncation earlier.
+
+    // CHECK-DAG: %[[INRANGE:.+]] = icmp ult i32 %b, 65536
+    // CHECK-DAG: tail call void @llvm.assume(i1 %[[INRANGE]])
+    // CHECK-DAG: %[[TRUNC:.+]] = trunc i32 %b to i16
+    // CHECK-DAG: shl i16 %a, %[[TRUNC]]
+    a.unchecked_shl(b)
+}
+
+// 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)
+}
+
+// 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
+    a.unchecked_shr(b)
+}
+
+// CHECK-LABEL: @unchecked_shr_signed_smaller
+#[no_mangle]
+pub unsafe fn unchecked_shr_signed_smaller(a: i16, b: u32) -> i16 {
+    // This uses -DAG to avoid failing on irrelevant reorderings,
+    // like emitting the truncation earlier.
+
+    // CHECK-DAG: %[[INRANGE:.+]] = icmp ult i32 %b, 32768
+    // CHECK-DAG: tail call void @llvm.assume(i1 %[[INRANGE]])
+    // CHECK-DAG: %[[TRUNC:.+]] = trunc i32 %b to i16
+    // CHECK-DAG: ashr i16 %a, %[[TRUNC]]
+    a.unchecked_shr(b)
+}
+
+// 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
new file mode 100644
index 00000000000..f169988e1f5
--- /dev/null
+++ b/tests/codegen/uninit-consts.rs
@@ -0,0 +1,55 @@
+// compile-flags: -C no-prepopulate-passes
+// min-llvm-version: 15.0 (for opaque pointers)
+
+// Check that we use undef (and not zero) for uninitialized bytes in constants.
+
+#![crate_type = "lib"]
+
+use std::mem::MaybeUninit;
+
+pub struct PartiallyUninit {
+    x: u32,
+    y: MaybeUninit<[u8; 10]>,
+}
+
+// CHECK: [[FULLY_UNINIT:@[0-9]+]] = private unnamed_addr constant <{ [10 x i8] }> undef
+
+// CHECK: [[PARTIALLY_UNINIT:@[0-9]+]] = private unnamed_addr constant <{ [4 x i8], [12 x i8] }> <{ [4 x i8] c"{{\\EF\\BE\\AD\\DE|\\DE\\AD\\BE\\EF}}", [12 x i8] undef }>, align 4
+
+// This shouldn't contain undef, since it contains more chunks
+// than the default value of uninit_const_chunk_threshold.
+// CHECK: [[UNINIT_PADDING_HUGE:@[0-9]+]] = private unnamed_addr constant <{ [32768 x i8] }> <{ [32768 x i8] c"{{.+}}" }>, align 4
+
+// CHECK: [[FULLY_UNINIT_HUGE:@[0-9]+]] = private unnamed_addr constant <{ [16384 x i8] }> undef
+
+// CHECK-LABEL: @fully_uninit
+#[no_mangle]
+pub const fn fully_uninit() -> MaybeUninit<[u8; 10]> {
+    const M: MaybeUninit<[u8; 10]> = MaybeUninit::uninit();
+    // CHECK: call void @llvm.memcpy.{{.+}}(ptr align 1 %_0, ptr align 1 {{.*}}[[FULLY_UNINIT]]{{.*}}, i{{(32|64)}} 10, i1 false)
+    M
+}
+
+// CHECK-LABEL: @partially_uninit
+#[no_mangle]
+pub const fn partially_uninit() -> PartiallyUninit {
+    const X: PartiallyUninit = PartiallyUninit { x: 0xdeadbeef, y: MaybeUninit::uninit() };
+    // CHECK: call void @llvm.memcpy.{{.+}}(ptr align 4 %_0, ptr align 4 {{.*}}[[PARTIALLY_UNINIT]]{{.*}}, i{{(32|64)}} 16, i1 false)
+    X
+}
+
+// CHECK-LABEL: @uninit_padding_huge
+#[no_mangle]
+pub const fn uninit_padding_huge() -> [(u32, u8); 4096] {
+    const X: [(u32, u8); 4096] = [(123, 45); 4096];
+    // CHECK: call void @llvm.memcpy.{{.+}}(ptr align 4 %_0, ptr align 4 {{.*}}[[UNINIT_PADDING_HUGE]]{{.*}}, i{{(32|64)}} 32768, i1 false)
+    X
+}
+
+// CHECK-LABEL: @fully_uninit_huge
+#[no_mangle]
+pub const fn fully_uninit_huge() -> MaybeUninit<[u32; 4096]> {
+    const F: MaybeUninit<[u32; 4096]> = MaybeUninit::uninit();
+    // 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
new file mode 100644
index 00000000000..653c5837daf
--- /dev/null
+++ b/tests/codegen/union-abi.rs
@@ -0,0 +1,76 @@
+// ignore-emscripten vectors passed directly
+// compile-flags: -O -C no-prepopulate-passes
+
+// This test that using union forward the abi of the inner type, as
+// discussed in #54668
+
+#![crate_type="lib"]
+#![feature(repr_simd)]
+
+#[derive(Copy, Clone)]
+pub enum Unhab {}
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct i64x4(i64, i64, i64, i64);
+
+#[derive(Copy, Clone)]
+pub union UnionI64x4{ a:(), b: i64x4 }
+
+// CHECK: define {{(dso_local )?}}void @test_UnionI64x4({{<4 x i64>\*|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 {{(dso_local )?}}void @test_UnionI64x4_({{<4 x i64>\*|ptr}} {{.*}} %_1)
+#[no_mangle]
+pub fn test_UnionI64x4_(_: UnionI64x4_) { loop {} }
+
+pub union UnionI64x4I64{ a: i64x4, b: i64 }
+
+// CHECK: define {{(dso_local )?}}void @test_UnionI64x4I64({{%UnionI64x4I64\*|ptr}} {{.*}} %_1)
+#[no_mangle]
+pub fn test_UnionI64x4I64(_: UnionI64x4I64) { loop {} }
+
+pub union UnionI64x4Tuple{ a: i64x4, b: (i64, i64, i64, i64) }
+
+// CHECK: define {{(dso_local )?}}void @test_UnionI64x4Tuple({{%UnionI64x4Tuple\*|ptr}} {{.*}} %_1)
+#[no_mangle]
+pub fn test_UnionI64x4Tuple(_: UnionI64x4Tuple) { loop {} }
+
+
+pub union UnionF32{a:f32}
+
+// 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 {{(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 {{(dso_local )?}}i32 @test_UnionF32U32(i32{{( %0)?}})
+#[no_mangle]
+pub fn test_UnionF32U32(_: UnionF32U32) -> UnionF32U32 { loop {} }
+
+pub union UnionU128{a:u128}
+// 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 {{(dso_local )?}}void @test_CUnionU128({{%CUnionU128\*|ptr}} {{.*}} %_1)
+#[no_mangle]
+pub fn test_CUnionU128(_: CUnionU128) { loop {} }
+
+pub union UnionBool { b:bool }
+// 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
diff --git a/tests/codegen/unpadded-simd.rs b/tests/codegen/unpadded-simd.rs
new file mode 100644
index 00000000000..eb44dbd9313
--- /dev/null
+++ b/tests/codegen/unpadded-simd.rs
@@ -0,0 +1,14 @@
+// Make sure that no 0-sized padding is inserted in structs and that
+// structs are represented as expected by Neon intrinsics in LLVM.
+// See #87254.
+
+#![crate_type = "lib"]
+#![feature(repr_simd)]
+
+#[derive(Copy, Clone, Debug)]
+#[repr(simd)]
+pub struct int16x4_t(pub i16, pub i16, pub i16, pub i16);
+
+#[derive(Copy, Clone, Debug)]
+pub struct int16x4x2_t(pub int16x4_t, pub int16x4_t);
+// CHECK: %int16x4x2_t = type { <4 x i16>, <4 x i16> }
diff --git a/tests/codegen/unwind-abis/aapcs-unwind-abi.rs b/tests/codegen/unwind-abis/aapcs-unwind-abi.rs
new file mode 100644
index 00000000000..c092e28a05a
--- /dev/null
+++ b/tests/codegen/unwind-abis/aapcs-unwind-abi.rs
@@ -0,0 +1,31 @@
+// needs-llvm-components: arm
+// compile-flags: --target=armv7-unknown-linux-gnueabihf --crate-type=rlib -Cno-prepopulate-passes
+#![no_core]
+#![feature(no_core, lang_items, c_unwind)]
+#[lang="sized"]
+trait Sized { }
+
+// Test that `nounwind` attributes are correctly applied to exported `aapcs` and
+// `aapcs-unwind` extern functions. `aapcs-unwind` functions MUST NOT have this attribute. We
+// disable optimizations above to prevent LLVM from inferring the attribute.
+
+// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
+#[no_mangle]
+pub extern "aapcs" fn rust_item_that_cannot_unwind() {
+}
+
+// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 {
+#[no_mangle]
+pub extern "aapcs-unwind" fn rust_item_that_can_unwind() {
+}
+
+// Now, make some assertions that the LLVM attributes for these functions are correct.  First, make
+// sure that the first item is correctly marked with the `nounwind` attribute:
+//
+// CHECK: attributes #0 = { {{.*}}nounwind{{.*}} }
+//
+// Next, let's assert that the second item, which CAN unwind, does not have this attribute.
+//
+// CHECK: attributes #1 = {
+// CHECK-NOT: nounwind
+// CHECK: }
diff --git a/tests/codegen/unwind-abis/c-unwind-abi-panic-abort.rs b/tests/codegen/unwind-abis/c-unwind-abi-panic-abort.rs
new file mode 100644
index 00000000000..ea5bae18e23
--- /dev/null
+++ b/tests/codegen/unwind-abis/c-unwind-abi-panic-abort.rs
@@ -0,0 +1,28 @@
+// compile-flags: -C panic=abort
+
+// Test that `nounwind` attributes are also applied to extern `C-unwind` Rust functions
+// when the code is compiled with `panic=abort`.
+
+#![crate_type = "lib"]
+#![feature(c_unwind)]
+
+// CHECK: @rust_item_that_can_unwind() unnamed_addr [[ATTR0:#[0-9]+]]
+#[no_mangle]
+pub unsafe extern "C-unwind" fn rust_item_that_can_unwind() {
+    // Handle both legacy and v0 symbol mangling.
+    // CHECK: call void @{{.*core9panicking19panic_cannot_unwind}}
+    may_unwind();
+}
+
+extern "C-unwind" {
+    // CHECK: @may_unwind() unnamed_addr [[ATTR1:#[0-9]+]]
+    fn may_unwind();
+}
+
+// Now, make sure that the LLVM attributes for this functions are correct.  First, make
+// sure that the first item is correctly marked with the `nounwind` attribute:
+//
+// CHECK: attributes [[ATTR0]] = { {{.*}}nounwind{{.*}} }
+//
+// Now, check that foreign item is correctly marked without the `nounwind` attribute.
+// CHECK-NOT: attributes [[ATTR1]] = { {{.*}}nounwind{{.*}} }
diff --git a/tests/codegen/unwind-abis/c-unwind-abi.rs b/tests/codegen/unwind-abis/c-unwind-abi.rs
new file mode 100644
index 00000000000..fa5b6bad75c
--- /dev/null
+++ b/tests/codegen/unwind-abis/c-unwind-abi.rs
@@ -0,0 +1,30 @@
+// 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
+// to prevent LLVM from inferring the attribute.
+
+#![crate_type = "lib"]
+#![feature(c_unwind)]
+
+// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
+#[no_mangle]
+pub extern "C" fn rust_item_that_cannot_unwind() {
+}
+
+// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 {
+#[no_mangle]
+pub extern "C-unwind" fn rust_item_that_can_unwind() {
+}
+
+// Now, make some assertions that the LLVM attributes for these functions are correct.  First, make
+// sure that the first item is correctly marked with the `nounwind` attribute:
+//
+// CHECK: attributes #0 = { {{.*}}nounwind{{.*}} }
+//
+// Next, let's assert that the second item, which CAN unwind, does not have this attribute.
+//
+// CHECK: attributes #1 = {
+// CHECK-NOT: nounwind
+// CHECK: }
diff --git a/tests/codegen/unwind-abis/cdecl-unwind-abi.rs b/tests/codegen/unwind-abis/cdecl-unwind-abi.rs
new file mode 100644
index 00000000000..64746d32175
--- /dev/null
+++ b/tests/codegen/unwind-abis/cdecl-unwind-abi.rs
@@ -0,0 +1,30 @@
+// 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
+// disable optimizations above to prevent LLVM from inferring the attribute.
+
+#![crate_type = "lib"]
+#![feature(c_unwind)]
+
+// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
+#[no_mangle]
+pub extern "cdecl" fn rust_item_that_cannot_unwind() {
+}
+
+// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 {
+#[no_mangle]
+pub extern "cdecl-unwind" fn rust_item_that_can_unwind() {
+}
+
+// Now, make some assertions that the LLVM attributes for these functions are correct.  First, make
+// sure that the first item is correctly marked with the `nounwind` attribute:
+//
+// CHECK: attributes #0 = { {{.*}}nounwind{{.*}} }
+//
+// Next, let's assert that the second item, which CAN unwind, does not have this attribute.
+//
+// CHECK: attributes #1 = {
+// CHECK-NOT: nounwind
+// CHECK: }
diff --git a/tests/codegen/unwind-abis/fastcall-unwind-abi.rs b/tests/codegen/unwind-abis/fastcall-unwind-abi.rs
new file mode 100644
index 00000000000..b74099a5d96
--- /dev/null
+++ b/tests/codegen/unwind-abis/fastcall-unwind-abi.rs
@@ -0,0 +1,31 @@
+// needs-llvm-components: x86
+// compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib -Cno-prepopulate-passes
+#![no_core]
+#![feature(no_core, lang_items, c_unwind)]
+#[lang="sized"]
+trait Sized { }
+
+// Test that `nounwind` attributes are correctly applied to exported `fastcall` and
+// `fastcall-unwind` extern functions. `fastcall-unwind` functions MUST NOT have this attribute. We
+// disable optimizations above to prevent LLVM from inferring the attribute.
+
+// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
+#[no_mangle]
+pub extern "fastcall" fn rust_item_that_cannot_unwind() {
+}
+
+// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 {
+#[no_mangle]
+pub extern "fastcall-unwind" fn rust_item_that_can_unwind() {
+}
+
+// Now, make some assertions that the LLVM attributes for these functions are correct.  First, make
+// sure that the first item is correctly marked with the `nounwind` attribute:
+//
+// CHECK: attributes #0 = { {{.*}}nounwind{{.*}} }
+//
+// Next, let's assert that the second item, which CAN unwind, does not have this attribute.
+//
+// CHECK: attributes #1 = {
+// CHECK-NOT: nounwind
+// CHECK: }
diff --git a/tests/codegen/unwind-abis/nounwind-on-stable-panic-abort.rs b/tests/codegen/unwind-abis/nounwind-on-stable-panic-abort.rs
new file mode 100644
index 00000000000..106d593b21d
--- /dev/null
+++ b/tests/codegen/unwind-abis/nounwind-on-stable-panic-abort.rs
@@ -0,0 +1,16 @@
+// compile-flags: -C opt-level=0 -Cpanic=abort
+// ignore-wasm32-bare compiled with panic=abort by default
+
+#![crate_type = "lib"]
+
+// We disable optimizations to prevent LLVM from inferring the attribute.
+
+// CHECK: Function Attrs:{{.*}}nounwind
+// CHECK-NEXT: @foo
+#[no_mangle]
+pub extern "C" fn foo() {}
+
+// CHECK: Function Attrs:{{.*}}nounwind
+// CHECK-NEXT: @bar
+#[no_mangle]
+pub fn bar() {}
diff --git a/tests/codegen/unwind-abis/nounwind-on-stable-panic-unwind.rs b/tests/codegen/unwind-abis/nounwind-on-stable-panic-unwind.rs
new file mode 100644
index 00000000000..dc3911cd4eb
--- /dev/null
+++ b/tests/codegen/unwind-abis/nounwind-on-stable-panic-unwind.rs
@@ -0,0 +1,18 @@
+// compile-flags: -C opt-level=0
+// ignore-wasm32-bare compiled with panic=abort by default
+// needs-unwind
+
+#![crate_type = "lib"]
+
+// We disable optimizations to prevent LLVM from inferring the attribute.
+
+extern "C" {
+    fn bar();
+}
+
+// CHECK-NOT: Function Attrs:{{.*}}nounwind
+pub unsafe extern "C" fn foo() {
+    bar();
+}
+
+// Note that this test will get removed when `C-unwind` is fully stabilized
diff --git a/tests/codegen/unwind-abis/nounwind.rs b/tests/codegen/unwind-abis/nounwind.rs
new file mode 100644
index 00000000000..c46d717331b
--- /dev/null
+++ b/tests/codegen/unwind-abis/nounwind.rs
@@ -0,0 +1,17 @@
+// compile-flags: -C opt-level=0 -Cpanic=abort
+// ignore-wasm32-bare compiled with panic=abort by default
+
+#![crate_type = "lib"]
+#![feature(c_unwind)]
+
+// We disable optimizations to prevent LLVM from inferring the attribute.
+
+// CHECK: Function Attrs:{{.*}}nounwind
+// CHECK-NEXT: @foo
+#[no_mangle]
+pub extern "C" fn foo() {}
+
+// CHECK: Function Attrs:{{.*}}nounwind
+// CHECK-NEXT: @bar
+#[no_mangle]
+pub fn bar() {}
diff --git a/tests/codegen/unwind-abis/stdcall-unwind-abi.rs b/tests/codegen/unwind-abis/stdcall-unwind-abi.rs
new file mode 100644
index 00000000000..8eff0719f8f
--- /dev/null
+++ b/tests/codegen/unwind-abis/stdcall-unwind-abi.rs
@@ -0,0 +1,31 @@
+// needs-llvm-components: x86
+// compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib -Cno-prepopulate-passes
+#![no_core]
+#![feature(no_core, lang_items, c_unwind)]
+#[lang="sized"]
+trait Sized { }
+
+// Test that `nounwind` attributes are correctly applied to exported `stdcall` and `stdcall-unwind`
+// extern functions. `stdcall-unwind` functions MUST NOT have this attribute. We disable
+// optimizations above to prevent LLVM from inferring the attribute.
+
+// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
+#[no_mangle]
+pub extern "stdcall" fn rust_item_that_cannot_unwind() {
+}
+
+// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 {
+#[no_mangle]
+pub extern "stdcall-unwind" fn rust_item_that_can_unwind() {
+}
+
+// Now, make some assertions that the LLVM attributes for these functions are correct.  First, make
+// sure that the first item is correctly marked with the `nounwind` attribute:
+//
+// CHECK: attributes #0 = { {{.*}}nounwind{{.*}} }
+//
+// Next, let's assert that the second item, which CAN unwind, does not have this attribute.
+//
+// CHECK: attributes #1 = {
+// CHECK-NOT: nounwind
+// CHECK: }
diff --git a/tests/codegen/unwind-abis/system-unwind-abi.rs b/tests/codegen/unwind-abis/system-unwind-abi.rs
new file mode 100644
index 00000000000..f274a33b099
--- /dev/null
+++ b/tests/codegen/unwind-abis/system-unwind-abi.rs
@@ -0,0 +1,30 @@
+// 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
+// optimizations above to prevent LLVM from inferring the attribute.
+
+#![crate_type = "lib"]
+#![feature(c_unwind)]
+
+// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
+#[no_mangle]
+pub extern "system" fn rust_item_that_cannot_unwind() {
+}
+
+// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 {
+#[no_mangle]
+pub extern "system-unwind" fn rust_item_that_can_unwind() {
+}
+
+// Now, make some assertions that the LLVM attributes for these functions are correct.  First, make
+// sure that the first item is correctly marked with the `nounwind` attribute:
+//
+// CHECK: attributes #0 = { {{.*}}nounwind{{.*}} }
+//
+// Next, let's assert that the second item, which CAN unwind, does not have this attribute.
+//
+// CHECK: attributes #1 = {
+// CHECK-NOT: nounwind
+// CHECK: }
diff --git a/tests/codegen/unwind-abis/sysv64-unwind-abi.rs b/tests/codegen/unwind-abis/sysv64-unwind-abi.rs
new file mode 100644
index 00000000000..694fde17c3c
--- /dev/null
+++ b/tests/codegen/unwind-abis/sysv64-unwind-abi.rs
@@ -0,0 +1,31 @@
+// needs-llvm-components: x86
+// compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=rlib -Cno-prepopulate-passes
+#![no_core]
+#![feature(no_core, lang_items, c_unwind)]
+#[lang="sized"]
+trait Sized { }
+
+// Test that `nounwind` attributes are correctly applied to exported `sysv64` and
+// `sysv64-unwind` extern functions. `sysv64-unwind` functions MUST NOT have this attribute. We
+// disable optimizations above to prevent LLVM from inferring the attribute.
+
+// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
+#[no_mangle]
+pub extern "sysv64" fn rust_item_that_cannot_unwind() {
+}
+
+// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 {
+#[no_mangle]
+pub extern "sysv64-unwind" fn rust_item_that_can_unwind() {
+}
+
+// Now, make some assertions that the LLVM attributes for these functions are correct.  First, make
+// sure that the first item is correctly marked with the `nounwind` attribute:
+//
+// CHECK: attributes #0 = { {{.*}}nounwind{{.*}} }
+//
+// Next, let's assert that the second item, which CAN unwind, does not have this attribute.
+//
+// CHECK: attributes #1 = {
+// CHECK-NOT: nounwind
+// CHECK: }
diff --git a/tests/codegen/unwind-abis/thiscall-unwind-abi.rs b/tests/codegen/unwind-abis/thiscall-unwind-abi.rs
new file mode 100644
index 00000000000..7e81367fc5b
--- /dev/null
+++ b/tests/codegen/unwind-abis/thiscall-unwind-abi.rs
@@ -0,0 +1,31 @@
+// needs-llvm-components: x86
+// compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib -Cno-prepopulate-passes
+#![no_core]
+#![feature(no_core, lang_items, c_unwind, abi_thiscall)]
+#[lang="sized"]
+trait Sized { }
+
+// Test that `nounwind` attributes are correctly applied to exported `thiscall` and
+// `thiscall-unwind` extern functions. `thiscall-unwind` functions MUST NOT have this attribute. We
+// disable optimizations above to prevent LLVM from inferring the attribute.
+
+// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
+#[no_mangle]
+pub extern "thiscall" fn rust_item_that_cannot_unwind() {
+}
+
+// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 {
+#[no_mangle]
+pub extern "thiscall-unwind" fn rust_item_that_can_unwind() {
+}
+
+// Now, make some assertions that the LLVM attributes for these functions are correct.  First, make
+// sure that the first item is correctly marked with the `nounwind` attribute:
+//
+// CHECK: attributes #0 = { {{.*}}nounwind{{.*}} }
+//
+// Next, let's assert that the second item, which CAN unwind, does not have this attribute.
+//
+// CHECK: attributes #1 = {
+// CHECK-NOT: nounwind
+// CHECK: }
diff --git a/tests/codegen/unwind-abis/vectorcall-unwind-abi.rs b/tests/codegen/unwind-abis/vectorcall-unwind-abi.rs
new file mode 100644
index 00000000000..d7eca2a9700
--- /dev/null
+++ b/tests/codegen/unwind-abis/vectorcall-unwind-abi.rs
@@ -0,0 +1,31 @@
+// needs-llvm-components: x86
+// compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib -Cno-prepopulate-passes
+#![no_core]
+#![feature(no_core, lang_items, c_unwind, abi_vectorcall)]
+#[lang="sized"]
+trait Sized { }
+
+// Test that `nounwind` attributes are correctly applied to exported `vectorcall` and
+// `vectorcall-unwind` extern functions. `vectorcall-unwind` functions MUST NOT have this attribute.
+// We disable optimizations above to prevent LLVM from inferring the attribute.
+
+// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
+#[no_mangle]
+pub extern "vectorcall" fn rust_item_that_cannot_unwind() {
+}
+
+// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 {
+#[no_mangle]
+pub extern "vectorcall-unwind" fn rust_item_that_can_unwind() {
+}
+
+// Now, make some assertions that the LLVM attributes for these functions are correct.  First, make
+// sure that the first item is correctly marked with the `nounwind` attribute:
+//
+// CHECK: attributes #0 = { {{.*}}nounwind{{.*}} }
+//
+// Next, let's assert that the second item, which CAN unwind, does not have this attribute.
+//
+// CHECK: attributes #1 = {
+// CHECK-NOT: nounwind
+// CHECK: }
diff --git a/tests/codegen/unwind-abis/win64-unwind-abi.rs b/tests/codegen/unwind-abis/win64-unwind-abi.rs
new file mode 100644
index 00000000000..6591348c35d
--- /dev/null
+++ b/tests/codegen/unwind-abis/win64-unwind-abi.rs
@@ -0,0 +1,31 @@
+// needs-llvm-components: x86
+// compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=rlib -Cno-prepopulate-passes
+#![no_core]
+#![feature(no_core, lang_items, c_unwind)]
+#[lang="sized"]
+trait Sized { }
+
+// Test that `nounwind` attributes are correctly applied to exported `win64` and
+// `win64-unwind` extern functions. `win64-unwind` functions MUST NOT have this attribute. We
+// disable optimizations above to prevent LLVM from inferring the attribute.
+
+// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
+#[no_mangle]
+pub extern "win64" fn rust_item_that_cannot_unwind() {
+}
+
+// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 {
+#[no_mangle]
+pub extern "win64-unwind" fn rust_item_that_can_unwind() {
+}
+
+// Now, make some assertions that the LLVM attributes for these functions are correct.  First, make
+// sure that the first item is correctly marked with the `nounwind` attribute:
+//
+// CHECK: attributes #0 = { {{.*}}nounwind{{.*}} }
+//
+// Next, let's assert that the second item, which CAN unwind, does not have this attribute.
+//
+// CHECK: attributes #1 = {
+// CHECK-NOT: nounwind
+// CHECK: }
diff --git a/tests/codegen/unwind-and-panic-abort.rs b/tests/codegen/unwind-and-panic-abort.rs
new file mode 100644
index 00000000000..e43e73b96b9
--- /dev/null
+++ b/tests/codegen/unwind-and-panic-abort.rs
@@ -0,0 +1,17 @@
+// compile-flags: -C panic=abort
+
+#![crate_type = "lib"]
+#![feature(c_unwind)]
+
+extern "C-unwind" {
+    fn bar();
+}
+
+// CHECK: Function Attrs:{{.*}}nounwind
+// CHECK-NEXT: define{{.*}}void @foo
+// Handle both legacy and v0 symbol mangling.
+// CHECK: call void @{{.*core9panicking19panic_cannot_unwind}}
+#[no_mangle]
+pub unsafe extern "C" fn foo() {
+    bar();
+}
diff --git a/tests/codegen/unwind-extern-exports.rs b/tests/codegen/unwind-extern-exports.rs
new file mode 100644
index 00000000000..4e1e719d5cd
--- /dev/null
+++ b/tests/codegen/unwind-extern-exports.rs
@@ -0,0 +1,17 @@
+// compile-flags: -C opt-level=0
+// ignore-wasm32-bare compiled with panic=abort by default
+// needs-unwind
+
+#![crate_type = "lib"]
+#![feature(c_unwind)]
+
+// Make sure these all do *not* get the attribute.
+// We disable optimizations to prevent LLVM from inferring the attribute.
+// CHECK-NOT: nounwind
+
+// "C" ABI
+pub extern "C-unwind" fn foo_unwind() {}
+
+// "Rust"
+// (`extern "Rust"` could be removed as all `fn` get it implicitly; we leave it in for clarity.)
+pub fn bar() {}
diff --git a/tests/codegen/unwind-extern-imports.rs b/tests/codegen/unwind-extern-imports.rs
new file mode 100644
index 00000000000..260dcc628cc
--- /dev/null
+++ b/tests/codegen/unwind-extern-imports.rs
@@ -0,0 +1,23 @@
+// compile-flags: -C no-prepopulate-passes
+// ignore-wasm32-bare compiled with panic=abort by default
+// needs-unwind
+
+#![crate_type = "lib"]
+#![feature(c_unwind)]
+
+extern "C" {
+    // CHECK: Function Attrs:{{.*}}nounwind
+    // CHECK-NEXT: declare{{.*}}void @extern_fn
+    fn extern_fn();
+}
+
+extern "C-unwind" {
+    // CHECK-NOT: nounwind
+    // CHECK: declare{{.*}}void @c_unwind_extern_fn
+    fn c_unwind_extern_fn();
+}
+
+pub unsafe fn force_declare() {
+    extern_fn();
+    c_unwind_extern_fn();
+}
diff --git a/tests/codegen/used_with_arg.rs b/tests/codegen/used_with_arg.rs
new file mode 100644
index 00000000000..4515cb2aed0
--- /dev/null
+++ b/tests/codegen/used_with_arg.rs
@@ -0,0 +1,10 @@
+#![crate_type = "lib"]
+#![feature(used_with_arg)]
+
+// CHECK: @llvm.used = appending global {{.*}}USED_LINKER
+#[used(linker)]
+static mut USED_LINKER: [usize; 1] = [0];
+
+// CHECK-NEXT: @llvm.compiler.used = appending global {{.*}}USED_COMPILER
+#[used(compiler)]
+static mut USED_COMPILER: [usize; 1] = [0];
diff --git a/tests/codegen/var-names.rs b/tests/codegen/var-names.rs
new file mode 100644
index 00000000000..d4715efad73
--- /dev/null
+++ b/tests/codegen/var-names.rs
@@ -0,0 +1,15 @@
+// compile-flags: -O -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: define{{.*}}i32 @test(i32 noundef %a, i32 noundef %b)
+#[no_mangle]
+pub fn test(a: u32, b: u32) -> u32 {
+    let c = a + b;
+    // CHECK: %c = add i32 %a, %b
+    let d = c;
+    let e = d * a;
+    // CHECK-NEXT: %e = mul i32 %c, %a
+    e
+    // CHECK-NEXT: ret i32 %e
+}
diff --git a/tests/codegen/vec-as-ptr.rs b/tests/codegen/vec-as-ptr.rs
new file mode 100644
index 00000000000..8ff7ba9cb64
--- /dev/null
+++ b/tests/codegen/vec-as-ptr.rs
@@ -0,0 +1,19 @@
+// compile-flags: -O -Zmerge-functions=disabled
+
+#![crate_type = "lib"]
+
+// 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
+#[no_mangle]
+pub fn vec_as_ptr(v: &Vec<u8>) -> *const u8 {
+    v.as_ptr()
+}
+
+// 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
+#[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-llvm14.rs b/tests/codegen/vec-calloc-llvm14.rs
new file mode 100644
index 00000000000..08302796c41
--- /dev/null
+++ b/tests/codegen/vec-calloc-llvm14.rs
@@ -0,0 +1,144 @@
+// compile-flags: -O
+// only-x86_64
+// ignore-debug
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @vec_zero_bytes
+#[no_mangle]
+pub fn vec_zero_bytes(n: usize) -> Vec<u8> {
+    // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+    // CHECK-NOT: call {{.*}}reserve
+    // CHECK-NOT: call {{.*}}__rust_alloc(
+    // CHECK-NOT: call {{.*}}llvm.memset
+
+    // CHECK: call {{.*}}__rust_alloc_zeroed(
+
+    // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+    // CHECK-NOT: call {{.*}}reserve
+    // CHECK-NOT: call {{.*}}__rust_alloc(
+    // CHECK-NOT: call {{.*}}llvm.memset
+
+    // CHECK: ret void
+    vec![0; n]
+}
+
+// CHECK-LABEL: @vec_one_bytes
+#[no_mangle]
+pub fn vec_one_bytes(n: usize) -> Vec<u8> {
+    // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+    // CHECK-NOT: call {{.*}}reserve
+    // CHECK-NOT: call {{.*}}__rust_alloc_zeroed(
+
+    // CHECK: call {{.*}}__rust_alloc(
+    // CHECK: call {{.*}}llvm.memset
+
+    // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+    // CHECK-NOT: call {{.*}}reserve
+    // CHECK-NOT: call {{.*}}__rust_alloc_zeroed(
+
+    // CHECK: ret void
+    vec![1; n]
+}
+
+// CHECK-LABEL: @vec_zero_scalar
+#[no_mangle]
+pub fn vec_zero_scalar(n: usize) -> Vec<i32> {
+    // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+    // CHECK-NOT: call {{.*}}reserve
+    // CHECK-NOT: call {{.*}}__rust_alloc(
+
+    // CHECK: call {{.*}}__rust_alloc_zeroed(
+
+    // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+    // CHECK-NOT: call {{.*}}reserve
+    // CHECK-NOT: call {{.*}}__rust_alloc(
+
+    // CHECK: ret void
+    vec![0; n]
+}
+
+// CHECK-LABEL: @vec_one_scalar
+#[no_mangle]
+pub fn vec_one_scalar(n: usize) -> Vec<i32> {
+    // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+    // CHECK-NOT: call {{.*}}reserve
+    // CHECK-NOT: call {{.*}}__rust_alloc_zeroed(
+
+    // CHECK: call {{.*}}__rust_alloc(
+
+    // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+    // CHECK-NOT: call {{.*}}reserve
+    // CHECK-NOT: call {{.*}}__rust_alloc_zeroed(
+
+    // CHECK: ret void
+    vec![1; n]
+}
+
+// CHECK-LABEL: @vec_zero_rgb48
+#[no_mangle]
+pub fn vec_zero_rgb48(n: usize) -> Vec<[u16; 3]> {
+    // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+    // CHECK-NOT: call {{.*}}reserve
+    // CHECK-NOT: call {{.*}}__rust_alloc(
+
+    // CHECK: call {{.*}}__rust_alloc_zeroed(
+
+    // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+    // CHECK-NOT: call {{.*}}reserve
+    // CHECK-NOT: call {{.*}}__rust_alloc(
+
+    // CHECK: ret void
+    vec![[0, 0, 0]; n]
+}
+
+// CHECK-LABEL: @vec_zero_array_16
+#[no_mangle]
+pub fn vec_zero_array_16(n: usize) -> Vec<[i64; 16]> {
+    // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+    // CHECK-NOT: call {{.*}}reserve
+    // CHECK-NOT: call {{.*}}__rust_alloc(
+
+    // CHECK: call {{.*}}__rust_alloc_zeroed(
+
+    // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+    // CHECK-NOT: call {{.*}}reserve
+    // CHECK-NOT: call {{.*}}__rust_alloc(
+
+    // CHECK: ret void
+    vec![[0_i64; 16]; n]
+}
+
+// CHECK-LABEL: @vec_zero_tuple
+#[no_mangle]
+pub fn vec_zero_tuple(n: usize) -> Vec<(i16, u8, char)> {
+    // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+    // CHECK-NOT: call {{.*}}reserve
+    // CHECK-NOT: call {{.*}}__rust_alloc(
+
+    // CHECK: call {{.*}}__rust_alloc_zeroed(
+
+    // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+    // CHECK-NOT: call {{.*}}reserve
+    // CHECK-NOT: call {{.*}}__rust_alloc(
+
+    // CHECK: ret void
+    vec![(0, 0, '\0'); n]
+}
+
+// CHECK-LABEL: @vec_non_zero_tuple
+#[no_mangle]
+pub fn vec_non_zero_tuple(n: usize) -> Vec<(i16, u8, char)> {
+    // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+    // CHECK-NOT: call {{.*}}reserve
+    // CHECK-NOT: call {{.*}}__rust_alloc_zeroed(
+
+    // CHECK: call {{.*}}__rust_alloc(
+
+    // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+    // CHECK-NOT: call {{.*}}reserve
+    // CHECK-NOT: call {{.*}}__rust_alloc_zeroed(
+
+    // CHECK: ret void
+    vec![(0, 0, 'A'); n]
+}
diff --git a/tests/codegen/vec-calloc.rs b/tests/codegen/vec-calloc.rs
new file mode 100644
index 00000000000..4481a9d1e99
--- /dev/null
+++ b/tests/codegen/vec-calloc.rs
@@ -0,0 +1,184 @@
+// compile-flags: -O -Z merge-functions=disabled
+// only-x86_64
+// ignore-debug
+// min-llvm-version: 15.0
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @vec_zero_bytes
+#[no_mangle]
+pub fn vec_zero_bytes(n: usize) -> Vec<u8> {
+    // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+    // CHECK-NOT: call {{.*}}reserve
+    // CHECK-NOT: call {{.*}}__rust_alloc(
+    // CHECK-NOT: call {{.*}}llvm.memset
+
+    // CHECK: call {{.*}}__rust_alloc_zeroed(
+
+    // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+    // CHECK-NOT: call {{.*}}reserve
+    // CHECK-NOT: call {{.*}}__rust_alloc(
+    // CHECK-NOT: call {{.*}}llvm.memset
+
+    // CHECK: ret void
+    vec![0; n]
+}
+
+// CHECK-LABEL: @vec_one_bytes
+#[no_mangle]
+pub fn vec_one_bytes(n: usize) -> Vec<u8> {
+    // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+    // CHECK-NOT: call {{.*}}reserve
+    // CHECK-NOT: call {{.*}}__rust_alloc_zeroed(
+
+    // CHECK: call {{.*}}__rust_alloc(
+    // CHECK: call {{.*}}llvm.memset
+
+    // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+    // CHECK-NOT: call {{.*}}reserve
+    // CHECK-NOT: call {{.*}}__rust_alloc_zeroed(
+
+    // CHECK: ret void
+    vec![1; n]
+}
+
+// CHECK-LABEL: @vec_zero_scalar
+#[no_mangle]
+pub fn vec_zero_scalar(n: usize) -> Vec<i32> {
+    // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+    // CHECK-NOT: call {{.*}}reserve
+    // CHECK-NOT: call {{.*}}__rust_alloc(
+
+    // CHECK: call {{.*}}__rust_alloc_zeroed(
+
+    // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+    // CHECK-NOT: call {{.*}}reserve
+    // CHECK-NOT: call {{.*}}__rust_alloc(
+
+    // CHECK: ret void
+    vec![0; n]
+}
+
+// CHECK-LABEL: @vec_one_scalar
+#[no_mangle]
+pub fn vec_one_scalar(n: usize) -> Vec<i32> {
+    // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+    // CHECK-NOT: call {{.*}}reserve
+    // CHECK-NOT: call {{.*}}__rust_alloc_zeroed(
+
+    // CHECK: call {{.*}}__rust_alloc(
+
+    // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+    // CHECK-NOT: call {{.*}}reserve
+    // CHECK-NOT: call {{.*}}__rust_alloc_zeroed(
+
+    // CHECK: ret void
+    vec![1; n]
+}
+
+// CHECK-LABEL: @vec_zero_rgb48
+#[no_mangle]
+pub fn vec_zero_rgb48(n: usize) -> Vec<[u16; 3]> {
+    // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+    // CHECK-NOT: call {{.*}}reserve
+    // CHECK-NOT: call {{.*}}__rust_alloc(
+
+    // CHECK: call {{.*}}__rust_alloc_zeroed(
+
+    // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+    // CHECK-NOT: call {{.*}}reserve
+    // CHECK-NOT: call {{.*}}__rust_alloc(
+
+    // CHECK: ret void
+    vec![[0, 0, 0]; n]
+}
+
+// CHECK-LABEL: @vec_zero_array_16
+#[no_mangle]
+pub fn vec_zero_array_16(n: usize) -> Vec<[i64; 16]> {
+    // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+    // CHECK-NOT: call {{.*}}reserve
+    // CHECK-NOT: call {{.*}}__rust_alloc(
+
+    // CHECK: call {{.*}}__rust_alloc_zeroed(
+
+    // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+    // CHECK-NOT: call {{.*}}reserve
+    // CHECK-NOT: call {{.*}}__rust_alloc(
+
+    // CHECK: ret void
+    vec![[0_i64; 16]; n]
+}
+
+// CHECK-LABEL: @vec_zero_tuple
+#[no_mangle]
+pub fn vec_zero_tuple(n: usize) -> Vec<(i16, u8, char)> {
+    // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+    // CHECK-NOT: call {{.*}}reserve
+    // CHECK-NOT: call {{.*}}__rust_alloc(
+
+    // CHECK: call {{.*}}__rust_alloc_zeroed(
+
+    // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+    // CHECK-NOT: call {{.*}}reserve
+    // CHECK-NOT: call {{.*}}__rust_alloc(
+
+    // CHECK: ret void
+    vec![(0, 0, '\0'); n]
+}
+
+// CHECK-LABEL: @vec_non_zero_tuple
+#[no_mangle]
+pub fn vec_non_zero_tuple(n: usize) -> Vec<(i16, u8, char)> {
+    // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+    // CHECK-NOT: call {{.*}}reserve
+    // CHECK-NOT: call {{.*}}__rust_alloc_zeroed(
+
+    // CHECK: call {{.*}}__rust_alloc(
+
+    // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+    // CHECK-NOT: call {{.*}}reserve
+    // CHECK-NOT: call {{.*}}__rust_alloc_zeroed(
+
+    // CHECK: ret void
+    vec![(0, 0, 'A'); n]
+}
+
+// CHECK-LABEL: @vec_option_bool
+#[no_mangle]
+pub fn vec_option_bool(n: usize) -> Vec<Option<bool>> {
+    // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+    // CHECK-NOT: call {{.*}}reserve
+    // CHECK-NOT: call {{.*}}__rust_alloc(
+
+    // CHECK: call {{.*}}__rust_alloc_zeroed(
+
+    // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+    // CHECK-NOT: call {{.*}}reserve
+    // CHECK-NOT: call {{.*}}__rust_alloc(
+
+    // CHECK: ret void
+    vec![Some(false); n]
+}
+
+// CHECK-LABEL: @vec_option_i32
+#[no_mangle]
+pub fn vec_option_i32(n: usize) -> Vec<Option<i32>> {
+    // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+    // CHECK-NOT: call {{.*}}reserve
+    // CHECK-NOT: call {{.*}}__rust_alloc(
+
+    // CHECK: call {{.*}}__rust_alloc_zeroed(
+
+    // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+    // CHECK-NOT: call {{.*}}reserve
+    // CHECK-NOT: call {{.*}}__rust_alloc(
+
+    // CHECK: ret void
+    vec![None; n]
+}
+
+// Ensure that __rust_alloc_zeroed gets the right attributes for LLVM to optimize it away.
+// CHECK: declare noalias noundef ptr @__rust_alloc_zeroed(i64 noundef, i64 allocalign noundef) unnamed_addr [[RUST_ALLOC_ZEROED_ATTRS:#[0-9]+]]
+
+// CHECK-DAG: attributes [[RUST_ALLOC_ZEROED_ATTRS]] = { {{.*}} allockind("alloc,zeroed,aligned") allocsize(0) uwtable "alloc-family"="__rust_alloc" {{.*}} }
diff --git a/tests/codegen/vec-in-place.rs b/tests/codegen/vec-in-place.rs
new file mode 100644
index 00000000000..d68067ceb19
--- /dev/null
+++ b/tests/codegen/vec-in-place.rs
@@ -0,0 +1,93 @@
+// ignore-debug: the debug assertions get in the way
+// compile-flags: -O -Z merge-functions=disabled
+// min-llvm-version: 16
+#![crate_type = "lib"]
+
+// Ensure that trivial casts of vec elements are O(1)
+
+pub struct Wrapper<T>(T);
+
+// previously repr(C) caused the optimization to fail
+#[repr(C)]
+pub struct Foo {
+    a: u64,
+    b: u64,
+    c: u64,
+    d: u64,
+}
+
+// implementing Copy exercises the TrustedRandomAccess specialization inside the in-place
+// specialization
+#[derive(Copy, Clone)]
+pub struct Bar {
+    a: u64,
+    b: u64,
+    c: u64,
+    d: u64,
+}
+
+// this exercises the try-fold codepath
+pub struct Baz {
+    a: u64,
+    b: u64,
+    c: u64,
+    d: u64,
+}
+
+// CHECK-LABEL: @vec_iterator_cast_primitive
+#[no_mangle]
+pub fn vec_iterator_cast_primitive(vec: Vec<i8>) -> Vec<u8> {
+    // CHECK-NOT: loop
+    // CHECK-NOT: call
+    vec.into_iter().map(|e| e as u8).collect()
+}
+
+// CHECK-LABEL: @vec_iterator_cast_wrapper
+#[no_mangle]
+pub fn vec_iterator_cast_wrapper(vec: Vec<u8>) -> Vec<Wrapper<u8>> {
+    // CHECK-NOT: loop
+    // CHECK-NOT: call
+    vec.into_iter().map(|e| Wrapper(e)).collect()
+}
+
+// CHECK-LABEL: @vec_iterator_cast_unwrap
+#[no_mangle]
+pub fn vec_iterator_cast_unwrap(vec: Vec<Wrapper<u8>>) -> Vec<u8> {
+    // CHECK-NOT: loop
+    // CHECK-NOT: call
+    vec.into_iter().map(|e| e.0).collect()
+}
+
+// CHECK-LABEL: @vec_iterator_cast_aggregate
+#[no_mangle]
+pub fn vec_iterator_cast_aggregate(vec: Vec<[u64; 4]>) -> Vec<Foo> {
+    // CHECK-NOT: loop
+    // CHECK-NOT: call
+    vec.into_iter().map(|e| unsafe { std::mem::transmute(e) }).collect()
+}
+
+// CHECK-LABEL: @vec_iterator_cast_deaggregate_tra
+#[no_mangle]
+pub fn vec_iterator_cast_deaggregate_tra(vec: Vec<Bar>) -> Vec<[u64; 4]> {
+    // CHECK-NOT: loop
+    // CHECK-NOT: call
+
+    // Safety: For the purpose of this test we assume that Bar layout matches [u64; 4].
+    // This currently is not guaranteed for repr(Rust) types, but it happens to work here and
+    // the UCG may add additional guarantees for homogenous types in the future that would make this
+    // correct.
+    vec.into_iter().map(|e| unsafe { std::mem::transmute(e) }).collect()
+}
+
+// CHECK-LABEL: @vec_iterator_cast_deaggregate_fold
+#[no_mangle]
+pub fn vec_iterator_cast_deaggregate_fold(vec: Vec<Baz>) -> Vec<[u64; 4]> {
+    // CHECK-NOT: loop
+    // CHECK-NOT: call
+
+    // Safety: For the purpose of this test we assume that Bar layout matches [u64; 4].
+    // This currently is not guaranteed for repr(Rust) types, but it happens to work here and
+    // the UCG may add additional guarantees for homogenous types in the future that would make this
+    // correct.
+    vec.into_iter().map(|e| unsafe { std::mem::transmute(e) }).collect()
+}
diff --git a/tests/codegen/vec-iter-collect-len.rs b/tests/codegen/vec-iter-collect-len.rs
new file mode 100644
index 00000000000..73348ddd063
--- /dev/null
+++ b/tests/codegen/vec-iter-collect-len.rs
@@ -0,0 +1,12 @@
+// ignore-debug: the debug assertions get in the way
+// no-system-llvm
+// compile-flags: -O
+#![crate_type="lib"]
+
+#[no_mangle]
+pub fn get_len() -> usize {
+    // CHECK-LABEL: @get_len
+    // CHECK-NOT: call
+    // CHECK-NOT: invoke
+    [1, 2, 3].iter().collect::<Vec<_>>().len()
+}
diff --git a/tests/codegen/vec-optimizes-away.rs b/tests/codegen/vec-optimizes-away.rs
new file mode 100644
index 00000000000..6f477a796b6
--- /dev/null
+++ b/tests/codegen/vec-optimizes-away.rs
@@ -0,0 +1,13 @@
+// ignore-debug: the debug assertions get in the way
+// no-system-llvm
+// compile-flags: -O
+#![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
new file mode 100644
index 00000000000..14fef4e2cd5
--- /dev/null
+++ b/tests/codegen/vec-shrink-panik.rs
@@ -0,0 +1,45 @@
+// revisions: old new
+// LLVM 17 realizes double panic is not possible and doesn't generate calls
+// to panic_cannot_unwind.
+// [old]ignore-llvm-version: 17 - 99
+// [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)]
+
+// Make sure that `Vec::shrink_to_fit` never emits panics via `RawVec::shrink_to_fit`,
+// "Tried to shrink to a larger capacity", because the length is *always* <= capacity.
+
+// CHECK-LABEL: @shrink_to_fit
+#[no_mangle]
+pub fn shrink_to_fit(vec: &mut Vec<u32>) {
+    // CHECK-NOT: panic
+    vec.shrink_to_fit();
+}
+
+// CHECK-LABEL: @issue71861
+#[no_mangle]
+pub fn issue71861(vec: Vec<u32>) -> Box<[u32]> {
+    // 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.
+    // old: filter
+    // old-NEXT: ; call core::panicking::panic_cannot_unwind
+    // old-NEXT: panic_cannot_unwind
+
+    // CHECK-NOT: panic
+    vec.into_boxed_slice()
+}
+
+// CHECK-LABEL: @issue75636
+#[no_mangle]
+pub fn issue75636<'a>(iter: &[&'a str]) -> Box<[&'a str]> {
+    // CHECK-NOT: panic
+    iter.iter().copied().collect()
+}
+
+// old: ; core::panicking::panic_cannot_unwind
+// old: declare void @{{.*}}panic_cannot_unwind
diff --git a/tests/codegen/vecdeque_no_panic.rs b/tests/codegen/vecdeque_no_panic.rs
new file mode 100644
index 00000000000..cbf420bada9
--- /dev/null
+++ b/tests/codegen/vecdeque_no_panic.rs
@@ -0,0 +1,19 @@
+// This test checks that `VecDeque::front[_mut]()` and `VecDeque::back[_mut]()` can't panic.
+
+// compile-flags: -O
+// ignore-debug: the debug assertions get in the way
+
+#![crate_type = "lib"]
+
+use std::collections::VecDeque;
+
+// CHECK-LABEL: @dont_panic
+#[no_mangle]
+pub fn dont_panic(v: &mut VecDeque<usize>) {
+    // CHECK-NOT: expect
+    // CHECK-NOT: panic
+    v.front();
+    v.front_mut();
+    v.back();
+    v.back_mut();
+}
diff --git a/tests/codegen/virtual-function-elimination-32bit.rs b/tests/codegen/virtual-function-elimination-32bit.rs
new file mode 100644
index 00000000000..6f963363a99
--- /dev/null
+++ b/tests/codegen/virtual-function-elimination-32bit.rs
@@ -0,0 +1,35 @@
+// compile-flags: -Zvirtual-function-elimination -Clto -O -Csymbol-mangling-version=v0
+// ignore-64bit
+
+// CHECK: @vtable.0 = {{.*}}, !type ![[TYPE0:[0-9]+]], !vcall_visibility ![[VCALL_VIS0:[0-9]+]]
+
+#![crate_type = "lib"]
+
+trait T {
+    // CHECK-LABEL: ; <virtual_function_elimination_32bit::S as virtual_function_elimination_32bit::T>::used
+    fn used(&self) -> i32 {
+        1
+    }
+    // CHECK-LABEL-NOT: {{.*}}::unused
+    fn unused(&self) -> i32 {
+        2
+    }
+}
+
+#[derive(Copy, Clone)]
+struct S;
+
+impl T for S {}
+
+fn taking_t(t: &dyn T) -> i32 {
+    // CHECK: @llvm.type.checked.load({{.*}}, i32 12, metadata !"[[MANGLED_TYPE0:[0-9a-zA-Z_]+]]")
+    t.used()
+}
+
+pub fn main() {
+    let s = S;
+    taking_t(&s);
+}
+
+// CHECK: ![[TYPE0]] = !{i32 0, !"[[MANGLED_TYPE0]]"}
+// CHECK: ![[VCALL_VIS0]] = !{i64 2}
diff --git a/tests/codegen/virtual-function-elimination.rs b/tests/codegen/virtual-function-elimination.rs
new file mode 100644
index 00000000000..f22176a024f
--- /dev/null
+++ b/tests/codegen/virtual-function-elimination.rs
@@ -0,0 +1,101 @@
+// compile-flags: -Zvirtual-function-elimination -Clto -O -Csymbol-mangling-version=v0
+// ignore-32bit
+// ignore-debug
+
+// CHECK: @vtable.0 = {{.*}}, !type ![[TYPE0:[0-9]+]], !vcall_visibility ![[VCALL_VIS0:[0-9]+]]
+// CHECK: @vtable.1 = {{.*}}, !type ![[TYPE1:[0-9]+]], !vcall_visibility ![[VCALL_VIS0:[0-9]+]]
+// CHECK: @vtable.2 = {{.*}}, !type ![[TYPE2:[0-9]+]], !vcall_visibility ![[VCALL_VIS2:[0-9]+]]
+
+#![crate_type = "lib"]
+#![allow(incomplete_features)]
+#![feature(unsized_locals)]
+
+use std::rc::Rc;
+
+trait T {
+    // CHECK-LABEL: ; <virtual_function_elimination::S as virtual_function_elimination::T>::used
+    fn used(&self) -> i32 {
+        1
+    }
+    // CHECK-LABEL: ; <virtual_function_elimination::S as virtual_function_elimination::T>::used_through_sub_trait
+    fn used_through_sub_trait(&self) -> i32 {
+        3
+    }
+    // CHECK-LABEL: ; <virtual_function_elimination::S as virtual_function_elimination::T>::by_rc
+    fn by_rc(self: Rc<Self>) -> i32 {
+        self.used() + self.used()
+    }
+    // CHECK-LABEL-NOT: {{.*}}::unused
+    fn unused(&self) -> i32 {
+        2
+    }
+    // CHECK-LABEL-NOT: {{.*}}::by_rc_unused
+    fn by_rc_unused(self: Rc<Self>) -> i32 {
+        self.by_rc()
+    }
+}
+
+trait U: T {
+    // CHECK-LABEL: ; <virtual_function_elimination::S as virtual_function_elimination::U>::subtrait_used
+    fn subtrait_used(&self) -> i32 {
+        4
+    }
+    // CHECK-LABEL-NOT: {{.*}}::subtrait_unused
+    fn subtrait_unused(&self) -> i32 {
+        5
+    }
+}
+
+pub trait V {
+    // CHECK-LABEL: ; <virtual_function_elimination::S as virtual_function_elimination::V>::public_function
+    fn public_function(&self) -> i32;
+}
+
+#[derive(Copy, Clone)]
+struct S;
+
+impl T for S {}
+
+impl U for S {}
+
+impl V for S {
+    fn public_function(&self) -> i32 {
+        6
+    }
+}
+
+fn taking_t(t: &dyn T) -> i32 {
+    // CHECK: @llvm.type.checked.load({{.*}}, i32 24, metadata !"[[MANGLED_TYPE0:[0-9a-zA-Z_]+]]")
+    t.used()
+}
+
+fn taking_rc_t(t: Rc<dyn T>) -> i32 {
+    // CHECK: @llvm.type.checked.load({{.*}}, i32 40, metadata !"[[MANGLED_TYPE0:[0-9a-zA-Z_]+]]")
+    t.by_rc()
+}
+
+fn taking_u(u: &dyn U) -> i32 {
+    // CHECK: @llvm.type.checked.load({{.*}}, i32 64, metadata !"[[MANGLED_TYPE1:[0-9a-zA-Z_]+]]")
+    // CHECK: @llvm.type.checked.load({{.*}}, i32 24, metadata !"[[MANGLED_TYPE1:[0-9a-zA-Z_]+]]")
+    // CHECK: @llvm.type.checked.load({{.*}}, i32 32, metadata !"[[MANGLED_TYPE1:[0-9a-zA-Z_]+]]")
+    u.subtrait_used() + u.used() + u.used_through_sub_trait()
+}
+
+pub fn taking_v(v: &dyn V) -> i32 {
+    // CHECK: @llvm.type.checked.load({{.*}}, i32 24, metadata !"NtCs64ITQYi9761_28virtual_function_elimination1V")
+    v.public_function()
+}
+
+pub fn main() {
+    let s = S;
+    taking_t(&s);
+    taking_rc_t(Rc::new(s));
+    taking_u(&s);
+    taking_v(&s);
+}
+
+// CHECK: ![[TYPE0]] = !{i64 0, !"[[MANGLED_TYPE0]]"}
+// CHECK: ![[VCALL_VIS0]] = !{i64 2}
+// CHECK: ![[TYPE1]] = !{i64 0, !"[[MANGLED_TYPE1]]"}
+// CHECK: ![[TYPE2]] = !{i64 0, !"NtCs64ITQYi9761_28virtual_function_elimination1V"}
+// CHECK: ![[VCALL_VIS2]] = !{i64 1}
diff --git a/tests/codegen/wasm_casts_trapping.rs b/tests/codegen/wasm_casts_trapping.rs
new file mode 100644
index 00000000000..eb06c4975bb
--- /dev/null
+++ b/tests/codegen/wasm_casts_trapping.rs
@@ -0,0 +1,157 @@
+// only-wasm32
+// compile-flags: -C target-feature=-nontrapping-fptoint
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @cast_f64_i64
+#[no_mangle]
+pub fn cast_f64_i64(a: f64) -> i64 {
+    // CHECK-NOT: fptosi double {{.*}} to i64
+    // CHECK-NOT: select i1 {{.*}}, i64 {{.*}}, i64 {{.*}}
+    // CHECK: {{.*}} call {{.*}} @llvm.fptosi.sat.i64.f64{{.*}}
+    a as _
+}
+
+// CHECK-LABEL: @cast_f64_i32
+#[no_mangle]
+pub fn cast_f64_i32(a: f64) -> i32 {
+    // CHECK-NOT: fptosi double {{.*}} to i32
+    // CHECK-NOT: select i1 {{.*}}, i32 {{.*}}, i32 {{.*}}
+    // CHECK: {{.*}} call {{.*}} @llvm.fptosi.sat.i32.f64{{.*}}
+    a as _
+}
+
+// CHECK-LABEL: @cast_f32_i64
+#[no_mangle]
+pub fn cast_f32_i64(a: f32) -> i64 {
+    // CHECK-NOT: fptosi float {{.*}} to i64
+    // CHECK-NOT: select i1 {{.*}}, i64 {{.*}}, i64 {{.*}}
+    // CHECK: {{.*}} call {{.*}} @llvm.fptosi.sat.i64.f32{{.*}}
+    a as _
+}
+
+// CHECK-LABEL: @cast_f32_i32
+#[no_mangle]
+pub fn cast_f32_i32(a: f32) -> i32 {
+    // CHECK-NOT: fptosi float {{.*}} to i32
+    // CHECK-NOT: select i1 {{.*}}, i32 {{.*}}, i32 {{.*}}
+    // CHECK: {{.*}} call {{.*}} @llvm.fptosi.sat.i32.f32{{.*}}
+    a as _
+}
+
+// CHECK-LABEL: @cast_f64_u64
+#[no_mangle]
+pub fn cast_f64_u64(a: f64) -> u64 {
+    // CHECK-NOT: fptoui double {{.*}} to i64
+    // CHECK-NOT: select i1 {{.*}}, i64 {{.*}}, i64 {{.*}}
+    // CHECK: {{.*}} call {{.*}} @llvm.fptoui.sat.i64.f64{{.*}}
+    a as _
+}
+
+// CHECK-LABEL: @cast_f64_u32
+#[no_mangle]
+pub fn cast_f64_u32(a: f64) -> u32 {
+    // CHECK-NOT: fptoui double {{.*}} to i32
+    // CHECK-NOT: select i1 {{.*}}, i32 {{.*}}, i32 {{.*}}
+    // CHECK: {{.*}} call {{.*}} @llvm.fptoui.sat.i32.f64{{.*}}
+    a as _
+}
+
+// CHECK-LABEL: @cast_f32_u64
+#[no_mangle]
+pub fn cast_f32_u64(a: f32) -> u64 {
+    // CHECK-NOT: fptoui float {{.*}} to i64
+    // CHECK-NOT: select i1 {{.*}}, i64 {{.*}}, i64 {{.*}}
+    // CHECK: {{.*}} call {{.*}} @llvm.fptoui.sat.i64.f32{{.*}}
+    a as _
+}
+
+// CHECK-LABEL: @cast_f32_u32
+#[no_mangle]
+pub fn cast_f32_u32(a: f32) -> u32 {
+    // CHECK-NOT: fptoui float {{.*}} to i32
+    // CHECK-NOT: select i1 {{.*}}, i32 {{.*}}, i32 {{.*}}
+    // CHECK: {{.*}} call {{.*}} @llvm.fptoui.sat.i32.f32{{.*}}
+    a as _
+}
+
+// CHECK-LABEL: @cast_f32_u8
+#[no_mangle]
+pub fn cast_f32_u8(a: f32) -> u8 {
+    // CHECK-NOT: fptoui float {{.*}} to i8
+    // CHECK-NOT: select i1 {{.*}}, i8 {{.*}}, i8 {{.*}}
+    // CHECK: {{.*}} call {{.*}} @llvm.fptoui.sat.i8.f32{{.*}}
+    a as _
+}
+
+// CHECK-LABEL: @cast_unchecked_f64_i64
+#[no_mangle]
+pub unsafe fn cast_unchecked_f64_i64(a: f64) -> i64 {
+    // CHECK: {{.*}} call {{.*}} @llvm.wasm.trunc.signed.{{.*}}
+    // CHECK-NEXT: ret i64 {{.*}}
+    a.to_int_unchecked()
+}
+
+// CHECK-LABEL: @cast_unchecked_f64_i32
+#[no_mangle]
+pub unsafe fn cast_unchecked_f64_i32(a: f64) -> i32 {
+    // CHECK: {{.*}} call {{.*}} @llvm.wasm.trunc.signed.{{.*}}
+    // CHECK-NEXT: ret i32 {{.*}}
+    a.to_int_unchecked()
+}
+
+// CHECK-LABEL: @cast_unchecked_f32_i64
+#[no_mangle]
+pub unsafe fn cast_unchecked_f32_i64(a: f32) -> i64 {
+    // CHECK: {{.*}} call {{.*}} @llvm.wasm.trunc.signed.{{.*}}
+    // CHECK-NEXT: ret i64 {{.*}}
+    a.to_int_unchecked()
+}
+
+// CHECK-LABEL: @cast_unchecked_f32_i32
+#[no_mangle]
+pub unsafe fn cast_unchecked_f32_i32(a: f32) -> i32 {
+    // CHECK: {{.*}} call {{.*}} @llvm.wasm.trunc.signed.{{.*}}
+    // CHECK-NEXT: ret i32 {{.*}}
+    a.to_int_unchecked()
+}
+
+// CHECK-LABEL: @cast_unchecked_f64_u64
+#[no_mangle]
+pub unsafe fn cast_unchecked_f64_u64(a: f64) -> u64 {
+    // CHECK: {{.*}} call {{.*}} @llvm.wasm.trunc.unsigned.{{.*}}
+    // CHECK-NEXT: ret i64 {{.*}}
+    a.to_int_unchecked()
+}
+
+// CHECK-LABEL: @cast_unchecked_f64_u32
+#[no_mangle]
+pub unsafe fn cast_unchecked_f64_u32(a: f64) -> u32 {
+    // CHECK: {{.*}} call {{.*}} @llvm.wasm.trunc.unsigned.{{.*}}
+    // CHECK-NEXT: ret i32 {{.*}}
+    a.to_int_unchecked()
+}
+
+// CHECK-LABEL: @cast_unchecked_f32_u64
+#[no_mangle]
+pub unsafe fn cast_unchecked_f32_u64(a: f32) -> u64 {
+    // CHECK: {{.*}} call {{.*}} @llvm.wasm.trunc.unsigned.{{.*}}
+    // CHECK-NEXT: ret i64 {{.*}}
+    a.to_int_unchecked()
+}
+
+// CHECK-LABEL: @cast_unchecked_f32_u32
+#[no_mangle]
+pub unsafe fn cast_unchecked_f32_u32(a: f32) -> u32 {
+    // CHECK: {{.*}} call {{.*}} @llvm.wasm.trunc.unsigned.{{.*}}
+    // CHECK-NEXT: ret i32 {{.*}}
+    a.to_int_unchecked()
+}
+
+// CHECK-LABEL: @cast_unchecked_f32_u8
+#[no_mangle]
+pub unsafe fn cast_unchecked_f32_u8(a: f32) -> u8 {
+    // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}}
+    // CHECK: fptoui float {{.*}} to i8
+    // CHECK-NEXT: ret i8 {{.*}}
+    a.to_int_unchecked()
+}
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
+}
diff --git a/tests/codegen/x86_64-macosx-deployment-target.rs b/tests/codegen/x86_64-macosx-deployment-target.rs
new file mode 100644
index 00000000000..8e673d11d98
--- /dev/null
+++ b/tests/codegen/x86_64-macosx-deployment-target.rs
@@ -0,0 +1,27 @@
+//
+// Checks that we correctly modify the target when MACOSX_DEPLOYMENT_TARGET is set.
+// See issue #60235.
+
+// compile-flags: -O --target=x86_64-apple-darwin --crate-type=rlib
+// needs-llvm-components: x86
+// rustc-env:MACOSX_DEPLOYMENT_TARGET=10.9
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang="sized"]
+trait Sized { }
+#[lang="freeze"]
+trait Freeze { }
+#[lang="copy"]
+trait Copy { }
+
+#[repr(C)]
+pub struct Bool {
+    b: bool,
+}
+
+// CHECK: target triple = "x86_64-apple-macosx10.9.0"
+#[no_mangle]
+pub extern "C" fn structbool() -> Bool {
+    Bool { b: true }
+}
diff --git a/tests/codegen/x86_64-no-macosx-deployment-target.rs b/tests/codegen/x86_64-no-macosx-deployment-target.rs
new file mode 100644
index 00000000000..25ae6924de0
--- /dev/null
+++ b/tests/codegen/x86_64-no-macosx-deployment-target.rs
@@ -0,0 +1,27 @@
+//
+// Checks that we leave the target alone when MACOSX_DEPLOYMENT_TARGET is unset.
+// See issue #60235.
+
+// compile-flags: -O --target=x86_64-apple-darwin --crate-type=rlib
+// needs-llvm-components: x86
+// unset-rustc-env:MACOSX_DEPLOYMENT_TARGET
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang="sized"]
+trait Sized { }
+#[lang="freeze"]
+trait Freeze { }
+#[lang="copy"]
+trait Copy { }
+
+#[repr(C)]
+pub struct Bool {
+    b: bool,
+}
+
+// CHECK: target triple = "x86_64-apple-macosx10.7.0"
+#[no_mangle]
+pub extern "C" fn structbool() -> Bool {
+    Bool { b: true }
+}
diff --git a/tests/codegen/zip.rs b/tests/codegen/zip.rs
new file mode 100644
index 00000000000..e55f4f1a2de
--- /dev/null
+++ b/tests/codegen/zip.rs
@@ -0,0 +1,21 @@
+// compile-flags: -C no-prepopulate-passes -O
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @zip_copy
+#[no_mangle]
+pub fn zip_copy(xs: &[u8], ys: &mut [u8]) {
+// CHECK: memcpy
+    for (x, y) in xs.iter().zip(ys) {
+        *y = *x;
+    }
+}
+
+// CHECK-LABEL: @zip_copy_mapped
+#[no_mangle]
+pub fn zip_copy_mapped(xs: &[u8], ys: &mut [u8]) {
+// CHECK: memcpy
+    for (x, y) in xs.iter().map(|&x| x).zip(ys) {
+        *y = x;
+    }
+}
diff --git a/tests/codegen/zst-offset.rs b/tests/codegen/zst-offset.rs
new file mode 100644
index 00000000000..cef4b9bdaaf
--- /dev/null
+++ b/tests/codegen/zst-offset.rs
@@ -0,0 +1,43 @@
+// compile-flags: -C no-prepopulate-passes -Copt-level=0
+
+#![crate_type = "lib"]
+#![feature(repr_simd)]
+
+// Hack to get the correct size for the length part in slices
+// CHECK: @helper([[USIZE:i[0-9]+]] %_1)
+#[no_mangle]
+pub fn helper(_: usize) {
+}
+
+// Check that we correctly generate a GEP for a ZST that is not included in Scalar layout
+// CHECK-LABEL: @scalar_layout
+#[no_mangle]
+pub fn scalar_layout(s: &(u64, ())) {
+// CHECK: getelementptr i8, {{.+}}, [[USIZE]] 8
+    let x = &s.1;
+    witness(&x); // keep variable in an alloca
+}
+
+// Check that we correctly generate a GEP for a ZST that is not included in ScalarPair layout
+// CHECK-LABEL: @scalarpair_layout
+#[no_mangle]
+pub fn scalarpair_layout(s: &(u64, u32, ())) {
+// CHECK: getelementptr i8, {{.+}}, [[USIZE]] 12
+    let x = &s.2;
+    witness(&x); // keep variable in an alloca
+}
+
+#[repr(simd)]
+pub struct U64x4(u64, u64, u64, u64);
+
+// Check that we correctly generate a GEP for a ZST that is not included in Vector layout
+// CHECK-LABEL: @vector_layout
+#[no_mangle]
+pub fn vector_layout(s: &(U64x4, ())) {
+// CHECK: getelementptr i8, {{.+}}, [[USIZE]] 32
+    let x = &s.1;
+    witness(&x); // keep variable in an alloca
+}
+
+#[inline(never)]
+fn witness(_: &impl Sized) {}