about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock4
-rw-r--r--bootstrap.example.toml8
-rw-r--r--compiler/rustc/Cargo.toml1
-rw-r--r--compiler/rustc_attr_parsing/messages.ftl8
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs69
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/crate_level.rs9
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/traits.rs8
-rw-r--r--compiler/rustc_attr_parsing/src/context.rs18
-rw-r--r--compiler/rustc_attr_parsing/src/session_diagnostics.rs28
-rw-r--r--compiler/rustc_borrowck/src/lib.rs3
-rw-r--r--compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs9
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs2
-rw-r--r--compiler/rustc_builtin_macros/Cargo.toml5
-rw-r--r--compiler/rustc_builtin_macros/src/autodiff.rs3
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs6
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/mod.rs9
-rw-r--r--compiler/rustc_codegen_llvm/Cargo.toml1
-rw-r--r--compiler/rustc_codegen_llvm/src/abi.rs11
-rw-r--r--compiler/rustc_codegen_llvm/src/back/lto.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs6
-rw-r--r--compiler/rustc_codegen_llvm/src/base.rs24
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs9
-rw-r--r--compiler/rustc_codegen_llvm/src/common.rs14
-rw-r--r--compiler/rustc_codegen_llvm/src/consts.rs226
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs110
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs101
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs27
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/mod.rs8
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs8
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs144
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/mod.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs57
-rw-r--r--compiler/rustc_codegen_ssa/src/codegen_attrs.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/rvalue.rs55
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/builder.rs41
-rw-r--r--compiler/rustc_const_eval/src/check_consts/check.rs3
-rw-r--r--compiler/rustc_const_eval/src/check_consts/qualifs.rs4
-rw-r--r--compiler/rustc_const_eval/src/check_consts/resolver.rs1
-rw-r--r--compiler/rustc_const_eval/src/interpret/memory.rs4
-rw-r--r--compiler/rustc_const_eval/src/interpret/step.rs8
-rw-r--r--compiler/rustc_data_structures/src/lib.rs1
-rw-r--r--compiler/rustc_data_structures/src/sorted_map.rs35
-rw-r--r--compiler/rustc_data_structures/src/sorted_map/tests.rs10
-rw-r--r--compiler/rustc_driver_impl/Cargo.toml1
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs8
-rw-r--r--compiler/rustc_hir/src/attrs/data_structures.rs12
-rw-r--r--compiler/rustc_hir/src/attrs/encode_cross_crate.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs44
-rw-r--r--compiler/rustc_hir_analysis/src/check/region.rs24
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs22
-rw-r--r--compiler/rustc_interface/Cargo.toml1
-rw-r--r--compiler/rustc_lint/src/unused.rs8
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp140
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp60
-rw-r--r--compiler/rustc_middle/src/hir/map.rs2
-rw-r--r--compiler/rustc_middle/src/middle/codegen_fn_attrs.rs6
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation.rs9
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs111
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs2
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs1
-rw-r--r--compiler/rustc_middle/src/mir/query.rs2
-rw-r--r--compiler/rustc_middle/src/mir/statement.rs2
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs10
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs25
-rw-r--r--compiler/rustc_middle/src/ty/util.rs9
-rw-r--r--compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs6
-rw-r--r--compiler/rustc_mir_build/src/builder/expr/as_place.rs2
-rw-r--r--compiler/rustc_mir_build/src/builder/matches/test.rs3
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs1
-rw-r--r--compiler/rustc_mir_dataflow/src/move_paths/builder.rs1
-rw-r--r--compiler/rustc_mir_transform/src/coroutine.rs47
-rw-r--r--compiler/rustc_mir_transform/src/dataflow_const_prop.rs38
-rw-r--r--compiler/rustc_mir_transform/src/dest_prop.rs28
-rw-r--r--compiler/rustc_mir_transform/src/gvn.rs77
-rw-r--r--compiler/rustc_mir_transform/src/known_panics_lint.rs15
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs4
-rw-r--r--compiler/rustc_mir_transform/src/lint.rs44
-rw-r--r--compiler/rustc_mir_transform/src/nrvo.rs234
-rw-r--r--compiler/rustc_mir_transform/src/promote_consts.rs4
-rw-r--r--compiler/rustc_mir_transform/src/validate.rs8
-rw-r--r--compiler/rustc_parse/messages.ftl4
-rw-r--r--compiler/rustc_parse/src/errors.rs12
-rw-r--r--compiler/rustc_parse/src/parser/pat.rs27
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs13
-rw-r--r--compiler/rustc_passes/src/check_attr.rs4
-rw-r--r--compiler/rustc_public/src/unstable/convert/stable/mir.rs1
-rw-r--r--compiler/rustc_span/src/symbol.rs3
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs13
-rw-r--r--library/alloc/src/boxed.rs2
-rw-r--r--library/alloc/src/collections/btree/map/entry.rs6
-rw-r--r--library/core/src/intrinsics/mir.rs11
-rw-r--r--library/core/src/iter/sources/repeat.rs7
-rw-r--r--library/core/src/lib.rs1
-rw-r--r--library/core/src/os/darwin/mod.rs19
-rw-r--r--library/core/src/os/darwin/objc.rs113
-rw-r--r--library/core/src/os/mod.rs24
-rw-r--r--library/coretests/tests/ascii.rs7
-rw-r--r--library/std/src/os/darwin/mod.rs2
-rw-r--r--library/std/src/os/darwin/objc.rs13
-rw-r--r--library/std/src/sys/args/zkvm.rs103
-rw-r--r--library/test/src/cli.rs4
-rw-r--r--src/bootstrap/bootstrap.py6
-rwxr-xr-xsrc/bootstrap/configure.py5
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs4
-rw-r--r--src/bootstrap/src/core/build_steps/llvm.rs4
-rw-r--r--src/bootstrap/src/core/builder/cargo.rs6
-rw-r--r--src/bootstrap/src/core/config/config.rs114
-rw-r--r--src/bootstrap/src/core/config/toml/rust.rs2
-rw-r--r--src/bootstrap/src/lib.rs6
-rw-r--r--src/bootstrap/src/utils/change_tracker.rs5
-rw-r--r--src/ci/docker/README.md8
-rw-r--r--src/ci/docker/host-aarch64/aarch64-gnu-llvm-20/Dockerfile (renamed from src/ci/docker/host-aarch64/aarch64-gnu-llvm-19/Dockerfile)8
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile66
-rw-r--r--src/ci/github-actions/jobs.yml35
-rw-r--r--src/doc/rustc-dev-guide/src/tests/intro.md4
-rw-r--r--src/doc/rustc/src/tests/index.md12
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs2
-rw-r--r--src/tools/compiletest/src/common.rs4
-rw-r--r--src/tools/compiletest/src/directives/needs.rs13
-rw-r--r--src/tools/tidy/Readme.md112
-rw-r--r--src/tools/tidy/src/pal.rs1
-rw-r--r--tests/assembly-llvm/riscv-soft-abi-with-float-features.rs10
-rw-r--r--tests/assembly-llvm/x86_64-bigint-helpers.rs1
-rw-r--r--tests/assembly-llvm/x86_64-cmp.rs73
-rw-r--r--tests/codegen-llvm/auxiliary/darwin_objc_aux.rs27
-rw-r--r--tests/codegen-llvm/comparison-operators-2-struct.rs1
-rw-r--r--tests/codegen-llvm/comparison-operators-2-tuple.rs1
-rw-r--r--tests/codegen-llvm/darwin-no-objc.rs52
-rw-r--r--tests/codegen-llvm/darwin-objc-abi-v1.rs100
-rw-r--r--tests/codegen-llvm/darwin-objc-abi-v2.rs185
-rw-r--r--tests/codegen-llvm/darwin-objc-cross-crate.rs58
-rw-r--r--tests/codegen-llvm/enum/enum-aggregate.rs1
-rw-r--r--tests/codegen-llvm/enum/enum-discriminant-eq.rs1
-rw-r--r--tests/codegen-llvm/integer-cmp.rs36
-rw-r--r--tests/codegen-llvm/intrinsics/three_way_compare.rs1
-rw-r--r--tests/codegen-llvm/issues/and-masked-comparison-131162.rs1
-rw-r--r--tests/codegen-llvm/issues/issue-101082.rs1
-rw-r--r--tests/codegen-llvm/issues/issue-129795.rs1
-rw-r--r--tests/codegen-llvm/issues/iter-max-no-unwrap-failed-129583.rs1
-rw-r--r--tests/codegen-llvm/issues/looping-over-ne-bytes-133528.rs1
-rw-r--r--tests/codegen-llvm/option-niche-eq.rs1
-rw-r--r--tests/codegen-llvm/slice-last-elements-optimization.rs1
-rw-r--r--tests/codegen-llvm/swap-small-types.rs1
-rw-r--r--tests/codegen-llvm/try_question_mark_nop.rs31
-rw-r--r--tests/codegen-llvm/union-aggregate.rs1
-rw-r--r--tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-abort.mir9
-rw-r--r--tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-unwind.mir9
-rw-r--r--tests/mir-opt/building/async_await.a-{closure#0}.coroutine_resume.0.mir10
-rw-r--r--tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir30
-rw-r--r--tests/mir-opt/building/coroutine.main-{closure#0}.StateTransform.after.mir207
-rw-r--r--tests/mir-opt/building/coroutine.main-{closure#1}.StateTransform.after.mir207
-rw-r--r--tests/mir-opt/building/coroutine.rs29
-rw-r--r--tests/mir-opt/building/custom/arrays.arrays.built.after.mir10
-rw-r--r--tests/mir-opt/building/custom/arrays.rs4
-rw-r--r--tests/mir-opt/building/match/array_len.const_array_len.built.after.panic-abort.mir155
-rw-r--r--tests/mir-opt/building/match/array_len.const_array_len.built.after.panic-unwind.mir155
-rw-r--r--tests/mir-opt/building/match/array_len.rs31
-rw-r--r--tests/mir-opt/building/match/array_len.slice_len.built.after.panic-abort.mir115
-rw-r--r--tests/mir-opt/building/match/array_len.slice_len.built.after.panic-unwind.mir115
-rw-r--r--tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-abort.mir7
-rw-r--r--tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-unwind.mir7
-rw-r--r--tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir16
-rw-r--r--tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-abort.diff77
-rw-r--r--tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-unwind.diff77
-rw-r--r--tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-abort.diff77
-rw-r--r--tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-unwind.diff77
-rw-r--r--tests/mir-opt/dataflow-const-prop/slice_len.rs34
-rw-r--r--tests/mir-opt/dest-prop/nrvo_borrowed.nrvo.DestinationPropagation.panic-abort.diff (renamed from tests/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.panic-abort.diff)31
-rw-r--r--tests/mir-opt/dest-prop/nrvo_borrowed.nrvo.DestinationPropagation.panic-unwind.diff (renamed from tests/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.panic-unwind.diff)31
-rw-r--r--tests/mir-opt/dest-prop/nrvo_borrowed.rs (renamed from tests/mir-opt/nrvo_simple.rs)4
-rw-r--r--tests/mir-opt/dest-prop/nrvo_miscompile_111005.rs (renamed from tests/mir-opt/nrvo_miscompile_111005.rs)7
-rw-r--r--tests/mir-opt/dest-prop/nrvo_miscompile_111005.wrong.DestinationPropagation.diff (renamed from tests/mir-opt/nrvo_miscompile_111005.wrong.RenameReturnPlace.diff)7
-rw-r--r--tests/mir-opt/gvn.array_len.GVN.panic-abort.diff6
-rw-r--r--tests/mir-opt/gvn.array_len.GVN.panic-unwind.diff6
-rw-r--r--tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff114
-rw-r--r--tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff122
-rw-r--r--tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-abort.diff71
-rw-r--r--tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-unwind.diff71
-rw-r--r--tests/mir-opt/instsimplify/combine_array_len.normN.InstSimplify-after-simplifycfg.panic-abort.diff71
-rw-r--r--tests/mir-opt/instsimplify/combine_array_len.normN.InstSimplify-after-simplifycfg.panic-unwind.diff71
-rw-r--r--tests/mir-opt/instsimplify/combine_array_len.rs25
-rw-r--r--tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff32
-rw-r--r--tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff32
-rw-r--r--tests/mir-opt/lower_array_len.array_len_raw.GVN.panic-abort.diff6
-rw-r--r--tests/mir-opt/lower_array_len.array_len_raw.GVN.panic-unwind.diff6
-rw-r--r--tests/mir-opt/lower_array_len.array_len_reborrow.GVN.panic-abort.diff6
-rw-r--r--tests/mir-opt/lower_array_len.array_len_reborrow.GVN.panic-unwind.diff6
-rw-r--r--tests/mir-opt/pre-codegen/checked_ops.rs3
-rw-r--r--tests/mir-opt/pre-codegen/checked_ops.saturating_sub_at_home.PreCodegen.after.panic-abort.mir6
-rw-r--r--tests/mir-opt/pre-codegen/checked_ops.saturating_sub_at_home.PreCodegen.after.panic-unwind.mir6
-rw-r--r--tests/mir-opt/pre-codegen/derived_ord.demo_le.PreCodegen.after.mir35
-rw-r--r--tests/mir-opt/pre-codegen/derived_ord.rs5
-rw-r--r--tests/mir-opt/pre-codegen/derived_ord.{impl#0}-partial_cmp.PreCodegen.after.mir32
-rw-r--r--tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir68
-rw-r--r--tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir68
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir240
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir70
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir182
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir182
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir54
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir54
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir72
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir72
-rw-r--r--tests/mir-opt/pre-codegen/tuple_ord.demo_ge_partial.PreCodegen.after.mir18
-rw-r--r--tests/mir-opt/pre-codegen/tuple_ord.demo_le_total.PreCodegen.after.mir18
-rw-r--r--tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff85
-rw-r--r--tests/run-make/musl-default-linking/rmake.rs10
-rw-r--r--tests/ui/README.md6
-rw-r--r--tests/ui/abi/sparcv8plus-llvm19.rs42
-rw-r--r--tests/ui/abi/sparcv8plus-llvm19.sparc.stderr8
-rw-r--r--tests/ui/abi/sparcv8plus-llvm19.sparc_cpu_v9.stderr8
-rw-r--r--tests/ui/abi/sparcv8plus-llvm19.sparc_cpu_v9_feature_v8plus.stderr8
-rw-r--r--tests/ui/abi/sparcv8plus-llvm19.sparc_feature_v8plus.stderr8
-rw-r--r--tests/ui/abi/sparcv8plus-llvm19.sparcv8plus.stderr8
-rw-r--r--tests/ui/abi/sparcv8plus.rs1
-rw-r--r--tests/ui/abi/sparcv8plus.sparc.stderr2
-rw-r--r--tests/ui/abi/sparcv8plus.sparc_cpu_v9.stderr2
-rw-r--r--tests/ui/abi/sparcv8plus.sparc_cpu_v9_feature_v8plus.stderr2
-rw-r--r--tests/ui/abi/sparcv8plus.sparc_feature_v8plus.stderr2
-rw-r--r--tests/ui/abi/sparcv8plus.sparcv8plus.stderr2
-rw-r--r--tests/ui/asm/loongarch/bad-reg.loongarch32_ilp32d.stderr12
-rw-r--r--tests/ui/asm/loongarch/bad-reg.loongarch32_ilp32s.stderr20
-rw-r--r--tests/ui/asm/loongarch/bad-reg.loongarch64_lp64d.stderr12
-rw-r--r--tests/ui/asm/loongarch/bad-reg.loongarch64_lp64s.stderr20
-rw-r--r--tests/ui/asm/loongarch/bad-reg.rs1
-rw-r--r--tests/ui/associated-types/associated-types-for-unimpl-trait.fixed2
-rw-r--r--tests/ui/borrowck/format-args-temporary-scopes.e2024.stderr27
-rw-r--r--tests/ui/borrowck/format-args-temporary-scopes.rs21
-rw-r--r--tests/ui/c-variadic/no-closure.rs11
-rw-r--r--tests/ui/c-variadic/no-closure.stderr27
-rw-r--r--tests/ui/coercion/coerce-block-tail.stderr7
-rw-r--r--tests/ui/coercion/coerce-box-new-to-unboxed.rs4
-rw-r--r--tests/ui/coercion/coerce-box-new-to-unboxed.stderr19
-rw-r--r--tests/ui/darwin-objc/darwin-objc-bad-arg.rs36
-rw-r--r--tests/ui/darwin-objc/darwin-objc-bad-arg.stderr50
-rw-r--r--tests/ui/darwin-objc/darwin-objc-bad-const.rs17
-rw-r--r--tests/ui/darwin-objc/darwin-objc-bad-const.stderr19
-rw-r--r--tests/ui/darwin-objc/darwin-objc-bad-ref.rs31
-rw-r--r--tests/ui/darwin-objc/darwin-objc-bad-ref.stderr39
-rw-r--r--tests/ui/darwin-objc/darwin-objc-class-selector.rs31
-rw-r--r--tests/ui/darwin-objc/darwin-objc-class.rs39
-rw-r--r--tests/ui/darwin-objc/darwin-objc-selector.rs36
-rw-r--r--tests/ui/drop/super-let-tail-expr-drop-order.rs192
-rw-r--r--tests/ui/issues/issue-18088.rs8
-rw-r--r--tests/ui/issues/issue-21950.rs12
-rw-r--r--tests/ui/issues/issue-2284.rs13
-rw-r--r--tests/ui/lifetimes/issue-105507.fixed2
-rw-r--r--tests/ui/lint/unused_parens_follow_ident.fixed17
-rw-r--r--tests/ui/lint/unused_parens_follow_ident.rs17
-rw-r--r--tests/ui/lint/unused_parens_follow_ident.stderr31
-rw-r--r--tests/ui/mir/lint/assignment-overlap.rs2
-rw-r--r--tests/ui/parser/expr-as-stmt.fixed4
-rw-r--r--tests/ui/rustc_public-ir-print/async-closure.rs2
-rw-r--r--tests/ui/rustc_public-ir-print/async-closure.stdout44
-rw-r--r--tests/ui/suggestions/apitit-unimplemented-method.rs5
-rw-r--r--tests/ui/suggestions/apitit-unimplemented-method.stderr10
-rw-r--r--tests/ui/suggestions/auxiliary/dep.rs14
-rw-r--r--tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.fixed2
-rw-r--r--tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed2
-rw-r--r--tests/ui/suggestions/trait-impl-bound-suggestions.fixed4
-rw-r--r--tests/ui/traits/associated_type_bound/assoc-type-via-another-trait-issue-19479.rs (renamed from tests/ui/issues/issue-19479.rs)6
-rw-r--r--tests/ui/traits/cast-as-dyn-trait-wo-assoc-type-issue-21950.rs19
-rw-r--r--tests/ui/traits/cast-as-dyn-trait-wo-assoc-type-issue-21950.stderr (renamed from tests/ui/issues/issue-21950.stderr)2
-rw-r--r--tests/ui/traits/core-marker-name-shadowing-issue-2284.rs21
-rw-r--r--tests/ui/traits/inheritance/supertrait-operator-issue-18088.rs13
-rw-r--r--tests/ui/type-inference/has_sigdrop.rs18
267 files changed, 5426 insertions, 2595 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 4677d34d2a6..d39cfefea0c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4817,9 +4817,9 @@ dependencies = [
 
 [[package]]
 name = "rustfix"
-version = "0.8.1"
+version = "0.8.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81864b097046da5df3758fdc6e4822bbb70afa06317e8ca45ea1b51cb8c5e5a4"
+checksum = "82fa69b198d894d84e23afde8e9ab2af4400b2cba20d6bf2b428a8b01c222c5a"
 dependencies = [
  "serde",
  "serde_json",
diff --git a/bootstrap.example.toml b/bootstrap.example.toml
index eac93957797..51529751dd5 100644
--- a/bootstrap.example.toml
+++ b/bootstrap.example.toml
@@ -859,6 +859,14 @@
 # Trigger a `DebugBreak` after an internal compiler error during bootstrap on Windows
 #rust.break-on-ice = true
 
+# Set the number of threads for the compiler frontend used during compilation of Rust code (passed to `-Zthreads`).
+# The valid options are:
+# 0 - Set the number of threads according to the detected number of threads of the host system
+# 1 - Use a single thread for compilation of Rust code (the default)
+# N - Number of threads used for compilation of Rust code
+#
+#rust.parallel-frontend-threads = 1
+
 # =============================================================================
 # Distribution options
 #
diff --git a/compiler/rustc/Cargo.toml b/compiler/rustc/Cargo.toml
index e3214d1ab9c..9ef8fa75062 100644
--- a/compiler/rustc/Cargo.toml
+++ b/compiler/rustc/Cargo.toml
@@ -30,6 +30,7 @@ features = ['unprefixed_malloc_on_supported_platforms']
 check_only = ['rustc_driver_impl/check_only']
 jemalloc = ['dep:tikv-jemalloc-sys']
 llvm = ['rustc_driver_impl/llvm']
+llvm_enzyme = ['rustc_driver_impl/llvm_enzyme']
 max_level_info = ['rustc_driver_impl/max_level_info']
 rustc_randomized_layouts = ['rustc_driver_impl/rustc_randomized_layouts']
 # tidy-alphabetical-end
diff --git a/compiler/rustc_attr_parsing/messages.ftl b/compiler/rustc_attr_parsing/messages.ftl
index 839a5d23c3b..81ec17077c1 100644
--- a/compiler/rustc_attr_parsing/messages.ftl
+++ b/compiler/rustc_attr_parsing/messages.ftl
@@ -122,6 +122,14 @@ attr_parsing_null_on_export = `export_name` may not contain null characters
 
 attr_parsing_null_on_link_section = `link_section` may not contain null characters
 
+attr_parsing_null_on_objc_class = `objc::class!` may not contain null characters
+
+attr_parsing_null_on_objc_selector = `objc::selector!` may not contain null characters
+
+attr_parsing_objc_class_expected_string_literal = `objc::class!` expected a string literal
+
+attr_parsing_objc_selector_expected_string_literal = `objc::selector!` expected a string literal
+
 attr_parsing_repr_ident =
     meta item in `repr` must be an identifier
 
diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
index d5d51f2e79a..262b8213977 100644
--- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
@@ -2,7 +2,10 @@ use rustc_hir::attrs::{CoverageAttrKind, OptimizeAttr, SanitizerSet, UsedBy};
 use rustc_session::parse::feature_err;
 
 use super::prelude::*;
-use crate::session_diagnostics::{NakedFunctionIncompatibleAttribute, NullOnExport};
+use crate::session_diagnostics::{
+    NakedFunctionIncompatibleAttribute, NullOnExport, NullOnObjcClass, NullOnObjcSelector,
+    ObjcClassExpectedStringLiteral, ObjcSelectorExpectedStringLiteral,
+};
 
 pub(crate) struct OptimizeParser;
 
@@ -150,6 +153,70 @@ impl<S: Stage> SingleAttributeParser<S> for ExportNameParser {
     }
 }
 
+pub(crate) struct ObjcClassParser;
+
+impl<S: Stage> SingleAttributeParser<S> for ObjcClassParser {
+    const PATH: &[rustc_span::Symbol] = &[sym::rustc_objc_class];
+    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
+    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const ALLOWED_TARGETS: AllowedTargets =
+        AllowedTargets::AllowList(&[Allow(Target::ForeignStatic)]);
+    const TEMPLATE: AttributeTemplate = template!(NameValueStr: "ClassName");
+
+    fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
+        let Some(nv) = args.name_value() else {
+            cx.expected_name_value(cx.attr_span, None);
+            return None;
+        };
+        let Some(classname) = nv.value_as_str() else {
+            // `#[rustc_objc_class = ...]` is expected to be used as an implementatioin detail
+            // inside a standard library macro, but `cx.expected_string_literal` exposes too much.
+            // Use a custom error message instead.
+            cx.emit_err(ObjcClassExpectedStringLiteral { span: nv.value_span });
+            return None;
+        };
+        if classname.as_str().contains('\0') {
+            // `#[rustc_objc_class = ...]` will be converted to a null-terminated string,
+            // so it may not contain any null characters.
+            cx.emit_err(NullOnObjcClass { span: nv.value_span });
+            return None;
+        }
+        Some(AttributeKind::ObjcClass { classname, span: cx.attr_span })
+    }
+}
+
+pub(crate) struct ObjcSelectorParser;
+
+impl<S: Stage> SingleAttributeParser<S> for ObjcSelectorParser {
+    const PATH: &[rustc_span::Symbol] = &[sym::rustc_objc_selector];
+    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
+    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const ALLOWED_TARGETS: AllowedTargets =
+        AllowedTargets::AllowList(&[Allow(Target::ForeignStatic)]);
+    const TEMPLATE: AttributeTemplate = template!(NameValueStr: "methodName");
+
+    fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
+        let Some(nv) = args.name_value() else {
+            cx.expected_name_value(cx.attr_span, None);
+            return None;
+        };
+        let Some(methname) = nv.value_as_str() else {
+            // `#[rustc_objc_selector = ...]` is expected to be used as an implementatioin detail
+            // inside a standard library macro, but `cx.expected_string_literal` exposes too much.
+            // Use a custom error message instead.
+            cx.emit_err(ObjcSelectorExpectedStringLiteral { span: nv.value_span });
+            return None;
+        };
+        if methname.as_str().contains('\0') {
+            // `#[rustc_objc_selector = ...]` will be converted to a null-terminated string,
+            // so it may not contain any null characters.
+            cx.emit_err(NullOnObjcSelector { span: nv.value_span });
+            return None;
+        }
+        Some(AttributeKind::ObjcSelector { methname, span: cx.attr_span })
+    }
+}
+
 #[derive(Default)]
 pub(crate) struct NakedParser {
     span: Option<Span>,
diff --git a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs
index 4611de44459..0a340cd5e93 100644
--- a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs
@@ -174,3 +174,12 @@ impl<S: Stage> NoArgsAttributeParser<S> for NoStdParser {
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
     const CREATE: fn(Span) -> AttributeKind = AttributeKind::NoStd;
 }
+
+pub(crate) struct RustcCoherenceIsCoreParser;
+
+impl<S: Stage> NoArgsAttributeParser<S> for RustcCoherenceIsCoreParser {
+    const PATH: &[Symbol] = &[sym::rustc_coherence_is_core];
+    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
+    const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcCoherenceIsCore;
+}
diff --git a/compiler/rustc_attr_parsing/src/attributes/traits.rs b/compiler/rustc_attr_parsing/src/attributes/traits.rs
index c756bce96e2..ced3bcad229 100644
--- a/compiler/rustc_attr_parsing/src/attributes/traits.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/traits.rs
@@ -149,14 +149,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for AllowIncoherentImplParser {
     const CREATE: fn(Span) -> AttributeKind = AttributeKind::AllowIncoherentImpl;
 }
 
-pub(crate) struct CoherenceIsCoreParser;
-impl<S: Stage> NoArgsAttributeParser<S> for CoherenceIsCoreParser {
-    const PATH: &[Symbol] = &[sym::rustc_coherence_is_core];
-    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
-    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
-    const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::CoherenceIsCore;
-}
-
 pub(crate) struct FundamentalParser;
 impl<S: Stage> NoArgsAttributeParser<S> for FundamentalParser {
     const PATH: &[Symbol] = &[sym::fundamental];
diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs
index d7998048be5..ee5b7322b02 100644
--- a/compiler/rustc_attr_parsing/src/context.rs
+++ b/compiler/rustc_attr_parsing/src/context.rs
@@ -20,13 +20,13 @@ use crate::attributes::allow_unstable::{
 use crate::attributes::body::CoroutineParser;
 use crate::attributes::codegen_attrs::{
     ColdParser, CoverageParser, ExportNameParser, ForceTargetFeatureParser, NakedParser,
-    NoMangleParser, OptimizeParser, SanitizeParser, TargetFeatureParser, TrackCallerParser,
-    UsedParser,
+    NoMangleParser, ObjcClassParser, ObjcSelectorParser, OptimizeParser, SanitizeParser,
+    TargetFeatureParser, TrackCallerParser, UsedParser,
 };
 use crate::attributes::confusables::ConfusablesParser;
 use crate::attributes::crate_level::{
     CrateNameParser, MoveSizeLimitParser, NoCoreParser, NoStdParser, PatternComplexityLimitParser,
-    RecursionLimitParser, TypeLengthLimitParser,
+    RecursionLimitParser, RustcCoherenceIsCoreParser, TypeLengthLimitParser,
 };
 use crate::attributes::deprecation::DeprecationParser;
 use crate::attributes::dummy::DummyParser;
@@ -61,10 +61,10 @@ use crate::attributes::stability::{
 };
 use crate::attributes::test_attrs::{IgnoreParser, ShouldPanicParser};
 use crate::attributes::traits::{
-    AllowIncoherentImplParser, CoherenceIsCoreParser, CoinductiveParser, ConstTraitParser,
-    DenyExplicitImplParser, DoNotImplementViaObjectParser, FundamentalParser, MarkerParser,
-    ParenSugarParser, PointeeParser, SkipDuringMethodDispatchParser, SpecializationTraitParser,
-    TypeConstParser, UnsafeSpecializationMarkerParser,
+    AllowIncoherentImplParser, CoinductiveParser, ConstTraitParser, DenyExplicitImplParser,
+    DoNotImplementViaObjectParser, FundamentalParser, MarkerParser, ParenSugarParser,
+    PointeeParser, SkipDuringMethodDispatchParser, SpecializationTraitParser, TypeConstParser,
+    UnsafeSpecializationMarkerParser,
 };
 use crate::attributes::transparency::TransparencyParser;
 use crate::attributes::{AttributeParser as _, Combine, Single, WithoutArgs};
@@ -185,6 +185,8 @@ attribute_parsers!(
         Single<LinkageParser>,
         Single<MoveSizeLimitParser>,
         Single<MustUseParser>,
+        Single<ObjcClassParser>,
+        Single<ObjcSelectorParser>,
         Single<OptimizeParser>,
         Single<PathAttributeParser>,
         Single<PatternComplexityLimitParser>,
@@ -204,7 +206,6 @@ attribute_parsers!(
         Single<WithoutArgs<AllowInternalUnsafeParser>>,
         Single<WithoutArgs<AsPtrParser>>,
         Single<WithoutArgs<AutomaticallyDerivedParser>>,
-        Single<WithoutArgs<CoherenceIsCoreParser>>,
         Single<WithoutArgs<CoinductiveParser>>,
         Single<WithoutArgs<ColdParser>>,
         Single<WithoutArgs<ConstContinueParser>>,
@@ -232,6 +233,7 @@ attribute_parsers!(
         Single<WithoutArgs<ProcMacroAttributeParser>>,
         Single<WithoutArgs<ProcMacroParser>>,
         Single<WithoutArgs<PubTransparentParser>>,
+        Single<WithoutArgs<RustcCoherenceIsCoreParser>>,
         Single<WithoutArgs<SpecializationTraitParser>>,
         Single<WithoutArgs<StdInternalSymbolParser>>,
         Single<WithoutArgs<TrackCallerParser>>,
diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs
index 32ea9005a97..2c2b14c8a68 100644
--- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs
+++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs
@@ -460,6 +460,34 @@ pub(crate) struct NullOnLinkSection {
 }
 
 #[derive(Diagnostic)]
+#[diag(attr_parsing_null_on_objc_class)]
+pub(crate) struct NullOnObjcClass {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(attr_parsing_null_on_objc_selector)]
+pub(crate) struct NullOnObjcSelector {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(attr_parsing_objc_class_expected_string_literal)]
+pub(crate) struct ObjcClassExpectedStringLiteral {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(attr_parsing_objc_selector_expected_string_literal)]
+pub(crate) struct ObjcSelectorExpectedStringLiteral {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
 #[diag(attr_parsing_stability_outside_std, code = E0734)]
 pub(crate) struct StabilityOutsideStd {
     #[primary_span]
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 5d2dda8b0e7..f196bd04d0e 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -1557,9 +1557,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
                 );
             }
 
-            &(Rvalue::Len(place) | Rvalue::Discriminant(place)) => {
+            &Rvalue::Discriminant(place) => {
                 let af = match *rvalue {
-                    Rvalue::Len(..) => Some(ArtificialField::ArrayLength),
                     Rvalue::Discriminant(..) => None,
                     _ => unreachable!(),
                 };
diff --git a/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs b/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs
index 99dd0b2dd46..c2ad6fcb4b7 100644
--- a/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs
+++ b/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs
@@ -306,16 +306,11 @@ impl<'a, 'tcx> LoanInvalidationsGenerator<'a, 'tcx> {
                 self.consume_operand(location, op);
             }
 
-            &(Rvalue::Len(place) | Rvalue::Discriminant(place)) => {
-                let af = match rvalue {
-                    Rvalue::Len(..) => Some(ArtificialField::ArrayLength),
-                    Rvalue::Discriminant(..) => None,
-                    _ => unreachable!(),
-                };
+            &Rvalue::Discriminant(place) => {
                 self.access_place(
                     location,
                     place,
-                    (Shallow(af), Read(ReadKind::Copy)),
+                    (Shallow(None), Read(ReadKind::Copy)),
                     LocalMutationIsAllowed::No,
                 );
             }
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 8c5447fe1e9..dcedf0b1532 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -1631,7 +1631,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
             | Rvalue::BinaryOp(..)
             | Rvalue::RawPtr(..)
             | Rvalue::ThreadLocalRef(..)
-            | Rvalue::Len(..)
             | Rvalue::Discriminant(..)
             | Rvalue::NullaryOp(NullOp::OffsetOf(..), _) => {}
         }
@@ -2201,7 +2200,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             | Rvalue::Repeat(..)
             | Rvalue::Ref(..)
             | Rvalue::RawPtr(..)
-            | Rvalue::Len(..)
             | Rvalue::Cast(..)
             | Rvalue::ShallowInitBox(..)
             | Rvalue::BinaryOp(..)
diff --git a/compiler/rustc_builtin_macros/Cargo.toml b/compiler/rustc_builtin_macros/Cargo.toml
index e56b9e641a1..ce9a3ce3f24 100644
--- a/compiler/rustc_builtin_macros/Cargo.toml
+++ b/compiler/rustc_builtin_macros/Cargo.toml
@@ -33,3 +33,8 @@ smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
 thin-vec = "0.2.12"
 tracing = "0.1"
 # tidy-alphabetical-end
+
+[features]
+# tidy-alphabetical-start
+llvm_enzyme = []
+# tidy-alphabetical-end
diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs
index 48d0795af5e..f4a923797e2 100644
--- a/compiler/rustc_builtin_macros/src/autodiff.rs
+++ b/compiler/rustc_builtin_macros/src/autodiff.rs
@@ -209,7 +209,8 @@ mod llvm_enzyme {
         mut item: Annotatable,
         mode: DiffMode,
     ) -> Vec<Annotatable> {
-        if cfg!(not(llvm_enzyme)) {
+        // FIXME(bjorn3) maybe have the backend directly tell if autodiff is supported?
+        if cfg!(not(feature = "llvm_enzyme")) {
             ecx.sess.dcx().emit_err(errors::AutoDiffSupportNotBuild { span: meta_item.span });
             return vec![item];
         }
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index 3a28dd7e73c..41e11e1de61 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -834,12 +834,6 @@ fn codegen_stmt<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, cur_block: Block, stmt:
                         fx.bcx.ins().nop();
                     }
                 }
-                Rvalue::Len(place) => {
-                    let place = codegen_place(fx, place);
-                    let usize_layout = fx.layout_of(fx.tcx.types.usize);
-                    let len = codegen_array_len(fx, place);
-                    lval.write_cvalue(fx, CValue::by_val(len, usize_layout));
-                }
                 Rvalue::ShallowInitBox(ref operand, content_ty) => {
                     let content_ty = fx.monomorphize(content_ty);
                     let box_layout = fx.layout_of(Ty::new_box(fx.tcx, content_ty));
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
index eb0a5336a1f..84fa56cf903 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
@@ -730,7 +730,7 @@ impl<'gcc, 'tcx> ArgAbiExt<'gcc, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
         if self.is_sized_indirect() {
             OperandValue::Ref(PlaceValue::new_sized(val, self.layout.align.abi)).store(bx, dst)
         } else if self.is_unsized_indirect() {
-            bug!("unsized `ArgAbi` must be handled through `store_fn_arg`");
+            bug!("unsized `ArgAbi` cannot be stored");
         } else if let PassMode::Cast { ref cast, .. } = self.mode {
             // FIXME(eddyb): Figure out when the simpler Store is safe, clang
             // uses it for i16 -> {i8, i8}, but not for i24 -> {i8, i8, i8}.
@@ -797,12 +797,7 @@ impl<'gcc, 'tcx> ArgAbiExt<'gcc, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
                 OperandValue::Pair(next(), next()).store(bx, dst);
             }
             PassMode::Indirect { meta_attrs: Some(_), .. } => {
-                let place_val = PlaceValue {
-                    llval: next(),
-                    llextra: Some(next()),
-                    align: self.layout.align.abi,
-                };
-                OperandValue::Ref(place_val).store(bx, dst);
+                bug!("unsized `ArgAbi` cannot be stored");
             }
             PassMode::Direct(_)
             | PassMode::Indirect { meta_attrs: None, .. }
diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml
index 2d11628250c..67bd1e59bb0 100644
--- a/compiler/rustc_codegen_llvm/Cargo.toml
+++ b/compiler/rustc_codegen_llvm/Cargo.toml
@@ -46,5 +46,6 @@ tracing = "0.1"
 [features]
 # tidy-alphabetical-start
 check_only = ["rustc_llvm/check_only"]
+llvm_enzyme = []
 # tidy-alphabetical-end
 
diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs
index ac7583f5666..11be7041167 100644
--- a/compiler/rustc_codegen_llvm/src/abi.rs
+++ b/compiler/rustc_codegen_llvm/src/abi.rs
@@ -215,9 +215,9 @@ impl<'ll, 'tcx> ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
                 let align = attrs.pointee_align.unwrap_or(self.layout.align.abi);
                 OperandValue::Ref(PlaceValue::new_sized(val, align)).store(bx, dst);
             }
-            // Unsized indirect qrguments
+            // Unsized indirect arguments cannot be stored
             PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => {
-                bug!("unsized `ArgAbi` must be handled through `store_fn_arg`");
+                bug!("unsized `ArgAbi` cannot be stored");
             }
             PassMode::Cast { cast, pad_i32: _ } => {
                 // The ABI mandates that the value is passed as a different struct representation.
@@ -272,12 +272,7 @@ impl<'ll, 'tcx> ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
                 OperandValue::Pair(next(), next()).store(bx, dst);
             }
             PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => {
-                let place_val = PlaceValue {
-                    llval: next(),
-                    llextra: Some(next()),
-                    align: self.layout.align.abi,
-                };
-                OperandValue::Ref(place_val).store(bx, dst);
+                bug!("unsized `ArgAbi` cannot be stored");
             }
             PassMode::Direct(_)
             | PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ }
diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs
index f571716d9dd..78107d95e5a 100644
--- a/compiler/rustc_codegen_llvm/src/back/lto.rs
+++ b/compiler/rustc_codegen_llvm/src/back/lto.rs
@@ -617,7 +617,7 @@ pub(crate) fn run_pass_manager(
         crate::builder::gpu_offload::handle_gpu_code(cgcx, &cx);
     }
 
-    if cfg!(llvm_enzyme) && enable_ad && !thin {
+    if cfg!(feature = "llvm_enzyme") && enable_ad && !thin {
         let opt_stage = llvm::OptStage::FatLTO;
         let stage = write::AutodiffStage::PostAD;
         if !config.autodiff.contains(&config::AutoDiff::NoPostopt) {
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index 423f0da4878..bda81fbd19e 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -574,7 +574,8 @@ pub(crate) unsafe fn llvm_optimize(
     // FIXME(ZuseZ4): In a future update we could figure out how to only optimize individual functions getting
     // differentiated.
 
-    let consider_ad = cfg!(llvm_enzyme) && config.autodiff.contains(&config::AutoDiff::Enable);
+    let consider_ad =
+        cfg!(feature = "llvm_enzyme") && config.autodiff.contains(&config::AutoDiff::Enable);
     let run_enzyme = autodiff_stage == AutodiffStage::DuringAD;
     let print_before_enzyme = config.autodiff.contains(&config::AutoDiff::PrintModBefore);
     let print_after_enzyme = config.autodiff.contains(&config::AutoDiff::PrintModAfter);
@@ -740,7 +741,8 @@ pub(crate) fn optimize(
 
         // If we know that we will later run AD, then we disable vectorization and loop unrolling.
         // Otherwise we pretend AD is already done and run the normal opt pipeline (=PostAD).
-        let consider_ad = cfg!(llvm_enzyme) && config.autodiff.contains(&config::AutoDiff::Enable);
+        let consider_ad =
+            cfg!(feature = "llvm_enzyme") && config.autodiff.contains(&config::AutoDiff::Enable);
         let autodiff_stage = if consider_ad { AutodiffStage::PreAD } else { AutodiffStage::PostAD };
         // The embedded bitcode is used to run LTO/ThinLTO.
         // The bitcode obtained during the `codegen` phase is no longer suitable for performing LTO.
diff --git a/compiler/rustc_codegen_llvm/src/base.rs b/compiler/rustc_codegen_llvm/src/base.rs
index 9cc5d8dbc21..978134cc32b 100644
--- a/compiler/rustc_codegen_llvm/src/base.rs
+++ b/compiler/rustc_codegen_llvm/src/base.rs
@@ -109,18 +109,36 @@ pub(crate) fn compile_codegen_unit(
                 attributes::apply_to_llfn(entry, llvm::AttributePlace::Function, &attrs);
             }
 
+            // Define Objective-C module info and module flags. Note, the module info will
+            // also be added to the `llvm.compiler.used` variable, created later.
+            //
+            // These are only necessary when we need the linker to do its Objective-C-specific
+            // magic. We could theoretically do it unconditionally, but at a slight cost to linker
+            // performance in the common case where it's unnecessary.
+            if !cx.objc_classrefs.borrow().is_empty() || !cx.objc_selrefs.borrow().is_empty() {
+                if cx.objc_abi_version() == 1 {
+                    cx.define_objc_module_info();
+                }
+                cx.add_objc_module_flags();
+            }
+
             // Finalize code coverage by injecting the coverage map. Note, the coverage map will
             // also be added to the `llvm.compiler.used` variable, created next.
             if cx.sess().instrument_coverage() {
                 cx.coverageinfo_finalize();
             }
 
-            // Create the llvm.used and llvm.compiler.used variables.
+            // Create the llvm.used variable.
             if !cx.used_statics.is_empty() {
                 cx.create_used_variable_impl(c"llvm.used", &cx.used_statics);
             }
-            if !cx.compiler_used_statics.is_empty() {
-                cx.create_used_variable_impl(c"llvm.compiler.used", &cx.compiler_used_statics);
+
+            // Create the llvm.compiler.used variable.
+            {
+                let compiler_used_statics = cx.compiler_used_statics.borrow();
+                if !compiler_used_statics.is_empty() {
+                    cx.create_used_variable_impl(c"llvm.compiler.used", &compiler_used_statics);
+                }
             }
 
             // Run replace-all-uses-with for statics that need it. This must
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 7d0691366e6..0f17cc9063a 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -1091,16 +1091,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         ty: Ty<'tcx>,
         lhs: Self::Value,
         rhs: Self::Value,
-    ) -> Option<Self::Value> {
-        // FIXME: See comment on the definition of `three_way_compare`.
-        if crate::llvm_util::get_version() < (20, 0, 0) {
-            return None;
-        }
-
+    ) -> Self::Value {
         let size = ty.primitive_size(self.tcx);
         let name = if ty.is_signed() { "llvm.scmp" } else { "llvm.ucmp" };
 
-        Some(self.call_intrinsic(name, &[self.type_i8(), self.type_ix(size.bits())], &[lhs, rhs]))
+        self.call_intrinsic(name, &[self.type_i8(), self.type_ix(size.bits())], &[lhs, rhs])
     }
 
     /* Miscellaneous instructions */
diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs
index 11b79a7fe68..aa2df46329f 100644
--- a/compiler/rustc_codegen_llvm/src/common.rs
+++ b/compiler/rustc_codegen_llvm/src/common.rs
@@ -108,6 +108,10 @@ impl<'ll, CX: Borrow<SCx<'ll>>> GenericCx<'ll, CX> {
         bytes_in_context(self.llcx(), bytes)
     }
 
+    pub(crate) fn null_terminate_const_bytes(&self, bytes: &[u8]) -> &'ll Value {
+        null_terminate_bytes_in_context(self.llcx(), bytes)
+    }
+
     pub(crate) fn const_get_elt(&self, v: &'ll Value, idx: u64) -> &'ll Value {
         unsafe {
             let idx = c_uint::try_from(idx).expect("LLVMGetAggregateElement index overflow");
@@ -381,6 +385,16 @@ pub(crate) fn bytes_in_context<'ll>(llcx: &'ll llvm::Context, bytes: &[u8]) -> &
     }
 }
 
+pub(crate) fn null_terminate_bytes_in_context<'ll>(
+    llcx: &'ll llvm::Context,
+    bytes: &[u8],
+) -> &'ll Value {
+    unsafe {
+        let ptr = bytes.as_ptr() as *const c_char;
+        llvm::LLVMConstStringInContext2(llcx, ptr, bytes.len(), FALSE)
+    }
+}
+
 pub(crate) fn named_struct<'ll>(ty: &'ll Type, elts: &[&'ll Value]) -> &'ll Value {
     let len = c_uint::try_from(elts.len()).expect("LLVMConstStructInContext elements len overflow");
     unsafe { llvm::LLVMConstNamedStruct(ty, elts.as_ptr(), len) }
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index dc9bb743560..a110ecbb75d 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -16,6 +16,7 @@ use rustc_middle::mir::mono::MonoItem;
 use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf};
 use rustc_middle::ty::{self, Instance};
 use rustc_middle::{bug, span_bug};
+use rustc_span::Symbol;
 use tracing::{debug, instrument, trace};
 
 use crate::common::CodegenCx;
@@ -331,6 +332,10 @@ impl<'ll> CodegenCx<'ll, '_> {
             }
 
             g
+        } else if let Some(classname) = fn_attrs.objc_class {
+            self.get_objc_classref(classname)
+        } else if let Some(methname) = fn_attrs.objc_selector {
+            self.get_objc_selref(methname)
         } else {
             check_and_apply_linkage(self, fn_attrs, llty, sym, def_id)
         };
@@ -543,8 +548,225 @@ impl<'ll> CodegenCx<'ll, '_> {
 
     /// Add a global value to a list to be stored in the `llvm.compiler.used` variable,
     /// an array of ptr.
-    pub(crate) fn add_compiler_used_global(&mut self, global: &'ll Value) {
-        self.compiler_used_statics.push(global);
+    pub(crate) fn add_compiler_used_global(&self, global: &'ll Value) {
+        self.compiler_used_statics.borrow_mut().push(global);
+    }
+
+    // We do our best here to match what Clang does when compiling Objective-C natively.
+    // See Clang's `CGObjCCommonMac::CreateCStringLiteral`:
+    // https://github.com/llvm/llvm-project/blob/llvmorg-20.1.8/clang/lib/CodeGen/CGObjCMac.cpp#L4134
+    fn define_objc_classname(&self, classname: &str) -> &'ll Value {
+        assert_eq!(self.objc_abi_version(), 1);
+
+        let llval = self.null_terminate_const_bytes(classname.as_bytes());
+        let llty = self.val_ty(llval);
+        let sym = self.generate_local_symbol_name("OBJC_CLASS_NAME_");
+        let g = self.define_global(&sym, llty).unwrap_or_else(|| {
+            bug!("symbol `{}` is already defined", sym);
+        });
+        set_global_alignment(self, g, self.tcx.data_layout.i8_align.abi);
+        llvm::set_initializer(g, llval);
+        llvm::set_linkage(g, llvm::Linkage::PrivateLinkage);
+        llvm::set_section(g, c"__TEXT,__cstring,cstring_literals");
+        llvm::LLVMSetGlobalConstant(g, llvm::TRUE);
+        llvm::LLVMSetUnnamedAddress(g, llvm::UnnamedAddr::Global);
+        self.add_compiler_used_global(g);
+
+        g
+    }
+
+    // We do our best here to match what Clang does when compiling Objective-C natively.
+    // See Clang's `ObjCNonFragileABITypesHelper`:
+    // https://github.com/llvm/llvm-project/blob/llvmorg-20.1.8/clang/lib/CodeGen/CGObjCMac.cpp#L6052
+    fn get_objc_class_t(&self) -> &'ll Type {
+        if let Some(class_t) = self.objc_class_t.get() {
+            return class_t;
+        }
+
+        assert_eq!(self.objc_abi_version(), 2);
+
+        // struct _class_t {
+        //     struct _class_t* isa;
+        //     struct _class_t* const superclass;
+        //     void* cache;
+        //     IMP* vtable;
+        //     struct class_ro_t* ro;
+        // }
+
+        let class_t = self.type_named_struct("struct._class_t");
+        let els = [self.type_ptr(); 5];
+        let packed = false;
+        self.set_struct_body(class_t, &els, packed);
+
+        self.objc_class_t.set(Some(class_t));
+        class_t
+    }
+
+    // We do our best here to match what Clang does when compiling Objective-C natively. We
+    // deduplicate references within a CGU, but we need a reference definition in each referencing
+    // CGU. All attempts at using external references to a single reference definition result in
+    // linker errors.
+    fn get_objc_classref(&self, classname: Symbol) -> &'ll Value {
+        let mut classrefs = self.objc_classrefs.borrow_mut();
+        if let Some(classref) = classrefs.get(&classname).copied() {
+            return classref;
+        }
+
+        let g = match self.objc_abi_version() {
+            1 => {
+                // See Clang's `CGObjCMac::EmitClassRefFromId`:
+                // https://github.com/llvm/llvm-project/blob/llvmorg-20.1.8/clang/lib/CodeGen/CGObjCMac.cpp#L5205
+                let llval = self.define_objc_classname(classname.as_str());
+                let llty = self.type_ptr();
+                let sym = self.generate_local_symbol_name("OBJC_CLASS_REFERENCES_");
+                let g = self.define_global(&sym, llty).unwrap_or_else(|| {
+                    bug!("symbol `{}` is already defined", sym);
+                });
+                set_global_alignment(self, g, self.tcx.data_layout.pointer_align().abi);
+                llvm::set_initializer(g, llval);
+                llvm::set_linkage(g, llvm::Linkage::PrivateLinkage);
+                llvm::set_section(g, c"__OBJC,__cls_refs,literal_pointers,no_dead_strip");
+                self.add_compiler_used_global(g);
+                g
+            }
+            2 => {
+                // See Clang's `CGObjCNonFragileABIMac::EmitClassRefFromId`:
+                // https://github.com/llvm/llvm-project/blob/llvmorg-20.1.8/clang/lib/CodeGen/CGObjCMac.cpp#L7423
+                let llval = {
+                    let extern_sym = format!("OBJC_CLASS_$_{}", classname.as_str());
+                    let extern_llty = self.get_objc_class_t();
+                    self.declare_global(&extern_sym, extern_llty)
+                };
+                let llty = self.type_ptr();
+                let sym = self.generate_local_symbol_name("OBJC_CLASSLIST_REFERENCES_$_");
+                let g = self.define_global(&sym, llty).unwrap_or_else(|| {
+                    bug!("symbol `{}` is already defined", sym);
+                });
+                set_global_alignment(self, g, self.tcx.data_layout.pointer_align().abi);
+                llvm::set_initializer(g, llval);
+                llvm::set_linkage(g, llvm::Linkage::InternalLinkage);
+                llvm::set_section(g, c"__DATA,__objc_classrefs,regular,no_dead_strip");
+                self.add_compiler_used_global(g);
+                g
+            }
+            _ => unreachable!(),
+        };
+
+        classrefs.insert(classname, g);
+        g
+    }
+
+    // We do our best here to match what Clang does when compiling Objective-C natively. We
+    // deduplicate references within a CGU, but we need a reference definition in each referencing
+    // CGU. All attempts at using external references to a single reference definition result in
+    // linker errors.
+    //
+    // Newer versions of Apple Clang generate calls to `@"objc_msgSend$methname"` selector stub
+    // functions. We don't currently do that. The code we generate is closer to what Apple Clang
+    // generates with the `-fno-objc-msgsend-selector-stubs` option.
+    fn get_objc_selref(&self, methname: Symbol) -> &'ll Value {
+        let mut selrefs = self.objc_selrefs.borrow_mut();
+        if let Some(selref) = selrefs.get(&methname).copied() {
+            return selref;
+        }
+
+        let abi_version = self.objc_abi_version();
+
+        // See Clang's `CGObjCCommonMac::CreateCStringLiteral`:
+        // https://github.com/llvm/llvm-project/blob/llvmorg-20.1.8/clang/lib/CodeGen/CGObjCMac.cpp#L4134
+        let methname_llval = self.null_terminate_const_bytes(methname.as_str().as_bytes());
+        let methname_llty = self.val_ty(methname_llval);
+        let methname_sym = self.generate_local_symbol_name("OBJC_METH_VAR_NAME_");
+        let methname_g = self.define_global(&methname_sym, methname_llty).unwrap_or_else(|| {
+            bug!("symbol `{}` is already defined", methname_sym);
+        });
+        set_global_alignment(self, methname_g, self.tcx.data_layout.i8_align.abi);
+        llvm::set_initializer(methname_g, methname_llval);
+        llvm::set_linkage(methname_g, llvm::Linkage::PrivateLinkage);
+        llvm::set_section(
+            methname_g,
+            match abi_version {
+                1 => c"__TEXT,__cstring,cstring_literals",
+                2 => c"__TEXT,__objc_methname,cstring_literals",
+                _ => unreachable!(),
+            },
+        );
+        llvm::LLVMSetGlobalConstant(methname_g, llvm::TRUE);
+        llvm::LLVMSetUnnamedAddress(methname_g, llvm::UnnamedAddr::Global);
+        self.add_compiler_used_global(methname_g);
+
+        // See Clang's `CGObjCMac::EmitSelectorAddr`:
+        // https://github.com/llvm/llvm-project/blob/llvmorg-20.1.8/clang/lib/CodeGen/CGObjCMac.cpp#L5243
+        // And Clang's `CGObjCNonFragileABIMac::EmitSelectorAddr`:
+        // https://github.com/llvm/llvm-project/blob/llvmorg-20.1.8/clang/lib/CodeGen/CGObjCMac.cpp#L7586
+        let selref_llval = methname_g;
+        let selref_llty = self.type_ptr();
+        let selref_sym = self.generate_local_symbol_name("OBJC_SELECTOR_REFERENCES_");
+        let selref_g = self.define_global(&selref_sym, selref_llty).unwrap_or_else(|| {
+            bug!("symbol `{}` is already defined", selref_sym);
+        });
+        set_global_alignment(self, selref_g, self.tcx.data_layout.pointer_align().abi);
+        llvm::set_initializer(selref_g, selref_llval);
+        llvm::set_externally_initialized(selref_g, true);
+        llvm::set_linkage(
+            selref_g,
+            match abi_version {
+                1 => llvm::Linkage::PrivateLinkage,
+                2 => llvm::Linkage::InternalLinkage,
+                _ => unreachable!(),
+            },
+        );
+        llvm::set_section(
+            selref_g,
+            match abi_version {
+                1 => c"__OBJC,__message_refs,literal_pointers,no_dead_strip",
+                2 => c"__DATA,__objc_selrefs,literal_pointers,no_dead_strip",
+                _ => unreachable!(),
+            },
+        );
+        self.add_compiler_used_global(selref_g);
+
+        selrefs.insert(methname, selref_g);
+        selref_g
+    }
+
+    // We do our best here to match what Clang does when compiling Objective-C natively.
+    // See Clang's `ObjCTypesHelper`:
+    // https://github.com/llvm/llvm-project/blob/llvmorg-20.1.8/clang/lib/CodeGen/CGObjCMac.cpp#L5936
+    // And Clang's `CGObjCMac::EmitModuleInfo`:
+    // https://github.com/llvm/llvm-project/blob/llvmorg-20.1.8/clang/lib/CodeGen/CGObjCMac.cpp#L5151
+    pub(crate) fn define_objc_module_info(&mut self) {
+        assert_eq!(self.objc_abi_version(), 1);
+
+        // struct _objc_module {
+        //     long version;                // Hardcoded to 7 in Clang.
+        //     long size;                   // sizeof(struct _objc_module)
+        //     char* name;                  // Hardcoded to classname "" in Clang.
+        //     struct _objc_symtab* symtab; // Null without class or category definitions.
+        //  }
+
+        let llty = self.type_named_struct("struct._objc_module");
+        let i32_llty = self.type_i32();
+        let ptr_llty = self.type_ptr();
+        let packed = false;
+        self.set_struct_body(llty, &[i32_llty, i32_llty, ptr_llty, ptr_llty], packed);
+
+        let version = self.const_uint(i32_llty, 7);
+        let size = self.const_uint(i32_llty, 16);
+        let name = self.define_objc_classname("");
+        let symtab = self.const_null(ptr_llty);
+        let llval = crate::common::named_struct(llty, &[version, size, name, symtab]);
+
+        let sym = "OBJC_MODULES";
+        let g = self.define_global(&sym, llty).unwrap_or_else(|| {
+            bug!("symbol `{}` is already defined", sym);
+        });
+        set_global_alignment(self, g, self.tcx.data_layout.pointer_align().abi);
+        llvm::set_initializer(g, llval);
+        llvm::set_linkage(g, llvm::Linkage::PrivateLinkage);
+        llvm::set_section(g, c"__OBJC,__module_info,regular,no_dead_strip");
+
+        self.add_compiler_used_global(g);
     }
 }
 
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index a69fa54a54a..4a8ea11a3a8 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -26,7 +26,7 @@ use rustc_session::config::{
     BranchProtection, CFGuard, CFProtection, CrateType, DebugInfo, FunctionReturn, PAuthKey, PacRet,
 };
 use rustc_span::source_map::Spanned;
-use rustc_span::{DUMMY_SP, Span};
+use rustc_span::{DUMMY_SP, Span, Symbol};
 use rustc_symbol_mangling::mangle_internal_symbol;
 use rustc_target::spec::{HasTargetSpec, RelocModel, SmallDataThresholdSupport, Target, TlsModel};
 use smallvec::SmallVec;
@@ -119,7 +119,7 @@ pub(crate) struct FullCx<'ll, 'tcx> {
 
     /// Statics that will be placed in the llvm.compiler.used variable
     /// See <https://llvm.org/docs/LangRef.html#the-llvm-compiler-used-global-variable> for details
-    pub compiler_used_statics: Vec<&'ll Value>,
+    pub compiler_used_statics: RefCell<Vec<&'ll Value>>,
 
     /// Mapping of non-scalar types to llvm types.
     pub type_lowering: RefCell<FxHashMap<(Ty<'tcx>, Option<VariantIdx>), &'ll Type>>,
@@ -146,6 +146,15 @@ pub(crate) struct FullCx<'ll, 'tcx> {
     /// `global_asm!` needs to be able to find this new global so that it can
     /// compute the correct mangled symbol name to insert into the asm.
     pub renamed_statics: RefCell<FxHashMap<DefId, &'ll Value>>,
+
+    /// Cached Objective-C class type
+    pub objc_class_t: Cell<Option<&'ll Type>>,
+
+    /// Cache of Objective-C class references
+    pub objc_classrefs: RefCell<FxHashMap<Symbol, &'ll Value>>,
+
+    /// Cache of Objective-C selector references
+    pub objc_selrefs: RefCell<FxHashMap<Symbol, &'ll Value>>,
 }
 
 fn to_llvm_tls_model(tls_model: TlsModel) -> llvm::ThreadLocalMode {
@@ -172,35 +181,6 @@ pub(crate) unsafe fn create_module<'ll>(
     let mut target_data_layout = sess.target.data_layout.to_string();
     let llvm_version = llvm_util::get_version();
 
-    if llvm_version < (20, 0, 0) {
-        if sess.target.arch == "aarch64" || sess.target.arch.starts_with("arm64") {
-            // LLVM 20 defines three additional address spaces for alternate
-            // pointer kinds used in Windows.
-            // See https://github.com/llvm/llvm-project/pull/111879
-            target_data_layout =
-                target_data_layout.replace("-p270:32:32-p271:32:32-p272:64:64", "");
-        }
-        if sess.target.arch.starts_with("sparc") {
-            // LLVM 20 updates the sparc layout to correctly align 128 bit integers to 128 bit.
-            // See https://github.com/llvm/llvm-project/pull/106951
-            target_data_layout = target_data_layout.replace("-i128:128", "");
-        }
-        if sess.target.arch.starts_with("mips64") {
-            // LLVM 20 updates the mips64 layout to correctly align 128 bit integers to 128 bit.
-            // See https://github.com/llvm/llvm-project/pull/112084
-            target_data_layout = target_data_layout.replace("-i128:128", "");
-        }
-        if sess.target.arch.starts_with("powerpc64") {
-            // LLVM 20 updates the powerpc64 layout to correctly align 128 bit integers to 128 bit.
-            // See https://github.com/llvm/llvm-project/pull/118004
-            target_data_layout = target_data_layout.replace("-i128:128", "");
-        }
-        if sess.target.arch.starts_with("wasm32") || sess.target.arch.starts_with("wasm64") {
-            // LLVM 20 updates the wasm(32|64) layout to correctly align 128 bit integers to 128 bit.
-            // See https://github.com/llvm/llvm-project/pull/119204
-            target_data_layout = target_data_layout.replace("-i128:128", "");
-        }
-    }
     if llvm_version < (21, 0, 0) {
         if sess.target.arch == "nvptx64" {
             // LLVM 21 updated the default layout on nvptx: https://github.com/llvm/llvm-project/pull/124961
@@ -644,7 +624,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
                 const_globals: Default::default(),
                 statics_to_rauw: RefCell::new(Vec::new()),
                 used_statics: Vec::new(),
-                compiler_used_statics: Vec::new(),
+                compiler_used_statics: Default::default(),
                 type_lowering: Default::default(),
                 scalar_lltypes: Default::default(),
                 coverage_cx,
@@ -655,6 +635,9 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
                 intrinsics: Default::default(),
                 local_gen_sym_counter: Cell::new(0),
                 renamed_statics: Default::default(),
+                objc_class_t: Cell::new(None),
+                objc_classrefs: Default::default(),
+                objc_selrefs: Default::default(),
             },
             PhantomData,
         )
@@ -679,6 +662,69 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
         llvm::set_linkage(g, llvm::Linkage::AppendingLinkage);
         llvm::set_section(g, c"llvm.metadata");
     }
+
+    /// The Objective-C ABI that is used.
+    ///
+    /// This corresponds to the `-fobjc-abi-version=` flag in Clang / GCC.
+    pub(crate) fn objc_abi_version(&self) -> u32 {
+        assert!(self.tcx.sess.target.is_like_darwin);
+        if self.tcx.sess.target.arch == "x86" && self.tcx.sess.target.os == "macos" {
+            // 32-bit x86 macOS uses ABI version 1 (a.k.a. the "fragile ABI").
+            1
+        } else {
+            // All other Darwin-like targets we support use ABI version 2
+            // (a.k.a the "non-fragile ABI").
+            2
+        }
+    }
+
+    // We do our best here to match what Clang does when compiling Objective-C natively.
+    // See Clang's `CGObjCCommonMac::EmitImageInfo`:
+    // https://github.com/llvm/llvm-project/blob/llvmorg-20.1.8/clang/lib/CodeGen/CGObjCMac.cpp#L5085
+    pub(crate) fn add_objc_module_flags(&self) {
+        let abi_version = self.objc_abi_version();
+
+        llvm::add_module_flag_u32(
+            self.llmod,
+            llvm::ModuleFlagMergeBehavior::Error,
+            "Objective-C Version",
+            abi_version,
+        );
+
+        llvm::add_module_flag_u32(
+            self.llmod,
+            llvm::ModuleFlagMergeBehavior::Error,
+            "Objective-C Image Info Version",
+            0,
+        );
+
+        llvm::add_module_flag_str(
+            self.llmod,
+            llvm::ModuleFlagMergeBehavior::Error,
+            "Objective-C Image Info Section",
+            match abi_version {
+                1 => "__OBJC,__image_info,regular",
+                2 => "__DATA,__objc_imageinfo,regular,no_dead_strip",
+                _ => unreachable!(),
+            },
+        );
+
+        if self.tcx.sess.target.env == "sim" {
+            llvm::add_module_flag_u32(
+                self.llmod,
+                llvm::ModuleFlagMergeBehavior::Error,
+                "Objective-C Is Simulated",
+                1 << 5,
+            );
+        }
+
+        llvm::add_module_flag_u32(
+            self.llmod,
+            llvm::ModuleFlagMergeBehavior::Error,
+            "Objective-C Class Properties",
+            1 << 6,
+        );
+    }
 }
 impl<'ll> SimpleCx<'ll> {
     pub(crate) fn get_type_of_global(&self, val: &'ll Value) -> &'ll Type {
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index dc3a84b6a15..0903ddab285 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -32,9 +32,7 @@ use self::type_map::{DINodeCreationResult, Stub, UniqueTypeId};
 use super::CodegenUnitDebugContext;
 use super::namespace::mangled_name_of_instance;
 use super::type_names::{compute_debuginfo_type_name, compute_debuginfo_vtable_name};
-use super::utils::{
-    DIB, create_DIArray, debug_context, get_namespace_for_item, is_node_local_to_unit,
-};
+use super::utils::{DIB, debug_context, get_namespace_for_item, is_node_local_to_unit};
 use crate::common::{AsCCharPtr, CodegenCx};
 use crate::debuginfo::dwarf_const;
 use crate::debuginfo::metadata::type_map::build_type_with_children;
@@ -119,17 +117,17 @@ fn build_fixed_size_array_di_node<'ll, 'tcx>(
         .try_to_target_usize(cx.tcx)
         .expect("expected monomorphic const in codegen") as c_longlong;
 
-    let subrange =
-        unsafe { Some(llvm::LLVMRustDIBuilderGetOrCreateSubrange(DIB(cx), 0, upper_bound)) };
+    let subrange = unsafe { llvm::LLVMRustDIBuilderGetOrCreateSubrange(DIB(cx), 0, upper_bound) };
+    let subscripts = &[subrange];
 
-    let subscripts = create_DIArray(DIB(cx), &[subrange]);
     let di_node = unsafe {
-        llvm::LLVMRustDIBuilderCreateArrayType(
+        llvm::LLVMDIBuilderCreateArrayType(
             DIB(cx),
             size.bits(),
             align.bits() as u32,
             element_type_di_node,
-            subscripts,
+            subscripts.as_ptr(),
+            subscripts.len() as c_uint,
         )
     };
 
@@ -175,17 +173,13 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
                 "ptr_type={ptr_type}, pointee_type={pointee_type}",
             );
 
-            let di_node = unsafe {
-                llvm::LLVMRustDIBuilderCreatePointerType(
-                    DIB(cx),
-                    pointee_type_di_node,
-                    pointer_size.bits(),
-                    pointer_align.abi.bits() as u32,
-                    0, // Ignore DWARF address space.
-                    ptr_type_debuginfo_name.as_c_char_ptr(),
-                    ptr_type_debuginfo_name.len(),
-                )
-            };
+            let di_node = create_pointer_type(
+                cx,
+                pointee_type_di_node,
+                pointer_size,
+                pointer_align.abi,
+                &ptr_type_debuginfo_name,
+            );
 
             DINodeCreationResult { di_node, already_stored_in_typemap: false }
         }
@@ -233,17 +227,13 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
 
                     // The data pointer type is a regular, thin pointer, regardless of whether this
                     // is a slice or a trait object.
-                    let data_ptr_type_di_node = unsafe {
-                        llvm::LLVMRustDIBuilderCreatePointerType(
-                            DIB(cx),
-                            pointee_type_di_node,
-                            addr_field.size.bits(),
-                            addr_field.align.abi.bits() as u32,
-                            0, // Ignore DWARF address space.
-                            std::ptr::null(),
-                            0,
-                        )
-                    };
+                    let data_ptr_type_di_node = create_pointer_type(
+                        cx,
+                        pointee_type_di_node,
+                        addr_field.size,
+                        addr_field.align.abi,
+                        "",
+                    );
 
                     smallvec![
                         build_field_di_node(
@@ -318,7 +308,7 @@ fn build_subroutine_type_di_node<'ll, 'tcx>(
 
     debug_context(cx).type_map.unique_id_to_di_node.borrow_mut().remove(&unique_type_id);
 
-    let fn_di_node = create_subroutine_type(cx, create_DIArray(DIB(cx), &signature_di_nodes[..]));
+    let fn_di_node = create_subroutine_type(cx, &signature_di_nodes[..]);
 
     // This is actually a function pointer, so wrap it in pointer DI.
     let name = compute_debuginfo_type_name(cx.tcx, fn_ty, false);
@@ -329,26 +319,44 @@ fn build_subroutine_type_di_node<'ll, 'tcx>(
         }
         _ => unreachable!(),
     };
-    let di_node = unsafe {
-        llvm::LLVMRustDIBuilderCreatePointerType(
-            DIB(cx),
-            fn_di_node,
-            size.bits(),
-            align.bits() as u32,
-            0, // Ignore DWARF address space.
-            name.as_c_char_ptr(),
-            name.len(),
-        )
-    };
+    let di_node = create_pointer_type(cx, fn_di_node, size, align, &name);
 
     DINodeCreationResult::new(di_node, false)
 }
 
 pub(super) fn create_subroutine_type<'ll>(
     cx: &CodegenCx<'ll, '_>,
-    signature: &'ll DICompositeType,
+    signature: &[Option<&'ll llvm::Metadata>],
 ) -> &'ll DICompositeType {
-    unsafe { llvm::LLVMRustDIBuilderCreateSubroutineType(DIB(cx), signature) }
+    unsafe {
+        llvm::LLVMDIBuilderCreateSubroutineType(
+            DIB(cx),
+            None, // ("File" is ignored and has no effect)
+            signature.as_ptr(),
+            signature.len() as c_uint,
+            DIFlags::FlagZero, // (default value)
+        )
+    }
+}
+
+fn create_pointer_type<'ll>(
+    cx: &CodegenCx<'ll, '_>,
+    pointee_ty: &'ll llvm::Metadata,
+    size: Size,
+    align: Align,
+    name: &str,
+) -> &'ll llvm::Metadata {
+    unsafe {
+        llvm::LLVMDIBuilderCreatePointerType(
+            DIB(cx),
+            pointee_ty,
+            size.bits(),
+            align.bits() as u32,
+            0, // Ignore DWARF address space.
+            name.as_ptr(),
+            name.len(),
+        )
+    }
 }
 
 /// Create debuginfo for `dyn SomeTrait` types. Currently these are empty structs
@@ -834,12 +842,13 @@ fn create_basic_type<'ll, 'tcx>(
     encoding: u32,
 ) -> &'ll DIBasicType {
     unsafe {
-        llvm::LLVMRustDIBuilderCreateBasicType(
+        llvm::LLVMDIBuilderCreateBasicType(
             DIB(cx),
-            name.as_c_char_ptr(),
+            name.as_ptr(),
             name.len(),
             size.bits(),
             encoding,
+            DIFlags::FlagZero,
         )
     }
 }
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs
index 18a783a348a..37200fdc41a 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs
@@ -1,5 +1,6 @@
 use std::cell::RefCell;
 
+use libc::c_uint;
 use rustc_abi::{Align, Size, VariantIdx};
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxHashMap;
@@ -9,7 +10,7 @@ use rustc_middle::bug;
 use rustc_middle::ty::{self, ExistentialTraitRef, Ty, TyCtxt};
 
 use super::{DefinitionLocation, SmallVec, UNKNOWN_LINE_NUMBER, unknown_file_metadata};
-use crate::common::{AsCCharPtr, CodegenCx};
+use crate::common::CodegenCx;
 use crate::debuginfo::utils::{DIB, create_DIArray, debug_context};
 use crate::llvm::debuginfo::{DIFlags, DIScope, DIType};
 use crate::llvm::{self};
@@ -191,7 +192,7 @@ pub(super) fn stub<'ll, 'tcx>(
     containing_scope: Option<&'ll DIScope>,
     flags: DIFlags,
 ) -> StubInfo<'ll, 'tcx> {
-    let empty_array = create_DIArray(DIB(cx), &[]);
+    let no_elements: &[Option<&llvm::Metadata>] = &[];
     let unique_type_id_str = unique_type_id.generate_unique_id_string(cx.tcx);
 
     let (file_metadata, line_number) = if let Some(def_location) = def_location {
@@ -207,10 +208,10 @@ pub(super) fn stub<'ll, 'tcx>(
                 _ => None,
             };
             unsafe {
-                llvm::LLVMRustDIBuilderCreateStructType(
+                llvm::LLVMDIBuilderCreateStructType(
                     DIB(cx),
                     containing_scope,
-                    name.as_c_char_ptr(),
+                    name.as_ptr(),
                     name.len(),
                     file_metadata,
                     line_number,
@@ -218,28 +219,30 @@ pub(super) fn stub<'ll, 'tcx>(
                     align.bits() as u32,
                     flags,
                     None,
-                    empty_array,
-                    0,
+                    no_elements.as_ptr(),
+                    no_elements.len() as c_uint,
+                    0u32, // (Objective-C runtime version; default is 0)
                     vtable_holder,
-                    unique_type_id_str.as_c_char_ptr(),
+                    unique_type_id_str.as_ptr(),
                     unique_type_id_str.len(),
                 )
             }
         }
         Stub::Union => unsafe {
-            llvm::LLVMRustDIBuilderCreateUnionType(
+            llvm::LLVMDIBuilderCreateUnionType(
                 DIB(cx),
                 containing_scope,
-                name.as_c_char_ptr(),
+                name.as_ptr(),
                 name.len(),
                 file_metadata,
                 line_number,
                 size.bits(),
                 align.bits() as u32,
                 flags,
-                Some(empty_array),
-                0,
-                unique_type_id_str.as_c_char_ptr(),
+                no_elements.as_ptr(),
+                no_elements.len() as c_uint,
+                0u32, // (Objective-C runtime version; default is 0)
+                unique_type_id_str.as_ptr(),
                 unique_type_id_str.len(),
             )
         },
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
index 79334f7f9fe..126082aa3aa 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
@@ -349,7 +349,7 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         let file_metadata = file_metadata(self, &loc.file);
 
         let function_type_metadata =
-            create_subroutine_type(self, get_function_signature(self, fn_abi));
+            create_subroutine_type(self, &get_function_signature(self, fn_abi));
 
         let mut name = String::with_capacity(64);
         type_names::push_item_name(tcx, def_id, false, &mut name);
@@ -441,9 +441,9 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         fn get_function_signature<'ll, 'tcx>(
             cx: &CodegenCx<'ll, 'tcx>,
             fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
-        ) -> &'ll DIArray {
+        ) -> Vec<Option<&'ll llvm::Metadata>> {
             if cx.sess().opts.debuginfo != DebugInfo::Full {
-                return create_DIArray(DIB(cx), &[]);
+                return vec![];
             }
 
             let mut signature = Vec::with_capacity(fn_abi.args.len() + 1);
@@ -484,7 +484,7 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
                     .extend(fn_abi.args.iter().map(|arg| Some(type_di_node(cx, arg.layout.ty))));
             }
 
-            create_DIArray(DIB(cx), &signature[..])
+            signature
         }
 
         fn get_template_parameters<'ll, 'tcx>(
diff --git a/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs
index 56d756e52cc..695435eb6da 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs
@@ -59,10 +59,10 @@ pub(crate) enum LLVMRustVerifierFailureAction {
     LLVMReturnStatusAction = 2,
 }
 
-#[cfg(llvm_enzyme)]
+#[cfg(feature = "llvm_enzyme")]
 pub(crate) use self::Enzyme_AD::*;
 
-#[cfg(llvm_enzyme)]
+#[cfg(feature = "llvm_enzyme")]
 pub(crate) mod Enzyme_AD {
     use std::ffi::{CString, c_char};
 
@@ -134,10 +134,10 @@ pub(crate) mod Enzyme_AD {
     }
 }
 
-#[cfg(not(llvm_enzyme))]
+#[cfg(not(feature = "llvm_enzyme"))]
 pub(crate) use self::Fallback_AD::*;
 
-#[cfg(not(llvm_enzyme))]
+#[cfg(not(feature = "llvm_enzyme"))]
 pub(crate) mod Fallback_AD {
     #![allow(unused_variables)]
 
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 0679f55ab7f..71d8b7d25fe 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -24,9 +24,9 @@ use rustc_target::spec::SymbolVisibility;
 
 use super::RustString;
 use super::debuginfo::{
-    DIArray, DIBasicType, DIBuilder, DICompositeType, DIDerivedType, DIDescriptor, DIEnumerator,
-    DIFile, DIFlags, DIGlobalVariableExpression, DILocation, DISPFlags, DIScope, DISubprogram,
-    DISubrange, DITemplateTypeParameter, DIType, DIVariable, DebugEmissionKind, DebugNameTableKind,
+    DIArray, DIBasicType, DIBuilder, DIDerivedType, DIDescriptor, DIEnumerator, DIFile, DIFlags,
+    DIGlobalVariableExpression, DILocation, DISPFlags, DIScope, DISubprogram, DISubrange,
+    DITemplateTypeParameter, DIType, DIVariable, DebugEmissionKind, DebugNameTableKind,
 };
 use crate::llvm;
 
@@ -1237,6 +1237,7 @@ unsafe extern "C" {
     pub(crate) safe fn LLVMSetGlobalConstant(GlobalVar: &Value, IsConstant: Bool);
     pub(crate) safe fn LLVMSetTailCall(CallInst: &Value, IsTailCall: Bool);
     pub(crate) safe fn LLVMSetTailCallKind(CallInst: &Value, kind: TailCallKind);
+    pub(crate) safe fn LLVMSetExternallyInitialized(GlobalVar: &Value, IsExtInit: Bool);
 
     // Operations on attributes
     pub(crate) fn LLVMCreateStringAttribute(
@@ -1870,6 +1871,78 @@ unsafe extern "C" {
         Scope: &'ll Metadata,
         InlinedAt: Option<&'ll Metadata>,
     ) -> &'ll Metadata;
+
+    pub(crate) fn LLVMDIBuilderCreateSubroutineType<'ll>(
+        Builder: &DIBuilder<'ll>,
+        File: Option<&'ll Metadata>, // (ignored and has no effect)
+        ParameterTypes: *const Option<&'ll Metadata>,
+        NumParameterTypes: c_uint,
+        Flags: DIFlags, // (default is `DIFlags::DIFlagZero`)
+    ) -> &'ll Metadata;
+
+    pub(crate) fn LLVMDIBuilderCreateUnionType<'ll>(
+        Builder: &DIBuilder<'ll>,
+        Scope: Option<&'ll Metadata>,
+        Name: *const c_uchar, // See "PTR_LEN_STR".
+        NameLen: size_t,
+        File: &'ll Metadata,
+        LineNumber: c_uint,
+        SizeInBits: u64,
+        AlignInBits: u32,
+        Flags: DIFlags,
+        Elements: *const Option<&'ll Metadata>,
+        NumElements: c_uint,
+        RunTimeLang: c_uint, // (optional Objective-C runtime version; default is 0)
+        UniqueId: *const c_uchar, // See "PTR_LEN_STR".
+        UniqueIdLen: size_t,
+    ) -> &'ll Metadata;
+
+    pub(crate) fn LLVMDIBuilderCreateArrayType<'ll>(
+        Builder: &DIBuilder<'ll>,
+        Size: u64,
+        Align: u32,
+        Ty: &'ll Metadata,
+        Subscripts: *const &'ll Metadata,
+        NumSubscripts: c_uint,
+    ) -> &'ll Metadata;
+
+    pub(crate) fn LLVMDIBuilderCreateBasicType<'ll>(
+        Builder: &DIBuilder<'ll>,
+        Name: *const c_uchar, // See "PTR_LEN_STR".
+        NameLen: size_t,
+        SizeInBits: u64,
+        Encoding: c_uint, // (`LLVMDWARFTypeEncoding`)
+        Flags: DIFlags,   // (default is `DIFlags::DIFlagZero`)
+    ) -> &'ll Metadata;
+
+    pub(crate) fn LLVMDIBuilderCreatePointerType<'ll>(
+        Builder: &DIBuilder<'ll>,
+        PointeeTy: &'ll Metadata,
+        SizeInBits: u64,
+        AlignInBits: u32,
+        AddressSpace: c_uint, // (optional DWARF address space; default is 0)
+        Name: *const c_uchar, // See "PTR_LEN_STR".
+        NameLen: size_t,
+    ) -> &'ll Metadata;
+
+    pub(crate) fn LLVMDIBuilderCreateStructType<'ll>(
+        Builder: &DIBuilder<'ll>,
+        Scope: Option<&'ll Metadata>,
+        Name: *const c_uchar, // See "PTR_LEN_STR".
+        NameLen: size_t,
+        File: &'ll Metadata,
+        LineNumber: c_uint,
+        SizeInBits: u64,
+        AlignInBits: u32,
+        Flags: DIFlags,
+        DerivedFrom: Option<&'ll Metadata>,
+        Elements: *const Option<&'ll Metadata>,
+        NumElements: c_uint,
+        RunTimeLang: c_uint, // (optional Objective-C runtime version; default is 0)
+        VTableHolder: Option<&'ll Metadata>,
+        UniqueId: *const c_uchar, // See "PTR_LEN_STR".
+        UniqueIdLen: size_t,
+    ) -> &'ll Metadata;
 }
 
 #[link(name = "llvm-wrapper", kind = "static")]
@@ -2172,11 +2245,6 @@ unsafe extern "C" {
         SourceLen: size_t,
     ) -> &'a DIFile;
 
-    pub(crate) fn LLVMRustDIBuilderCreateSubroutineType<'a>(
-        Builder: &DIBuilder<'a>,
-        ParameterTypes: &'a DIArray,
-    ) -> &'a DICompositeType;
-
     pub(crate) fn LLVMRustDIBuilderCreateFunction<'a>(
         Builder: &DIBuilder<'a>,
         Scope: &'a DIDescriptor,
@@ -2210,14 +2278,6 @@ unsafe extern "C" {
         TParam: &'a DIArray,
     ) -> &'a DISubprogram;
 
-    pub(crate) fn LLVMRustDIBuilderCreateBasicType<'a>(
-        Builder: &DIBuilder<'a>,
-        Name: *const c_char,
-        NameLen: size_t,
-        SizeInBits: u64,
-        Encoding: c_uint,
-    ) -> &'a DIBasicType;
-
     pub(crate) fn LLVMRustDIBuilderCreateTypedef<'a>(
         Builder: &DIBuilder<'a>,
         Type: &'a DIBasicType,
@@ -2228,34 +2288,6 @@ unsafe extern "C" {
         Scope: Option<&'a DIScope>,
     ) -> &'a DIDerivedType;
 
-    pub(crate) fn LLVMRustDIBuilderCreatePointerType<'a>(
-        Builder: &DIBuilder<'a>,
-        PointeeTy: &'a DIType,
-        SizeInBits: u64,
-        AlignInBits: u32,
-        AddressSpace: c_uint,
-        Name: *const c_char,
-        NameLen: size_t,
-    ) -> &'a DIDerivedType;
-
-    pub(crate) fn LLVMRustDIBuilderCreateStructType<'a>(
-        Builder: &DIBuilder<'a>,
-        Scope: Option<&'a DIDescriptor>,
-        Name: *const c_char,
-        NameLen: size_t,
-        File: &'a DIFile,
-        LineNumber: c_uint,
-        SizeInBits: u64,
-        AlignInBits: u32,
-        Flags: DIFlags,
-        DerivedFrom: Option<&'a DIType>,
-        Elements: &'a DIArray,
-        RunTimeLang: c_uint,
-        VTableHolder: Option<&'a DIType>,
-        UniqueId: *const c_char,
-        UniqueIdLen: size_t,
-    ) -> &'a DICompositeType;
-
     pub(crate) fn LLVMRustDIBuilderCreateMemberType<'a>(
         Builder: &DIBuilder<'a>,
         Scope: &'a DIDescriptor,
@@ -2335,14 +2367,6 @@ unsafe extern "C" {
         AlignInBits: u32,
     ) -> &'a DIVariable;
 
-    pub(crate) fn LLVMRustDIBuilderCreateArrayType<'a>(
-        Builder: &DIBuilder<'a>,
-        Size: u64,
-        AlignInBits: u32,
-        Ty: &'a DIType,
-        Subscripts: &'a DIArray,
-    ) -> &'a DIType;
-
     pub(crate) fn LLVMRustDIBuilderGetOrCreateSubrange<'a>(
         Builder: &DIBuilder<'a>,
         Lo: i64,
@@ -2388,22 +2412,6 @@ unsafe extern "C" {
         IsScoped: bool,
     ) -> &'a DIType;
 
-    pub(crate) fn LLVMRustDIBuilderCreateUnionType<'a>(
-        Builder: &DIBuilder<'a>,
-        Scope: Option<&'a DIScope>,
-        Name: *const c_char,
-        NameLen: size_t,
-        File: &'a DIFile,
-        LineNumber: c_uint,
-        SizeInBits: u64,
-        AlignInBits: u32,
-        Flags: DIFlags,
-        Elements: Option<&'a DIArray>,
-        RunTimeLang: c_uint,
-        UniqueId: *const c_char,
-        UniqueIdLen: size_t,
-    ) -> &'a DIType;
-
     pub(crate) fn LLVMRustDIBuilderCreateVariantPart<'a>(
         Builder: &DIBuilder<'a>,
         Scope: &'a DIScope,
diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs
index d6974e22c85..1115d82fa85 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs
@@ -258,6 +258,10 @@ pub(crate) fn set_alignment(llglobal: &Value, align: Align) {
     }
 }
 
+pub(crate) fn set_externally_initialized(llglobal: &Value, is_ext_init: bool) {
+    LLVMSetExternallyInitialized(llglobal, is_ext_init.to_llvm_bool());
+}
+
 /// Get the `name`d comdat from `llmod` and assign it to `llglobal`.
 ///
 /// Inserts the comdat into `llmod` if it does not exist.
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index d927ffd78c2..8461c8b03d5 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -246,9 +246,6 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
         ("aarch64", "pmuv3") => Some(LLVMFeature::new("perfmon")),
         ("aarch64", "paca") => Some(LLVMFeature::new("pauth")),
         ("aarch64", "pacg") => Some(LLVMFeature::new("pauth")),
-        // Before LLVM 20 those two features were packaged together as b16b16
-        ("aarch64", "sve-b16b16") if get_version().0 < 20 => Some(LLVMFeature::new("b16b16")),
-        ("aarch64", "sme-b16b16") if get_version().0 < 20 => Some(LLVMFeature::new("b16b16")),
         ("aarch64", "flagm2") => Some(LLVMFeature::new("altnzcv")),
         // Rust ties fp and neon together.
         ("aarch64", "neon") => Some(LLVMFeature::with_dependencies(
@@ -262,57 +259,17 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
         // Filter out features that are not supported by the current LLVM version
         ("aarch64", "fpmr") => None, // only existed in 18
         ("arm", "fp16") => Some(LLVMFeature::new("fullfp16")),
-        // NVPTX targets added in LLVM 20
-        ("nvptx64", "sm_100") if get_version().0 < 20 => None,
-        ("nvptx64", "sm_100a") if get_version().0 < 20 => None,
-        ("nvptx64", "sm_101") if get_version().0 < 20 => None,
-        ("nvptx64", "sm_101a") if get_version().0 < 20 => None,
-        ("nvptx64", "sm_120") if get_version().0 < 20 => None,
-        ("nvptx64", "sm_120a") if get_version().0 < 20 => None,
-        ("nvptx64", "ptx86") if get_version().0 < 20 => None,
-        ("nvptx64", "ptx87") if get_version().0 < 20 => None,
         // Filter out features that are not supported by the current LLVM version
-        ("loongarch64", "div32" | "lam-bh" | "lamcas" | "ld-seq-sa" | "scq")
-            if get_version().0 < 20 =>
-        {
-            None
-        }
         ("loongarch32" | "loongarch64", "32s") if get_version().0 < 21 => None,
-        // Filter out features that are not supported by the current LLVM version
-        ("riscv32" | "riscv64", "zacas" | "rva23u64" | "supm") if get_version().0 < 20 => None,
-        (
-            "s390x",
-            "message-security-assist-extension12"
-            | "concurrent-functions"
-            | "miscellaneous-extensions-4"
-            | "vector-enhancements-3"
-            | "vector-packed-decimal-enhancement-3",
-        ) if get_version().0 < 20 => None,
         // Enable the evex512 target feature if an avx512 target feature is enabled.
         ("x86", s) if s.starts_with("avx512") => Some(LLVMFeature::with_dependencies(
             s,
             smallvec![TargetFeatureFoldStrength::EnableOnly("evex512")],
         )),
-        // Support for `wide-arithmetic` will first land in LLVM 20 as part of
-        // llvm/llvm-project#111598
-        ("wasm32" | "wasm64", "wide-arithmetic") if get_version() < (20, 0, 0) => None,
         ("sparc", "leoncasa") => Some(LLVMFeature::new("hasleoncasa")),
-        // In LLVM 19, there is no `v8plus` feature and `v9` means "SPARC-V9 instruction available and SPARC-V8+ ABI used".
-        // https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp#L27-L28
-        // Before LLVM 19, there was no `v8plus` feature and `v9` means "SPARC-V9 instruction available".
-        // https://github.com/llvm/llvm-project/blob/llvmorg-18.1.0/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp#L26
-        ("sparc", "v8plus") if get_version().0 == 19 => Some(LLVMFeature::new("v9")),
         ("powerpc", "power8-crypto") => Some(LLVMFeature::new("crypto")),
-        // These new `amx` variants and `movrs` were introduced in LLVM20
-        ("x86", "amx-avx512" | "amx-fp8" | "amx-movrs" | "amx-tf32" | "amx-transpose")
-            if get_version().0 < 20 =>
-        {
-            None
-        }
-        ("x86", "movrs") if get_version().0 < 20 => None,
         ("x86", "avx10.1") => Some(LLVMFeature::new("avx10.1-512")),
-        ("x86", "avx10.2") if get_version().0 < 20 => None,
-        ("x86", "avx10.2") if get_version().0 >= 20 => Some(LLVMFeature::new("avx10.2-512")),
+        ("x86", "avx10.2") => Some(LLVMFeature::new("avx10.2-512")),
         ("x86", "apxf") => Some(LLVMFeature::with_dependencies(
             "egpr",
             smallvec![
@@ -716,17 +673,7 @@ pub(crate) fn global_llvm_features(
     };
 
     // Features implied by an implicit or explicit `--target`.
-    features.extend(
-        sess.target
-            .features
-            .split(',')
-            .filter(|v| !v.is_empty())
-            // Drop +v8plus feature introduced in LLVM 20.
-            // (Hard-coded target features do not go through `to_llvm_feature` since they already
-            // are LLVM feature names, hence we need a special case here.)
-            .filter(|v| *v != "+v8plus" || get_version() >= (20, 0, 0))
-            .map(String::from),
-    );
+    features.extend(sess.target.features.split(',').filter(|v| !v.is_empty()).map(String::from));
 
     if wants_wasm_eh(sess) && sess.panic_strategy() == PanicStrategy::Unwind {
         features.push("+exception-handling".into());
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index dc500c363f4..32ae810ecc8 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -296,6 +296,12 @@ fn process_builtin_attrs(
                 AttributeKind::Sanitize { span, .. } => {
                     interesting_spans.sanitize = Some(*span);
                 }
+                AttributeKind::ObjcClass { classname, .. } => {
+                    codegen_fn_attrs.objc_class = Some(*classname);
+                }
+                AttributeKind::ObjcSelector { methname, .. } => {
+                    codegen_fn_attrs.objc_selector = Some(*methname);
+                }
                 _ => {}
             }
         }
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index f8755874014..2602bf82095 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -7,9 +7,9 @@ use rustc_middle::{bug, mir, span_bug};
 use rustc_session::config::OptLevel;
 use tracing::{debug, instrument};
 
+use super::FunctionCx;
 use super::operand::{OperandRef, OperandRefBuilder, OperandValue};
 use super::place::{PlaceRef, PlaceValue, codegen_tag_value};
-use super::{FunctionCx, LocalRef};
 use crate::common::{IntPredicate, TypeKind};
 use crate::traits::*;
 use crate::{MemFlags, base};
@@ -510,14 +510,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 self.codegen_place_to_pointer(bx, place, mk_ptr)
             }
 
-            mir::Rvalue::Len(place) => {
-                let size = self.evaluate_array_len(bx, place);
-                OperandRef {
-                    val: OperandValue::Immediate(size),
-                    layout: bx.cx().layout_of(bx.tcx().types.usize),
-                }
-            }
-
             mir::Rvalue::BinaryOp(op_with_overflow, box (ref lhs, ref rhs))
                 if let Some(op) = op_with_overflow.overflowing_to_wrapping() =>
             {
@@ -749,21 +741,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         }
     }
 
-    fn evaluate_array_len(&mut self, bx: &mut Bx, place: mir::Place<'tcx>) -> Bx::Value {
-        // ZST are passed as operands and require special handling
-        // because codegen_place() panics if Local is operand.
-        if let Some(index) = place.as_local()
-            && let LocalRef::Operand(op) = self.locals[index]
-            && let ty::Array(_, n) = op.layout.ty.kind()
-        {
-            let n = n.try_to_target_usize(bx.tcx()).expect("expected monomorphic const in codegen");
-            return bx.cx().const_usize(n);
-        }
-        // use common size calculation for non zero-sized types
-        let cg_value = self.codegen_place(bx, place.as_ref());
-        cg_value.len(bx.cx())
-    }
-
     /// Codegen an `Rvalue::RawPtr` or `Rvalue::Ref`
     fn codegen_place_to_pointer(
         &mut self,
@@ -901,36 +878,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 }
             }
             mir::BinOp::Cmp => {
-                use std::cmp::Ordering;
                 assert!(!is_float);
-                if let Some(value) = bx.three_way_compare(lhs_ty, lhs, rhs) {
-                    return value;
-                }
-                let pred = |op| base::bin_op_to_icmp_predicate(op, is_signed);
-                if bx.cx().tcx().sess.opts.optimize == OptLevel::No {
-                    // FIXME: This actually generates tighter assembly, and is a classic trick
-                    // <https://graphics.stanford.edu/~seander/bithacks.html#CopyIntegerSign>
-                    // However, as of 2023-11 it optimizes worse in things like derived
-                    // `PartialOrd`, so only use it in debug for now. Once LLVM can handle it
-                    // better (see <https://github.com/llvm/llvm-project/issues/73417>), it'll
-                    // be worth trying it in optimized builds as well.
-                    let is_gt = bx.icmp(pred(mir::BinOp::Gt), lhs, rhs);
-                    let gtext = bx.zext(is_gt, bx.type_i8());
-                    let is_lt = bx.icmp(pred(mir::BinOp::Lt), lhs, rhs);
-                    let ltext = bx.zext(is_lt, bx.type_i8());
-                    bx.unchecked_ssub(gtext, ltext)
-                } else {
-                    // These operations are those expected by `tests/codegen-llvm/integer-cmp.rs`,
-                    // from <https://github.com/rust-lang/rust/pull/63767>.
-                    let is_lt = bx.icmp(pred(mir::BinOp::Lt), lhs, rhs);
-                    let is_ne = bx.icmp(pred(mir::BinOp::Ne), lhs, rhs);
-                    let ge = bx.select(
-                        is_ne,
-                        bx.cx().const_i8(Ordering::Greater as i8),
-                        bx.cx().const_i8(Ordering::Equal as i8),
-                    );
-                    bx.select(is_lt, bx.cx().const_i8(Ordering::Less as i8), ge)
-                }
+                bx.three_way_compare(lhs_ty, lhs, rhs)
             }
             mir::BinOp::AddWithOverflow
             | mir::BinOp::SubWithOverflow
diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs
index f417d1a7bf7..4a5694e97fa 100644
--- a/compiler/rustc_codegen_ssa/src/traits/builder.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs
@@ -3,6 +3,7 @@ use std::ops::Deref;
 
 use rustc_abi::{Align, Scalar, Size, WrappingRange};
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
+use rustc_middle::mir;
 use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout};
 use rustc_middle::ty::{AtomicOrdering, Instance, Ty};
 use rustc_session::config::OptLevel;
@@ -405,15 +406,41 @@ pub trait BuilderMethods<'a, 'tcx>:
     fn fcmp(&mut self, op: RealPredicate, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
 
     /// Returns `-1` if `lhs < rhs`, `0` if `lhs == rhs`, and `1` if `lhs > rhs`.
-    // FIXME: Move the default implementation from `codegen_scalar_binop` into this method and
-    // remove the `Option` return once LLVM 20 is the minimum version.
     fn three_way_compare(
         &mut self,
-        _ty: Ty<'tcx>,
-        _lhs: Self::Value,
-        _rhs: Self::Value,
-    ) -> Option<Self::Value> {
-        None
+        ty: Ty<'tcx>,
+        lhs: Self::Value,
+        rhs: Self::Value,
+    ) -> Self::Value {
+        // FIXME: This implementation was designed around LLVM's ability to optimize, but `cg_llvm`
+        // overrides this to just use `@llvm.scmp`/`ucmp` since LLVM 20. This default impl should be
+        // reevaluated with respect to the remaining backends like cg_gcc, whether they might use
+        // specialized implementations as well, or continue to use a generic implementation here.
+        use std::cmp::Ordering;
+        let pred = |op| crate::base::bin_op_to_icmp_predicate(op, ty.is_signed());
+        if self.cx().sess().opts.optimize == OptLevel::No {
+            // This actually generates tighter assembly, and is a classic trick:
+            // <https://graphics.stanford.edu/~seander/bithacks.html#CopyIntegerSign>.
+            // However, as of 2023-11 it optimized worse in LLVM in things like derived
+            // `PartialOrd`, so we were only using it in debug. Since LLVM now uses its own
+            // intrinsics, it may be be worth trying it in optimized builds for other backends.
+            let is_gt = self.icmp(pred(mir::BinOp::Gt), lhs, rhs);
+            let gtext = self.zext(is_gt, self.type_i8());
+            let is_lt = self.icmp(pred(mir::BinOp::Lt), lhs, rhs);
+            let ltext = self.zext(is_lt, self.type_i8());
+            self.unchecked_ssub(gtext, ltext)
+        } else {
+            // These operations were better optimized by LLVM, before `@llvm.scmp`/`ucmp` in 20.
+            // See <https://github.com/rust-lang/rust/pull/63767>.
+            let is_lt = self.icmp(pred(mir::BinOp::Lt), lhs, rhs);
+            let is_ne = self.icmp(pred(mir::BinOp::Ne), lhs, rhs);
+            let ge = self.select(
+                is_ne,
+                self.cx().const_i8(Ordering::Greater as i8),
+                self.cx().const_i8(Ordering::Equal as i8),
+            );
+            self.select(is_lt, self.cx().const_i8(Ordering::Less as i8), ge)
+        }
     }
 
     fn memcpy(
diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs
index ca707b50d50..3397bd9a68e 100644
--- a/compiler/rustc_const_eval/src/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/check_consts/check.rs
@@ -573,8 +573,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
             Rvalue::Use(_)
             | Rvalue::CopyForDeref(..)
             | Rvalue::Repeat(..)
-            | Rvalue::Discriminant(..)
-            | Rvalue::Len(_) => {}
+            | Rvalue::Discriminant(..) => {}
 
             Rvalue::Aggregate(kind, ..) => {
                 if let AggregateKind::Coroutine(def_id, ..) = kind.as_ref()
diff --git a/compiler/rustc_const_eval/src/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/check_consts/qualifs.rs
index faf41f1658b..34d1fdd8c86 100644
--- a/compiler/rustc_const_eval/src/check_consts/qualifs.rs
+++ b/compiler/rustc_const_eval/src/check_consts/qualifs.rs
@@ -232,9 +232,7 @@ where
             Q::in_any_value_of_ty(cx, rvalue.ty(cx.body, cx.tcx))
         }
 
-        Rvalue::Discriminant(place) | Rvalue::Len(place) => {
-            in_place::<Q, _>(cx, in_local, place.as_ref())
-        }
+        Rvalue::Discriminant(place) => in_place::<Q, _>(cx, in_local, place.as_ref()),
 
         Rvalue::CopyForDeref(place) => in_place::<Q, _>(cx, in_local, place.as_ref()),
 
diff --git a/compiler/rustc_const_eval/src/check_consts/resolver.rs b/compiler/rustc_const_eval/src/check_consts/resolver.rs
index d98e5027e4d..664dda8701a 100644
--- a/compiler/rustc_const_eval/src/check_consts/resolver.rs
+++ b/compiler/rustc_const_eval/src/check_consts/resolver.rs
@@ -197,7 +197,6 @@ where
             | mir::Rvalue::CopyForDeref(..)
             | mir::Rvalue::ThreadLocalRef(..)
             | mir::Rvalue::Repeat(..)
-            | mir::Rvalue::Len(..)
             | mir::Rvalue::BinaryOp(..)
             | mir::Rvalue::NullaryOp(..)
             | mir::Rvalue::UnaryOp(..)
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index ebcdb9461d0..323e1cefd58 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -1504,7 +1504,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         // This will also error if copying partial provenance is not supported.
         let provenance = src_alloc
             .provenance()
-            .prepare_copy(src_range, dest_offset, num_copies, self)
+            .prepare_copy(src_range, self)
             .map_err(|e| e.to_interp_error(src_alloc_id))?;
         // Prepare a copy of the initialization mask.
         let init = src_alloc.init_mask().prepare_copy(src_range);
@@ -1590,7 +1590,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
             num_copies,
         );
         // copy the provenance to the destination
-        dest_alloc.provenance_apply_copy(provenance);
+        dest_alloc.provenance_apply_copy(provenance, alloc_range(dest_offset, size), num_copies);
 
         interp_ok(())
     }
diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs
index 46950d60f8c..923e00ad4cf 100644
--- a/compiler/rustc_const_eval/src/interpret/step.rs
+++ b/compiler/rustc_const_eval/src/interpret/step.rs
@@ -17,7 +17,7 @@ use tracing::{info, instrument, trace};
 
 use super::{
     FnArg, FnVal, ImmTy, Immediate, InterpCx, InterpResult, Machine, MemPlaceMeta, PlaceTy,
-    Projectable, Scalar, interp_ok, throw_ub, throw_unsup_format,
+    Projectable, interp_ok, throw_ub, throw_unsup_format,
 };
 use crate::interpret::EnteredTraceSpan;
 use crate::{enter_trace_span, util};
@@ -225,12 +225,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 self.write_repeat(operand, &dest)?;
             }
 
-            Len(place) => {
-                let src = self.eval_place(place)?;
-                let len = src.len(self)?;
-                self.write_scalar(Scalar::from_target_usize(len, self), &dest)?;
-            }
-
             Ref(_, borrow_kind, place) => {
                 let src = self.eval_place(place)?;
                 let place = self.force_allocation(&src)?;
diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index 17da3ea83c8..e4e86bcc41a 100644
--- a/compiler/rustc_data_structures/src/lib.rs
+++ b/compiler/rustc_data_structures/src/lib.rs
@@ -34,6 +34,7 @@
 #![feature(sized_hierarchy)]
 #![feature(test)]
 #![feature(thread_id_value)]
+#![feature(trusted_len)]
 #![feature(type_alias_impl_trait)]
 #![feature(unwrap_infallible)]
 // tidy-alphabetical-end
diff --git a/compiler/rustc_data_structures/src/sorted_map.rs b/compiler/rustc_data_structures/src/sorted_map.rs
index c002d47815b..15e3e6ea4c3 100644
--- a/compiler/rustc_data_structures/src/sorted_map.rs
+++ b/compiler/rustc_data_structures/src/sorted_map.rs
@@ -1,6 +1,7 @@
 use std::borrow::Borrow;
 use std::cmp::Ordering;
 use std::fmt::Debug;
+use std::iter::TrustedLen;
 use std::mem;
 use std::ops::{Bound, Index, IndexMut, RangeBounds};
 
@@ -215,36 +216,40 @@ impl<K: Ord, V> SortedMap<K, V> {
     /// It is up to the caller to make sure that the elements are sorted by key
     /// and that there are no duplicates.
     #[inline]
-    pub fn insert_presorted(&mut self, elements: Vec<(K, V)>) {
-        if elements.is_empty() {
+    pub fn insert_presorted(
+        &mut self,
+        // We require `TrustedLen` to ensure that the `splice` below is actually efficient.
+        mut elements: impl Iterator<Item = (K, V)> + DoubleEndedIterator + TrustedLen,
+    ) {
+        let Some(first) = elements.next() else {
             return;
-        }
-
-        debug_assert!(elements.array_windows().all(|[fst, snd]| fst.0 < snd.0));
+        };
 
-        let start_index = self.lookup_index_for(&elements[0].0);
+        let start_index = self.lookup_index_for(&first.0);
 
         let elements = match start_index {
             Ok(index) => {
-                let mut elements = elements.into_iter();
-                self.data[index] = elements.next().unwrap();
-                elements
+                self.data[index] = first; // overwrite first element
+                elements.chain(None) // insert the rest below
             }
             Err(index) => {
-                if index == self.data.len() || elements.last().unwrap().0 < self.data[index].0 {
+                let last = elements.next_back();
+                if index == self.data.len()
+                    || last.as_ref().is_none_or(|l| l.0 < self.data[index].0)
+                {
                     // We can copy the whole range without having to mix with
                     // existing elements.
-                    self.data.splice(index..index, elements);
+                    self.data
+                        .splice(index..index, std::iter::once(first).chain(elements).chain(last));
                     return;
                 }
 
-                let mut elements = elements.into_iter();
-                self.data.insert(index, elements.next().unwrap());
-                elements
+                self.data.insert(index, first);
+                elements.chain(last) // insert the rest below
             }
         };
 
-        // Insert the rest
+        // Insert the rest. This is super inefficicent since each insertion copies the entire tail.
         for (k, v) in elements {
             self.insert(k, v);
         }
diff --git a/compiler/rustc_data_structures/src/sorted_map/tests.rs b/compiler/rustc_data_structures/src/sorted_map/tests.rs
index ea4d2f1feac..17d0d3cb170 100644
--- a/compiler/rustc_data_structures/src/sorted_map/tests.rs
+++ b/compiler/rustc_data_structures/src/sorted_map/tests.rs
@@ -171,7 +171,7 @@ fn test_insert_presorted_non_overlapping() {
     map.insert(2, 0);
     map.insert(8, 0);
 
-    map.insert_presorted(vec![(3, 0), (7, 0)]);
+    map.insert_presorted(vec![(3, 0), (7, 0)].into_iter());
 
     let expected = vec![2, 3, 7, 8];
     assert_eq!(keys(map), expected);
@@ -183,7 +183,7 @@ fn test_insert_presorted_first_elem_equal() {
     map.insert(2, 2);
     map.insert(8, 8);
 
-    map.insert_presorted(vec![(2, 0), (7, 7)]);
+    map.insert_presorted(vec![(2, 0), (7, 7)].into_iter());
 
     let expected = vec![(2, 0), (7, 7), (8, 8)];
     assert_eq!(elements(map), expected);
@@ -195,7 +195,7 @@ fn test_insert_presorted_last_elem_equal() {
     map.insert(2, 2);
     map.insert(8, 8);
 
-    map.insert_presorted(vec![(3, 3), (8, 0)]);
+    map.insert_presorted(vec![(3, 3), (8, 0)].into_iter());
 
     let expected = vec![(2, 2), (3, 3), (8, 0)];
     assert_eq!(elements(map), expected);
@@ -207,7 +207,7 @@ fn test_insert_presorted_shuffle() {
     map.insert(2, 2);
     map.insert(7, 7);
 
-    map.insert_presorted(vec![(1, 1), (3, 3), (8, 8)]);
+    map.insert_presorted(vec![(1, 1), (3, 3), (8, 8)].into_iter());
 
     let expected = vec![(1, 1), (2, 2), (3, 3), (7, 7), (8, 8)];
     assert_eq!(elements(map), expected);
@@ -219,7 +219,7 @@ fn test_insert_presorted_at_end() {
     map.insert(1, 1);
     map.insert(2, 2);
 
-    map.insert_presorted(vec![(3, 3), (8, 8)]);
+    map.insert_presorted(vec![(3, 3), (8, 8)].into_iter());
 
     let expected = vec![(1, 1), (2, 2), (3, 3), (8, 8)];
     assert_eq!(elements(map), expected);
diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml
index ae1dbd2cf51..46efa50cff3 100644
--- a/compiler/rustc_driver_impl/Cargo.toml
+++ b/compiler/rustc_driver_impl/Cargo.toml
@@ -74,6 +74,7 @@ ctrlc = "3.4.4"
 # tidy-alphabetical-start
 check_only = ['rustc_interface/check_only']
 llvm = ['rustc_interface/llvm']
+llvm_enzyme = ['rustc_interface/llvm_enzyme']
 max_level_info = ['rustc_log/max_level_info']
 rustc_randomized_layouts = [
     'rustc_index/rustc_randomized_layouts',
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 129ab7eccb5..99d6e93faa9 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -1057,6 +1057,14 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         rustc_std_internal_symbol, Normal, template!(Word), WarnFollowing,
         EncodeCrossCrate::No,
     ),
+    rustc_attr!(
+        rustc_objc_class, Normal, template!(NameValueStr: "ClassName"), ErrorPreceding,
+        EncodeCrossCrate::No,
+    ),
+    rustc_attr!(
+        rustc_objc_selector, Normal, template!(NameValueStr: "methodName"), ErrorPreceding,
+        EncodeCrossCrate::No,
+    ),
 
     // ==========================================================================
     // Internal attributes, Macro related:
diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs
index ea11a99efbc..0784675b177 100644
--- a/compiler/rustc_hir/src/attrs/data_structures.rs
+++ b/compiler/rustc_hir/src/attrs/data_structures.rs
@@ -444,9 +444,6 @@ pub enum AttributeKind {
         span: Span,
     },
 
-    /// Represents `#[rustc_coherence_is_core]`.
-    CoherenceIsCore,
-
     /// Represents `#[rustc_coinductive]`.
     Coinductive(Span),
 
@@ -594,6 +591,12 @@ pub enum AttributeKind {
     /// Represents `#[non_exhaustive]`
     NonExhaustive(Span),
 
+    /// Represents `#[rustc_objc_class]`
+    ObjcClass { classname: Symbol, span: Span },
+
+    /// Represents `#[rustc_objc_selector]`
+    ObjcSelector { methname: Symbol, span: Span },
+
     /// Represents `#[optimize(size|speed)]`
     Optimize(OptimizeAttr, Span),
 
@@ -633,6 +636,9 @@ pub enum AttributeKind {
     /// Represents `#[rustc_builtin_macro]`.
     RustcBuiltinMacro { builtin_name: Option<Symbol>, helper_attrs: ThinVec<Symbol>, span: Span },
 
+    /// Represents `#[rustc_coherence_is_core]`
+    RustcCoherenceIsCore(Span),
+
     /// Represents `#[rustc_layout_scalar_valid_range_end]`.
     RustcLayoutScalarValidRangeEnd(Box<u128>, Span),
 
diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs
index 55521c15854..563e7a58c6d 100644
--- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs
+++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs
@@ -26,7 +26,6 @@ impl AttributeKind {
             AsPtr(..) => Yes,
             AutomaticallyDerived(..) => Yes,
             BodyStability { .. } => No,
-            CoherenceIsCore => No,
             Coinductive(..) => No,
             Cold(..) => No,
             Confusables { .. } => Yes,
@@ -69,6 +68,8 @@ impl AttributeKind {
             NoMangle(..) => Yes, // Needed for rustdoc
             NoStd(..) => No,
             NonExhaustive(..) => Yes, // Needed for rustdoc
+            ObjcClass { .. } => No,
+            ObjcSelector { .. } => No,
             Optimize(..) => No,
             ParenSugar(..) => No,
             PassByValue(..) => Yes,
@@ -82,6 +83,7 @@ impl AttributeKind {
             RecursionLimit { .. } => No,
             Repr { .. } => No,
             RustcBuiltinMacro { .. } => Yes,
+            RustcCoherenceIsCore(..) => No,
             RustcLayoutScalarValidRangeEnd(..) => Yes,
             RustcLayoutScalarValidRangeStart(..) => Yes,
             RustcObjectLifetimeDefault => No,
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 63d0f400aef..e70d5505aae 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -70,6 +70,7 @@ pub mod intrinsic;
 mod region;
 pub mod wfcheck;
 
+use std::borrow::Cow;
 use std::num::NonZero;
 
 pub use check::{check_abi, check_custom_abi};
@@ -86,7 +87,7 @@ use rustc_middle::query::Providers;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::print::with_types_for_signature;
 use rustc_middle::ty::{
-    self, GenericArgs, GenericArgsRef, GenericParamDefKind, Ty, TyCtxt, TypingMode,
+    self, GenericArgs, GenericArgsRef, OutlivesPredicate, Region, Ty, TyCtxt, TypingMode,
 };
 use rustc_middle::{bug, span_bug};
 use rustc_session::parse::feature_err;
@@ -335,6 +336,7 @@ fn bounds_from_generic_predicates<'tcx>(
     assoc: ty::AssocItem,
 ) -> (String, String) {
     let mut types: FxIndexMap<Ty<'tcx>, Vec<DefId>> = FxIndexMap::default();
+    let mut regions: FxIndexMap<Region<'tcx>, Vec<Region<'tcx>>> = FxIndexMap::default();
     let mut projections = vec![];
     for (predicate, _) in predicates {
         debug!("predicate {:?}", predicate);
@@ -351,20 +353,23 @@ fn bounds_from_generic_predicates<'tcx>(
             ty::ClauseKind::Projection(projection_pred) => {
                 projections.push(bound_predicate.rebind(projection_pred));
             }
+            ty::ClauseKind::RegionOutlives(OutlivesPredicate(a, b)) => {
+                regions.entry(a).or_default().push(b);
+            }
             _ => {}
         }
     }
 
     let mut where_clauses = vec![];
     let generics = tcx.generics_of(assoc.def_id);
-    let types_str = generics
+    let params = generics
         .own_params
         .iter()
-        .filter(|p| matches!(p.kind, GenericParamDefKind::Type { synthetic: false, .. }))
-        .map(|p| {
-            // we just checked that it's a type, so the unwrap can't fail
-            let ty = tcx.mk_param_from_def(p).as_type().unwrap();
-            if let Some(bounds) = types.get(&ty) {
+        .filter(|p| !p.kind.is_synthetic())
+        .map(|p| match tcx.mk_param_from_def(p).kind() {
+            ty::GenericArgKind::Type(ty) => {
+                let bounds =
+                    types.get(&ty).map(Cow::Borrowed).unwrap_or_else(|| Cow::Owned(Vec::new()));
                 let mut bounds_str = vec![];
                 for bound in bounds.iter().copied() {
                     let mut projections_str = vec![];
@@ -377,7 +382,11 @@ fn bounds_from_generic_predicates<'tcx>(
                             projections_str.push(format!("{} = {}", name, p.term));
                         }
                     }
-                    let bound_def_path = tcx.def_path_str(bound);
+                    let bound_def_path = if tcx.is_lang_item(bound, LangItem::MetaSized) {
+                        String::from("?Sized")
+                    } else {
+                        tcx.def_path_str(bound)
+                    };
                     if projections_str.is_empty() {
                         where_clauses.push(format!("{}: {}", ty, bound_def_path));
                     } else {
@@ -393,8 +402,21 @@ fn bounds_from_generic_predicates<'tcx>(
                 } else {
                     format!("{}: {}", ty, bounds_str.join(" + "))
                 }
-            } else {
-                ty.to_string()
+            }
+            ty::GenericArgKind::Const(ct) => {
+                format!("const {ct}: {}", tcx.type_of(p.def_id).skip_binder())
+            }
+            ty::GenericArgKind::Lifetime(region) => {
+                if let Some(v) = regions.get(&region)
+                    && !v.is_empty()
+                {
+                    format!(
+                        "{region}: {}",
+                        v.into_iter().map(Region::to_string).collect::<Vec<_>>().join(" + ")
+                    )
+                } else {
+                    region.to_string()
+                }
             }
         })
         .collect::<Vec<_>>();
@@ -409,7 +431,7 @@ fn bounds_from_generic_predicates<'tcx>(
     }
 
     let generics =
-        if types_str.is_empty() { "".to_string() } else { format!("<{}>", types_str.join(", ")) };
+        if params.is_empty() { "".to_string() } else { format!("<{}>", params.join(", ")) };
 
     let where_clauses = if where_clauses.is_empty() {
         "".to_string()
diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs
index 2ba7ed46f92..43e6f5fe104 100644
--- a/compiler/rustc_hir_analysis/src/check/region.rs
+++ b/compiler/rustc_hir_analysis/src/check/region.rs
@@ -467,8 +467,12 @@ fn resolve_local<'tcx>(
     // A, but the inner rvalues `a()` and `b()` have an extended lifetime
     // due to rule C.
 
-    if let_kind == LetKind::Super {
-        if let Some(scope) = visitor.extended_super_lets.remove(&pat.unwrap().hir_id.local_id) {
+    let extend_initializer = match let_kind {
+        LetKind::Regular => true,
+        LetKind::Super
+            if let Some(scope) =
+                visitor.extended_super_lets.remove(&pat.unwrap().hir_id.local_id) =>
+        {
             // This expression was lifetime-extended by a parent let binding. E.g.
             //
             //     let a = {
@@ -481,7 +485,10 @@ fn resolve_local<'tcx>(
             // Processing of `let a` will have already decided to extend the lifetime of this
             // `super let` to its own var_scope. We use that scope.
             visitor.cx.var_parent = scope;
-        } else {
+            // Extend temporaries to live in the same scope as the parent `let`'s bindings.
+            true
+        }
+        LetKind::Super => {
             // This `super let` is not subject to lifetime extension from a parent let binding. E.g.
             //
             //     identity({ super let x = temp(); &x }).method();
@@ -493,10 +500,17 @@ fn resolve_local<'tcx>(
             if let Some(inner_scope) = visitor.cx.var_parent {
                 (visitor.cx.var_parent, _) = visitor.scope_tree.default_temporary_scope(inner_scope)
             }
+            // Don't lifetime-extend child `super let`s or block tail expressions' temporaries in
+            // the initializer when this `super let` is not itself extended by a parent `let`
+            // (#145784). Block tail expressions are temporary drop scopes in Editions 2024 and
+            // later, their temps shouldn't outlive the block in e.g. `f(pin!({ &temp() }))`.
+            false
         }
-    }
+    };
 
-    if let Some(expr) = init {
+    if let Some(expr) = init
+        && extend_initializer
+    {
         record_rvalue_scope_if_borrow_expr(visitor, expr, visitor.cx.var_parent);
 
         if let Some(pat) = pat {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 1998a1884b7..a5c6a7f34ef 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -3021,6 +3021,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         )
                     {
                         let deref_kind = if checked_ty.is_box() {
+                            // detect Box::new(..)
+                            if let ExprKind::Call(box_new, [_]) = expr.kind
+                                && let ExprKind::Path(qpath) = &box_new.kind
+                                && let Res::Def(DefKind::AssocFn, fn_id) =
+                                    self.typeck_results.borrow().qpath_res(qpath, box_new.hir_id)
+                                && let Some(impl_id) = self.tcx.inherent_impl_of_assoc(fn_id)
+                                && self.tcx.type_of(impl_id).skip_binder().is_box()
+                                && self.tcx.item_name(fn_id) == sym::new
+                            {
+                                let l_paren = self.tcx.sess.source_map().next_point(box_new.span);
+                                let r_paren = self.tcx.sess.source_map().end_point(expr.span);
+                                return Some((
+                                    vec![
+                                        (box_new.span.to(l_paren), String::new()),
+                                        (r_paren, String::new()),
+                                    ],
+                                    "consider removing the Box".to_string(),
+                                    Applicability::MachineApplicable,
+                                    false,
+                                    false,
+                                ));
+                            }
                             "unboxing the value"
                         } else if checked_ty.is_ref() {
                             "dereferencing the borrow"
diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml
index 473ac5e0cea..f0836c47740 100644
--- a/compiler/rustc_interface/Cargo.toml
+++ b/compiler/rustc_interface/Cargo.toml
@@ -58,4 +58,5 @@ rustc_abi = { path = "../rustc_abi" }
 # tidy-alphabetical-start
 check_only = ['rustc_codegen_llvm?/check_only']
 llvm = ['dep:rustc_codegen_llvm']
+llvm_enzyme = ['rustc_builtin_macros/llvm_enzyme', 'rustc_codegen_llvm/llvm_enzyme']
 # tidy-alphabetical-end
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 22d89d24612..edbbfba4f34 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -843,6 +843,10 @@ trait UnusedDelimLint {
                 && !snip.ends_with(' ')
             {
                 " "
+            } else if let Ok(snip) = sm.span_to_prev_source(value_span)
+                && snip.ends_with(|c: char| c.is_alphanumeric())
+            {
+                " "
             } else {
                 ""
             };
@@ -852,6 +856,10 @@ trait UnusedDelimLint {
                 && !snip.starts_with(' ')
             {
                 " "
+            } else if let Ok(snip) = sm.span_to_prev_source(value_span)
+                && snip.starts_with(|c: char| c.is_alphanumeric())
+            {
+                " "
             } else {
                 ""
             };
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index 91d11ba317a..ab5d5c03e81 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -344,7 +344,6 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
   Options.EmitStackSizeSection = EmitStackSizeSection;
 
   if (ArgsCstrBuff != nullptr) {
-#if LLVM_VERSION_GE(20, 0)
     size_t buffer_offset = 0;
     assert(ArgsCstrBuff[ArgsCstrBuffLen - 1] == '\0');
     auto Arg0 = std::string(ArgsCstrBuff);
@@ -362,33 +361,6 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
     OS.flush();
     Options.MCOptions.Argv0 = Arg0;
     Options.MCOptions.CommandlineArgs = CommandlineArgs;
-#else
-    size_t buffer_offset = 0;
-    assert(ArgsCstrBuff[ArgsCstrBuffLen - 1] == '\0');
-
-    const size_t arg0_len = std::strlen(ArgsCstrBuff);
-    char *arg0 = new char[arg0_len + 1];
-    memcpy(arg0, ArgsCstrBuff, arg0_len);
-    arg0[arg0_len] = '\0';
-    buffer_offset += arg0_len + 1;
-
-    const size_t num_cmd_arg_strings = std::count(
-        &ArgsCstrBuff[buffer_offset], &ArgsCstrBuff[ArgsCstrBuffLen], '\0');
-
-    std::string *cmd_arg_strings = new std::string[num_cmd_arg_strings];
-    for (size_t i = 0; i < num_cmd_arg_strings; ++i) {
-      assert(buffer_offset < ArgsCstrBuffLen);
-      const size_t len = std::strlen(ArgsCstrBuff + buffer_offset);
-      cmd_arg_strings[i] = std::string(&ArgsCstrBuff[buffer_offset], len);
-      buffer_offset += len + 1;
-    }
-
-    assert(buffer_offset == ArgsCstrBuffLen);
-
-    Options.MCOptions.Argv0 = arg0;
-    Options.MCOptions.CommandLineArgs =
-        llvm::ArrayRef<std::string>(cmd_arg_strings, num_cmd_arg_strings);
-#endif
   }
 
 #if LLVM_VERSION_GE(21, 0)
@@ -402,12 +374,6 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
 }
 
 extern "C" void LLVMRustDisposeTargetMachine(LLVMTargetMachineRef TM) {
-#if LLVM_VERSION_LT(20, 0)
-  MCTargetOptions &MCOptions = unwrap(TM)->Options.MCOptions;
-  delete[] MCOptions.Argv0;
-  delete[] MCOptions.CommandLineArgs.data();
-#endif
-
   delete unwrap(TM);
 }
 
@@ -688,14 +654,9 @@ extern "C" LLVMRustResult LLVMRustOptimize(
   // the PassBuilder does not create a pipeline.
   std::vector<std::function<void(ModulePassManager &, OptimizationLevel)>>
       PipelineStartEPCallbacks;
-#if LLVM_VERSION_GE(20, 0)
   std::vector<std::function<void(ModulePassManager &, OptimizationLevel,
                                  ThinOrFullLTOPhase)>>
       OptimizerLastEPCallbacks;
-#else
-  std::vector<std::function<void(ModulePassManager &, OptimizationLevel)>>
-      OptimizerLastEPCallbacks;
-#endif
 
   if (!IsLinkerPluginLTO && SanitizerOptions && SanitizerOptions->SanitizeCFI &&
       !NoPrepopulatePasses) {
@@ -747,12 +708,8 @@ extern "C" LLVMRustResult LLVMRustOptimize(
           SanitizerOptions->SanitizeDataFlowABIList +
               SanitizerOptions->SanitizeDataFlowABIListLen);
       OptimizerLastEPCallbacks.push_back(
-#if LLVM_VERSION_GE(20, 0)
           [ABIListFiles](ModulePassManager &MPM, OptimizationLevel Level,
                          ThinOrFullLTOPhase phase) {
-#else
-          [ABIListFiles](ModulePassManager &MPM, OptimizationLevel Level) {
-#endif
             MPM.addPass(DataFlowSanitizerPass(ABIListFiles));
           });
     }
@@ -763,66 +720,48 @@ extern "C" LLVMRustResult LLVMRustOptimize(
           SanitizerOptions->SanitizeMemoryRecover,
           /*CompileKernel=*/false,
           /*EagerChecks=*/true);
-      OptimizerLastEPCallbacks.push_back(
-#if LLVM_VERSION_GE(20, 0)
-          [Options](ModulePassManager &MPM, OptimizationLevel Level,
-                    ThinOrFullLTOPhase phase) {
-#else
-          [Options](ModulePassManager &MPM, OptimizationLevel Level) {
-#endif
-            MPM.addPass(MemorySanitizerPass(Options));
-          });
+      OptimizerLastEPCallbacks.push_back([Options](ModulePassManager &MPM,
+                                                   OptimizationLevel Level,
+                                                   ThinOrFullLTOPhase phase) {
+        MPM.addPass(MemorySanitizerPass(Options));
+      });
     }
 
     if (SanitizerOptions->SanitizeThread) {
-      OptimizerLastEPCallbacks.push_back(
-#if LLVM_VERSION_GE(20, 0)
-          [](ModulePassManager &MPM, OptimizationLevel Level,
-             ThinOrFullLTOPhase phase) {
-#else
-          [](ModulePassManager &MPM, OptimizationLevel Level) {
-#endif
-            MPM.addPass(ModuleThreadSanitizerPass());
-            MPM.addPass(
-                createModuleToFunctionPassAdaptor(ThreadSanitizerPass()));
-          });
+      OptimizerLastEPCallbacks.push_back([](ModulePassManager &MPM,
+                                            OptimizationLevel Level,
+                                            ThinOrFullLTOPhase phase) {
+        MPM.addPass(ModuleThreadSanitizerPass());
+        MPM.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass()));
+      });
     }
 
     if (SanitizerOptions->SanitizeAddress ||
         SanitizerOptions->SanitizeKernelAddress) {
-      OptimizerLastEPCallbacks.push_back(
-#if LLVM_VERSION_GE(20, 0)
-          [SanitizerOptions, TM](ModulePassManager &MPM,
-                                 OptimizationLevel Level,
-                                 ThinOrFullLTOPhase phase) {
-#else
-          [SanitizerOptions, TM](ModulePassManager &MPM,
-                                 OptimizationLevel Level) {
-#endif
-            auto CompileKernel = SanitizerOptions->SanitizeKernelAddress;
-            AddressSanitizerOptions opts = AddressSanitizerOptions{
-                CompileKernel,
-                SanitizerOptions->SanitizeAddressRecover ||
-                    SanitizerOptions->SanitizeKernelAddressRecover,
-                /*UseAfterScope=*/true,
-                AsanDetectStackUseAfterReturnMode::Runtime,
-            };
-            MPM.addPass(AddressSanitizerPass(
-                opts,
-                /*UseGlobalGC*/ true,
-                // UseOdrIndicator should be false on windows machines
-                // https://reviews.llvm.org/D137227
-                !TM->getTargetTriple().isOSWindows()));
-          });
+      OptimizerLastEPCallbacks.push_back([SanitizerOptions,
+                                          TM](ModulePassManager &MPM,
+                                              OptimizationLevel Level,
+                                              ThinOrFullLTOPhase phase) {
+        auto CompileKernel = SanitizerOptions->SanitizeKernelAddress;
+        AddressSanitizerOptions opts = AddressSanitizerOptions{
+            CompileKernel,
+            SanitizerOptions->SanitizeAddressRecover ||
+                SanitizerOptions->SanitizeKernelAddressRecover,
+            /*UseAfterScope=*/true,
+            AsanDetectStackUseAfterReturnMode::Runtime,
+        };
+        MPM.addPass(
+            AddressSanitizerPass(opts,
+                                 /*UseGlobalGC*/ true,
+                                 // UseOdrIndicator should be false on windows
+                                 // machines https://reviews.llvm.org/D137227
+                                 !TM->getTargetTriple().isOSWindows()));
+      });
     }
     if (SanitizerOptions->SanitizeHWAddress) {
       OptimizerLastEPCallbacks.push_back(
-#if LLVM_VERSION_GE(20, 0)
           [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level,
                              ThinOrFullLTOPhase phase) {
-#else
-          [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) {
-#endif
             HWAddressSanitizerOptions opts(
                 /*CompileKernel=*/false,
                 SanitizerOptions->SanitizeHWAddressRecover,
@@ -904,11 +843,7 @@ extern "C" LLVMRustResult LLVMRustOptimize(
     for (const auto &C : PipelineStartEPCallbacks)
       C(MPM, OptLevel);
     for (const auto &C : OptimizerLastEPCallbacks)
-#if LLVM_VERSION_GE(20, 0)
       C(MPM, OptLevel, ThinOrFullLTOPhase::None);
-#else
-      C(MPM, OptLevel);
-#endif
   }
 
   if (ExtraPassesLen) {
@@ -1185,11 +1120,7 @@ struct LLVMRustThinLTOData {
 
   // Not 100% sure what these are, but they impact what's internalized and
   // what's inlined across modules, I believe.
-#if LLVM_VERSION_GE(20, 0)
   FunctionImporter::ImportListsTy ImportLists;
-#else
-  DenseMap<StringRef, FunctionImporter::ImportMapTy> ImportLists;
-#endif
   DenseMap<StringRef, FunctionImporter::ExportSetTy> ExportLists;
   DenseMap<StringRef, GVSummaryMapTy> ModuleToDefinedGVSummaries;
   StringMap<std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>> ResolvedODR;
@@ -1531,13 +1462,8 @@ extern "C" void LLVMRustComputeLTOCacheKey(RustStringRef KeyOut,
   const auto &ExportList = Data->ExportLists.lookup(ModId);
   const auto &ResolvedODR = Data->ResolvedODR.lookup(ModId);
   const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(ModId);
-#if LLVM_VERSION_GE(20, 0)
   DenseSet<GlobalValue::GUID> CfiFunctionDefs;
   DenseSet<GlobalValue::GUID> CfiFunctionDecls;
-#else
-  std::set<GlobalValue::GUID> CfiFunctionDefs;
-  std::set<GlobalValue::GUID> CfiFunctionDecls;
-#endif
 
   // Based on the 'InProcessThinBackend' constructor in LLVM
 #if LLVM_VERSION_GE(21, 0)
@@ -1556,15 +1482,9 @@ extern "C" void LLVMRustComputeLTOCacheKey(RustStringRef KeyOut,
         GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Name)));
 #endif
 
-#if LLVM_VERSION_GE(20, 0)
   Key = llvm::computeLTOCacheKey(conf, Data->Index, ModId, ImportList,
                                  ExportList, ResolvedODR, DefinedGlobals,
                                  CfiFunctionDefs, CfiFunctionDecls);
-#else
-  llvm::computeLTOCacheKey(Key, conf, Data->Index, ModId, ImportList,
-                           ExportList, ResolvedODR, DefinedGlobals,
-                           CfiFunctionDefs, CfiFunctionDecls);
-#endif
 
   auto OS = RawRustStringOstream(KeyOut);
   OS << Key.str();
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index 361a5f76551..b4ca641674f 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -1026,13 +1026,6 @@ LLVMRustDIBuilderCreateFile(LLVMDIBuilderRef Builder, const char *Filename,
                                           CSInfo, oSource));
 }
 
-extern "C" LLVMMetadataRef
-LLVMRustDIBuilderCreateSubroutineType(LLVMDIBuilderRef Builder,
-                                      LLVMMetadataRef ParameterTypes) {
-  return wrap(unwrap(Builder)->createSubroutineType(
-      DITypeRefArray(unwrap<MDTuple>(ParameterTypes))));
-}
-
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
     LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
     size_t NameLen, const char *LinkageName, size_t LinkageNameLen,
@@ -1072,14 +1065,6 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMethod(
 }
 
 extern "C" LLVMMetadataRef
-LLVMRustDIBuilderCreateBasicType(LLVMDIBuilderRef Builder, const char *Name,
-                                 size_t NameLen, uint64_t SizeInBits,
-                                 unsigned Encoding) {
-  return wrap(unwrap(Builder)->createBasicType(StringRef(Name, NameLen),
-                                               SizeInBits, Encoding));
-}
-
-extern "C" LLVMMetadataRef
 LLVMRustDIBuilderCreateTypedef(LLVMDIBuilderRef Builder, LLVMMetadataRef Type,
                                const char *Name, size_t NameLen,
                                LLVMMetadataRef File, unsigned LineNo,
@@ -1089,29 +1074,6 @@ LLVMRustDIBuilderCreateTypedef(LLVMDIBuilderRef Builder, LLVMMetadataRef Type,
       LineNo, unwrapDIPtr<DIScope>(Scope)));
 }
 
-extern "C" LLVMMetadataRef LLVMRustDIBuilderCreatePointerType(
-    LLVMDIBuilderRef Builder, LLVMMetadataRef PointeeTy, uint64_t SizeInBits,
-    uint32_t AlignInBits, unsigned AddressSpace, const char *Name,
-    size_t NameLen) {
-  return wrap(unwrap(Builder)->createPointerType(
-      unwrapDI<DIType>(PointeeTy), SizeInBits, AlignInBits, AddressSpace,
-      StringRef(Name, NameLen)));
-}
-
-extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStructType(
-    LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
-    size_t NameLen, LLVMMetadataRef File, unsigned LineNumber,
-    uint64_t SizeInBits, uint32_t AlignInBits, LLVMDIFlags Flags,
-    LLVMMetadataRef DerivedFrom, LLVMMetadataRef Elements, unsigned RunTimeLang,
-    LLVMMetadataRef VTableHolder, const char *UniqueId, size_t UniqueIdLen) {
-  return wrap(unwrap(Builder)->createStructType(
-      unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
-      unwrapDI<DIFile>(File), LineNumber, SizeInBits, AlignInBits,
-      fromRust(Flags), unwrapDI<DIType>(DerivedFrom),
-      DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
-      unwrapDI<DIType>(VTableHolder), StringRef(UniqueId, UniqueIdLen)));
-}
-
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantPart(
     LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
     size_t NameLen, LLVMMetadataRef File, unsigned LineNumber,
@@ -1219,15 +1181,6 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariable(
 }
 
 extern "C" LLVMMetadataRef
-LLVMRustDIBuilderCreateArrayType(LLVMDIBuilderRef Builder, uint64_t Size,
-                                 uint32_t AlignInBits, LLVMMetadataRef Ty,
-                                 LLVMMetadataRef Subscripts) {
-  return wrap(unwrap(Builder)->createArrayType(
-      Size, AlignInBits, unwrapDI<DIType>(Ty),
-      DINodeArray(unwrapDI<MDTuple>(Subscripts))));
-}
-
-extern "C" LLVMMetadataRef
 LLVMRustDIBuilderGetOrCreateSubrange(LLVMDIBuilderRef Builder, int64_t Lo,
                                      int64_t Count) {
   return wrap(unwrap(Builder)->getOrCreateSubrange(Lo, Count));
@@ -1275,19 +1228,6 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType(
       /* RunTimeLang */ 0, "", IsScoped));
 }
 
-extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateUnionType(
-    LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
-    size_t NameLen, LLVMMetadataRef File, unsigned LineNumber,
-    uint64_t SizeInBits, uint32_t AlignInBits, LLVMDIFlags Flags,
-    LLVMMetadataRef Elements, unsigned RunTimeLang, const char *UniqueId,
-    size_t UniqueIdLen) {
-  return wrap(unwrap(Builder)->createUnionType(
-      unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
-      unwrapDI<DIFile>(File), LineNumber, SizeInBits, AlignInBits,
-      fromRust(Flags), DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
-      StringRef(UniqueId, UniqueIdLen)));
-}
-
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTemplateTypeParameter(
     LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
     size_t NameLen, LLVMMetadataRef Ty) {
diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs
index 4370816d38e..430cd329408 100644
--- a/compiler/rustc_middle/src/hir/map.rs
+++ b/compiler/rustc_middle/src/hir/map.rs
@@ -370,7 +370,7 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 
     pub fn hir_rustc_coherence_is_core(self) -> bool {
-        find_attr!(self.hir_krate_attrs(), AttributeKind::CoherenceIsCore)
+        find_attr!(self.hir_krate_attrs(), AttributeKind::RustcCoherenceIsCore(..))
     }
 
     pub fn hir_get_module(self, module: LocalModDefId) -> (&'tcx Mod<'tcx>, Span, HirId) {
diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
index 8b4503073b0..f0d96c6ac89 100644
--- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
+++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
@@ -69,6 +69,10 @@ pub struct CodegenFnAttrs {
     /// The `#[patchable_function_entry(...)]` attribute. Indicates how many nops should be around
     /// the function entry.
     pub patchable_function_entry: Option<PatchableFunctionEntry>,
+    /// The `#[rustc_objc_class = "..."]` attribute.
+    pub objc_class: Option<Symbol>,
+    /// The `#[rustc_objc_selector = "..."]` attribute.
+    pub objc_selector: Option<Symbol>,
 }
 
 #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable, PartialEq, Eq)]
@@ -185,6 +189,8 @@ impl CodegenFnAttrs {
             instruction_set: None,
             alignment: None,
             patchable_function_entry: None,
+            objc_class: None,
+            objc_selector: None,
         }
     }
 
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs
index 67962813ae4..8e603ce1b91 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs
@@ -849,8 +849,13 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
     ///
     /// This is dangerous to use as it can violate internal `Allocation` invariants!
     /// It only exists to support an efficient implementation of `mem_copy_repeatedly`.
-    pub fn provenance_apply_copy(&mut self, copy: ProvenanceCopy<Prov>) {
-        self.provenance.apply_copy(copy)
+    pub fn provenance_apply_copy(
+        &mut self,
+        copy: ProvenanceCopy<Prov>,
+        range: AllocRange,
+        repeat: u64,
+    ) {
+        self.provenance.apply_copy(copy, range, repeat)
     }
 
     /// Applies a previously prepared copy of the init mask.
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs
index 720e58d7aa0..67baf63bbfa 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs
@@ -278,90 +278,78 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
 
 /// A partial, owned list of provenance to transfer into another allocation.
 ///
-/// Offsets are already adjusted to the destination allocation.
+/// Offsets are relative to the beginning of the copied range.
 pub struct ProvenanceCopy<Prov> {
-    dest_ptrs: Option<Box<[(Size, Prov)]>>,
-    dest_bytes: Option<Box<[(Size, (Prov, u8))]>>,
+    ptrs: Box<[(Size, Prov)]>,
+    bytes: Box<[(Size, (Prov, u8))]>,
 }
 
 impl<Prov: Provenance> ProvenanceMap<Prov> {
     pub fn prepare_copy(
         &self,
-        src: AllocRange,
-        dest: Size,
-        count: u64,
+        range: AllocRange,
         cx: &impl HasDataLayout,
     ) -> AllocResult<ProvenanceCopy<Prov>> {
-        let shift_offset = move |idx, offset| {
-            // compute offset for current repetition
-            let dest_offset = dest + src.size * idx; // `Size` operations
-            // shift offsets from source allocation to destination allocation
-            (offset - src.start) + dest_offset // `Size` operations
-        };
+        let shift_offset = move |offset| offset - range.start;
         let ptr_size = cx.data_layout().pointer_size();
 
         // # Pointer-sized provenances
         // Get the provenances that are entirely within this range.
         // (Different from `range_get_ptrs` which asks if they overlap the range.)
         // Only makes sense if we are copying at least one pointer worth of bytes.
-        let mut dest_ptrs_box = None;
-        if src.size >= ptr_size {
-            let adjusted_end = Size::from_bytes(src.end().bytes() - (ptr_size.bytes() - 1));
-            let ptrs = self.ptrs.range(src.start..adjusted_end);
-            // If `count` is large, this is rather wasteful -- we are allocating a big array here, which
-            // is mostly filled with redundant information since it's just N copies of the same `Prov`s
-            // at slightly adjusted offsets. The reason we do this is so that in `mark_provenance_range`
-            // we can use `insert_presorted`. That wouldn't work with an `Iterator` that just produces
-            // the right sequence of provenance for all N copies.
-            // Basically, this large array would have to be created anyway in the target allocation.
-            let mut dest_ptrs = Vec::with_capacity(ptrs.len() * (count as usize));
-            for i in 0..count {
-                dest_ptrs
-                    .extend(ptrs.iter().map(|&(offset, reloc)| (shift_offset(i, offset), reloc)));
-            }
-            debug_assert_eq!(dest_ptrs.len(), dest_ptrs.capacity());
-            dest_ptrs_box = Some(dest_ptrs.into_boxed_slice());
+        let mut ptrs_box: Box<[_]> = Box::new([]);
+        if range.size >= ptr_size {
+            let adjusted_end = Size::from_bytes(range.end().bytes() - (ptr_size.bytes() - 1));
+            let ptrs = self.ptrs.range(range.start..adjusted_end);
+            ptrs_box = ptrs.iter().map(|&(offset, reloc)| (shift_offset(offset), reloc)).collect();
         };
 
         // # Byte-sized provenances
         // This includes the existing bytewise provenance in the range, and ptr provenance
         // that overlaps with the begin/end of the range.
-        let mut dest_bytes_box = None;
-        let begin_overlap = self.range_ptrs_get(alloc_range(src.start, Size::ZERO), cx).first();
-        let end_overlap = self.range_ptrs_get(alloc_range(src.end(), Size::ZERO), cx).first();
+        let mut bytes_box: Box<[_]> = Box::new([]);
+        let begin_overlap = self.range_ptrs_get(alloc_range(range.start, Size::ZERO), cx).first();
+        let end_overlap = self.range_ptrs_get(alloc_range(range.end(), Size::ZERO), cx).first();
         // We only need to go here if there is some overlap or some bytewise provenance.
         if begin_overlap.is_some() || end_overlap.is_some() || self.bytes.is_some() {
             let mut bytes: Vec<(Size, (Prov, u8))> = Vec::new();
             // First, if there is a part of a pointer at the start, add that.
             if let Some(entry) = begin_overlap {
                 trace!("start overlapping entry: {entry:?}");
-                // For really small copies, make sure we don't run off the end of the `src` range.
-                let entry_end = cmp::min(entry.0 + ptr_size, src.end());
-                for offset in src.start..entry_end {
-                    bytes.push((offset, (entry.1, (offset - entry.0).bytes() as u8)));
+                // For really small copies, make sure we don't run off the end of the range.
+                let entry_end = cmp::min(entry.0 + ptr_size, range.end());
+                for offset in range.start..entry_end {
+                    bytes.push((shift_offset(offset), (entry.1, (offset - entry.0).bytes() as u8)));
                 }
             } else {
                 trace!("no start overlapping entry");
             }
 
             // Then the main part, bytewise provenance from `self.bytes`.
-            bytes.extend(self.range_bytes_get(src));
+            bytes.extend(
+                self.range_bytes_get(range)
+                    .iter()
+                    .map(|&(offset, reloc)| (shift_offset(offset), reloc)),
+            );
 
             // And finally possibly parts of a pointer at the end.
             if let Some(entry) = end_overlap {
                 trace!("end overlapping entry: {entry:?}");
-                // For really small copies, make sure we don't start before `src` does.
-                let entry_start = cmp::max(entry.0, src.start);
-                for offset in entry_start..src.end() {
+                // For really small copies, make sure we don't start before `range` does.
+                let entry_start = cmp::max(entry.0, range.start);
+                for offset in entry_start..range.end() {
                     if bytes.last().is_none_or(|bytes_entry| bytes_entry.0 < offset) {
                         // The last entry, if it exists, has a lower offset than us, so we
                         // can add it at the end and remain sorted.
-                        bytes.push((offset, (entry.1, (offset - entry.0).bytes() as u8)));
+                        bytes.push((
+                            shift_offset(offset),
+                            (entry.1, (offset - entry.0).bytes() as u8),
+                        ));
                     } else {
                         // There already is an entry for this offset in there! This can happen when the
                         // start and end range checks actually end up hitting the same pointer, so we
                         // already added this in the "pointer at the start" part above.
-                        assert!(entry.0 <= src.start);
+                        assert!(entry.0 <= range.start);
                     }
                 }
             } else {
@@ -372,33 +360,40 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
             if !bytes.is_empty() && !Prov::OFFSET_IS_ADDR {
                 // FIXME(#146291): We need to ensure that we don't mix different pointers with
                 // the same provenance.
-                return Err(AllocError::ReadPartialPointer(src.start));
+                return Err(AllocError::ReadPartialPointer(range.start));
             }
 
             // And again a buffer for the new list on the target side.
-            let mut dest_bytes = Vec::with_capacity(bytes.len() * (count as usize));
-            for i in 0..count {
-                dest_bytes
-                    .extend(bytes.iter().map(|&(offset, reloc)| (shift_offset(i, offset), reloc)));
-            }
-            debug_assert_eq!(dest_bytes.len(), dest_bytes.capacity());
-            dest_bytes_box = Some(dest_bytes.into_boxed_slice());
+            bytes_box = bytes.into_boxed_slice();
         }
 
-        Ok(ProvenanceCopy { dest_ptrs: dest_ptrs_box, dest_bytes: dest_bytes_box })
+        Ok(ProvenanceCopy { ptrs: ptrs_box, bytes: bytes_box })
     }
 
     /// Applies a provenance copy.
     /// The affected range, as defined in the parameters to `prepare_copy` is expected
     /// to be clear of provenance.
-    pub fn apply_copy(&mut self, copy: ProvenanceCopy<Prov>) {
-        if let Some(dest_ptrs) = copy.dest_ptrs {
-            self.ptrs.insert_presorted(dest_ptrs.into());
+    pub fn apply_copy(&mut self, copy: ProvenanceCopy<Prov>, range: AllocRange, repeat: u64) {
+        let shift_offset = |idx: u64, offset: Size| offset + range.start + idx * range.size;
+        if !copy.ptrs.is_empty() {
+            // We want to call `insert_presorted` only once so that, if possible, the entries
+            // after the range we insert are moved back only once.
+            let chunk_len = copy.ptrs.len() as u64;
+            self.ptrs.insert_presorted((0..chunk_len * repeat).map(|i| {
+                let chunk = i / chunk_len;
+                let (offset, reloc) = copy.ptrs[(i % chunk_len) as usize];
+                (shift_offset(chunk, offset), reloc)
+            }));
         }
-        if let Some(dest_bytes) = copy.dest_bytes
-            && !dest_bytes.is_empty()
-        {
-            self.bytes.get_or_insert_with(Box::default).insert_presorted(dest_bytes.into());
+        if !copy.bytes.is_empty() {
+            let chunk_len = copy.bytes.len() as u64;
+            self.bytes.get_or_insert_with(Box::default).insert_presorted(
+                (0..chunk_len * repeat).map(|i| {
+                    let chunk = i / chunk_len;
+                    let (offset, reloc) = copy.bytes[(i % chunk_len) as usize];
+                    (shift_offset(chunk, offset), reloc)
+                }),
+            );
         }
     }
 }
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index da2245b12d2..28142382b13 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -471,7 +471,7 @@ impl<'tcx> Body<'tcx> {
 
     /// Returns an iterator over all function arguments.
     #[inline]
-    pub fn args_iter(&self) -> impl Iterator<Item = Local> + ExactSizeIterator {
+    pub fn args_iter(&self) -> impl Iterator<Item = Local> + ExactSizeIterator + use<> {
         (1..self.arg_count + 1).map(Local::new)
     }
 
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index f9d0a5f0a3b..96148fd5b92 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -1062,7 +1062,6 @@ impl<'tcx> Debug for Rvalue<'tcx> {
                 pretty_print_const(b, fmt, false)?;
                 write!(fmt, "]")
             }
-            Len(ref a) => write!(fmt, "Len({a:?})"),
             Cast(ref kind, ref place, ref ty) => {
                 with_no_trimmed_paths!(write!(fmt, "{place:?} as {ty} ({kind:?})"))
             }
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index 466b9c7a3c2..a509c40c89c 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -17,7 +17,7 @@ use crate::ty::{self, CoroutineArgsExt, OpaqueHiddenType, Ty};
 rustc_index::newtype_index! {
     #[derive(HashStable)]
     #[encodable]
-    #[debug_format = "_{}"]
+    #[debug_format = "_s{}"]
     pub struct CoroutineSavedLocal {}
 }
 
diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs
index ec2a8e86077..28294b47e90 100644
--- a/compiler/rustc_middle/src/mir/statement.rs
+++ b/compiler/rustc_middle/src/mir/statement.rs
@@ -697,7 +697,6 @@ impl<'tcx> Rvalue<'tcx> {
             | Rvalue::Ref(_, _, _)
             | Rvalue::ThreadLocalRef(_)
             | Rvalue::RawPtr(_, _)
-            | Rvalue::Len(_)
             | Rvalue::Cast(
                 CastKind::IntToInt
                 | CastKind::FloatToInt
@@ -739,7 +738,6 @@ impl<'tcx> Rvalue<'tcx> {
                 let place_ty = place.ty(local_decls, tcx).ty;
                 Ty::new_ptr(tcx, place_ty, kind.to_mutbl_lossy())
             }
-            Rvalue::Len(..) => tcx.types.usize,
             Rvalue::Cast(.., ty) => ty,
             Rvalue::BinaryOp(op, box (ref lhs, ref rhs)) => {
                 let lhs_ty = lhs.ty(local_decls, tcx);
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index d402ea4b04f..e6c8512564e 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -1407,16 +1407,6 @@ pub enum Rvalue<'tcx> {
     /// model.
     RawPtr(RawPtrKind, Place<'tcx>),
 
-    /// Yields the length of the place, as a `usize`.
-    ///
-    /// If the type of the place is an array, this is the array length. For slices (`[T]`, not
-    /// `&[T]`) this accesses the place's metadata to determine the length. This rvalue is
-    /// ill-formed for places of other types.
-    ///
-    /// This cannot be a `UnOp(PtrMetadata, _)` because that expects a value, and we only
-    /// have a place, and `UnOp(PtrMetadata, RawPtr(place))` is not a thing.
-    Len(Place<'tcx>),
-
     /// Performs essentially all of the casts that can be performed via `as`.
     ///
     /// This allows for casts from/to a variety of types.
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index b498b7b8912..81df239dee4 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -717,14 +717,6 @@ macro_rules! make_mir_visitor {
                         self.visit_place(path, ctx, location);
                     }
 
-                    Rvalue::Len(path) => {
-                        self.visit_place(
-                            path,
-                            PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
-                            location
-                        );
-                    }
-
                     Rvalue::Cast(_cast_kind, operand, ty) => {
                         self.visit_operand(operand, location);
                         self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
@@ -1483,3 +1475,20 @@ impl PlaceContext {
         }
     }
 }
+
+/// Small utility to visit places and locals without manually implementing a full visitor.
+pub struct VisitPlacesWith<F>(pub F);
+
+impl<'tcx, F> Visitor<'tcx> for VisitPlacesWith<F>
+where
+    F: FnMut(Place<'tcx>, PlaceContext),
+{
+    fn visit_local(&mut self, local: Local, ctxt: PlaceContext, _: Location) {
+        (self.0)(local.into(), ctxt);
+    }
+
+    fn visit_place(&mut self, place: &Place<'tcx>, ctxt: PlaceContext, location: Location) {
+        (self.0)(*place, ctxt);
+        self.visit_projection(place.as_ref(), ctxt, location);
+    }
+}
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 029586a9c55..b79b67c5927 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -1359,6 +1359,7 @@ impl<'tcx> Ty<'tcx> {
     /// 2229 drop reorder migration analysis.
     #[inline]
     pub fn has_significant_drop(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> bool {
+        assert!(!self.has_non_region_infer());
         // Avoid querying in simple cases.
         match needs_drop_components(tcx, self) {
             Err(AlwaysRequiresDrop) => true,
@@ -1371,14 +1372,6 @@ impl<'tcx> Ty<'tcx> {
                     _ => self,
                 };
 
-                // FIXME(#86868): We should be canonicalizing, or else moving this to a method of inference
-                // context, or *something* like that, but for now just avoid passing inference
-                // variables to queries that can't cope with them. Instead, conservatively
-                // return "true" (may change drop order).
-                if query_ty.has_infer() {
-                    return true;
-                }
-
                 // This doesn't depend on regions, so try to minimize distinct
                 // query keys used.
                 let erased = tcx.normalize_erasing_regions(typing_env, query_ty);
diff --git a/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs
index 41d3aefcbe6..54490e00509 100644
--- a/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs
+++ b/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs
@@ -229,6 +229,11 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> {
                 let source = self.parse_operand(args[0])?;
                 Ok(Rvalue::Cast(CastKind::PtrToPtr, source, expr.ty))
             },
+            @call(mir_cast_unsize, args) => {
+                let source = self.parse_operand(args[0])?;
+                let kind = CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize, CoercionSource::AsCast);
+                Ok(Rvalue::Cast(kind, source, expr.ty))
+            },
             @call(mir_checked, args) => {
                 parse_by_kind!(self, args[0], _, "binary op",
                     ExprKind::Binary { op, lhs, rhs } => {
@@ -247,7 +252,6 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> {
                 let offset = self.parse_operand(args[1])?;
                 Ok(Rvalue::BinaryOp(BinOp::Offset, Box::new((ptr, offset))))
             },
-            @call(mir_len, args) => Ok(Rvalue::Len(self.parse_place(args[0])?)),
             @call(mir_ptr_metadata, args) => Ok(Rvalue::UnaryOp(UnOp::PtrMetadata, self.parse_operand(args[0])?)),
             @call(mir_copy_for_deref, args) => Ok(Rvalue::CopyForDeref(self.parse_place(args[0])?)),
             ExprKind::Borrow { borrow_kind, arg } => Ok(
diff --git a/compiler/rustc_mir_build/src/builder/expr/as_place.rs b/compiler/rustc_mir_build/src/builder/expr/as_place.rs
index 7c851ec465b..5a6bd2f413c 100644
--- a/compiler/rustc_mir_build/src/builder/expr/as_place.rs
+++ b/compiler/rustc_mir_build/src/builder/expr/as_place.rs
@@ -663,7 +663,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     ///
     /// For arrays it'll be `Operand::Constant` with the actual length;
     /// For slices it'll be `Operand::Move` of a local using `PtrMetadata`.
-    fn len_of_slice_or_array(
+    pub(in crate::builder) fn len_of_slice_or_array(
         &mut self,
         block: BasicBlock,
         place: Place<'tcx>,
diff --git a/compiler/rustc_mir_build/src/builder/matches/test.rs b/compiler/rustc_mir_build/src/builder/matches/test.rs
index d03794fe2d5..1b6d96e49f0 100644
--- a/compiler/rustc_mir_build/src/builder/matches/test.rs
+++ b/compiler/rustc_mir_build/src/builder/matches/test.rs
@@ -309,7 +309,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 let actual = self.temp(usize_ty, test.span);
 
                 // actual = len(place)
-                self.cfg.push_assign(block, source_info, actual, Rvalue::Len(place));
+                let length_op = self.len_of_slice_or_array(block, place, test.span, source_info);
+                self.cfg.push_assign(block, source_info, actual, Rvalue::Use(length_op));
 
                 // expected = <N>
                 let expected = self.push_usize(block, source_info, len);
diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
index 9abb8343432..a4e4e30a8bb 100644
--- a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
@@ -91,7 +91,6 @@ where
             | Rvalue::Use(..)
             | Rvalue::ThreadLocalRef(..)
             | Rvalue::Repeat(..)
-            | Rvalue::Len(..)
             | Rvalue::BinaryOp(..)
             | Rvalue::NullaryOp(..)
             | Rvalue::UnaryOp(..)
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
index 48718cad597..f38bb445824 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
@@ -413,7 +413,6 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> {
             Rvalue::Ref(..)
             | Rvalue::RawPtr(..)
             | Rvalue::Discriminant(..)
-            | Rvalue::Len(..)
             | Rvalue::NullaryOp(
                 NullOp::SizeOf
                 | NullOp::AlignOf
diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs
index 4603c695ded..08316aaed3b 100644
--- a/compiler/rustc_mir_transform/src/coroutine.rs
+++ b/compiler/rustc_mir_transform/src/coroutine.rs
@@ -1340,14 +1340,13 @@ fn create_cases<'tcx>(
                     }
                 }
 
-                if operation == Operation::Resume {
+                if operation == Operation::Resume && point.resume_arg != CTX_ARG.into() {
                     // Move the resume argument to the destination place of the `Yield` terminator
-                    let resume_arg = CTX_ARG;
                     statements.push(Statement::new(
                         source_info,
                         StatementKind::Assign(Box::new((
                             point.resume_arg,
-                            Rvalue::Use(Operand::Move(resume_arg.into())),
+                            Rvalue::Use(Operand::Move(CTX_ARG.into())),
                         ))),
                     ));
                 }
@@ -1439,7 +1438,10 @@ fn check_field_tys_sized<'tcx>(
 }
 
 impl<'tcx> crate::MirPass<'tcx> for StateTransform {
+    #[instrument(level = "debug", skip(self, tcx, body), ret)]
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+        debug!(def_id = ?body.source.def_id());
+
         let Some(old_yield_ty) = body.yield_ty() else {
             // This only applies to coroutines
             return;
@@ -1518,31 +1520,7 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform {
             cleanup_async_drops(body);
         }
 
-        // We also replace the resume argument and insert an `Assign`.
-        // This is needed because the resume argument `_2` might be live across a `yield`, in which
-        // case there is no `Assign` to it that the transform can turn into a store to the coroutine
-        // state. After the yield the slot in the coroutine state would then be uninitialized.
-        let resume_local = CTX_ARG;
-        let resume_ty = body.local_decls[resume_local].ty;
-        let old_resume_local = replace_local(resume_local, resume_ty, body, tcx);
-
-        // When first entering the coroutine, move the resume argument into its old local
-        // (which is now a generator interior).
-        let source_info = SourceInfo::outermost(body.span);
-        let stmts = &mut body.basic_blocks_mut()[START_BLOCK].statements;
-        stmts.insert(
-            0,
-            Statement::new(
-                source_info,
-                StatementKind::Assign(Box::new((
-                    old_resume_local.into(),
-                    Rvalue::Use(Operand::Move(resume_local.into())),
-                ))),
-            ),
-        );
-
         let always_live_locals = always_storage_live_locals(body);
-
         let movable = coroutine_kind.movability() == hir::Movability::Movable;
         let liveness_info =
             locals_live_across_suspend_points(tcx, body, &always_live_locals, movable);
@@ -1583,6 +1561,21 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform {
         };
         transform.visit_body(body);
 
+        // MIR parameters are not explicitly assigned-to when entering the MIR body.
+        // If we want to save their values inside the coroutine state, we need to do so explicitly.
+        let source_info = SourceInfo::outermost(body.span);
+        let args_iter = body.args_iter();
+        body.basic_blocks.as_mut()[START_BLOCK].statements.splice(
+            0..0,
+            args_iter.filter_map(|local| {
+                let (ty, variant_index, idx) = transform.remap[local]?;
+                let lhs = transform.make_field(variant_index, idx, ty);
+                let rhs = Rvalue::Use(Operand::Move(local.into()));
+                let assign = StatementKind::Assign(Box::new((lhs, rhs)));
+                Some(Statement::new(source_info, assign))
+            }),
+        );
+
         // Update our MIR struct to reflect the changes we've made
         body.arg_count = 2; // self, resume arg
         body.spread_arg = None;
diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
index fe53de31f75..5c984984d3c 100644
--- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
+++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
@@ -412,18 +412,6 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
         state: &mut State<FlatSet<Scalar>>,
     ) -> ValueOrPlace<FlatSet<Scalar>> {
         let val = match rvalue {
-            Rvalue::Len(place) => {
-                let place_ty = place.ty(self.local_decls, self.tcx);
-                if let ty::Array(_, len) = place_ty.ty.kind() {
-                    Const::Ty(self.tcx.types.usize, *len)
-                        .try_eval_scalar(self.tcx, self.typing_env)
-                        .map_or(FlatSet::Top, FlatSet::Elem)
-                } else if let [ProjectionElem::Deref] = place.projection[..] {
-                    state.get_len(place.local.into(), &self.map)
-                } else {
-                    FlatSet::Top
-                }
-            }
             Rvalue::Cast(CastKind::IntToInt | CastKind::IntToFloat, operand, ty) => {
                 let Ok(layout) = self.tcx.layout_of(self.typing_env.as_query_input(*ty)) else {
                     return ValueOrPlace::Value(FlatSet::Top);
@@ -465,15 +453,23 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
                 let (val, _overflow) = self.binary_op(state, *op, left, right);
                 val
             }
-            Rvalue::UnaryOp(op, operand) => match self.eval_operand(operand, state) {
-                FlatSet::Elem(value) => self
-                    .ecx
-                    .unary_op(*op, &value)
-                    .discard_err()
-                    .map_or(FlatSet::Top, |val| self.wrap_immediate(*val)),
-                FlatSet::Bottom => FlatSet::Bottom,
-                FlatSet::Top => FlatSet::Top,
-            },
+            Rvalue::UnaryOp(op, operand) => {
+                if let UnOp::PtrMetadata = op
+                    && let Some(place) = operand.place()
+                    && let Some(len) = self.map.find_len(place.as_ref())
+                {
+                    return ValueOrPlace::Place(len);
+                }
+                match self.eval_operand(operand, state) {
+                    FlatSet::Elem(value) => self
+                        .ecx
+                        .unary_op(*op, &value)
+                        .discard_err()
+                        .map_or(FlatSet::Top, |val| self.wrap_immediate(*val)),
+                    FlatSet::Bottom => FlatSet::Bottom,
+                    FlatSet::Top => FlatSet::Top,
+                }
+            }
             Rvalue::NullaryOp(null_op, ty) => {
                 let Ok(layout) = self.tcx.layout_of(self.typing_env.as_query_input(*ty)) else {
                     return ValueOrPlace::Value(FlatSet::Top);
diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs
index c57483a6811..74c22ff10c1 100644
--- a/compiler/rustc_mir_transform/src/dest_prop.rs
+++ b/compiler/rustc_mir_transform/src/dest_prop.rs
@@ -141,7 +141,7 @@ use rustc_data_structures::union_find::UnionFind;
 use rustc_index::bit_set::DenseBitSet;
 use rustc_index::interval::SparseIntervalMatrix;
 use rustc_index::{IndexVec, newtype_index};
-use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
+use rustc_middle::mir::visit::{MutVisitor, PlaceContext, VisitPlacesWith, Visitor};
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
 use rustc_mir_dataflow::impls::{DefUse, MaybeLiveLocals};
@@ -153,15 +153,7 @@ pub(super) struct DestinationPropagation;
 
 impl<'tcx> crate::MirPass<'tcx> for DestinationPropagation {
     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
-        // For now, only run at MIR opt level 3. Two things need to be changed before this can be
-        // turned on by default:
-        //  1. Because of the overeager removal of storage statements, this can cause stack space
-        //     regressions. This opt is not the place to fix this though, it's a more general
-        //     problem in MIR.
-        //  2. Despite being an overall perf improvement, this still causes a 30% regression in
-        //     keccak. We can temporarily fix this by bounding function size, but in the long term
-        //     we should fix this by being smarter about invalidating analysis results.
-        sess.mir_opt_level() >= 3
+        sess.mir_opt_level() >= 2
     }
 
     #[tracing::instrument(level = "trace", skip(self, tcx, body))]
@@ -511,22 +503,6 @@ impl TwoStepIndex {
     }
 }
 
-struct VisitPlacesWith<F>(F);
-
-impl<'tcx, F> Visitor<'tcx> for VisitPlacesWith<F>
-where
-    F: FnMut(Place<'tcx>, PlaceContext),
-{
-    fn visit_local(&mut self, local: Local, ctxt: PlaceContext, _: Location) {
-        (self.0)(local.into(), ctxt);
-    }
-
-    fn visit_place(&mut self, place: &Place<'tcx>, ctxt: PlaceContext, location: Location) {
-        (self.0)(*place, ctxt);
-        self.visit_projection(place.as_ref(), ctxt, location);
-    }
-}
-
 /// Add points depending on the result of the given dataflow analysis.
 fn save_as_intervals<'tcx>(
     elements: &DenseLocationMap,
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index bf6aa800d20..30e68a3f650 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -200,8 +200,6 @@ enum Value<'tcx> {
     Projection(VnIndex, ProjectionElem<VnIndex, ()>),
     /// Discriminant of the given value.
     Discriminant(VnIndex),
-    /// Length of an array or slice.
-    Len(VnIndex),
 
     // Operations.
     NullaryOp(NullOp<'tcx>, Ty<'tcx>),
@@ -477,11 +475,6 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
                     self.ecx.discriminant_for_variant(base.layout.ty, variant).discard_err()?;
                 discr_value.into()
             }
-            Len(slice) => {
-                let slice = self.evaluated[slice].as_ref()?;
-                let len = slice.len(&self.ecx).discard_err()?;
-                ImmTy::from_uint(len, ty).into()
-            }
             NullaryOp(null_op, arg_ty) => {
                 let arg_layout = self.ecx.layout_of(arg_ty).ok()?;
                 if let NullOp::SizeOf | NullOp::AlignOf = null_op
@@ -841,7 +834,6 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
             }
 
             // Operations.
-            Rvalue::Len(ref mut place) => return self.simplify_len(place, location),
             Rvalue::Cast(ref mut kind, ref mut value, to) => {
                 return self.simplify_cast(kind, value, to, location);
             }
@@ -1049,7 +1041,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
         if op == UnOp::PtrMetadata {
             let mut was_updated = false;
             loop {
-                match self.get(arg_index) {
+                arg_index = match self.get(arg_index) {
                     // Pointer casts that preserve metadata, such as
                     // `*const [i32]` <-> `*mut [i32]` <-> `*mut [f32]`.
                     // It's critical that this not eliminate cases like
@@ -1061,9 +1053,19 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
                     Value::Cast { kind: CastKind::PtrToPtr, value: inner }
                         if self.pointers_have_same_metadata(self.ty(*inner), arg_ty) =>
                     {
-                        arg_index = *inner;
-                        was_updated = true;
-                        continue;
+                        *inner
+                    }
+
+                    // We have an unsizing cast, which assigns the length to wide pointer metadata.
+                    Value::Cast {
+                        kind: CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize, _),
+                        value: from,
+                    } if let Some(from) = self.ty(*from).builtin_deref(true)
+                        && let ty::Array(_, len) = from.kind()
+                        && let Some(to) = self.ty(arg_index).builtin_deref(true)
+                        && let ty::Slice(..) = to.kind() =>
+                    {
+                        return Some(self.insert_constant(Const::Ty(self.tcx.types.usize, *len)));
                     }
 
                     // `&mut *p`, `&raw *p`, etc don't change metadata.
@@ -1072,18 +1074,16 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
                             place.as_ref()
                             && let Some(local_index) = self.locals[local] =>
                     {
-                        arg_index = local_index;
-                        was_updated = true;
-                        continue;
+                        local_index
                     }
 
-                    _ => {
-                        if was_updated && let Some(op) = self.try_as_operand(arg_index, location) {
-                            *arg_op = op;
-                        }
-                        break;
-                    }
-                }
+                    _ => break,
+                };
+                was_updated = true;
+            }
+
+            if was_updated && let Some(op) = self.try_as_operand(arg_index, location) {
+                *arg_op = op;
             }
         }
 
@@ -1407,39 +1407,6 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
         Some(self.insert(to, Value::Cast { kind, value }))
     }
 
-    fn simplify_len(&mut self, place: &mut Place<'tcx>, location: Location) -> Option<VnIndex> {
-        // Trivial case: we are fetching a statically known length.
-        let place_ty = place.ty(self.local_decls, self.tcx).ty;
-        if let ty::Array(_, len) = place_ty.kind() {
-            return Some(self.insert_constant(Const::Ty(self.tcx.types.usize, *len)));
-        }
-
-        let mut inner = self.simplify_place_value(place, location)?;
-
-        // The length information is stored in the wide pointer.
-        // Reborrowing copies length information from one pointer to the other.
-        while let Value::Address { place: borrowed, .. } = self.get(inner)
-            && let [PlaceElem::Deref] = borrowed.projection[..]
-            && let Some(borrowed) = self.locals[borrowed.local]
-        {
-            inner = borrowed;
-        }
-
-        // We have an unsizing cast, which assigns the length to wide pointer metadata.
-        if let Value::Cast { kind, value: from } = self.get(inner)
-            && let CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize, _) = kind
-            && let Some(from) = self.ty(*from).builtin_deref(true)
-            && let ty::Array(_, len) = from.kind()
-            && let Some(to) = self.ty(inner).builtin_deref(true)
-            && let ty::Slice(..) = to.kind()
-        {
-            return Some(self.insert_constant(Const::Ty(self.tcx.types.usize, *len)));
-        }
-
-        // Fallback: a symbolic `Len`.
-        Some(self.insert(self.tcx.types.usize, Value::Len(inner)))
-    }
-
     fn pointers_have_same_metadata(&self, left_ptr_ty: Ty<'tcx>, right_ptr_ty: Ty<'tcx>) -> bool {
         let left_meta_ty = left_ptr_ty.pointee_metadata_ty_or_projection(self.tcx);
         let right_meta_ty = right_ptr_ty.pointee_metadata_ty_or_projection(self.tcx);
diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs
index 481c7941909..aaacc5866a2 100644
--- a/compiler/rustc_mir_transform/src/known_panics_lint.rs
+++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs
@@ -441,7 +441,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
             | Rvalue::Use(..)
             | Rvalue::CopyForDeref(..)
             | Rvalue::Repeat(..)
-            | Rvalue::Len(..)
             | Rvalue::Cast(..)
             | Rvalue::ShallowInitBox(..)
             | Rvalue::Discriminant(..)
@@ -604,20 +603,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                 return None;
             }
 
-            Len(place) => {
-                let len = if let ty::Array(_, n) = place.ty(self.local_decls(), self.tcx).ty.kind()
-                {
-                    n.try_to_target_usize(self.tcx)?
-                } else {
-                    match self.get_const(place)? {
-                        Value::Immediate(src) => src.len(&self.ecx).discard_err()?,
-                        Value::Aggregate { fields, .. } => fields.len() as u64,
-                        Value::Uninit => return None,
-                    }
-                };
-                ImmTy::from_scalar(Scalar::from_target_usize(len, self), layout).into()
-            }
-
             Ref(..) | RawPtr(..) => return None,
 
             NullaryOp(ref null_op, ty) => {
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 1663dfa744f..9ff7e0b5500 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -156,7 +156,6 @@ declare_passes! {
     mod match_branches : MatchBranchSimplification;
     mod mentioned_items : MentionedItems;
     mod multiple_return_terminators : MultipleReturnTerminators;
-    mod nrvo : RenameReturnPlace;
     mod post_drop_elaboration : CheckLiveDrops;
     mod prettify : ReorderBasicBlocks, ReorderLocals;
     mod promote_consts : PromoteTemps;
@@ -715,7 +714,6 @@ pub(crate) fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'
             &jump_threading::JumpThreading,
             &early_otherwise_branch::EarlyOtherwiseBranch,
             &simplify_comparison_integral::SimplifyComparisonIntegral,
-            &dest_prop::DestinationPropagation,
             &o1(simplify_branches::SimplifyConstCondition::Final),
             &o1(remove_noop_landing_pads::RemoveNoopLandingPads),
             &o1(simplify::SimplifyCfg::Final),
@@ -723,7 +721,7 @@ pub(crate) fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'
             &strip_debuginfo::StripDebugInfo,
             &copy_prop::CopyProp,
             &dead_store_elimination::DeadStoreElimination::Final,
-            &nrvo::RenameReturnPlace,
+            &dest_prop::DestinationPropagation,
             &simplify::SimplifyLocals::Final,
             &multiple_return_terminators::MultipleReturnTerminators,
             &large_enums::EnumSizeOpt { discrepancy: 128 },
diff --git a/compiler/rustc_mir_transform/src/lint.rs b/compiler/rustc_mir_transform/src/lint.rs
index f472c7cb493..2ab49645dc4 100644
--- a/compiler/rustc_mir_transform/src/lint.rs
+++ b/compiler/rustc_mir_transform/src/lint.rs
@@ -6,7 +6,7 @@ use std::borrow::Cow;
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_index::bit_set::DenseBitSet;
-use rustc_middle::mir::visit::{PlaceContext, Visitor};
+use rustc_middle::mir::visit::{PlaceContext, VisitPlacesWith, Visitor};
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
 use rustc_mir_dataflow::impls::{MaybeStorageDead, MaybeStorageLive, always_storage_live_locals};
@@ -79,15 +79,39 @@ impl<'a, 'tcx> Visitor<'tcx> for Lint<'a, 'tcx> {
     fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
         match &statement.kind {
             StatementKind::Assign(box (dest, rvalue)) => {
-                if let Rvalue::Use(Operand::Copy(src) | Operand::Move(src)) = rvalue {
-                    // The sides of an assignment must not alias. Currently this just checks whether
-                    // the places are identical.
-                    if dest == src {
-                        self.fail(
-                            location,
-                            "encountered `Assign` statement with overlapping memory",
-                        );
-                    }
+                let forbid_aliasing = match rvalue {
+                    Rvalue::Use(..)
+                    | Rvalue::CopyForDeref(..)
+                    | Rvalue::Repeat(..)
+                    | Rvalue::Aggregate(..)
+                    | Rvalue::Cast(..)
+                    | Rvalue::ShallowInitBox(..)
+                    | Rvalue::WrapUnsafeBinder(..) => true,
+                    Rvalue::ThreadLocalRef(..)
+                    | Rvalue::NullaryOp(..)
+                    | Rvalue::UnaryOp(..)
+                    | Rvalue::BinaryOp(..)
+                    | Rvalue::Ref(..)
+                    | Rvalue::RawPtr(..)
+                    | Rvalue::Discriminant(..) => false,
+                };
+                // The sides of an assignment must not alias.
+                if forbid_aliasing {
+                    VisitPlacesWith(|src: Place<'tcx>, _| {
+                        if *dest == src
+                            || (dest.local == src.local
+                                && !dest.is_indirect()
+                                && !src.is_indirect())
+                        {
+                            self.fail(
+                                location,
+                                format!(
+                                    "encountered `{statement:?}` statement with overlapping memory"
+                                ),
+                            );
+                        }
+                    })
+                    .visit_rvalue(rvalue, location);
                 }
             }
             StatementKind::StorageLive(local) => {
diff --git a/compiler/rustc_mir_transform/src/nrvo.rs b/compiler/rustc_mir_transform/src/nrvo.rs
deleted file mode 100644
index 965002aae04..00000000000
--- a/compiler/rustc_mir_transform/src/nrvo.rs
+++ /dev/null
@@ -1,234 +0,0 @@
-//! See the docs for [`RenameReturnPlace`].
-
-use rustc_hir::Mutability;
-use rustc_index::bit_set::DenseBitSet;
-use rustc_middle::bug;
-use rustc_middle::mir::visit::{MutVisitor, NonUseContext, PlaceContext, Visitor};
-use rustc_middle::mir::{self, BasicBlock, Local, Location};
-use rustc_middle::ty::TyCtxt;
-use tracing::{debug, trace};
-
-/// This pass looks for MIR that always copies the same local into the return place and eliminates
-/// the copy by renaming all uses of that local to `_0`.
-///
-/// This allows LLVM to perform an optimization similar to the named return value optimization
-/// (NRVO) that is guaranteed in C++. This avoids a stack allocation and `memcpy` for the
-/// relatively common pattern of allocating a buffer on the stack, mutating it, and returning it by
-/// value like so:
-///
-/// ```rust
-/// fn foo(init: fn(&mut [u8; 1024])) -> [u8; 1024] {
-///     let mut buf = [0; 1024];
-///     init(&mut buf);
-///     buf
-/// }
-/// ```
-///
-/// For now, this pass is very simple and only capable of eliminating a single copy. A more general
-/// version of copy propagation, such as the one based on non-overlapping live ranges in [#47954] and
-/// [#71003], could yield even more benefits.
-///
-/// [#47954]: https://github.com/rust-lang/rust/pull/47954
-/// [#71003]: https://github.com/rust-lang/rust/pull/71003
-pub(super) struct RenameReturnPlace;
-
-impl<'tcx> crate::MirPass<'tcx> for RenameReturnPlace {
-    fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
-        // unsound: #111005
-        sess.mir_opt_level() > 0 && sess.opts.unstable_opts.unsound_mir_opts
-    }
-
-    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut mir::Body<'tcx>) {
-        let def_id = body.source.def_id();
-        let Some(returned_local) = local_eligible_for_nrvo(body) else {
-            debug!("`{:?}` was ineligible for NRVO", def_id);
-            return;
-        };
-
-        debug!(
-            "`{:?}` was eligible for NRVO, making {:?} the return place",
-            def_id, returned_local
-        );
-
-        RenameToReturnPlace { tcx, to_rename: returned_local }.visit_body_preserves_cfg(body);
-
-        // Clean up the `NOP`s we inserted for statements made useless by our renaming.
-        for block_data in body.basic_blocks.as_mut_preserves_cfg() {
-            block_data.statements.retain(|stmt| stmt.kind != mir::StatementKind::Nop);
-        }
-
-        // Overwrite the debuginfo of `_0` with that of the renamed local.
-        let (renamed_decl, ret_decl) =
-            body.local_decls.pick2_mut(returned_local, mir::RETURN_PLACE);
-
-        // Sometimes, the return place is assigned a local of a different but coercible type, for
-        // example `&mut T` instead of `&T`. Overwriting the `LocalInfo` for the return place means
-        // its type may no longer match the return type of its function. This doesn't cause a
-        // problem in codegen because these two types are layout-compatible, but may be unexpected.
-        debug!("_0: {:?} = {:?}: {:?}", ret_decl.ty, returned_local, renamed_decl.ty);
-        ret_decl.clone_from(renamed_decl);
-
-        // The return place is always mutable.
-        ret_decl.mutability = Mutability::Mut;
-    }
-
-    fn is_required(&self) -> bool {
-        false
-    }
-}
-
-/// MIR that is eligible for the NRVO must fulfill two conditions:
-///   1. The return place must not be read prior to the `Return` terminator.
-///   2. A simple assignment of a whole local to the return place (e.g., `_0 = _1`) must be the
-///      only definition of the return place reaching the `Return` terminator.
-///
-/// If the MIR fulfills both these conditions, this function returns the `Local` that is assigned
-/// to the return place along all possible paths through the control-flow graph.
-fn local_eligible_for_nrvo(body: &mir::Body<'_>) -> Option<Local> {
-    if IsReturnPlaceRead::run(body) {
-        return None;
-    }
-
-    let mut copied_to_return_place = None;
-    for block in body.basic_blocks.indices() {
-        // Look for blocks with a `Return` terminator.
-        if !matches!(body[block].terminator().kind, mir::TerminatorKind::Return) {
-            continue;
-        }
-
-        // Look for an assignment of a single local to the return place prior to the `Return`.
-        let returned_local = find_local_assigned_to_return_place(block, body)?;
-        match body.local_kind(returned_local) {
-            // FIXME: Can we do this for arguments as well?
-            mir::LocalKind::Arg => return None,
-
-            mir::LocalKind::ReturnPointer => bug!("Return place was assigned to itself?"),
-            mir::LocalKind::Temp => {}
-        }
-
-        // If multiple different locals are copied to the return place. We can't pick a
-        // single one to rename.
-        if copied_to_return_place.is_some_and(|old| old != returned_local) {
-            return None;
-        }
-
-        copied_to_return_place = Some(returned_local);
-    }
-
-    copied_to_return_place
-}
-
-fn find_local_assigned_to_return_place(start: BasicBlock, body: &mir::Body<'_>) -> Option<Local> {
-    let mut block = start;
-    let mut seen = DenseBitSet::new_empty(body.basic_blocks.len());
-
-    // Iterate as long as `block` has exactly one predecessor that we have not yet visited.
-    while seen.insert(block) {
-        trace!("Looking for assignments to `_0` in {:?}", block);
-
-        let local = body[block].statements.iter().rev().find_map(as_local_assigned_to_return_place);
-        if local.is_some() {
-            return local;
-        }
-
-        match body.basic_blocks.predecessors()[block].as_slice() {
-            &[pred] => block = pred,
-            _ => return None,
-        }
-    }
-
-    None
-}
-
-// If this statement is an assignment of an unprojected local to the return place,
-// return that local.
-fn as_local_assigned_to_return_place(stmt: &mir::Statement<'_>) -> Option<Local> {
-    if let mir::StatementKind::Assign(box (lhs, rhs)) = &stmt.kind {
-        if lhs.as_local() == Some(mir::RETURN_PLACE) {
-            if let mir::Rvalue::Use(mir::Operand::Copy(rhs) | mir::Operand::Move(rhs)) = rhs {
-                return rhs.as_local();
-            }
-        }
-    }
-
-    None
-}
-
-struct RenameToReturnPlace<'tcx> {
-    to_rename: Local,
-    tcx: TyCtxt<'tcx>,
-}
-
-/// Replaces all uses of `self.to_rename` with `_0`.
-impl<'tcx> MutVisitor<'tcx> for RenameToReturnPlace<'tcx> {
-    fn tcx(&self) -> TyCtxt<'tcx> {
-        self.tcx
-    }
-
-    fn visit_statement(&mut self, stmt: &mut mir::Statement<'tcx>, loc: Location) {
-        // Remove assignments of the local being replaced to the return place, since it is now the
-        // return place:
-        //     _0 = _1
-        if as_local_assigned_to_return_place(stmt) == Some(self.to_rename) {
-            stmt.kind = mir::StatementKind::Nop;
-            return;
-        }
-
-        // Remove storage annotations for the local being replaced:
-        //     StorageLive(_1)
-        if let mir::StatementKind::StorageLive(local) | mir::StatementKind::StorageDead(local) =
-            stmt.kind
-        {
-            if local == self.to_rename {
-                stmt.kind = mir::StatementKind::Nop;
-                return;
-            }
-        }
-
-        self.super_statement(stmt, loc)
-    }
-
-    fn visit_terminator(&mut self, terminator: &mut mir::Terminator<'tcx>, loc: Location) {
-        // Ignore the implicit "use" of the return place in a `Return` statement.
-        if let mir::TerminatorKind::Return = terminator.kind {
-            return;
-        }
-
-        self.super_terminator(terminator, loc);
-    }
-
-    fn visit_local(&mut self, l: &mut Local, ctxt: PlaceContext, _: Location) {
-        if *l == mir::RETURN_PLACE {
-            assert_eq!(ctxt, PlaceContext::NonUse(NonUseContext::VarDebugInfo));
-        } else if *l == self.to_rename {
-            *l = mir::RETURN_PLACE;
-        }
-    }
-}
-
-struct IsReturnPlaceRead(bool);
-
-impl IsReturnPlaceRead {
-    fn run(body: &mir::Body<'_>) -> bool {
-        let mut vis = IsReturnPlaceRead(false);
-        vis.visit_body(body);
-        vis.0
-    }
-}
-
-impl<'tcx> Visitor<'tcx> for IsReturnPlaceRead {
-    fn visit_local(&mut self, l: Local, ctxt: PlaceContext, _: Location) {
-        if l == mir::RETURN_PLACE && ctxt.is_use() && !ctxt.is_place_assignment() {
-            self.0 = true;
-        }
-    }
-
-    fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, loc: Location) {
-        // Ignore the implicit "use" of the return place in a `Return` statement.
-        if let mir::TerminatorKind::Return = terminator.kind {
-            return;
-        }
-
-        self.super_terminator(terminator, loc);
-    }
-}
diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs
index 9ea2eb4f25d..a0b0c8c990f 100644
--- a/compiler/rustc_mir_transform/src/promote_consts.rs
+++ b/compiler/rustc_mir_transform/src/promote_consts.rs
@@ -437,9 +437,7 @@ impl<'tcx> Validator<'_, 'tcx> {
                 self.validate_operand(op)?
             }
 
-            Rvalue::Discriminant(place) | Rvalue::Len(place) => {
-                self.validate_place(place.as_ref())?
-            }
+            Rvalue::Discriminant(place) => self.validate_place(place.as_ref())?,
 
             Rvalue::ThreadLocalRef(_) => return Err(Unpromotable),
 
diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs
index 99e4782e470..c8a9a88dc3f 100644
--- a/compiler/rustc_mir_transform/src/validate.rs
+++ b/compiler/rustc_mir_transform/src/validate.rs
@@ -1064,14 +1064,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                 }
             }
             Rvalue::Ref(..) => {}
-            Rvalue::Len(p) => {
-                let pty = p.ty(&self.body.local_decls, self.tcx).ty;
-                check_kinds!(
-                    pty,
-                    "Cannot compute length of non-array type {:?}",
-                    ty::Array(..) | ty::Slice(..)
-                );
-            }
             Rvalue::BinaryOp(op, vals) => {
                 use BinOp::*;
                 let a = vals.0.ty(&self.body.local_decls, self.tcx);
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index 72cd75f6d89..f83cf645f82 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -189,6 +189,10 @@ parse_dotdotdot = unexpected token: `...`
 parse_dotdotdot_rest_pattern = unexpected `...`
     .label = not a valid pattern
     .suggestion = for a rest pattern, use `..` instead of `...`
+    .note = only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
+
+parse_dotdotdot_rest_type = unexpected `...`
+    .note = only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
 
 parse_double_colon_in_bound = expected `:` followed by trait or lifetime
     .suggestion = use single colon
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 00ca5acd84d..1abeee6fe43 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -2723,7 +2723,9 @@ pub(crate) struct DotDotDotRestPattern {
     #[label]
     pub span: Span,
     #[suggestion(style = "verbose", code = "", applicability = "machine-applicable")]
-    pub suggestion: Span,
+    pub suggestion: Option<Span>,
+    #[note]
+    pub var_args: Option<()>,
 }
 
 #[derive(Diagnostic)]
@@ -3031,6 +3033,14 @@ pub(crate) struct NestedCVariadicType {
 }
 
 #[derive(Diagnostic)]
+#[diag(parse_dotdotdot_rest_type)]
+#[note]
+pub(crate) struct InvalidCVariadicType {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
 #[diag(parse_invalid_dyn_keyword)]
 #[help]
 pub(crate) struct InvalidDynKeyword {
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index c4d30b3d328..fda19d62bc7 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -756,7 +756,7 @@ impl<'a> Parser<'a> {
             self.bump(); // `..`
             PatKind::Rest
         } else if self.check(exp!(DotDotDot)) && !self.is_pat_range_end_start(1) {
-            self.recover_dotdotdot_rest_pat(lo)
+            self.recover_dotdotdot_rest_pat(lo, expected)
         } else if let Some(form) = self.parse_range_end() {
             self.parse_pat_range_to(form)? // `..=X`, `...X`, or `..X`.
         } else if self.eat(exp!(Bang)) {
@@ -886,16 +886,27 @@ impl<'a> Parser<'a> {
 
     /// Recover from a typoed `...` pattern that was encountered
     /// Ref: Issue #70388
-    fn recover_dotdotdot_rest_pat(&mut self, lo: Span) -> PatKind {
+    fn recover_dotdotdot_rest_pat(&mut self, lo: Span, expected: Option<Expected>) -> PatKind {
         // A typoed rest pattern `...`.
         self.bump(); // `...`
 
-        // The user probably mistook `...` for a rest pattern `..`.
-        self.dcx().emit_err(DotDotDotRestPattern {
-            span: lo,
-            suggestion: lo.with_lo(lo.hi() - BytePos(1)),
-        });
-        PatKind::Rest
+        if let Some(Expected::ParameterName) = expected {
+            // We have `...` in a closure argument, likely meant to be var-arg, which aren't
+            // supported in closures (#146489).
+            PatKind::Err(self.dcx().emit_err(DotDotDotRestPattern {
+                span: lo,
+                suggestion: None,
+                var_args: Some(()),
+            }))
+        } else {
+            // The user probably mistook `...` for a rest pattern `..`.
+            self.dcx().emit_err(DotDotDotRestPattern {
+                span: lo,
+                suggestion: Some(lo.with_lo(lo.hi() - BytePos(1))),
+                var_args: None,
+            });
+            PatKind::Rest
+        }
     }
 
     /// Try to recover the more general form `intersect ::= $pat_lhs @ $pat_rhs`.
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index 23aaafac934..65347496599 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -15,8 +15,8 @@ use super::{Parser, PathStyle, SeqSep, TokenType, Trailing};
 use crate::errors::{
     self, AttributeOnEmptyType, AttributeOnType, DynAfterMut, ExpectedFnPathFoundFnKeyword,
     ExpectedMutOrConstInRawPointerType, FnPtrWithGenerics, FnPtrWithGenericsSugg,
-    HelpUseLatestEdition, InvalidDynKeyword, LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime,
-    NestedCVariadicType, ReturnTypesUseThinArrow,
+    HelpUseLatestEdition, InvalidCVariadicType, InvalidDynKeyword, LifetimeAfterMut,
+    NeedPlusAfterTraitObjectLifetime, NestedCVariadicType, ReturnTypesUseThinArrow,
 };
 use crate::parser::item::FrontMatterParsingMode;
 use crate::parser::{FnContext, FnParseMode};
@@ -106,6 +106,15 @@ fn can_begin_dyn_bound_in_edition_2015(t: &Token) -> bool {
 impl<'a> Parser<'a> {
     /// Parses a type.
     pub fn parse_ty(&mut self) -> PResult<'a, Box<Ty>> {
+        if self.token == token::DotDotDot {
+            // We special case this so that we don't talk about "nested C-variadics" in types.
+            // We still pass in `AllowCVariadic::No` so that `parse_ty_common` can complain about
+            // things like `Vec<...>`.
+            let span = self.token.span;
+            self.bump();
+            let kind = TyKind::Err(self.dcx().emit_err(InvalidCVariadicType { span }));
+            return Ok(self.mk_ty(span, kind));
+        }
         // Make sure deeply nested types don't overflow the stack.
         ensure_sufficient_stack(|| {
             self.parse_ty_common(
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 2562d2e0b83..4d5a8447695 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -246,7 +246,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                     | AttributeKind::Repr { .. }
                     | AttributeKind::Cold(..)
                     | AttributeKind::ExportName { .. }
-                    | AttributeKind::CoherenceIsCore
                     | AttributeKind::Fundamental
                     | AttributeKind::Optimize(..)
                     | AttributeKind::LinkSection { .. }
@@ -276,6 +275,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                     | AttributeKind::PatternComplexityLimit { .. }
                     | AttributeKind::NoCore { .. }
                     | AttributeKind::NoStd { .. }
+                    | AttributeKind::ObjcClass { .. }
+                    | AttributeKind::ObjcSelector { .. }
+                    | AttributeKind::RustcCoherenceIsCore(..)
                 ) => { /* do nothing  */ }
                 Attribute::Unparsed(attr_item) => {
                     style = Some(attr_item.style);
diff --git a/compiler/rustc_public/src/unstable/convert/stable/mir.rs b/compiler/rustc_public/src/unstable/convert/stable/mir.rs
index be8ee80bed3..b10af6526ea 100644
--- a/compiler/rustc_public/src/unstable/convert/stable/mir.rs
+++ b/compiler/rustc_public/src/unstable/convert/stable/mir.rs
@@ -215,7 +215,6 @@ impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> {
                 mutability.stable(tables, cx),
                 place.stable(tables, cx),
             ),
-            Len(place) => crate::mir::Rvalue::Len(place.stable(tables, cx)),
             Cast(cast_kind, op, ty) => crate::mir::Rvalue::Cast(
                 cast_kind.stable(tables, cx),
                 op.stable(tables, cx),
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index cdb0b5b58da..4fef65f46b1 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1413,6 +1413,7 @@ symbols! {
         mir_call,
         mir_cast_ptr_to_ptr,
         mir_cast_transmute,
+        mir_cast_unsize,
         mir_checked,
         mir_copy_for_deref,
         mir_debuginfo,
@@ -1917,6 +1918,8 @@ symbols! {
         rustc_no_mir_inline,
         rustc_nonnull_optimization_guaranteed,
         rustc_nounwind,
+        rustc_objc_class,
+        rustc_objc_selector,
         rustc_object_lifetime_default,
         rustc_on_unimplemented,
         rustc_outlives,
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
index edab530590b..75283dc4ffa 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
@@ -4,11 +4,12 @@ use std::path::PathBuf;
 
 use rustc_errors::codes::*;
 use rustc_errors::{Diag, IntoDiagArg};
-use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{self, Visitor};
-use rustc_hir::{Body, Closure, Expr, ExprKind, FnRetTy, HirId, LetStmt, LocalSource};
+use rustc_hir::{
+    self as hir, Body, Closure, Expr, ExprKind, FnRetTy, HirId, LetStmt, LocalSource, PatKind,
+};
 use rustc_middle::bug;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
@@ -512,7 +513,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     type_name: ty_to_string(self, ty, def_id),
                 });
             }
-            InferSourceKind::ClosureArg { insert_span, ty } => {
+            InferSourceKind::ClosureArg { insert_span, ty, .. } => {
                 infer_subdiags.push(SourceKindSubdiag::LetLike {
                     span: insert_span,
                     name: String::new(),
@@ -652,6 +653,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             }),
         };
         *err.long_ty_path() = long_ty_path;
+        if let InferSourceKind::ClosureArg { kind: PatKind::Err(_), .. } = kind {
+            // We will have already emitted an error about this pattern.
+            err.downgrade_to_delayed_bug();
+        }
         err
     }
 }
@@ -673,6 +678,7 @@ enum InferSourceKind<'tcx> {
     ClosureArg {
         insert_span: Span,
         ty: Ty<'tcx>,
+        kind: PatKind<'tcx>,
     },
     GenericArg {
         insert_span: Span,
@@ -1197,6 +1203,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
                     kind: InferSourceKind::ClosureArg {
                         insert_span: param.pat.span.shrink_to_hi(),
                         ty: param_ty,
+                        kind: param.pat.kind,
                     },
                 })
             }
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index 98c9f6b51ab..7d2dd12c6ea 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -640,7 +640,7 @@ impl<T> Box<[T]> {
     /// values[0].write(1);
     /// values[1].write(2);
     /// values[2].write(3);
-    /// let values = unsafe {values.assume_init() };
+    /// let values = unsafe { values.assume_init() };
     ///
     /// assert_eq!(*values, [1, 2, 3])
     /// ```
diff --git a/library/alloc/src/collections/btree/map/entry.rs b/library/alloc/src/collections/btree/map/entry.rs
index ec9b774c308..21486651b0b 100644
--- a/library/alloc/src/collections/btree/map/entry.rs
+++ b/library/alloc/src/collections/btree/map/entry.rs
@@ -271,7 +271,6 @@ impl<'a, K: Ord, V, A: Allocator + Clone> Entry<'a, K, V, A> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(btree_entry_insert)]
     /// use std::collections::BTreeMap;
     ///
     /// let mut map: BTreeMap<&str, String> = BTreeMap::new();
@@ -280,7 +279,7 @@ impl<'a, K: Ord, V, A: Allocator + Clone> Entry<'a, K, V, A> {
     /// assert_eq!(entry.key(), &"poneyland");
     /// ```
     #[inline]
-    #[unstable(feature = "btree_entry_insert", issue = "65225")]
+    #[stable(feature = "btree_entry_insert", since = "CURRENT_RUSTC_VERSION")]
     pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V, A> {
         match self {
             Occupied(mut entry) => {
@@ -379,7 +378,6 @@ impl<'a, K: Ord, V, A: Allocator + Clone> VacantEntry<'a, K, V, A> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(btree_entry_insert)]
     /// use std::collections::BTreeMap;
     /// use std::collections::btree_map::Entry;
     ///
@@ -391,7 +389,7 @@ impl<'a, K: Ord, V, A: Allocator + Clone> VacantEntry<'a, K, V, A> {
     /// }
     /// assert_eq!(map["poneyland"], 37);
     /// ```
-    #[unstable(feature = "btree_entry_insert", issue = "65225")]
+    #[stable(feature = "btree_entry_insert", since = "CURRENT_RUSTC_VERSION")]
     pub fn insert_entry(mut self, value: V) -> OccupiedEntry<'a, K, V, A> {
         let handle = match self.handle {
             None => {
diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs
index 55dcf7cd47e..a800ef1cb93 100644
--- a/library/core/src/intrinsics/mir.rs
+++ b/library/core/src/intrinsics/mir.rs
@@ -233,7 +233,8 @@
 //!
 //!  - Operands implicitly convert to `Use` rvalues.
 //!  - `&`, `&mut`, `addr_of!`, and `addr_of_mut!` all work to create their associated rvalue.
-//!  - [`Discriminant`], [`Len`], and [`CopyForDeref`] have associated functions.
+//!  - [`CopyForDeref`], [`CastTransmute`], [`CastPtrToPtr`], [`CastUnsize`], and [`Discriminant`]
+//!    have associated functions.
 //!  - Unary and binary operations use their normal Rust syntax - `a * b`, `!c`, etc.
 //!  - The binary operation `Offset` can be created via [`Offset`].
 //!  - Checked binary operations are represented by wrapping the associated binop in [`Checked`].
@@ -401,7 +402,6 @@ define!("mir_storage_dead", fn StorageDead<T>(local: T));
 define!("mir_assume", fn Assume(operand: bool));
 define!("mir_deinit", fn Deinit<T>(place: T));
 define!("mir_checked", fn Checked<T>(binop: T) -> (T, bool));
-define!("mir_len", fn Len<T>(place: T) -> usize);
 define!(
     "mir_ptr_metadata",
     fn PtrMetadata<P: ?Sized>(place: *const P) -> <P as ::core::ptr::Pointee>::Metadata
@@ -492,6 +492,13 @@ define!(
     fn CastPtrToPtr<T, U>(operand: T) -> U
 );
 define!(
+    "mir_cast_unsize",
+    /// Emits a `CastKind::PointerCoercion(Unsize)` cast.
+    ///
+    /// This allows bypassing normal validation to generate strange casts.
+    fn CastUnsize<T, U>(operand: T) -> U
+);
+define!(
     "mir_make_place",
     #[doc(hidden)]
     fn __internal_make_place<T>(place: T) -> *mut T
diff --git a/library/core/src/iter/sources/repeat.rs b/library/core/src/iter/sources/repeat.rs
index c4f5a483e5c..4bcd5b16aea 100644
--- a/library/core/src/iter/sources/repeat.rs
+++ b/library/core/src/iter/sources/repeat.rs
@@ -9,7 +9,7 @@ use crate::num::NonZero;
 /// [`Iterator::take()`], in order to make them finite.
 ///
 /// Use [`str::repeat()`] instead of this function if you just want to repeat
-/// a char/string `n`th times.
+/// a char/string `n` times.
 ///
 /// If the element type of the iterator you need does not implement `Clone`,
 /// or if you do not want to keep the repeated element in memory, you can
@@ -98,11 +98,12 @@ impl<A: Clone> Iterator for Repeat<A> {
     }
 
     fn last(self) -> Option<A> {
-        loop {}
+        Some(self.element)
     }
 
+    #[track_caller]
     fn count(self) -> usize {
-        loop {}
+        panic!("iterator is infinite");
     }
 }
 
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 86a68e18b0a..5d52bfb1b12 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -313,6 +313,7 @@ pub mod io;
 pub mod iter;
 pub mod net;
 pub mod option;
+pub mod os;
 pub mod panic;
 pub mod panicking;
 #[unstable(feature = "pattern_type_macro", issue = "123646")]
diff --git a/library/core/src/os/darwin/mod.rs b/library/core/src/os/darwin/mod.rs
new file mode 100644
index 00000000000..8426d82b8ce
--- /dev/null
+++ b/library/core/src/os/darwin/mod.rs
@@ -0,0 +1,19 @@
+//! Platform-specific extensions to `core` for Darwin / Apple platforms.
+//!
+//! This is available on the following operating systems:
+//! - macOS
+//! - iOS
+//! - tvOS
+//! - watchOS
+//! - visionOS
+//!
+//! Note: This module is called "Darwin" as that's the name of the underlying
+//! core OS of the above operating systems, but it should not be confused with
+//! the `-darwin` suffix in the `x86_64-apple-darwin` and
+//! `aarch64-apple-darwin` target names, which are mostly named that way for
+//! legacy reasons.
+
+#![unstable(feature = "darwin_objc", issue = "145496")]
+#![doc(cfg(target_vendor = "apple"))]
+
+pub mod objc;
diff --git a/library/core/src/os/darwin/objc.rs b/library/core/src/os/darwin/objc.rs
new file mode 100644
index 00000000000..928cb54e82c
--- /dev/null
+++ b/library/core/src/os/darwin/objc.rs
@@ -0,0 +1,113 @@
+//! Defines types and macros for Objective-C interoperability.
+
+#![unstable(feature = "darwin_objc", issue = "145496")]
+#![allow(nonstandard_style)]
+
+use crate::fmt;
+
+/// Equivalent to Objective-C’s `struct objc_class` type.
+#[cfg_attr(not(doc), repr(u8))] // An implementation detail we don't want to show up in rustdoc
+pub enum objc_class {
+    #[unstable(
+        feature = "objc_class_variant",
+        reason = "temporary implementation detail",
+        issue = "none"
+    )]
+    #[doc(hidden)]
+    __variant1,
+    #[unstable(
+        feature = "objc_class_variant",
+        reason = "temporary implementation detail",
+        issue = "none"
+    )]
+    #[doc(hidden)]
+    __variant2,
+}
+
+impl fmt::Debug for objc_class {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("objc_class").finish()
+    }
+}
+
+/// Equivalent to Objective-C’s `struct objc_selector` type.
+#[cfg_attr(not(doc), repr(u8))] // An implementation detail we don't want to show up in rustdoc
+pub enum objc_selector {
+    #[unstable(
+        feature = "objc_selector_variant",
+        reason = "temporary implementation detail",
+        issue = "none"
+    )]
+    #[doc(hidden)]
+    __variant1,
+    #[unstable(
+        feature = "objc_selector_variant",
+        reason = "temporary implementation detail",
+        issue = "none"
+    )]
+    #[doc(hidden)]
+    __variant2,
+}
+
+impl fmt::Debug for objc_selector {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("objc_selector").finish()
+    }
+}
+
+/// Equivalent to Objective-C’s `Class` type.
+pub type Class = *mut objc_class;
+
+/// Equivalent to Objective-C’s `SEL` type.
+pub type SEL = *mut objc_selector;
+
+/// Gets a reference to an Objective-C class.
+///
+/// This macro will yield an expression of type [`Class`] for the given class name string literal.
+///
+/// # Example
+///
+/// ```no_run
+/// #![feature(darwin_objc)]
+/// use core::os::darwin::objc;
+///
+/// let string_class = objc::class!("NSString");
+/// ```
+#[allow_internal_unstable(rustc_attrs)]
+pub macro class($classname:expr) {{
+    // Since static Objective-C class references actually end up with multiple definitions
+    // across dylib boundaries, we only expose the value of the static and don't provide a way to
+    // get the address of or a reference to the static.
+    unsafe extern "C" {
+        #[rustc_objc_class = $classname]
+        safe static VAL: $crate::os::darwin::objc::Class;
+    }
+    VAL
+}}
+
+/// Gets a reference to an Objective-C selector.
+///
+/// This macro will yield an expression of type [`SEL`] for the given method name string literal.
+///
+/// It is similar to Objective-C’s `@selector` directive.
+///
+/// # Examples
+///
+/// ```no_run
+/// #![feature(darwin_objc)]
+/// use core::os::darwin::objc;
+///
+/// let alloc_sel = objc::selector!("alloc");
+/// let init_sel = objc::selector!("initWithCString:encoding:");
+/// ```
+#[allow_internal_unstable(rustc_attrs)]
+pub macro selector($methname:expr) {{
+    // Since static Objective-C selector references actually end up with multiple definitions
+    // across dylib boundaries, we only expose the value of the static and don't provide a way to
+    // get the address of or a reference to the static.
+    unsafe extern "C" {
+        #[rustc_objc_selector = $methname]
+        safe static VAL: $crate::os::darwin::objc::SEL;
+    }
+    VAL
+}}
diff --git a/library/core/src/os/mod.rs b/library/core/src/os/mod.rs
new file mode 100644
index 00000000000..897f59f530e
--- /dev/null
+++ b/library/core/src/os/mod.rs
@@ -0,0 +1,24 @@
+//! OS-specific functionality.
+
+#![unstable(feature = "darwin_objc", issue = "145496")]
+
+#[cfg(all(
+    doc,
+    any(
+        all(target_arch = "wasm32", not(target_os = "wasi")),
+        all(target_vendor = "fortanix", target_env = "sgx")
+    )
+))]
+#[unstable(issue = "none", feature = "std_internals")]
+pub mod darwin {}
+
+// darwin
+#[cfg(not(all(
+    doc,
+    any(
+        all(target_arch = "wasm32", not(target_os = "wasi")),
+        all(target_vendor = "fortanix", target_env = "sgx")
+    )
+)))]
+#[cfg(any(target_vendor = "apple", doc))]
+pub mod darwin;
diff --git a/library/coretests/tests/ascii.rs b/library/coretests/tests/ascii.rs
index ce09ee507f1..297aa114e00 100644
--- a/library/coretests/tests/ascii.rs
+++ b/library/coretests/tests/ascii.rs
@@ -505,3 +505,10 @@ fn test_escape_ascii_iter() {
     let _ = it.advance_back_by(4);
     assert_eq!(it.to_string(), r#"fastpath\xffremainder"#);
 }
+
+#[test]
+fn test_invalid_u8() {
+    for c in 128..=255 {
+        assert_eq!(core::ascii::Char::from_u8(c), None);
+    }
+}
diff --git a/library/std/src/os/darwin/mod.rs b/library/std/src/os/darwin/mod.rs
index 3b1bd974fa3..ff184f477fb 100644
--- a/library/std/src/os/darwin/mod.rs
+++ b/library/std/src/os/darwin/mod.rs
@@ -17,6 +17,8 @@
 #![doc(cfg(target_vendor = "apple"))]
 
 pub mod fs;
+pub mod objc;
+
 // deprecated, but used for public reexport under `std::os::unix::raw`, as
 // well as `std::os::macos`/`std::os::ios`, because those modules precede the
 // decision to remove these.
diff --git a/library/std/src/os/darwin/objc.rs b/library/std/src/os/darwin/objc.rs
new file mode 100644
index 00000000000..a4b31fee7c5
--- /dev/null
+++ b/library/std/src/os/darwin/objc.rs
@@ -0,0 +1,13 @@
+//! Defines types and macros for Objective-C interoperability.
+//!
+//! This module re-exports all the items in [`core::os::darwin::objc`].
+//!
+//! [`core::os::darwin::objc`]: ../../../../core/os/darwin/objc/index.html "mod core::os::darwin::objc"
+
+#![unstable(feature = "darwin_objc", issue = "145496")]
+
+// We can't generate an intra-doc link for this automatically since `core::os::darwin` isn't
+// compiled into `core` on every platform even though it's documented on every platform.
+// We just link to it directly in the module documentation above instead.
+#[cfg(not(doc))]
+pub use core::os::darwin::objc::*;
diff --git a/library/std/src/sys/args/zkvm.rs b/library/std/src/sys/args/zkvm.rs
index 194ba7159d4..d26bf1eaff9 100644
--- a/library/std/src/sys/args/zkvm.rs
+++ b/library/std/src/sys/args/zkvm.rs
@@ -1,25 +1,20 @@
-use crate::ffi::OsString;
-use crate::fmt;
-use crate::sys::os_str;
+use crate::ffi::{OsStr, OsString};
+use crate::num::NonZero;
+use crate::sync::OnceLock;
 use crate::sys::pal::{WORD_SIZE, abi};
-use crate::sys_common::FromInner;
-
-pub struct Args {
-    i_forward: usize,
-    i_back: usize,
-    count: usize,
-}
+use crate::{fmt, ptr, slice};
 
 pub fn args() -> Args {
-    let count = unsafe { abi::sys_argc() };
-    Args { i_forward: 0, i_back: 0, count }
+    Args { iter: ARGS.get_or_init(|| get_args()).iter() }
 }
 
-impl Args {
-    /// Use sys_argv to get the arg at the requested index. Does not check that i is less than argc
-    /// and will not return if the index is out of bounds.
-    fn argv(i: usize) -> OsString {
-        let arg_len = unsafe { abi::sys_argv(crate::ptr::null_mut(), 0, i) };
+fn get_args() -> Vec<&'static OsStr> {
+    let argc = unsafe { abi::sys_argc() };
+    let mut args = Vec::with_capacity(argc);
+
+    for i in 0..argc {
+        // Get the size of the argument then the data.
+        let arg_len = unsafe { abi::sys_argv(ptr::null_mut(), 0, i) };
 
         let arg_len_words = (arg_len + WORD_SIZE - 1) / WORD_SIZE;
         let words = unsafe { abi::sys_alloc_words(arg_len_words) };
@@ -27,20 +22,24 @@ impl Args {
         let arg_len2 = unsafe { abi::sys_argv(words, arg_len_words, i) };
         debug_assert_eq!(arg_len, arg_len2);
 
-        // Convert to OsString.
-        //
-        // FIXME: We can probably get rid of the extra copy here if we
-        // reimplement "os_str" instead of just using the generic unix
-        // "os_str".
-        let arg_bytes: &[u8] =
-            unsafe { crate::slice::from_raw_parts(words.cast() as *const u8, arg_len) };
-        OsString::from_inner(os_str::Buf { inner: arg_bytes.to_vec() })
+        let arg_bytes = unsafe { slice::from_raw_parts(words.cast(), arg_len) };
+        args.push(unsafe { OsStr::from_encoded_bytes_unchecked(arg_bytes) });
     }
+    args
 }
 
+static ARGS: OnceLock<Vec<&'static OsStr>> = OnceLock::new();
+
+pub struct Args {
+    iter: slice::Iter<'static, &'static OsStr>,
+}
+
+impl !Send for Args {}
+impl !Sync for Args {}
+
 impl fmt::Debug for Args {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_list().finish()
+        self.iter.as_slice().fmt(f)
     }
 }
 
@@ -48,34 +47,48 @@ impl Iterator for Args {
     type Item = OsString;
 
     fn next(&mut self) -> Option<OsString> {
-        if self.i_forward >= self.count - self.i_back {
-            None
-        } else {
-            let arg = Self::argv(self.i_forward);
-            self.i_forward += 1;
-            Some(arg)
-        }
+        self.iter.next().map(|arg| arg.to_os_string())
     }
 
+    #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
-        (self.count, Some(self.count))
+        self.iter.size_hint()
     }
-}
 
-impl ExactSizeIterator for Args {
-    fn len(&self) -> usize {
-        self.count
+    #[inline]
+    fn count(self) -> usize {
+        self.iter.len()
+    }
+
+    fn last(self) -> Option<OsString> {
+        self.iter.last().map(|arg| arg.to_os_string())
+    }
+
+    #[inline]
+    fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
+        self.iter.advance_by(n)
     }
 }
 
 impl DoubleEndedIterator for Args {
     fn next_back(&mut self) -> Option<OsString> {
-        if self.i_back >= self.count - self.i_forward {
-            None
-        } else {
-            let arg = Self::argv(self.count - 1 - self.i_back);
-            self.i_back += 1;
-            Some(arg)
-        }
+        self.iter.next_back().map(|arg| arg.to_os_string())
+    }
+
+    #[inline]
+    fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
+        self.iter.advance_back_by(n)
+    }
+}
+
+impl ExactSizeIterator for Args {
+    #[inline]
+    fn len(&self) -> usize {
+        self.iter.len()
+    }
+
+    #[inline]
+    fn is_empty(&self) -> bool {
+        self.iter.is_empty()
     }
 }
diff --git a/library/test/src/cli.rs b/library/test/src/cli.rs
index 1b3f9e2564c..35291cc15c9 100644
--- a/library/test/src/cli.rs
+++ b/library/test/src/cli.rs
@@ -57,6 +57,7 @@ fn optgroups() -> getopts::Options {
         .optflag("", "test", "Run tests and not benchmarks")
         .optflag("", "bench", "Run benchmarks instead of tests")
         .optflag("", "list", "List all tests and benchmarks")
+        .optflag("", "fail-fast", "Don't start new tests after the first failure")
         .optflag("h", "help", "Display this message")
         .optopt("", "logfile", "Write logs to the specified file (deprecated)", "PATH")
         .optflag(
@@ -260,6 +261,7 @@ fn parse_opts_impl(matches: getopts::Matches) -> OptRes {
     // Unstable flags
     let force_run_in_process = unstable_optflag!(matches, allow_unstable, "force-run-in-process");
     let exclude_should_panic = unstable_optflag!(matches, allow_unstable, "exclude-should-panic");
+    let fail_fast = unstable_optflag!(matches, allow_unstable, "fail-fast");
     let time_options = get_time_options(&matches, allow_unstable)?;
     let shuffle = get_shuffle(&matches, allow_unstable)?;
     let shuffle_seed = get_shuffle_seed(&matches, allow_unstable)?;
@@ -306,7 +308,7 @@ fn parse_opts_impl(matches: getopts::Matches) -> OptRes {
         skip,
         time_options,
         options,
-        fail_fast: false,
+        fail_fast,
     };
 
     Ok(test_opts)
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 19e87f9c293..effd33d288f 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -1193,8 +1193,6 @@ class RustBuild(object):
             return "<commit>"
         cmd = [
             "git",
-            "-C",
-            repo_path,
             "rev-list",
             "--author",
             author_email,
@@ -1202,7 +1200,9 @@ class RustBuild(object):
             "HEAD",
         ]
         try:
-            commit = subprocess.check_output(cmd, universal_newlines=True).strip()
+            commit = subprocess.check_output(
+                cmd, universal_newlines=True, cwd=repo_path
+            ).strip()
             return commit or "<commit>"
         except subprocess.CalledProcessError:
             return "<commit>"
diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py
index b05a5cc8b81..1915986be28 100755
--- a/src/bootstrap/configure.py
+++ b/src/bootstrap/configure.py
@@ -340,6 +340,11 @@ o(
     "don't truncate options when printing them in this configure script",
 )
 v("set", None, "set arbitrary key/value pairs in TOML configuration")
+v(
+    "parallel-frontend-threads",
+    "rust.parallel-frontend-threads",
+    "number of parallel threads for rustc compilation",
+)
 
 
 def p(msg):
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index 1458b0beefa..14104d7d1d7 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -1357,10 +1357,6 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetS
         cargo.env("RUSTC_VERIFY_LLVM_IR", "1");
     }
 
-    if builder.config.llvm_enzyme {
-        cargo.rustflag("--cfg=llvm_enzyme");
-    }
-
     // These conditionals represent a tension between three forces:
     // - For non-check builds, we need to define some LLVM-related environment
     //   variables, requiring LLVM to have been built.
diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs
index 83ed7430c39..d43d261ad6c 100644
--- a/src/bootstrap/src/core/build_steps/llvm.rs
+++ b/src/bootstrap/src/core/build_steps/llvm.rs
@@ -619,11 +619,11 @@ fn check_llvm_version(builder: &Builder<'_>, llvm_config: &Path) {
     let version = get_llvm_version(builder, llvm_config);
     let mut parts = version.split('.').take(2).filter_map(|s| s.parse::<u32>().ok());
     if let (Some(major), Some(_minor)) = (parts.next(), parts.next())
-        && major >= 19
+        && major >= 20
     {
         return;
     }
-    panic!("\n\nbad LLVM version: {version}, need >=19\n\n")
+    panic!("\n\nbad LLVM version: {version}, need >=20\n\n")
 }
 
 fn configure_cmake(
diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs
index 8e65ec7ce50..6121bf7d9cd 100644
--- a/src/bootstrap/src/core/builder/cargo.rs
+++ b/src/bootstrap/src/core/builder/cargo.rs
@@ -679,6 +679,12 @@ impl Builder<'_> {
         // cargo would implicitly add it, it was discover that sometimes bootstrap only use
         // `rustflags` without `cargo` making it required.
         rustflags.arg("-Zunstable-options");
+
+        // Add parallel frontend threads configuration
+        if let Some(threads) = self.config.rust_parallel_frontend_threads {
+            rustflags.arg(&format!("-Zthreads={threads}"));
+        }
+
         for (restricted_mode, name, values) in EXTRA_CHECK_CFGS {
             if restricted_mode.is_none() || *restricted_mode == Some(mode) {
                 rustflags.arg(&check_cfg_arg(name, *values));
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index 678a9b63952..efb7ad91699 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -191,7 +191,6 @@ pub struct Config {
     pub rust_optimize: RustOptimize,
     pub rust_codegen_units: Option<u32>,
     pub rust_codegen_units_std: Option<u32>,
-
     pub rustc_debug_assertions: bool,
     pub std_debug_assertions: bool,
     pub tools_debug_assertions: bool,
@@ -222,6 +221,8 @@ pub struct Config {
     pub rust_validate_mir_opts: Option<u32>,
     pub rust_std_features: BTreeSet<String>,
     pub rust_break_on_ice: bool,
+    pub rust_parallel_frontend_threads: Option<u32>,
+
     pub llvm_profile_use: Option<String>,
     pub llvm_profile_generate: bool,
     pub llvm_libunwind_default: Option<LlvmLibunwind>,
@@ -534,6 +535,7 @@ impl Config {
             backtrace_on_ice: rust_backtrace_on_ice,
             verify_llvm_ir: rust_verify_llvm_ir,
             thin_lto_import_instr_limit: rust_thin_lto_import_instr_limit,
+            parallel_frontend_threads: rust_parallel_frontend_threads,
             remap_debuginfo: rust_remap_debuginfo,
             jemalloc: rust_jemalloc,
             test_compare_mode: rust_test_compare_mode,
@@ -1298,6 +1300,7 @@ impl Config {
             rust_overflow_checks_std: rust_overflow_checks_std
                 .or(rust_overflow_checks)
                 .unwrap_or(rust_debug == Some(true)),
+            rust_parallel_frontend_threads: rust_parallel_frontend_threads.map(threads_from_config),
             rust_profile_generate: flags_rust_profile_generate.or(rust_profile_generate),
             rust_profile_use: flags_rust_profile_use.or(rust_profile_use),
             rust_randomize_layout: rust_randomize_layout.unwrap_or(false),
@@ -1853,13 +1856,7 @@ fn load_toml_config(
         } else {
             toml_path.clone()
         });
-        (
-            get_toml(&toml_path).unwrap_or_else(|e| {
-                eprintln!("ERROR: Failed to parse '{}': {e}", toml_path.display());
-                exit!(2);
-            }),
-            path,
-        )
+        (get_toml(&toml_path).unwrap_or_else(|e| bad_config(&toml_path, e)), path)
     } else {
         (TomlConfig::default(), None)
     }
@@ -1892,10 +1889,8 @@ fn postprocess_toml(
             .unwrap()
             .join(include_path);
 
-        let included_toml = get_toml(&include_path).unwrap_or_else(|e| {
-            eprintln!("ERROR: Failed to parse '{}': {e}", include_path.display());
-            exit!(2);
-        });
+        let included_toml =
+            get_toml(&include_path).unwrap_or_else(|e| bad_config(&include_path, e));
         toml.merge(
             Some(include_path),
             &mut Default::default(),
@@ -2398,3 +2393,98 @@ pub(crate) fn read_file_by_commit<'a>(
     git.arg("show").arg(format!("{commit}:{}", file.to_str().unwrap()));
     git.run_capture_stdout(dwn_ctx.exec_ctx).stdout()
 }
+
+fn bad_config(toml_path: &Path, e: toml::de::Error) -> ! {
+    eprintln!("ERROR: Failed to parse '{}': {e}", toml_path.display());
+    let e_s = e.to_string();
+    if e_s.contains("unknown field")
+        && let Some(field_name) = e_s.split("`").nth(1)
+        && let sections = find_correct_section_for_field(field_name)
+        && !sections.is_empty()
+    {
+        if sections.len() == 1 {
+            match sections[0] {
+                WouldBeValidFor::TopLevel { is_section } => {
+                    if is_section {
+                        eprintln!(
+                            "hint: section name `{field_name}` used as a key within a section"
+                        );
+                    } else {
+                        eprintln!("hint: try using `{field_name}` as a top level key");
+                    }
+                }
+                WouldBeValidFor::Section(section) => {
+                    eprintln!("hint: try moving `{field_name}` to the `{section}` section")
+                }
+            }
+        } else {
+            eprintln!(
+                "hint: `{field_name}` would be valid {}",
+                join_oxford_comma(sections.iter(), "or"),
+            );
+        }
+    }
+
+    exit!(2);
+}
+
+#[derive(Copy, Clone, Debug)]
+enum WouldBeValidFor {
+    TopLevel { is_section: bool },
+    Section(&'static str),
+}
+
+fn join_oxford_comma(
+    mut parts: impl ExactSizeIterator<Item = impl std::fmt::Display>,
+    conj: &str,
+) -> String {
+    use std::fmt::Write;
+    let mut out = String::new();
+
+    assert!(parts.len() > 1);
+    while let Some(part) = parts.next() {
+        if parts.len() == 0 {
+            write!(&mut out, "{conj} {part}")
+        } else {
+            write!(&mut out, "{part}, ")
+        }
+        .unwrap();
+    }
+    out
+}
+
+impl std::fmt::Display for WouldBeValidFor {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        match self {
+            Self::TopLevel { .. } => write!(f, "at top level"),
+            Self::Section(section_name) => write!(f, "in section `{section_name}`"),
+        }
+    }
+}
+
+fn find_correct_section_for_field(field_name: &str) -> Vec<WouldBeValidFor> {
+    let sections = ["build", "install", "llvm", "gcc", "rust", "dist"];
+    sections
+        .iter()
+        .map(Some)
+        .chain([None])
+        .filter_map(|section_name| {
+            let dummy_config_str = if let Some(section_name) = section_name {
+                format!("{section_name}.{field_name} = 0\n")
+            } else {
+                format!("{field_name} = 0\n")
+            };
+            let is_unknown_field = toml::from_str::<toml::Value>(&dummy_config_str)
+                .and_then(TomlConfig::deserialize)
+                .err()
+                .is_some_and(|e| e.to_string().contains("unknown field"));
+            if is_unknown_field {
+                None
+            } else {
+                Some(section_name.copied().map(WouldBeValidFor::Section).unwrap_or_else(|| {
+                    WouldBeValidFor::TopLevel { is_section: sections.contains(&field_name) }
+                }))
+            }
+        })
+        .collect()
+}
diff --git a/src/bootstrap/src/core/config/toml/rust.rs b/src/bootstrap/src/core/config/toml/rust.rs
index 4832a1d37b7..e5987d7040a 100644
--- a/src/bootstrap/src/core/config/toml/rust.rs
+++ b/src/bootstrap/src/core/config/toml/rust.rs
@@ -66,6 +66,7 @@ define_config! {
         validate_mir_opts: Option<u32> = "validate-mir-opts",
         std_features: Option<BTreeSet<String>> = "std-features",
         break_on_ice: Option<bool> = "break-on-ice",
+        parallel_frontend_threads: Option<u32> = "parallel-frontend-threads",
     }
 }
 
@@ -357,6 +358,7 @@ pub fn check_incompatible_options_for_ci_rustc(
         validate_mir_opts: _,
         frame_pointers: _,
         break_on_ice: _,
+        parallel_frontend_threads: _,
     } = ci_rust_config;
 
     // There are two kinds of checks for CI rustc incompatible options:
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index a2aeed20948..e953fe2945e 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -87,9 +87,6 @@ const EXTRA_CHECK_CFGS: &[(Option<Mode>, &str, Option<&[&'static str]>)] = &[
     (Some(Mode::Codegen), "bootstrap", None),
     (Some(Mode::ToolRustcPrivate), "bootstrap", None),
     (Some(Mode::ToolStd), "bootstrap", None),
-    (Some(Mode::Rustc), "llvm_enzyme", None),
-    (Some(Mode::Codegen), "llvm_enzyme", None),
-    (Some(Mode::ToolRustcPrivate), "llvm_enzyme", None),
     (Some(Mode::ToolRustcPrivate), "rust_analyzer", None),
     (Some(Mode::ToolStd), "rust_analyzer", None),
     // Any library specific cfgs like `target_os`, `target_arch` should be put in
@@ -869,6 +866,9 @@ impl Build {
         if (self.config.llvm_enabled(target) || kind == Kind::Check) && check("llvm") {
             features.push("llvm");
         }
+        if self.config.llvm_enzyme {
+            features.push("llvm_enzyme");
+        }
         // keep in sync with `bootstrap/compile.rs:rustc_cargo_env`
         if self.config.rust_randomize_layout && check("rustc_randomized_layouts") {
             features.push("rustc_randomized_layouts");
diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs
index 03b39882e30..2c48cebd2df 100644
--- a/src/bootstrap/src/utils/change_tracker.rs
+++ b/src/bootstrap/src/utils/change_tracker.rs
@@ -546,4 +546,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
         severity: ChangeSeverity::Info,
         summary: "The default value of the `gcc.download-ci-gcc` option has been changed to `true`.",
     },
+    ChangeInfo {
+        change_id: 146458,
+        severity: ChangeSeverity::Info,
+        summary: "There is now a bootstrap option called `rust.parallel-frontend-threads`, which can be used to set the number of threads for the compiler frontend used during compilation of Rust code.",
+    },
 ];
diff --git a/src/ci/docker/README.md b/src/ci/docker/README.md
index 488a6a2bce1..4ee02e9bf00 100644
--- a/src/ci/docker/README.md
+++ b/src/ci/docker/README.md
@@ -14,9 +14,9 @@ To run a specific CI job locally, you can use the `citool` Rust crate:
 cargo run --manifest-path src/ci/citool/Cargo.toml run-local <job-name>
 ```
 
-For example, to run the `x86_64-gnu-llvm-19-1` job:
+For example, to run the `x86_64-gnu-llvm-20-1` job:
 ```
-cargo run --manifest-path src/ci/citool/Cargo.toml run-local x86_64-gnu-llvm-19-1
+cargo run --manifest-path src/ci/citool/Cargo.toml run-local x86_64-gnu-llvm-20-1
 ```
 
 The job will output artifacts in an `obj/<image-name>` dir at the root of a repository. Note
@@ -27,10 +27,10 @@ Docker image executed in the given CI job.
 while locally, to the `obj/<image-name>` directory. This is primarily to prevent
 strange linker errors when using multiple Docker images.
 
-For some Linux workflows (for example `x86_64-gnu-llvm-19-N`), the process is more involved. You will need to see which script is executed for the given workflow inside the [`jobs.yml`](../github-actions/jobs.yml) file and pass it through the `DOCKER_SCRIPT` environment variable. For example, to reproduce the `x86_64-gnu-llvm-19-3` workflow, you can run the following script:
+For some Linux workflows (for example `x86_64-gnu-llvm-20-N`), the process is more involved. You will need to see which script is executed for the given workflow inside the [`jobs.yml`](../github-actions/jobs.yml) file and pass it through the `DOCKER_SCRIPT` environment variable. For example, to reproduce the `x86_64-gnu-llvm-20-3` workflow, you can run the following script:
 
 ```
-DOCKER_SCRIPT=x86_64-gnu-llvm3.sh ./src/ci/docker/run.sh x86_64-gnu-llvm-19
+DOCKER_SCRIPT=x86_64-gnu-llvm3.sh ./src/ci/docker/run.sh x86_64-gnu-llvm-20
 ```
 
 ## Local Development
diff --git a/src/ci/docker/host-aarch64/aarch64-gnu-llvm-19/Dockerfile b/src/ci/docker/host-aarch64/aarch64-gnu-llvm-20/Dockerfile
index e73fbe506f7..adbb1f03378 100644
--- a/src/ci/docker/host-aarch64/aarch64-gnu-llvm-19/Dockerfile
+++ b/src/ci/docker/host-aarch64/aarch64-gnu-llvm-20/Dockerfile
@@ -1,4 +1,4 @@
-FROM ubuntu:24.10
+FROM ubuntu:25.04
 
 ARG DEBIAN_FRONTEND=noninteractive
 
@@ -15,8 +15,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   cmake \
   sudo \
   gdb \
-  llvm-19-tools \
-  llvm-19-dev \
+  llvm-20-tools \
+  llvm-20-dev \
   libedit-dev \
   libssl-dev \
   pkg-config \
@@ -43,7 +43,7 @@ ENV EXTERNAL_LLVM 1
 # Using llvm-link-shared due to libffi issues -- see #34486
 ENV RUST_CONFIGURE_ARGS \
       --build=aarch64-unknown-linux-gnu \
-      --llvm-root=/usr/lib/llvm-19 \
+      --llvm-root=/usr/lib/llvm-20 \
       --enable-llvm-link-shared \
       --set rust.randomize-layout=true \
       --set rust.thin-lto-import-instr-limit=10
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile
deleted file mode 100644
index 5cba7c564f1..00000000000
--- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile
+++ /dev/null
@@ -1,66 +0,0 @@
-FROM ubuntu:24.10
-
-ARG DEBIAN_FRONTEND=noninteractive
-
-RUN apt-get update && apt-get install -y --no-install-recommends \
-  bzip2 \
-  g++ \
-  gcc-multilib \
-  make \
-  ninja-build \
-  file \
-  curl \
-  ca-certificates \
-  python3 \
-  git \
-  cmake \
-  sudo \
-  gdb \
-  llvm-19-tools \
-  llvm-19-dev \
-  libedit-dev \
-  libssl-dev \
-  pkg-config \
-  zlib1g-dev \
-  xz-utils \
-  nodejs \
-  mingw-w64 \
-  # libgccjit dependencies
-  flex \
-  libmpfr-dev \
-  libgmp-dev \
-  libmpc3 \
-  libmpc-dev \
-  && rm -rf /var/lib/apt/lists/*
-
-# Install powershell (universal package) so we can test x.ps1 on Linux
-# FIXME: need a "universal" version that supports libicu74, but for now it still works to ignore that dep.
-RUN curl -sL "https://github.com/PowerShell/PowerShell/releases/download/v7.3.1/powershell_7.3.1-1.deb_amd64.deb" > powershell.deb && \
-    dpkg --ignore-depends=libicu72 -i powershell.deb && \
-    rm -f powershell.deb
-
-COPY scripts/sccache.sh /scripts/
-RUN sh /scripts/sccache.sh
-
-# We are disabling CI LLVM since this builder is intentionally using a host
-# LLVM, rather than the typical src/llvm-project LLVM.
-ENV NO_DOWNLOAD_CI_LLVM 1
-ENV EXTERNAL_LLVM 1
-
-# Using llvm-link-shared due to libffi issues -- see #34486
-ENV RUST_CONFIGURE_ARGS \
-      --build=x86_64-unknown-linux-gnu \
-      --llvm-root=/usr/lib/llvm-19 \
-      --enable-llvm-link-shared \
-      --set rust.randomize-layout=true \
-      --set rust.thin-lto-import-instr-limit=10
-
-COPY scripts/shared.sh /scripts/
-
-COPY scripts/x86_64-gnu-llvm.sh /scripts/
-COPY scripts/x86_64-gnu-llvm2.sh /scripts/
-COPY scripts/x86_64-gnu-llvm3.sh /scripts/
-COPY scripts/stage_2_test_set1.sh /scripts/
-COPY scripts/stage_2_test_set2.sh /scripts/
-
-ENV SCRIPT "Must specify DOCKER_SCRIPT for this image"
diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml
index 35b9456d37d..b3e3fe7d96a 100644
--- a/src/ci/github-actions/jobs.yml
+++ b/src/ci/github-actions/jobs.yml
@@ -122,19 +122,19 @@ pr:
       # tidy. This speeds up the PR CI job by ~1 minute.
       SKIP_SUBMODULES: src/gcc
     <<: *job-linux-4c
-  - name: x86_64-gnu-llvm-19
+  - name: x86_64-gnu-llvm-20
     env:
       ENABLE_GCC_CODEGEN: "1"
       DOCKER_SCRIPT: x86_64-gnu-llvm.sh
     <<: *job-linux-4c
-  - name: aarch64-gnu-llvm-19-1
+  - name: aarch64-gnu-llvm-20-1
     env:
-      IMAGE: aarch64-gnu-llvm-19
+      IMAGE: aarch64-gnu-llvm-20
       DOCKER_SCRIPT: stage_2_test_set1.sh
     <<: *job-aarch64-linux
-  - name: aarch64-gnu-llvm-19-2
+  - name: aarch64-gnu-llvm-20-2
     env:
-      IMAGE: aarch64-gnu-llvm-19
+      IMAGE: aarch64-gnu-llvm-20
       DOCKER_SCRIPT: stage_2_test_set2.sh
     <<: *job-aarch64-linux
   - name: x86_64-gnu-tools
@@ -397,31 +397,6 @@ auto:
       DOCKER_SCRIPT: x86_64-gnu-llvm3.sh
     <<: *job-linux-4c
 
-  # The x86_64-gnu-llvm-19 job is split into multiple jobs to run tests in parallel.
-  # x86_64-gnu-llvm-19-1 skips tests that run in x86_64-gnu-llvm-19-{2,3}.
-  - name: x86_64-gnu-llvm-19-1
-    env:
-      RUST_BACKTRACE: 1
-      IMAGE: x86_64-gnu-llvm-19
-      DOCKER_SCRIPT: stage_2_test_set2.sh
-    <<: *job-linux-4c
-
-  # Skip tests that run in x86_64-gnu-llvm-19-{1,3}
-  - name: x86_64-gnu-llvm-19-2
-    env:
-      RUST_BACKTRACE: 1
-      IMAGE: x86_64-gnu-llvm-19
-      DOCKER_SCRIPT: x86_64-gnu-llvm2.sh
-    <<: *job-linux-4c
-
-  # Skip tests that run in x86_64-gnu-llvm-19-{1,2}
-  - name: x86_64-gnu-llvm-19-3
-    env:
-      RUST_BACKTRACE: 1
-      IMAGE: x86_64-gnu-llvm-19
-      DOCKER_SCRIPT: x86_64-gnu-llvm3.sh
-    <<: *job-linux-4c
-
   - name: x86_64-gnu-nopt
     <<: *job-linux-4c
 
diff --git a/src/doc/rustc-dev-guide/src/tests/intro.md b/src/doc/rustc-dev-guide/src/tests/intro.md
index b90c16d602c..4fa63b83b17 100644
--- a/src/doc/rustc-dev-guide/src/tests/intro.md
+++ b/src/doc/rustc-dev-guide/src/tests/intro.md
@@ -70,10 +70,12 @@ package tests:
 
 Tidy is a custom tool used for validating source code style and formatting
 conventions, such as rejecting long lines. There is more information in the
-[section on coding conventions](../conventions.md#formatting).
+[section on coding conventions](../conventions.md#formatting) or the [Tidy Readme].
 
 > Examples: `./x test tidy`
 
+[Tidy Readme]: https://github.com/rust-lang/rust/blob/master/src/tools/tidy/Readme.md
+
 
 ### Formatting
 
diff --git a/src/doc/rustc/src/tests/index.md b/src/doc/rustc/src/tests/index.md
index 7609ed23351..7a108a71beb 100644
--- a/src/doc/rustc/src/tests/index.md
+++ b/src/doc/rustc/src/tests/index.md
@@ -158,6 +158,18 @@ unstable-options` flag. See [tracking issue
 
 The following options affect how tests are executed.
 
+#### `--fail-fast`
+
+Stops tests after the first failure.
+
+If running tests in parallel (which is the default), then tests that have already been started on
+other threads will be allowed to run to completion before the process exits.
+
+Note that when running tests in parallel, the test execution order is non-deterministic:
+if multiple tests would fail, the first failure encountered will be reported.
+
+⚠️ 🚧 This requires the `-Z unstable-options` flag.
+
 #### `--test-threads` _NUM_THREADS_
 
 Sets the number of threads to use for running tests in parallel. By default,
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 24bb93c388fb8c211a37986539f24a819dc669d
+Subproject 966f94733bbc94ca51ff9f1e4c49ad250ebbdc5
diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
index 68f0b5ea255..40fd2cdeb86 100644
--- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
@@ -126,7 +126,7 @@ fn check_rvalue<'tcx>(
 ) -> McfResult {
     match rvalue {
         Rvalue::ThreadLocalRef(_) => Err((span, "cannot access thread local storage in const fn".into())),
-        Rvalue::Len(place) | Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) | Rvalue::RawPtr(_, place) => {
+        Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) | Rvalue::RawPtr(_, place) => {
             check_place(cx, *place, span, body, msrv)
         },
         Rvalue::CopyForDeref(place) => check_place(cx, *place, span, body, msrv),
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 143ccdcb9e5..6da102b1b5f 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -203,6 +203,10 @@ impl CodegenBackend {
             Self::Llvm => "llvm",
         }
     }
+
+    pub fn is_llvm(self) -> bool {
+        matches!(self, Self::Llvm)
+    }
 }
 
 /// Configuration for `compiletest` *per invocation*.
diff --git a/src/tools/compiletest/src/directives/needs.rs b/src/tools/compiletest/src/directives/needs.rs
index ee46f4c70cb..3b7a9478717 100644
--- a/src/tools/compiletest/src/directives/needs.rs
+++ b/src/tools/compiletest/src/directives/needs.rs
@@ -81,8 +81,8 @@ pub(super) fn handle_needs(
         },
         Need {
             name: "needs-enzyme",
-            condition: config.has_enzyme,
-            ignore_reason: "ignored when LLVM Enzyme is disabled",
+            condition: config.has_enzyme && config.default_codegen_backend.is_llvm(),
+            ignore_reason: "ignored when LLVM Enzyme is disabled or LLVM is not the default codegen backend",
         },
         Need {
             name: "needs-run-enabled",
@@ -161,8 +161,8 @@ pub(super) fn handle_needs(
         },
         Need {
             name: "needs-llvm-zstd",
-            condition: cache.llvm_zstd,
-            ignore_reason: "ignored if LLVM wasn't build with zstd for ELF section compression",
+            condition: cache.llvm_zstd && config.default_codegen_backend.is_llvm(),
+            ignore_reason: "ignored if LLVM wasn't build with zstd for ELF section compression or LLVM is not the default codegen backend",
         },
         Need {
             name: "needs-rustc-debug-assertions",
@@ -279,7 +279,10 @@ pub(super) fn handle_needs(
 
     // Handled elsewhere.
     if name == "needs-llvm-components" {
-        return IgnoreDecision::Continue;
+        if config.default_codegen_backend.is_llvm() {
+            return IgnoreDecision::Continue;
+        }
+        return IgnoreDecision::Ignore { reason: "LLVM specific test".into() };
     }
 
     let mut found_valid = false;
diff --git a/src/tools/tidy/Readme.md b/src/tools/tidy/Readme.md
new file mode 100644
index 00000000000..fc9dc6350e9
--- /dev/null
+++ b/src/tools/tidy/Readme.md
@@ -0,0 +1,112 @@
+# Tidy
+Tidy is the Rust project's custom internal linter and a crucial part of our testing and continuous integration (CI) infrastructure. It is designed to enforce a consistent style and formatting across the entire codebase, but its role extends beyond simple linting. Tidy also helps with infrastructure, policy, and documentation, ensuring the project remains organized, functional, and... tidy.
+
+This document will cover how to use tidy, the specific checks tidy performs, and using tidy directives to manage its behavior. By understanding and utilizing tidy, you can help us maintain the high standards of the Rust project.
+## Tidy Checks
+### Style and Code Quality
+These lints focus on enforcing consistent formatting, style, and general code health.
+* [`alphabetical`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/alphabetical/index.html): Checks that lists are sorted alphabetically
+* [`style`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/style/index.html): Check to enforce various stylistic guidelines on the Rust codebase.
+* [`filenames`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/filenames/index.html): Check to prevent invalid characters in file names.
+* [`pal`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/pal/index.html): Check to enforce rules about platform-specific code in std.
+* [`target_policy`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/target_policy/index.html): Check for target tier policy compliance.
+* [`error_codes`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/error_codes/index.html): Check to ensure error codes are properly documented and tested.
+
+### Infrastructure
+These checks focus on the integrity of the project's dependencies, internal tools, and documentation.
+* [`bins`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/bins/index.html): Prevent stray binaries from being checked into the source tree.
+* [`fluent_alphabetical`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/fluent_alphabetical/index.html) / [`fluent_period`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/fluent_period/index.html) / [`fluent_used`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/fluent_used/index.html): Various checks related to [Fluent](https://github.com/projectfluent) for localization and natural language translation.
+* [`deps`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/deps/index.html) / [`extdeps`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/extdeps/index.html): Check for valid licenses and sources for external dependencies.
+* [`gcc_submodule`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/gcc_submodule/index.html): Check that the `src/gcc` submodule version is valid.
+* [`triagebot`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/triagebot/index.html): Check to ensure paths mentioned in `triagebot.toml` exist in the project.
+* [`x_version`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/x_version/index.html): Validates the current version of the `x` tool.
+
+* [`edition`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/edition/index.html) / [`features`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/features/index.html): Check for a valid Rust edition and proper ordering of unstable features.
+* [`rustdoc_css_themes`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/rustdoc_css_themes/index.html) / [`rustdoc_templates`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/rustdoc_templates/index.html): Verify that Rust documentation templates and themes are correct.
+* [`unstable_book`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/unstable_book/index.html): Synchronizes the unstable book with unstable features.
+### Testing
+These checks ensure that tests are correctly structured, cleaned up, and free of common errors.
+* [`tests_placement`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/tests_placement/index.html) / [`unit_tests`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/unit_tests/index.html): Verify that tests are located in the correct directories and are not using improper attributes.
+* [`known_bug`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/known_bug/index.html) / [`unknown_revision`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/unknown_revision/index.html): Ensure that test directives and annotations are used correctly.
+* [`debug_artifacts`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/debug_artifacts/index.html) / [`mir_opt_tests`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/mir_opt_tests/index.html): Prevent unnecessary artifacts and stale files in test directories.
+* [`tests_revision_unpaired_stdout_stderr`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/tests_revision_unpaired_stdout_stderr/index.html) / [`ui_tests`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/ui_tests/index.html): Check for unpaired or stray test output files.
+* [`target_specific_tests`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/target_specific_tests/index.html): Check to ensure that all target specific tests (those that require a --target flag) also require the pre-requisite LLVM components to run.
+* [`rustdoc_gui_tests`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/rustdoc_gui_tests/index.html): Checks that rustdoc gui tests start with a small description
+* [`rustdoc_json`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/rustdoc_json/index.html): Verify that `FORMAT_VERSION` is in sync with `rust-json-types`.
+## Using Tidy
+
+Tidy is used in a number of different ways.
+* Every time `./x test` is used tidy will run automatically.
+
+* On every pull request, tidy will run automatically during CI checks.
+* Optionally, with the use of git-hooks, tidy can run locally on every push. This can be setup with `./x setup`. See the [rustc-dev-guide](https://rustc-dev-guide.rust-lang.org/building/suggested.html#installing-a-pre-push-hook) for more information.
+
+You can run tidy manually with:
+
+`./x test tidy`
+
+To first run the relevant formatter and then run tidy you can add `--bless`.
+
+`./x test tidy --bless`
+### Extra Checks
+[`extra_checks`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/extra_checks/index.html) are optional checks primarily focused on other file types and programming languages.
+
+Example usage:
+
+`./x test tidy --extra-checks=py,cpp,js,spellcheck`
+
+All options for `--extra-checks`:
+* `cpp`, `cpp:fmt`
+* `py`, `py:lint`, `py:fmt`
+* `js`, `js:lint`, `js:fmt`, `js:typecheck`
+* `shell`, `shell:lint`
+* `spellcheck`
+
+Default values for tidy's `extra-checks` can be set in `bootstrap.toml`. For example, `build.tidy-extra-checks = "js,py"`.
+
+Any argument without a suffix (eg. `py` or `js`) will include all possible checks. For example, `--extra-checks=js` is the same as `extra-checks=js:lint,js:fmt,js:typecheck`.
+
+Any argument can be prefixed with `auto:` to only run if relevant files are modified (eg. `--extra-checks=auto:py`).
+
+A specific configuration file or folder can be passed to tidy after a double dash (`--extra-checks=py -- foo.py`)
+
+## Tidy Directives
+
+Tidy directives are special comments that help tidy operate.
+
+Tidy directives can be used in the following types of comments:
+* `// `
+* `# `
+* `/* {...} */`
+* `<!-- {...} -->`
+
+You might find yourself needing to ignore a specific tidy style check and can do so with:
+* `ignore-tidy-cr`
+* `ignore-tidy-undocumented-unsafe`
+* `ignore-tidy-tab`
+* `ignore-tidy-linelength`
+* `ignore-tidy-filelength`
+
+* `ignore-tidy-end-whitespace`
+* `ignore-tidy-trailing-newlines`
+* `ignore-tidy-leading-newlines`
+* `ignore-tidy-copyright`
+* `ignore-tidy-dbg`
+* `ignore-tidy-odd-backticks`
+* `ignore-tidy-todo`
+
+Some checks, like `alphabetical`, require a tidy directive to use:
+```
+// tidy-alphabetical-start
+fn aaa() {}
+fn eee() {}
+fn z() {}
+// tidy-alphabetical-end
+```
+<!--ignore-tidy-todo-->While not exactly a tidy directive, // TODO will fail tidy and make sure you can't merge a PR with unfinished work.
+
+### Test Specific Directives
+
+`target-specific-tests` can be ignored with `// ignore-tidy-target-specific-tests`
+
+Tidy's `unknown_revision` check can be suppressed by adding the revision name to `//@ unused-revision-names:{revision}` or with `//@ unused-revision-names:*`.
diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs
index 5b8b44429bb..991ad55809c 100644
--- a/src/tools/tidy/src/pal.rs
+++ b/src/tools/tidy/src/pal.rs
@@ -53,6 +53,7 @@ const EXCEPTION_PATHS: &[&str] = &[
     // core::ffi contains platform-specific type and linkage configuration
     "library/core/src/ffi/mod.rs",
     "library/core/src/ffi/primitives.rs",
+    "library/core/src/os", // Platform-specific public interfaces
     "library/std/src/sys", // Platform-specific code for std lives here.
     "library/std/src/os",  // Platform-specific public interfaces
     // Temporary `std` exceptions
diff --git a/tests/assembly-llvm/riscv-soft-abi-with-float-features.rs b/tests/assembly-llvm/riscv-soft-abi-with-float-features.rs
index 72cbd3841c1..085ea9facd0 100644
--- a/tests/assembly-llvm/riscv-soft-abi-with-float-features.rs
+++ b/tests/assembly-llvm/riscv-soft-abi-with-float-features.rs
@@ -2,9 +2,6 @@
 //@ assembly-output: emit-asm
 //@ compile-flags: --target riscv64imac-unknown-none-elf -Ctarget-feature=+f,+d
 //@ needs-llvm-components: riscv
-//@ revisions: LLVM-PRE-20 LLVM-POST-20
-//@ [LLVM-PRE-20] max-llvm-major-version: 19
-//@ [LLVM-POST-20] min-llvm-version: 20
 
 #![feature(no_core, lang_items, f16)]
 #![crate_type = "lib"]
@@ -28,11 +25,8 @@ pub extern "C" fn read_f16(x: &f16) -> f16 {
 // CHECK-LABEL: read_f32
 #[no_mangle]
 pub extern "C" fn read_f32(x: &f32) -> f32 {
-    // LLVM-PRE-20: flw fa5, 0(a0)
-    // LLVM-PRE-20-NEXT: fmv.x.w a0, fa5
-    // LLVM-PRE-20-NEXT: ret
-    // LLVM-POST-20: lw a0, 0(a0)
-    // LLVM-POST-20-NEXT: ret
+    // CHECK: lw a0, 0(a0)
+    // CHECK-NEXT: ret
     *x
 }
 
diff --git a/tests/assembly-llvm/x86_64-bigint-helpers.rs b/tests/assembly-llvm/x86_64-bigint-helpers.rs
index c5efda58fd6..64aa0257238 100644
--- a/tests/assembly-llvm/x86_64-bigint-helpers.rs
+++ b/tests/assembly-llvm/x86_64-bigint-helpers.rs
@@ -2,7 +2,6 @@
 //@ assembly-output: emit-asm
 //@ compile-flags: --crate-type=lib -Copt-level=3 -C target-cpu=x86-64-v4
 //@ compile-flags: -C llvm-args=-x86-asm-syntax=intel
-//@ min-llvm-version: 20
 
 #![no_std]
 #![feature(bigint_helper_methods)]
diff --git a/tests/assembly-llvm/x86_64-cmp.rs b/tests/assembly-llvm/x86_64-cmp.rs
index 26c9013d96f..1f1fe7fd005 100644
--- a/tests/assembly-llvm/x86_64-cmp.rs
+++ b/tests/assembly-llvm/x86_64-cmp.rs
@@ -1,12 +1,6 @@
-//@ revisions: LLVM-PRE-20-DEBUG LLVM-20-DEBUG LLVM-PRE-20-OPTIM LLVM-20-OPTIM
-//@ [LLVM-PRE-20-DEBUG] compile-flags: -C opt-level=0
-//@ [LLVM-PRE-20-DEBUG] max-llvm-major-version: 19
-//@ [LLVM-20-DEBUG] compile-flags: -C opt-level=0
-//@ [LLVM-20-DEBUG] min-llvm-version: 20
-//@ [LLVM-PRE-20-OPTIM] compile-flags: -C opt-level=3
-//@ [LLVM-PRE-20-OPTIM] max-llvm-major-version: 19
-//@ [LLVM-20-OPTIM] compile-flags: -C opt-level=3
-//@ [LLVM-20-OPTIM] min-llvm-version: 20
+//@ revisions: DEBUG OPTIM
+//@ [DEBUG] compile-flags: -C opt-level=0
+//@ [OPTIM] compile-flags: -C opt-level=3
 //@ assembly-output: emit-asm
 //@ compile-flags: --crate-type=lib -C llvm-args=-x86-asm-syntax=intel
 //@ only-x86_64
@@ -19,61 +13,22 @@ use std::intrinsics::three_way_compare;
 #[no_mangle]
 // CHECK-LABEL: signed_cmp:
 pub fn signed_cmp(a: i16, b: i16) -> std::cmp::Ordering {
-    // LLVM-PRE-20-DEBUG: cmp
-    // LLVM-PRE-20-DEBUG: setg
-    // LLVM-PRE-20-DEBUG: and
-    // LLVM-PRE-20-DEBUG: cmp
-    // LLVM-PRE-20-DEBUG: setl
-    // LLVM-PRE-20-DEBUG: and
-    // LLVM-PRE-20-DEBUG: sub
-    //
-    // LLVM-20-DEBUG: sub
-    // LLVM-20-DEBUG: setl
-    // LLVM-20-DEBUG: setg
-    // LLVM-20-DEBUG: sub
-    // LLVM-20-DEBUG: ret
-
-    // LLVM-PRE-20-OPTIM: xor
-    // LLVM-PRE-20-OPTIM: cmp
-    // LLVM-PRE-20-OPTIM: setne
-    // LLVM-PRE-20-OPTIM: mov
-    // LLVM-PRE-20-OPTIM: cmovge
-    // LLVM-PRE-20-OPTIM: ret
-    //
-    // LLVM-20-OPTIM: cmp
-    // LLVM-20-OPTIM: setl
-    // LLVM-20-OPTIM: setg
-    // LLVM-20-OPTIM: sub
-    // LLVM-20-OPTIM: ret
+    // DEBUG: sub
+    // OPTIM: cmp
+    // CHECK: setl
+    // CHECK: setg
+    // CHECK: sub
+    // CHECK: ret
     three_way_compare(a, b)
 }
 
 #[no_mangle]
 // CHECK-LABEL: unsigned_cmp:
 pub fn unsigned_cmp(a: u16, b: u16) -> std::cmp::Ordering {
-    // LLVM-PRE-20-DEBUG: cmp
-    // LLVM-PRE-20-DEBUG: seta
-    // LLVM-PRE-20-DEBUG: and
-    // LLVM-PRE-20-DEBUG: cmp
-    // LLVM-PRE-20-DEBUG: setb
-    // LLVM-PRE-20-DEBUG: and
-    // LLVM-PRE-20-DEBUG: sub
-    //
-    // LLVM-20-DEBUG: sub
-    // LLVM-20-DEBUG: seta
-    // LLVM-20-DEBUG: sbb
-    // LLVM-20-DEBUG: ret
-
-    // LLVM-PRE-20-OPTIM: xor
-    // LLVM-PRE-20-OPTIM: cmp
-    // LLVM-PRE-20-OPTIM: setne
-    // LLVM-PRE-20-OPTIM: mov
-    // LLVM-PRE-20-OPTIM: cmovae
-    // LLVM-PRE-20-OPTIM: ret
-    //
-    // LLVM-20-OPTIM: cmp
-    // LLVM-20-OPTIM: seta
-    // LLVM-20-OPTIM: sbb
-    // LLVM-20-OPTIM: ret
+    // DEBUG: sub
+    // OPTIM: cmp
+    // CHECK: seta
+    // CHECK: sbb
+    // CHECK: ret
     three_way_compare(a, b)
 }
diff --git a/tests/codegen-llvm/auxiliary/darwin_objc_aux.rs b/tests/codegen-llvm/auxiliary/darwin_objc_aux.rs
new file mode 100644
index 00000000000..3c35d003c8a
--- /dev/null
+++ b/tests/codegen-llvm/auxiliary/darwin_objc_aux.rs
@@ -0,0 +1,27 @@
+#![crate_type = "lib"]
+#![feature(darwin_objc)]
+
+use std::os::darwin::objc;
+
+#[link(name = "Foundation", kind = "framework")]
+unsafe extern "C" {}
+
+#[inline(always)]
+pub fn inline_get_object_class() -> objc::Class {
+    objc::class!("NSObject")
+}
+
+#[inline(always)]
+pub fn inline_get_alloc_selector() -> objc::SEL {
+    objc::selector!("alloc")
+}
+
+#[inline(never)]
+pub fn never_inline_get_string_class() -> objc::Class {
+    objc::class!("NSString")
+}
+
+#[inline(never)]
+pub fn never_inline_get_init_selector() -> objc::SEL {
+    objc::selector!("init")
+}
diff --git a/tests/codegen-llvm/comparison-operators-2-struct.rs b/tests/codegen-llvm/comparison-operators-2-struct.rs
index e179066ebfd..d44f92f511b 100644
--- a/tests/codegen-llvm/comparison-operators-2-struct.rs
+++ b/tests/codegen-llvm/comparison-operators-2-struct.rs
@@ -1,5 +1,4 @@
 //@ compile-flags: -C opt-level=1
-//@ min-llvm-version: 20
 
 // The `derive(PartialOrd)` for a 2-field type doesn't override `lt`/`le`/`gt`/`ge`.
 // This double-checks that the `Option<Ordering>` intermediate values used
diff --git a/tests/codegen-llvm/comparison-operators-2-tuple.rs b/tests/codegen-llvm/comparison-operators-2-tuple.rs
index 6a7e489c82d..37a7c5dfdaf 100644
--- a/tests/codegen-llvm/comparison-operators-2-tuple.rs
+++ b/tests/codegen-llvm/comparison-operators-2-tuple.rs
@@ -1,5 +1,4 @@
 //@ compile-flags: -C opt-level=1 -Z merge-functions=disabled
-//@ min-llvm-version: 20
 
 #![crate_type = "lib"]
 
diff --git a/tests/codegen-llvm/darwin-no-objc.rs b/tests/codegen-llvm/darwin-no-objc.rs
new file mode 100644
index 00000000000..fda3671fb6d
--- /dev/null
+++ b/tests/codegen-llvm/darwin-no-objc.rs
@@ -0,0 +1,52 @@
+// Test that we don't generate Objective-C definitions or image info unnecessarily.
+
+//@ add-core-stubs
+//@ revisions: i686_apple_darwin
+//@ [i686_apple_darwin] compile-flags: --target i686-apple-darwin
+//@ [i686_apple_darwin] needs-llvm-components: x86
+//@ revisions: x86_64_macos
+//@ [x86_64_macos] compile-flags: --target x86_64-apple-darwin
+//@ [x86_64_macos] needs-llvm-components: x86
+//@ revisions: aarch64_macos
+//@ [aarch64_macos] compile-flags: --target aarch64-apple-darwin
+//@ [aarch64_macos] needs-llvm-components: aarch64
+//@ revisions: i386_ios
+//@ [i386_ios] compile-flags: --target i386-apple-ios
+//@ [i386_ios] needs-llvm-components: x86
+//@ revisions: x86_64_ios
+//@ [x86_64_ios] compile-flags: --target x86_64-apple-ios
+//@ [x86_64_ios] needs-llvm-components: x86
+//@ revisions: armv7s_ios
+//@ [armv7s_ios] compile-flags: --target armv7s-apple-ios
+//@ [armv7s_ios] needs-llvm-components: arm
+//@ revisions: aarch64_ios
+//@ [aarch64_ios] compile-flags: --target aarch64-apple-ios
+//@ [aarch64_ios] needs-llvm-components: aarch64
+//@ revisions: aarch64_ios_sim
+//@ [aarch64_ios_sim] compile-flags: --target aarch64-apple-ios-sim
+//@ [aarch64_ios_sim] needs-llvm-components: aarch64
+
+#![crate_type = "lib"]
+#![feature(no_core, lang_items)]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
+
+#[no_mangle]
+pub fn foo() {}
+
+// CHECK-NOT: %struct._class_t
+// CHECK-NOT: %struct._objc_module
+// CHECK-NOT: @OBJC_CLASS_NAME_
+// CHECK-NOT: @"OBJC_CLASS_$_{{[0-9A-Z_a-z]+}}"
+// CHECK-NOT: @"OBJC_CLASSLIST_REFERENCES_$_.{{[0-9]+}}"
+// CHECK-NOT: @OBJC_METH_VAR_NAME_
+// CHECK-NOT: @OBJC_SELECTOR_REFERENCES_
+// CHECK-NOT: @OBJC_MODULES
+
+// CHECK-NOT: !"Objective-C Version"
+// CHECK-NOT: !"Objective-C Image Info Version"
+// CHECK-NOT: !"Objective-C Image Info Section"
+// CHECK-NOT: !"Objective-C Is Simulated"
+// CHECK-NOT: !"Objective-C Class Properties"
diff --git a/tests/codegen-llvm/darwin-objc-abi-v1.rs b/tests/codegen-llvm/darwin-objc-abi-v1.rs
new file mode 100644
index 00000000000..0fc1de9332a
--- /dev/null
+++ b/tests/codegen-llvm/darwin-objc-abi-v1.rs
@@ -0,0 +1,100 @@
+// ignore-tidy-linelength
+//@ add-core-stubs
+//@ revisions: i686_apple_darwin
+//@ [i686_apple_darwin] compile-flags: --target i686-apple-darwin
+//@ [i686_apple_darwin] needs-llvm-components: x86
+
+#![crate_type = "lib"]
+#![feature(no_core, lang_items, rustc_attrs)]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
+
+#[no_mangle]
+pub fn get_class() -> *mut () {
+    unsafe extern "C" {
+        #[rustc_objc_class = "MyClass"]
+        safe static VAL: *mut ();
+    }
+    VAL
+}
+
+#[no_mangle]
+pub fn get_class_again() -> *mut () {
+    // Codegen should de-duplicate this class with the one from get_class above.
+    unsafe extern "C" {
+        #[rustc_objc_class = "MyClass"]
+        safe static VAL: *mut ();
+    }
+    VAL
+}
+
+#[no_mangle]
+pub fn get_selector() -> *mut () {
+    unsafe extern "C" {
+        #[rustc_objc_selector = "myMethod"]
+        safe static VAL: *mut ();
+    }
+    VAL
+}
+
+#[no_mangle]
+pub fn get_selector_again() -> *mut () {
+    // Codegen should de-duplicate this selector with the one from get_selector above.
+    unsafe extern "C" {
+        #[rustc_objc_selector = "myMethod"]
+        safe static VAL: *mut ();
+    }
+    VAL
+}
+
+#[no_mangle]
+pub fn get_other_class() -> *mut () {
+    unsafe extern "C" {
+        #[rustc_objc_class = "OtherClass"]
+        safe static VAL: *mut ();
+    }
+    VAL
+}
+
+#[no_mangle]
+pub fn get_other_selector() -> *mut () {
+    unsafe extern "C" {
+        #[rustc_objc_selector = "otherMethod"]
+        safe static VAL: *mut ();
+    }
+    VAL
+}
+
+// CHECK: %struct._objc_module = type { i32, i32, ptr, ptr }
+
+// CHECK: @OBJC_CLASS_NAME_.{{[0-9]+}} = private unnamed_addr constant [8 x i8] c"MyClass\00", section "__TEXT,__cstring,cstring_literals", align 1
+// CHECK: @OBJC_CLASS_REFERENCES_.{{[0-9]+}} = private global ptr @OBJC_CLASS_NAME_.{{[0-9]+}}, section "__OBJC,__cls_refs,literal_pointers,no_dead_strip", align 4
+// CHECK-NOT: @OBJC_CLASS_NAME_
+// CHECK-NOT: @OBJC_CLASS_REFERENCES_
+
+// CHECK: @OBJC_METH_VAR_NAME_.{{[0-9]+}} = private unnamed_addr constant [9 x i8] c"myMethod\00", section "__TEXT,__cstring,cstring_literals", align 1
+// CHECK: @OBJC_SELECTOR_REFERENCES_.{{[0-9]+}} = private externally_initialized global ptr @OBJC_METH_VAR_NAME_.{{[0-9]+}}, section "__OBJC,__message_refs,literal_pointers,no_dead_strip", align 4
+// CHECK-NOT: @OBJC_METH_VAR_NAME_
+// CHECK-NOT: @OBJC_SELECTOR_REFERENCES_
+
+// CHECK: @OBJC_CLASS_NAME_.{{[0-9]+}} = private unnamed_addr constant [11 x i8] c"OtherClass\00", section "__TEXT,__cstring,cstring_literals", align 1
+// CHECK: @OBJC_CLASS_REFERENCES_.{{[0-9]+}} = private global ptr @OBJC_CLASS_NAME_.{{[0-9]+}}, section "__OBJC,__cls_refs,literal_pointers,no_dead_strip", align 4
+
+// CHECK: @OBJC_METH_VAR_NAME_.{{[0-9]+}} = private unnamed_addr constant [12 x i8] c"otherMethod\00", section "__TEXT,__cstring,cstring_literals", align 1
+// CHECK: @OBJC_SELECTOR_REFERENCES_.{{[0-9]+}} = private externally_initialized global ptr @OBJC_METH_VAR_NAME_.{{[0-9]+}}, section "__OBJC,__message_refs,literal_pointers,no_dead_strip", align 4
+
+// CHECK: @OBJC_CLASS_NAME_.{{[0-9]+}} = private unnamed_addr constant [1 x i8] zeroinitializer, section "__TEXT,__cstring,cstring_literals", align 1
+// CHECK: @OBJC_MODULES = private global %struct._objc_module { i32 7, i32 16, ptr @OBJC_CLASS_NAME_.{{[0-9]+}}, ptr null }, section "__OBJC,__module_info,regular,no_dead_strip", align 4
+
+// CHECK: load ptr, ptr @OBJC_CLASS_REFERENCES_.{{[0-9]+}}, align 4
+// CHECK: load ptr, ptr @OBJC_SELECTOR_REFERENCES_.{{[0-9]+}}, align 4
+// CHECK: load ptr, ptr @OBJC_CLASS_REFERENCES_.{{[0-9]+}}, align 4
+// CHECK: load ptr, ptr @OBJC_SELECTOR_REFERENCES_.{{[0-9]+}}, align 4
+
+// CHECK: !{{[0-9]+}} = !{i32 1, !"Objective-C Version", i32 1}
+// CHECK: !{{[0-9]+}} = !{i32 1, !"Objective-C Image Info Version", i32 0}
+// CHECK: !{{[0-9]+}} = !{i32 1, !"Objective-C Image Info Section", !"__OBJC,__image_info,regular"}
+// CHECK-NOT: !{{[0-9]+}} = !{i32 1, !"Objective-C Is Simulated", i32 32}
+// CHECK: !{{[0-9]+}} = !{i32 1, !"Objective-C Class Properties", i32 64}
diff --git a/tests/codegen-llvm/darwin-objc-abi-v2.rs b/tests/codegen-llvm/darwin-objc-abi-v2.rs
new file mode 100644
index 00000000000..f142371d582
--- /dev/null
+++ b/tests/codegen-llvm/darwin-objc-abi-v2.rs
@@ -0,0 +1,185 @@
+// ignore-tidy-linelength
+//@ add-core-stubs
+//@ revisions: x86_64_macos
+//@ [x86_64_macos] compile-flags: --target x86_64-apple-darwin
+//@ [x86_64_macos] needs-llvm-components: x86
+//@ revisions: aarch64_macos
+//@ [aarch64_macos] compile-flags: --target aarch64-apple-darwin
+//@ [aarch64_macos] needs-llvm-components: aarch64
+//@ revisions: i386_ios
+//@ [i386_ios] compile-flags: --target i386-apple-ios
+//@ [i386_ios] needs-llvm-components: x86
+//@ revisions: x86_64_ios
+//@ [x86_64_ios] compile-flags: --target x86_64-apple-ios
+//@ [x86_64_ios] needs-llvm-components: x86
+//@ revisions: armv7s_ios
+//@ [armv7s_ios] compile-flags: --target armv7s-apple-ios
+//@ [armv7s_ios] needs-llvm-components: arm
+//@ revisions: aarch64_ios
+//@ [aarch64_ios] compile-flags: --target aarch64-apple-ios
+//@ [aarch64_ios] needs-llvm-components: aarch64
+//@ revisions: aarch64_ios_sim
+//@ [aarch64_ios_sim] compile-flags: --target aarch64-apple-ios-sim
+//@ [aarch64_ios_sim] needs-llvm-components: aarch64
+
+#![crate_type = "lib"]
+#![feature(no_core, lang_items, rustc_attrs)]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
+
+#[no_mangle]
+pub fn get_class() -> *mut () {
+    unsafe extern "C" {
+        #[rustc_objc_class = "MyClass"]
+        safe static VAL: *mut ();
+    }
+    VAL
+}
+
+#[no_mangle]
+pub fn get_class_again() -> *mut () {
+    // Codegen should de-duplicate this class with the one from get_class above.
+    unsafe extern "C" {
+        #[rustc_objc_class = "MyClass"]
+        safe static VAL: *mut ();
+    }
+    VAL
+}
+
+#[no_mangle]
+pub fn get_selector() -> *mut () {
+    unsafe extern "C" {
+        #[rustc_objc_selector = "myMethod"]
+        safe static VAL: *mut ();
+    }
+    VAL
+}
+
+#[no_mangle]
+pub fn get_selector_again() -> *mut () {
+    // Codegen should de-duplicate this selector with the one from get_selector above.
+    unsafe extern "C" {
+        #[rustc_objc_selector = "myMethod"]
+        safe static VAL: *mut ();
+    }
+    VAL
+}
+
+#[no_mangle]
+pub fn get_other_class() -> *mut () {
+    unsafe extern "C" {
+        #[rustc_objc_class = "OtherClass"]
+        safe static VAL: *mut ();
+    }
+    VAL
+}
+
+#[no_mangle]
+pub fn get_other_selector() -> *mut () {
+    unsafe extern "C" {
+        #[rustc_objc_selector = "otherMethod"]
+        safe static VAL: *mut ();
+    }
+    VAL
+}
+
+// CHECK: %struct._class_t = type { ptr, ptr, ptr, ptr, ptr }
+
+// CHECK: @"OBJC_CLASS_$_MyClass" = external global %struct._class_t
+// CHECK: @"OBJC_CLASSLIST_REFERENCES_$_.{{[0-9]+}}" = internal global ptr @"OBJC_CLASS_$_MyClass", section "__DATA,__objc_classrefs,regular,no_dead_strip",
+// x86_64_macos-SAME: align 8
+// aarch64_macos-SAME: align 8
+// i386_ios-SAME: align 4
+// x86_64_ios-SAME: align 8
+// armv7s_ios-SAME: align 4
+// aarch64_ios-SAME: align 8
+// aarch64_ios_sim-SAME: align 8
+// CHECK-NOT: @"OBJC_CLASS_$_MyClass"
+// CHECK-NOT: @"OBJC_CLASSLIST_REFERENCES_$_
+
+// CHECK: @OBJC_METH_VAR_NAME_.{{[0-9]+}} = private unnamed_addr constant [9 x i8] c"myMethod\00", section "__TEXT,__objc_methname,cstring_literals", align 1
+// CHECK: @OBJC_SELECTOR_REFERENCES_.{{[0-9]+}} = internal externally_initialized global ptr @OBJC_METH_VAR_NAME_.{{[0-9]+}}, section "__DATA,__objc_selrefs,literal_pointers,no_dead_strip",
+// x86_64_macos-SAME: align 8
+// aarch64_macos-SAME: align 8
+// i386_ios-SAME: align 4
+// x86_64_ios-SAME: align 8
+// armv7s_ios-SAME: align 4
+// aarch64_ios-SAME: align 8
+// aarch64_ios_sim-SAME: align 8
+// CHECK-NOT: @OBJC_METH_VAR_NAME_
+// CHECK-NOT: @OBJC_SELECTOR_REFERENCES_
+
+// CHECK: @"OBJC_CLASS_$_OtherClass" = external global %struct._class_t
+// CHECK: @"OBJC_CLASSLIST_REFERENCES_$_.{{[0-9]+}}" = internal global ptr @"OBJC_CLASS_$_OtherClass", section "__DATA,__objc_classrefs,regular,no_dead_strip",
+// x86_64_macos-SAME: align 8
+// aarch64_macos-SAME: align 8
+// i386_ios-SAME: align 4
+// x86_64_ios-SAME: align 8
+// armv7s_ios-SAME: align 4
+// aarch64_ios-SAME: align 8
+// aarch64_ios_sim-SAME: align 8
+
+// CHECK: @OBJC_METH_VAR_NAME_.{{[0-9]+}} = private unnamed_addr constant [12 x i8] c"otherMethod\00", section "__TEXT,__objc_methname,cstring_literals", align 1
+// CHECK: @OBJC_SELECTOR_REFERENCES_.{{[0-9]+}} = internal externally_initialized global ptr @OBJC_METH_VAR_NAME_.{{[0-9]+}}, section "__DATA,__objc_selrefs,literal_pointers,no_dead_strip",
+// x86_64_macos-SAME: align 8
+// aarch64_macos-SAME: align 8
+// i386_ios-SAME: align 4
+// x86_64_ios-SAME: align 8
+// armv7s_ios-SAME: align 4
+// aarch64_ios-SAME: align 8
+// aarch64_ios_sim-SAME: align 8
+
+// CHECK-NOT: @OBJC_CLASS_NAME_
+// CHECK-NOT: @OBJC_MODULES
+
+// CHECK: load ptr, ptr @"OBJC_CLASSLIST_REFERENCES_$_.{{[0-9]+}}",
+// x86_64_macos-SAME: align 8
+// aarch64_macos-SAME: align 8
+// i386_ios-SAME: align 4
+// x86_64_ios-SAME: align 8
+// armv7s_ios-SAME: align 4
+// aarch64_ios-SAME: align 8
+// aarch64_ios_sim-SAME: align 8
+
+// CHECK: load ptr, ptr @OBJC_SELECTOR_REFERENCES_.{{[0-9]+}},
+// x86_64_macos-SAME: align 8
+// aarch64_macos-SAME: align 8
+// i386_ios-SAME: align 4
+// x86_64_ios-SAME: align 8
+// armv7s_ios-SAME: align 4
+// aarch64_ios-SAME: align 8
+// aarch64_ios_sim-SAME: align 8
+
+// CHECK: load ptr, ptr @"OBJC_CLASSLIST_REFERENCES_$_.{{[0-9]+}}",
+// x86_64_macos-SAME: align 8
+// aarch64_macos-SAME: align 8
+// i386_ios-SAME: align 4
+// x86_64_ios-SAME: align 8
+// armv7s_ios-SAME: align 4
+// aarch64_ios-SAME: align 8
+// aarch64_ios_sim-SAME: align 8
+
+// CHECK: load ptr, ptr @OBJC_SELECTOR_REFERENCES_.{{[0-9]+}},
+// x86_64_macos-SAME: align 8
+// aarch64_macos-SAME: align 8
+// i386_ios-SAME: align 4
+// x86_64_ios-SAME: align 8
+// armv7s_ios-SAME: align 4
+// aarch64_ios-SAME: align 8
+// aarch64_ios_sim-SAME: align 8
+
+// CHECK: !{{[0-9]+}} = !{i32 1, !"Objective-C Version", i32 2}
+// CHECK: !{{[0-9]+}} = !{i32 1, !"Objective-C Image Info Version", i32 0}
+// CHECK: !{{[0-9]+}} = !{i32 1, !"Objective-C Image Info Section", !"__DATA,__objc_imageinfo,regular,no_dead_strip"}
+
+// x86_64_macos-NOT: !{{[0-9]+}} = !{i32 1, !"Objective-C Is Simulated", i32 32}
+// aarch64_macos-NOT: !{{[0-9]+}} = !{i32 1, !"Objective-C Is Simulated", i32 32}
+// i386_ios: !{{[0-9]+}} = !{i32 1, !"Objective-C Is Simulated", i32 32}
+// x86_64_ios: !{{[0-9]+}} = !{i32 1, !"Objective-C Is Simulated", i32 32}
+// armv7s_ios-NOT: !{{[0-9]+}} = !{i32 1, !"Objective-C Is Simulated", i32 32}
+// aarch64_ios-NOT: !{{[0-9]+}} = !{i32 1, !"Objective-C Is Simulated", i32 32}
+// aarch64_ios_sim: !{{[0-9]+}} = !{i32 1, !"Objective-C Is Simulated", i32 32}
+
+// CHECK: !{{[0-9]+}} = !{i32 1, !"Objective-C Class Properties", i32 64}
diff --git a/tests/codegen-llvm/darwin-objc-cross-crate.rs b/tests/codegen-llvm/darwin-objc-cross-crate.rs
new file mode 100644
index 00000000000..74ad9a27346
--- /dev/null
+++ b/tests/codegen-llvm/darwin-objc-cross-crate.rs
@@ -0,0 +1,58 @@
+// Test that Objective-C class and selector references inlined across crates
+// get defined in this CGU but non-inline references don't.
+
+// ignore-tidy-linelength
+//@ aux-build: darwin_objc_aux.rs
+//@ revisions: x86_64_macos aarch64_macos
+//@ [x86_64_macos] only-x86_64-apple-darwin
+//@ [aarch64_macos] only-aarch64-apple-darwin
+
+#![crate_type = "lib"]
+#![feature(darwin_objc)]
+
+use std::os::darwin::objc;
+
+extern crate darwin_objc_aux as aux;
+
+#[no_mangle]
+pub fn get_object_class() -> objc::Class {
+    aux::inline_get_object_class()
+}
+
+#[no_mangle]
+pub fn get_alloc_selector() -> objc::SEL {
+    aux::inline_get_alloc_selector()
+}
+
+#[no_mangle]
+pub fn get_string_class() -> objc::Class {
+    aux::never_inline_get_string_class()
+}
+
+#[no_mangle]
+pub fn get_init_selector() -> objc::SEL {
+    aux::never_inline_get_init_selector()
+}
+
+// CHECK: %struct._class_t = type { ptr, ptr, ptr, ptr, ptr }
+
+// CHECK: @"OBJC_CLASS_$_NSObject" = external global %struct._class_t
+// CHECK: @"OBJC_CLASSLIST_REFERENCES_$_.{{[0-9]+}}" = internal global ptr @"OBJC_CLASS_$_NSObject", section "__DATA,__objc_classrefs,regular,no_dead_strip", align 8
+
+// CHECK: @OBJC_METH_VAR_NAME_.{{[0-9]+}} = private unnamed_addr constant [6 x i8] c"alloc\00", section "__TEXT,__objc_methname,cstring_literals", align 1
+// CHECK: @OBJC_SELECTOR_REFERENCES_.{{[0-9]+}} = internal externally_initialized global ptr @OBJC_METH_VAR_NAME_.{{[0-9]+}}, section "__DATA,__objc_selrefs,literal_pointers,no_dead_strip", align 8
+
+// CHECK-NOT: @"OBJC_CLASS_$_NSString" = external global %struct._class_t
+// CHECK-NOT: @"OBJC_CLASSLIST_REFERENCES_$_.{{[0-9]+}}" = internal global ptr @"OBJC_CLASS_$_NSString"
+
+// CHECK-NOT: @OBJC_METH_VAR_NAME_.{{[0-9]+}} = private unnamed_addr constant [5 x i8] c"init\00"
+// CHECK-NOT: @OBJC_SELECTOR_REFERENCES_.{{[0-9]+}} = internal externally_initialized global ptr @OBJC_METH_VAR_NAME_.{{[0-9]+}}
+
+// CHECK: load ptr, ptr @"OBJC_CLASSLIST_REFERENCES_$_.{{[0-9]+}}", align 8
+// CHECK: load ptr, ptr @OBJC_SELECTOR_REFERENCES_.{{[0-9]+}}, align 8
+
+// CHECK: !{{[0-9]+}} = !{i32 1, !"Objective-C Version", i32 2}
+// CHECK: !{{[0-9]+}} = !{i32 1, !"Objective-C Image Info Version", i32 0}
+// CHECK: !{{[0-9]+}} = !{i32 1, !"Objective-C Image Info Section", !"__DATA,__objc_imageinfo,regular,no_dead_strip"}
+// CHECK-NOT: !{{[0-9]+}} = !{i32 1, !"Objective-C Is Simulated", i32 32}
+// CHECK: !{{[0-9]+}} = !{i32 1, !"Objective-C Class Properties", i32 64}
diff --git a/tests/codegen-llvm/enum/enum-aggregate.rs b/tests/codegen-llvm/enum/enum-aggregate.rs
index f58d7ef12b6..7d450a89e2e 100644
--- a/tests/codegen-llvm/enum/enum-aggregate.rs
+++ b/tests/codegen-llvm/enum/enum-aggregate.rs
@@ -1,5 +1,4 @@
 //@ compile-flags: -Copt-level=0 -Cno-prepopulate-passes
-//@ min-llvm-version: 19
 //@ only-64bit
 
 #![crate_type = "lib"]
diff --git a/tests/codegen-llvm/enum/enum-discriminant-eq.rs b/tests/codegen-llvm/enum/enum-discriminant-eq.rs
index a1ab5e5c6e2..68cd58643e8 100644
--- a/tests/codegen-llvm/enum/enum-discriminant-eq.rs
+++ b/tests/codegen-llvm/enum/enum-discriminant-eq.rs
@@ -1,5 +1,4 @@
 //@ compile-flags: -Copt-level=3 -Zmerge-functions=disabled
-//@ min-llvm-version: 20
 //@ only-64bit
 //@ revisions: LLVM20 LLVM21
 //@ [LLVM21] min-llvm-version: 21
diff --git a/tests/codegen-llvm/integer-cmp.rs b/tests/codegen-llvm/integer-cmp.rs
index 812fa8e4a42..2233a575f8e 100644
--- a/tests/codegen-llvm/integer-cmp.rs
+++ b/tests/codegen-llvm/integer-cmp.rs
@@ -1,9 +1,6 @@
 // This is test for more optimal Ord implementation for integers.
 // See <https://github.com/rust-lang/rust/issues/63758> for more info.
 
-//@ revisions: llvm-pre-20 llvm-20
-//@ [llvm-20] min-llvm-version: 20
-//@ [llvm-pre-20] max-llvm-major-version: 19
 //@ compile-flags: -C opt-level=3 -Zmerge-functions=disabled
 
 #![crate_type = "lib"]
@@ -13,50 +10,29 @@ use std::cmp::Ordering;
 // CHECK-LABEL: @cmp_signed
 #[no_mangle]
 pub fn cmp_signed(a: i64, b: i64) -> Ordering {
-    // llvm-20: call{{.*}} i8 @llvm.scmp.i8.i64
-    // llvm-pre-20: icmp slt
-    // llvm-pre-20: icmp ne
-    // llvm-pre-20: zext i1
-    // llvm-pre-20: select i1
+    // CHECK: call{{.*}} i8 @llvm.scmp.i8.i64
     a.cmp(&b)
 }
 
 // CHECK-LABEL: @cmp_unsigned
 #[no_mangle]
 pub fn cmp_unsigned(a: u32, b: u32) -> Ordering {
-    // llvm-20: call{{.*}} i8 @llvm.ucmp.i8.i32
-    // llvm-pre-20: icmp ult
-    // llvm-pre-20: icmp ne
-    // llvm-pre-20: zext i1
-    // llvm-pre-20: select i1
+    // CHECK: call{{.*}} i8 @llvm.ucmp.i8.i32
     a.cmp(&b)
 }
 
 // CHECK-LABEL: @cmp_char
 #[no_mangle]
 pub fn cmp_char(a: char, b: char) -> Ordering {
-    // llvm-20: call{{.*}} i8 @llvm.ucmp.i8.i32
-    // llvm-pre-20: icmp ult
-    // llvm-pre-20: icmp ne
-    // llvm-pre-20: zext i1
-    // llvm-pre-20: select i1
+    // CHECK: call{{.*}} i8 @llvm.ucmp.i8.i32
     a.cmp(&b)
 }
 
 // CHECK-LABEL: @cmp_tuple
 #[no_mangle]
 pub fn cmp_tuple(a: (i16, u16), b: (i16, u16)) -> Ordering {
-    // llvm-20-DAG: call{{.*}} i8 @llvm.ucmp.i8.i16
-    // llvm-20-DAG: call{{.*}} i8 @llvm.scmp.i8.i16
-    // llvm-20: ret i8
-    // llvm-pre-20: icmp slt
-    // llvm-pre-20: icmp ne
-    // llvm-pre-20: zext i1
-    // llvm-pre-20: select i1
-    // llvm-pre-20: icmp ult
-    // llvm-pre-20: icmp ne
-    // llvm-pre-20: zext i1
-    // llvm-pre-20: select i1
-    // llvm-pre-20: select i1
+    // CHECK-DAG: call{{.*}} i8 @llvm.ucmp.i8.i16
+    // CHECK-DAG: call{{.*}} i8 @llvm.scmp.i8.i16
+    // CHECK: ret i8
     a.cmp(&b)
 }
diff --git a/tests/codegen-llvm/intrinsics/three_way_compare.rs b/tests/codegen-llvm/intrinsics/three_way_compare.rs
index 95fcb636f7c..89bf69561e9 100644
--- a/tests/codegen-llvm/intrinsics/three_way_compare.rs
+++ b/tests/codegen-llvm/intrinsics/three_way_compare.rs
@@ -2,7 +2,6 @@
 //@ [DEBUG] compile-flags: -C opt-level=0
 //@ [OPTIM] compile-flags: -C opt-level=3
 //@ compile-flags: -C no-prepopulate-passes
-//@ min-llvm-version: 20
 
 #![crate_type = "lib"]
 #![feature(core_intrinsics)]
diff --git a/tests/codegen-llvm/issues/and-masked-comparison-131162.rs b/tests/codegen-llvm/issues/and-masked-comparison-131162.rs
index bdf021092fd..fc4b0341a31 100644
--- a/tests/codegen-llvm/issues/and-masked-comparison-131162.rs
+++ b/tests/codegen-llvm/issues/and-masked-comparison-131162.rs
@@ -1,5 +1,4 @@
 //@ compile-flags: -Copt-level=3
-//@ min-llvm-version: 20
 
 #![crate_type = "lib"]
 
diff --git a/tests/codegen-llvm/issues/issue-101082.rs b/tests/codegen-llvm/issues/issue-101082.rs
index 8d15921ddb4..0c1f90f951a 100644
--- a/tests/codegen-llvm/issues/issue-101082.rs
+++ b/tests/codegen-llvm/issues/issue-101082.rs
@@ -1,6 +1,5 @@
 //@ compile-flags: -Copt-level=3
 //@ revisions: host x86-64 x86-64-v3
-//@ min-llvm-version: 20
 
 //@[host] ignore-x86_64
 
diff --git a/tests/codegen-llvm/issues/issue-129795.rs b/tests/codegen-llvm/issues/issue-129795.rs
index dc64ee35c97..7a928389fab 100644
--- a/tests/codegen-llvm/issues/issue-129795.rs
+++ b/tests/codegen-llvm/issues/issue-129795.rs
@@ -1,5 +1,4 @@
 //@ compile-flags: -Copt-level=3
-//@ min-llvm-version: 20
 #![crate_type = "lib"]
 
 // Ensure that a modulo operation with an operand that is known to be
diff --git a/tests/codegen-llvm/issues/iter-max-no-unwrap-failed-129583.rs b/tests/codegen-llvm/issues/iter-max-no-unwrap-failed-129583.rs
index 4d3fa4993ef..4c4eebeabb5 100644
--- a/tests/codegen-llvm/issues/iter-max-no-unwrap-failed-129583.rs
+++ b/tests/codegen-llvm/issues/iter-max-no-unwrap-failed-129583.rs
@@ -3,7 +3,6 @@
 // use a larger value to prevent unrolling.
 
 //@ compile-flags: -Copt-level=3
-//@ min-llvm-version: 20
 
 #![crate_type = "lib"]
 
diff --git a/tests/codegen-llvm/issues/looping-over-ne-bytes-133528.rs b/tests/codegen-llvm/issues/looping-over-ne-bytes-133528.rs
index 35acf765d69..b686f8c4b3a 100644
--- a/tests/codegen-llvm/issues/looping-over-ne-bytes-133528.rs
+++ b/tests/codegen-llvm/issues/looping-over-ne-bytes-133528.rs
@@ -1,5 +1,4 @@
 //@ compile-flags: -Copt-level=3
-//@ min-llvm-version: 20
 #![crate_type = "lib"]
 
 /// Ensure the function is properly optimized
diff --git a/tests/codegen-llvm/option-niche-eq.rs b/tests/codegen-llvm/option-niche-eq.rs
index 3900cb79aa2..e9c3fa2407e 100644
--- a/tests/codegen-llvm/option-niche-eq.rs
+++ b/tests/codegen-llvm/option-niche-eq.rs
@@ -1,5 +1,4 @@
 //@ revisions: REGULAR LLVM21
-//@ min-llvm-version: 20
 //@ compile-flags: -Copt-level=3 -Zmerge-functions=disabled
 //@ [LLVM21] min-llvm-version: 21
 #![crate_type = "lib"]
diff --git a/tests/codegen-llvm/slice-last-elements-optimization.rs b/tests/codegen-llvm/slice-last-elements-optimization.rs
index d982cda709d..77fc1d21cd9 100644
--- a/tests/codegen-llvm/slice-last-elements-optimization.rs
+++ b/tests/codegen-llvm/slice-last-elements-optimization.rs
@@ -1,5 +1,4 @@
 //@ compile-flags: -Copt-level=3
-//@ min-llvm-version: 20
 #![crate_type = "lib"]
 
 // This test verifies that LLVM 20 properly optimizes the bounds check
diff --git a/tests/codegen-llvm/swap-small-types.rs b/tests/codegen-llvm/swap-small-types.rs
index 7aa613ae9c2..0799ff76331 100644
--- a/tests/codegen-llvm/swap-small-types.rs
+++ b/tests/codegen-llvm/swap-small-types.rs
@@ -1,6 +1,5 @@
 //@ compile-flags: -Copt-level=3 -Z merge-functions=disabled
 //@ only-x86_64
-//@ min-llvm-version: 20
 //@ ignore-std-debug-assertions (`ptr::swap_nonoverlapping` has one which blocks some optimizations)
 
 #![crate_type = "lib"]
diff --git a/tests/codegen-llvm/try_question_mark_nop.rs b/tests/codegen-llvm/try_question_mark_nop.rs
index 398c9a580bc..a09fa0a4901 100644
--- a/tests/codegen-llvm/try_question_mark_nop.rs
+++ b/tests/codegen-llvm/try_question_mark_nop.rs
@@ -1,9 +1,6 @@
 //@ compile-flags: -Copt-level=3 -Z merge-functions=disabled
 //@ edition: 2021
 //@ only-x86_64
-//@ revisions: NINETEEN TWENTY
-//@[NINETEEN] exact-llvm-major-version: 19
-//@[TWENTY] min-llvm-version: 20
 
 #![crate_type = "lib"]
 #![feature(try_blocks)]
@@ -17,13 +14,9 @@ pub fn option_nop_match_32(x: Option<u32>) -> Option<u32> {
     // CHECK: start:
     // CHECK-NEXT: [[TRUNC:%.*]] = trunc nuw i32 %0 to i1
 
-    // NINETEEN-NEXT: [[SELECT:%.*]] = select i1 [[TRUNC]], i32 %0, i32 0
-    // NINETEEN-NEXT: [[REG2:%.*]] = insertvalue { i32, i32 } poison, i32 [[SELECT]], 0
-    // NINETEEN-NEXT: [[REG3:%.*]] = insertvalue { i32, i32 } [[REG2]], i32 %1, 1
-
-    // TWENTY-NEXT: [[SELECT:%.*]] = select i1 [[TRUNC]], i32 %1, i32 undef
-    // TWENTY-NEXT: [[REG2:%.*]] = insertvalue { i32, i32 } poison, i32 %0, 0
-    // TWENTY-NEXT: [[REG3:%.*]] = insertvalue { i32, i32 } [[REG2]], i32 [[SELECT]], 1
+    // CHECK-NEXT: [[SELECT:%.*]] = select i1 [[TRUNC]], i32 %1, i32 undef
+    // CHECK-NEXT: [[REG2:%.*]] = insertvalue { i32, i32 } poison, i32 %0, 0
+    // CHECK-NEXT: [[REG3:%.*]] = insertvalue { i32, i32 } [[REG2]], i32 [[SELECT]], 1
 
     // CHECK-NEXT: ret { i32, i32 } [[REG3]]
     match x {
@@ -36,8 +29,8 @@ pub fn option_nop_match_32(x: Option<u32>) -> Option<u32> {
 #[no_mangle]
 pub fn option_nop_traits_32(x: Option<u32>) -> Option<u32> {
     // CHECK: start:
-    // TWENTY-NEXT: %[[IS_SOME:.+]] = trunc nuw i32 %0 to i1
-    // TWENTY-NEXT: select i1 %[[IS_SOME]], i32 %1, i32 undef
+    // CHECK-NEXT: %[[IS_SOME:.+]] = trunc nuw i32 %0 to i1
+    // CHECK-NEXT: select i1 %[[IS_SOME]], i32 %1, i32 undef
     // CHECK-NEXT: insertvalue { i32, i32 }
     // CHECK-NEXT: insertvalue { i32, i32 }
     // CHECK-NEXT: ret { i32, i32 }
@@ -96,13 +89,9 @@ pub fn option_nop_match_64(x: Option<u64>) -> Option<u64> {
     // CHECK: start:
     // CHECK-NEXT: [[TRUNC:%.*]] = trunc nuw i64 %0 to i1
 
-    // NINETEEN-NEXT: [[SELECT:%.*]] = select i1 [[TRUNC]], i64 %0, i64 0
-    // NINETEEN-NEXT: [[REG2:%.*]] = insertvalue { i64, i64 } poison, i64 [[SELECT]], 0
-    // NINETEEN-NEXT: [[REG3:%.*]] = insertvalue { i64, i64 } [[REG2]], i64 %1, 1
-
-    // TWENTY-NEXT: [[SELECT:%.*]] = select i1 [[TRUNC]], i64 %1, i64 undef
-    // TWENTY-NEXT: [[REG2:%.*]] = insertvalue { i64, i64 } poison, i64 %0, 0
-    // TWENTY-NEXT: [[REG3:%.*]] = insertvalue { i64, i64 } [[REG2]], i64 [[SELECT]], 1
+    // CHECK-NEXT: [[SELECT:%.*]] = select i1 [[TRUNC]], i64 %1, i64 undef
+    // CHECK-NEXT: [[REG2:%.*]] = insertvalue { i64, i64 } poison, i64 %0, 0
+    // CHECK-NEXT: [[REG3:%.*]] = insertvalue { i64, i64 } [[REG2]], i64 [[SELECT]], 1
 
     // CHECK-NEXT: ret { i64, i64 } [[REG3]]
     match x {
@@ -115,8 +104,8 @@ pub fn option_nop_match_64(x: Option<u64>) -> Option<u64> {
 #[no_mangle]
 pub fn option_nop_traits_64(x: Option<u64>) -> Option<u64> {
     // CHECK: start:
-    // TWENTY-NEXT: %[[TRUNC:[0-9]+]] = trunc nuw i64 %0 to i1
-    // TWENTY-NEXT: %[[SEL:\.[0-9]+]] = select i1 %[[TRUNC]], i64 %1, i64 undef
+    // CHECK-NEXT: %[[TRUNC:[0-9]+]] = trunc nuw i64 %0 to i1
+    // CHECK-NEXT: %[[SEL:\.[0-9]+]] = select i1 %[[TRUNC]], i64 %1, i64 undef
     // CHECK-NEXT: insertvalue { i64, i64 }
     // CHECK-NEXT: insertvalue { i64, i64 }
     // CHECK-NEXT: ret { i64, i64 }
diff --git a/tests/codegen-llvm/union-aggregate.rs b/tests/codegen-llvm/union-aggregate.rs
index aac66c5dcdd..7faa66804fe 100644
--- a/tests/codegen-llvm/union-aggregate.rs
+++ b/tests/codegen-llvm/union-aggregate.rs
@@ -1,5 +1,4 @@
 //@ compile-flags: -Copt-level=0 -Cno-prepopulate-passes
-//@ min-llvm-version: 19
 //@ only-64bit
 
 #![crate_type = "lib"]
diff --git a/tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-abort.mir b/tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-abort.mir
index 347e4119cd0..050aac7c3ff 100644
--- a/tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-abort.mir
+++ b/tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-abort.mir
@@ -1,7 +1,7 @@
 // MIR for `a::{closure#0}` 0 coroutine_drop_async
 
 fn a::{closure#0}(_1: Pin<&mut {async fn body of a<T>()}>, _2: &mut Context<'_>) -> Poll<()> {
-    debug _task_context => _19;
+    debug _task_context => _2;
     debug x => ((*(_1.0: &mut {async fn body of a<T>()})).0: T);
     let mut _0: std::task::Poll<()>;
     let _3: T;
@@ -20,15 +20,14 @@ fn a::{closure#0}(_1: Pin<&mut {async fn body of a<T>()}>, _2: &mut Context<'_>)
     let mut _16: &mut impl std::future::Future<Output = ()>;
     let mut _17: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
     let mut _18: isize;
-    let mut _19: &mut std::task::Context<'_>;
-    let mut _20: u32;
+    let mut _19: u32;
     scope 1 {
         debug x => (((*(_1.0: &mut {async fn body of a<T>()})) as variant#4).0: T);
     }
 
     bb0: {
-        _20 = discriminant((*(_1.0: &mut {async fn body of a<T>()})));
-        switchInt(move _20) -> [0: bb9, 3: bb12, 4: bb13, otherwise: bb14];
+        _19 = discriminant((*(_1.0: &mut {async fn body of a<T>()})));
+        switchInt(move _19) -> [0: bb9, 3: bb12, 4: bb13, otherwise: bb14];
     }
 
     bb1: {
diff --git a/tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-unwind.mir b/tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-unwind.mir
index b1cf5373f91..796e95ff3d8 100644
--- a/tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-unwind.mir
+++ b/tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-unwind.mir
@@ -1,7 +1,7 @@
 // MIR for `a::{closure#0}` 0 coroutine_drop_async
 
 fn a::{closure#0}(_1: Pin<&mut {async fn body of a<T>()}>, _2: &mut Context<'_>) -> Poll<()> {
-    debug _task_context => _19;
+    debug _task_context => _2;
     debug x => ((*(_1.0: &mut {async fn body of a<T>()})).0: T);
     let mut _0: std::task::Poll<()>;
     let _3: T;
@@ -20,15 +20,14 @@ fn a::{closure#0}(_1: Pin<&mut {async fn body of a<T>()}>, _2: &mut Context<'_>)
     let mut _16: &mut impl std::future::Future<Output = ()>;
     let mut _17: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
     let mut _18: isize;
-    let mut _19: &mut std::task::Context<'_>;
-    let mut _20: u32;
+    let mut _19: u32;
     scope 1 {
         debug x => (((*(_1.0: &mut {async fn body of a<T>()})) as variant#4).0: T);
     }
 
     bb0: {
-        _20 = discriminant((*(_1.0: &mut {async fn body of a<T>()})));
-        switchInt(move _20) -> [0: bb12, 2: bb18, 3: bb16, 4: bb17, otherwise: bb19];
+        _19 = discriminant((*(_1.0: &mut {async fn body of a<T>()})));
+        switchInt(move _19) -> [0: bb12, 2: bb18, 3: bb16, 4: bb17, otherwise: bb19];
     }
 
     bb1: {
diff --git a/tests/mir-opt/building/async_await.a-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/building/async_await.a-{closure#0}.coroutine_resume.0.mir
index 7480324b177..2e2876cb3fc 100644
--- a/tests/mir-opt/building/async_await.a-{closure#0}.coroutine_resume.0.mir
+++ b/tests/mir-opt/building/async_await.a-{closure#0}.coroutine_resume.0.mir
@@ -10,19 +10,17 @@
 } */
 
 fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) -> Poll<()> {
-    debug _task_context => _4;
+    debug _task_context => _2;
     let mut _0: std::task::Poll<()>;
     let mut _3: ();
-    let mut _4: &mut std::task::Context<'_>;
-    let mut _5: u32;
+    let mut _4: u32;
 
     bb0: {
-        _5 = discriminant((*(_1.0: &mut {async fn body of a()})));
-        switchInt(move _5) -> [0: bb1, 1: bb4, otherwise: bb5];
+        _4 = discriminant((*(_1.0: &mut {async fn body of a()})));
+        switchInt(move _4) -> [0: bb1, 1: bb4, otherwise: bb5];
     }
 
     bb1: {
-        _4 = move _2;
         _3 = const ();
         goto -> bb3;
     }
diff --git a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir
index 9bff257e063..20fc4112ef2 100644
--- a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir
+++ b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir
@@ -1,7 +1,7 @@
 // MIR for `b::{closure#0}` 0 coroutine_resume
 /* coroutine_layout = CoroutineLayout {
     field_tys: {
-        _0: CoroutineSavedTy {
+        _s0: CoroutineSavedTy {
             ty: Coroutine(
                 DefId(0:5 ~ async_await[ccf8]::a::{closure#0}),
                 [
@@ -18,7 +18,7 @@
             },
             ignore_for_traits: false,
         },
-        _1: CoroutineSavedTy {
+        _s1: CoroutineSavedTy {
             ty: Coroutine(
                 DefId(0:5 ~ async_await[ccf8]::a::{closure#0}),
                 [
@@ -40,17 +40,17 @@
         Unresumed(0): [],
         Returned (1): [],
         Panicked (2): [],
-        Suspend0 (3): [_0],
-        Suspend1 (4): [_1],
+        Suspend0 (3): [_s0],
+        Suspend1 (4): [_s1],
     },
     storage_conflicts: BitMatrix(2x2) {
-        (_0, _0),
-        (_1, _1),
+        (_s0, _s0),
+        (_s1, _s1),
     },
 } */
 
 fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> Poll<()> {
-    debug _task_context => _38;
+    debug _task_context => _2;
     let mut _0: std::task::Poll<()>;
     let _3: ();
     let mut _4: {async fn body of a()};
@@ -85,8 +85,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) ->
     let mut _35: &mut std::task::Context<'_>;
     let mut _36: ();
     let mut _37: ();
-    let mut _38: &mut std::task::Context<'_>;
-    let mut _39: u32;
+    let mut _38: u32;
     scope 1 {
         debug __awaitee => (((*(_1.0: &mut {async fn body of b()})) as variant#3).0: {async fn body of a()});
         let _17: ();
@@ -103,12 +102,11 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) ->
     }
 
     bb0: {
-        _39 = discriminant((*(_1.0: &mut {async fn body of b()})));
-        switchInt(move _39) -> [0: bb1, 1: bb29, 3: bb27, 4: bb28, otherwise: bb8];
+        _38 = discriminant((*(_1.0: &mut {async fn body of b()})));
+        switchInt(move _38) -> [0: bb1, 1: bb29, 3: bb27, 4: bb28, otherwise: bb8];
     }
 
     bb1: {
-        _38 = move _2;
         StorageLive(_3);
         StorageLive(_4);
         StorageLive(_5);
@@ -143,7 +141,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) ->
         StorageLive(_13);
         StorageLive(_14);
         StorageLive(_15);
-        _15 = copy _38;
+        _15 = copy _2;
         _14 = move _15;
         goto -> bb6;
     }
@@ -198,7 +196,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) ->
 
     bb11: {
         StorageDead(_20);
-        _38 = move _19;
+        _2 = move _19;
         StorageDead(_19);
         _7 = const ();
         goto -> bb4;
@@ -245,7 +243,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) ->
         StorageLive(_29);
         StorageLive(_30);
         StorageLive(_31);
-        _31 = copy _38;
+        _31 = copy _2;
         _30 = move _31;
         goto -> bb18;
     }
@@ -295,7 +293,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) ->
 
     bb22: {
         StorageDead(_36);
-        _38 = move _35;
+        _2 = move _35;
         StorageDead(_35);
         _7 = const ();
         goto -> bb16;
diff --git a/tests/mir-opt/building/coroutine.main-{closure#0}.StateTransform.after.mir b/tests/mir-opt/building/coroutine.main-{closure#0}.StateTransform.after.mir
new file mode 100644
index 00000000000..d8fdb446135
--- /dev/null
+++ b/tests/mir-opt/building/coroutine.main-{closure#0}.StateTransform.after.mir
@@ -0,0 +1,207 @@
+// MIR for `main::{closure#0}` after StateTransform
+/* coroutine_layout = CoroutineLayout {
+    field_tys: {
+        _s0: CoroutineSavedTy {
+            ty: std::string::String,
+            source_info: SourceInfo {
+                span: $DIR/coroutine.rs:18:6: 18:9 (#0),
+                scope: scope[0],
+            },
+            ignore_for_traits: false,
+        },
+    },
+    variant_fields: {
+        Unresumed(0): [],
+        Returned (1): [],
+        Panicked (2): [],
+        Suspend0 (3): [_s0],
+        Suspend1 (4): [_s0],
+    },
+    storage_conflicts: BitMatrix(1x1) {
+        (_s0, _s0),
+    },
+} */
+
+fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2: String) -> CoroutineState<(&str, String, &Location<'_>), ()> {
+    debug arg => (((*(_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18})) as variant#4).0: std::string::String);
+    let mut _0: std::ops::CoroutineState<(&str, std::string::String, &std::panic::Location<'_>), ()>;
+    let _3: std::string::String;
+    let mut _4: (&str, std::string::String, &std::panic::Location<'_>);
+    let mut _5: std::string::String;
+    let mut _6: &std::string::String;
+    let mut _7: &std::panic::Location<'_>;
+    let _8: std::string::String;
+    let mut _9: (&str, std::string::String, &std::panic::Location<'_>);
+    let mut _10: &str;
+    let _11: &str;
+    let mut _12: std::string::String;
+    let mut _13: &std::string::String;
+    let mut _14: &std::panic::Location<'_>;
+    let _15: &std::panic::Location<'_>;
+    let mut _16: ();
+    let mut _17: u32;
+    let mut _18: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18};
+    let mut _19: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18};
+    let mut _20: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18};
+    let mut _21: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18};
+    let mut _22: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18};
+    let mut _23: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18};
+    let mut _24: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18};
+    let mut _25: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18};
+
+    bb0: {
+        _18 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18});
+        _17 = discriminant((*_18));
+        switchInt(move _17) -> [0: bb1, 1: bb19, 3: bb17, 4: bb18, otherwise: bb20];
+    }
+
+    bb1: {
+        _19 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18});
+        (((*_19) as variant#4).0: std::string::String) = move _2;
+        StorageLive(_3);
+        StorageLive(_4);
+        StorageLive(_5);
+        StorageLive(_6);
+        _20 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18});
+        _6 = &(((*_20) as variant#4).0: std::string::String);
+        _5 = <String as Clone>::clone(move _6) -> [return: bb2, unwind unreachable];
+    }
+
+    bb2: {
+        StorageDead(_6);
+        StorageLive(_7);
+        _7 = Location::<'_>::caller() -> [return: bb3, unwind unreachable];
+    }
+
+    bb3: {
+        _4 = (const "first", move _5, move _7);
+        StorageDead(_7);
+        goto -> bb4;
+    }
+
+    bb4: {
+        StorageDead(_5);
+        _0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Yielded(move _4);
+        StorageDead(_3);
+        StorageDead(_4);
+        _21 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18});
+        discriminant((*_21)) = 3;
+        return;
+    }
+
+    bb5: {
+        goto -> bb6;
+    }
+
+    bb6: {
+        StorageDead(_4);
+        drop(_3) -> [return: bb7, unwind unreachable];
+    }
+
+    bb7: {
+        StorageDead(_3);
+        StorageLive(_8);
+        StorageLive(_9);
+        StorageLive(_10);
+        StorageLive(_11);
+        _11 = const "second";
+        _10 = &(*_11);
+        StorageLive(_12);
+        StorageLive(_13);
+        _22 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18});
+        _13 = &(((*_22) as variant#4).0: std::string::String);
+        _12 = <String as Clone>::clone(move _13) -> [return: bb8, unwind unreachable];
+    }
+
+    bb8: {
+        StorageDead(_13);
+        StorageLive(_14);
+        StorageLive(_15);
+        _15 = Location::<'_>::caller() -> [return: bb9, unwind unreachable];
+    }
+
+    bb9: {
+        _14 = &(*_15);
+        _9 = (move _10, move _12, move _14);
+        StorageDead(_14);
+        goto -> bb10;
+    }
+
+    bb10: {
+        StorageDead(_12);
+        StorageDead(_10);
+        _0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Yielded(move _9);
+        StorageDead(_8);
+        StorageDead(_9);
+        StorageDead(_11);
+        StorageDead(_15);
+        _23 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18});
+        discriminant((*_23)) = 4;
+        return;
+    }
+
+    bb11: {
+        goto -> bb12;
+    }
+
+    bb12: {
+        StorageDead(_9);
+        drop(_8) -> [return: bb13, unwind unreachable];
+    }
+
+    bb13: {
+        StorageDead(_15);
+        StorageDead(_11);
+        StorageDead(_8);
+        _16 = const ();
+        _24 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18});
+        drop((((*_24) as variant#4).0: std::string::String)) -> [return: bb14, unwind unreachable];
+    }
+
+    bb14: {
+        goto -> bb16;
+    }
+
+    bb15: {
+        _0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Complete(move _16);
+        _25 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18});
+        discriminant((*_25)) = 1;
+        return;
+    }
+
+    bb16: {
+        goto -> bb15;
+    }
+
+    bb17: {
+        StorageLive(_3);
+        StorageLive(_4);
+        _3 = move _2;
+        goto -> bb5;
+    }
+
+    bb18: {
+        StorageLive(_8);
+        StorageLive(_9);
+        StorageLive(_11);
+        StorageLive(_15);
+        _8 = move _2;
+        goto -> bb11;
+    }
+
+    bb19: {
+        assert(const false, "coroutine resumed after completion") -> [success: bb19, unwind unreachable];
+    }
+
+    bb20: {
+        unreachable;
+    }
+}
+
+ALLOC0 (size: 6, align: 1) {
+    73 65 63 6f 6e 64                               │ second
+}
+
+ALLOC1 (size: 5, align: 1) {
+    66 69 72 73 74                                  │ first
+}
diff --git a/tests/mir-opt/building/coroutine.main-{closure#1}.StateTransform.after.mir b/tests/mir-opt/building/coroutine.main-{closure#1}.StateTransform.after.mir
new file mode 100644
index 00000000000..dd17afad656
--- /dev/null
+++ b/tests/mir-opt/building/coroutine.main-{closure#1}.StateTransform.after.mir
@@ -0,0 +1,207 @@
+// MIR for `main::{closure#1}` after StateTransform
+/* coroutine_layout = CoroutineLayout {
+    field_tys: {
+        _s0: CoroutineSavedTy {
+            ty: std::string::String,
+            source_info: SourceInfo {
+                span: $DIR/coroutine.rs:25:6: 25:9 (#0),
+                scope: scope[0],
+            },
+            ignore_for_traits: false,
+        },
+    },
+    variant_fields: {
+        Unresumed(0): [],
+        Returned (1): [],
+        Panicked (2): [],
+        Suspend0 (3): [_s0],
+        Suspend1 (4): [_s0],
+    },
+    storage_conflicts: BitMatrix(1x1) {
+        (_s0, _s0),
+    },
+} */
+
+fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2: String) -> CoroutineState<(&str, String, &Location<'_>), ()> {
+    debug arg => (((*(_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18})) as variant#4).0: std::string::String);
+    let mut _0: std::ops::CoroutineState<(&str, std::string::String, &std::panic::Location<'_>), ()>;
+    let _3: std::string::String;
+    let mut _4: (&str, std::string::String, &std::panic::Location<'_>);
+    let mut _5: std::string::String;
+    let mut _6: &std::string::String;
+    let mut _7: &std::panic::Location<'_>;
+    let _8: std::string::String;
+    let mut _9: (&str, std::string::String, &std::panic::Location<'_>);
+    let mut _10: &str;
+    let _11: &str;
+    let mut _12: std::string::String;
+    let mut _13: &std::string::String;
+    let mut _14: &std::panic::Location<'_>;
+    let _15: &std::panic::Location<'_>;
+    let mut _16: ();
+    let mut _17: u32;
+    let mut _18: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18};
+    let mut _19: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18};
+    let mut _20: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18};
+    let mut _21: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18};
+    let mut _22: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18};
+    let mut _23: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18};
+    let mut _24: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18};
+    let mut _25: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18};
+
+    bb0: {
+        _18 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18});
+        _17 = discriminant((*_18));
+        switchInt(move _17) -> [0: bb1, 1: bb19, 3: bb17, 4: bb18, otherwise: bb20];
+    }
+
+    bb1: {
+        _19 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18});
+        (((*_19) as variant#4).0: std::string::String) = move _2;
+        StorageLive(_3);
+        StorageLive(_4);
+        StorageLive(_5);
+        StorageLive(_6);
+        _20 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18});
+        _6 = &(((*_20) as variant#4).0: std::string::String);
+        _5 = <String as Clone>::clone(move _6) -> [return: bb2, unwind unreachable];
+    }
+
+    bb2: {
+        StorageDead(_6);
+        StorageLive(_7);
+        _7 = Location::<'_>::caller() -> [return: bb3, unwind unreachable];
+    }
+
+    bb3: {
+        _4 = (const "first", move _5, move _7);
+        StorageDead(_7);
+        goto -> bb4;
+    }
+
+    bb4: {
+        StorageDead(_5);
+        _0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Yielded(move _4);
+        StorageDead(_3);
+        StorageDead(_4);
+        _21 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18});
+        discriminant((*_21)) = 3;
+        return;
+    }
+
+    bb5: {
+        goto -> bb6;
+    }
+
+    bb6: {
+        StorageDead(_4);
+        drop(_3) -> [return: bb7, unwind unreachable];
+    }
+
+    bb7: {
+        StorageDead(_3);
+        StorageLive(_8);
+        StorageLive(_9);
+        StorageLive(_10);
+        StorageLive(_11);
+        _11 = const "second";
+        _10 = &(*_11);
+        StorageLive(_12);
+        StorageLive(_13);
+        _22 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18});
+        _13 = &(((*_22) as variant#4).0: std::string::String);
+        _12 = <String as Clone>::clone(move _13) -> [return: bb8, unwind unreachable];
+    }
+
+    bb8: {
+        StorageDead(_13);
+        StorageLive(_14);
+        StorageLive(_15);
+        _15 = Location::<'_>::caller() -> [return: bb9, unwind unreachable];
+    }
+
+    bb9: {
+        _14 = &(*_15);
+        _9 = (move _10, move _12, move _14);
+        StorageDead(_14);
+        goto -> bb10;
+    }
+
+    bb10: {
+        StorageDead(_12);
+        StorageDead(_10);
+        _0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Yielded(move _9);
+        StorageDead(_8);
+        StorageDead(_9);
+        StorageDead(_11);
+        StorageDead(_15);
+        _23 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18});
+        discriminant((*_23)) = 4;
+        return;
+    }
+
+    bb11: {
+        goto -> bb12;
+    }
+
+    bb12: {
+        StorageDead(_9);
+        drop(_8) -> [return: bb13, unwind unreachable];
+    }
+
+    bb13: {
+        StorageDead(_15);
+        StorageDead(_11);
+        StorageDead(_8);
+        _16 = const ();
+        _24 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18});
+        drop((((*_24) as variant#4).0: std::string::String)) -> [return: bb14, unwind unreachable];
+    }
+
+    bb14: {
+        goto -> bb16;
+    }
+
+    bb15: {
+        _0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Complete(move _16);
+        _25 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18});
+        discriminant((*_25)) = 1;
+        return;
+    }
+
+    bb16: {
+        goto -> bb15;
+    }
+
+    bb17: {
+        StorageLive(_3);
+        StorageLive(_4);
+        _3 = move _2;
+        goto -> bb5;
+    }
+
+    bb18: {
+        StorageLive(_8);
+        StorageLive(_9);
+        StorageLive(_11);
+        StorageLive(_15);
+        _8 = move _2;
+        goto -> bb11;
+    }
+
+    bb19: {
+        assert(const false, "coroutine resumed after completion") -> [success: bb19, unwind unreachable];
+    }
+
+    bb20: {
+        unreachable;
+    }
+}
+
+ALLOC0 (size: 6, align: 1) {
+    73 65 63 6f 6e 64                               │ second
+}
+
+ALLOC1 (size: 5, align: 1) {
+    66 69 72 73 74                                  │ first
+}
diff --git a/tests/mir-opt/building/coroutine.rs b/tests/mir-opt/building/coroutine.rs
new file mode 100644
index 00000000000..6d50c4d90b1
--- /dev/null
+++ b/tests/mir-opt/building/coroutine.rs
@@ -0,0 +1,29 @@
+// skip-filecheck
+//@ edition:2024
+//@ compile-flags: -Zmir-opt-level=0 -C panic=abort
+
+#![feature(stmt_expr_attributes)]
+#![feature(closure_track_caller)]
+#![feature(coroutine_trait)]
+#![feature(coroutines)]
+
+use std::ops::{Coroutine, CoroutineState};
+use std::panic::Location;
+use std::pin::Pin;
+
+// EMIT_MIR coroutine.main-{closure#0}.StateTransform.after.mir
+// EMIT_MIR coroutine.main-{closure#1}.StateTransform.after.mir
+fn main() {
+    let simple = #[coroutine]
+    |arg: String| {
+        yield ("first", arg.clone(), Location::caller());
+        yield ("second", arg.clone(), Location::caller());
+    };
+
+    let track_caller = #[track_caller]
+    #[coroutine]
+    |arg: String| {
+        yield ("first", arg.clone(), Location::caller());
+        yield ("second", arg.clone(), Location::caller());
+    };
+}
diff --git a/tests/mir-opt/building/custom/arrays.arrays.built.after.mir b/tests/mir-opt/building/custom/arrays.arrays.built.after.mir
index 30d11e31e4d..f9f24c8eabe 100644
--- a/tests/mir-opt/building/custom/arrays.arrays.built.after.mir
+++ b/tests/mir-opt/building/custom/arrays.arrays.built.after.mir
@@ -3,12 +3,16 @@
 fn arrays() -> usize {
     let mut _0: usize;
     let mut _1: [i32; C];
-    let mut _2: usize;
+    let mut _2: *const [i32; C];
+    let mut _3: *const [i32];
+    let mut _4: usize;
 
     bb0: {
         _1 = [const 5_i32; C];
-        _2 = Len(_1);
-        _0 = copy _2;
+        _2 = &raw const _1;
+        _3 = copy _2 as *const [i32] (PointerCoercion(Unsize, AsCast));
+        _4 = PtrMetadata(copy _3);
+        _0 = copy _4;
         return;
     }
 }
diff --git a/tests/mir-opt/building/custom/arrays.rs b/tests/mir-opt/building/custom/arrays.rs
index 4bd6f93e113..e9cdded4a0e 100644
--- a/tests/mir-opt/building/custom/arrays.rs
+++ b/tests/mir-opt/building/custom/arrays.rs
@@ -10,7 +10,9 @@ fn arrays<const C: usize>() -> usize {
     mir! {
         {
             let x = [5_i32; C];
-            let c = Len(x);
+            let y = &raw const x;
+            let z = CastUnsize::<_, *const [i32]>(y);
+            let c = PtrMetadata(z);
             RET = c;
             Return()
         }
diff --git a/tests/mir-opt/building/match/array_len.const_array_len.built.after.panic-abort.mir b/tests/mir-opt/building/match/array_len.const_array_len.built.after.panic-abort.mir
new file mode 100644
index 00000000000..8d16f074b1e
--- /dev/null
+++ b/tests/mir-opt/building/match/array_len.const_array_len.built.after.panic-abort.mir
@@ -0,0 +1,155 @@
+// MIR for `const_array_len` after built
+
+fn const_array_len(_1: [T; 5]) -> () {
+    debug x => _1;
+    let mut _0: ();
+    let _6: ();
+    let mut _7: T;
+    let _8: ();
+    let mut _9: T;
+    let _10: ();
+    let mut _11: [T; 2];
+    let _12: ();
+    let mut _13: T;
+    scope 1 {
+        debug a => _2;
+        debug b => _3;
+        debug rest => _4;
+        debug e => _5;
+        let _2: T;
+        let _3: T;
+        let _4: [T; 2];
+        let _5: T;
+    }
+
+    bb0: {
+        PlaceMention(_1);
+        falseEdge -> [real: bb2, imaginary: bb1];
+    }
+
+    bb1: {
+        goto -> bb7;
+    }
+
+    bb2: {
+        StorageLive(_2);
+        _2 = move _1[0 of 5];
+        StorageLive(_3);
+        _3 = move _1[1 of 5];
+        StorageLive(_4);
+        _4 = move _1[2..4];
+        StorageLive(_5);
+        _5 = move _1[4 of 5];
+        StorageLive(_6);
+        StorageLive(_7);
+        _7 = move _2;
+        _6 = opaque::<T>(move _7) -> [return: bb3, unwind: bb17];
+    }
+
+    bb3: {
+        StorageDead(_7);
+        StorageDead(_6);
+        StorageLive(_8);
+        StorageLive(_9);
+        _9 = move _3;
+        _8 = opaque::<T>(move _9) -> [return: bb4, unwind: bb16];
+    }
+
+    bb4: {
+        StorageDead(_9);
+        StorageDead(_8);
+        StorageLive(_10);
+        StorageLive(_11);
+        _11 = move _4;
+        _10 = opaque::<[T; 2]>(move _11) -> [return: bb5, unwind: bb15];
+    }
+
+    bb5: {
+        StorageDead(_11);
+        StorageDead(_10);
+        StorageLive(_12);
+        StorageLive(_13);
+        _13 = move _5;
+        _12 = opaque::<T>(move _13) -> [return: bb6, unwind: bb14];
+    }
+
+    bb6: {
+        StorageDead(_13);
+        StorageDead(_12);
+        _0 = const ();
+        drop(_5) -> [return: bb8, unwind: bb19];
+    }
+
+    bb7: {
+        _0 = const ();
+        goto -> bb12;
+    }
+
+    bb8: {
+        StorageDead(_5);
+        drop(_4) -> [return: bb9, unwind: bb20];
+    }
+
+    bb9: {
+        StorageDead(_4);
+        drop(_3) -> [return: bb10, unwind: bb21];
+    }
+
+    bb10: {
+        StorageDead(_3);
+        drop(_2) -> [return: bb11, unwind: bb22];
+    }
+
+    bb11: {
+        StorageDead(_2);
+        goto -> bb12;
+    }
+
+    bb12: {
+        drop(_1) -> [return: bb13, unwind: bb23];
+    }
+
+    bb13: {
+        return;
+    }
+
+    bb14 (cleanup): {
+        drop(_13) -> [return: bb18, unwind terminate(cleanup)];
+    }
+
+    bb15 (cleanup): {
+        drop(_11) -> [return: bb18, unwind terminate(cleanup)];
+    }
+
+    bb16 (cleanup): {
+        drop(_9) -> [return: bb18, unwind terminate(cleanup)];
+    }
+
+    bb17 (cleanup): {
+        drop(_7) -> [return: bb18, unwind terminate(cleanup)];
+    }
+
+    bb18 (cleanup): {
+        drop(_5) -> [return: bb19, unwind terminate(cleanup)];
+    }
+
+    bb19 (cleanup): {
+        drop(_4) -> [return: bb20, unwind terminate(cleanup)];
+    }
+
+    bb20 (cleanup): {
+        drop(_3) -> [return: bb21, unwind terminate(cleanup)];
+    }
+
+    bb21 (cleanup): {
+        drop(_2) -> [return: bb22, unwind terminate(cleanup)];
+    }
+
+    bb22 (cleanup): {
+        drop(_1) -> [return: bb23, unwind terminate(cleanup)];
+    }
+
+    bb23 (cleanup): {
+        resume;
+    }
+}
diff --git a/tests/mir-opt/building/match/array_len.const_array_len.built.after.panic-unwind.mir b/tests/mir-opt/building/match/array_len.const_array_len.built.after.panic-unwind.mir
new file mode 100644
index 00000000000..8d16f074b1e
--- /dev/null
+++ b/tests/mir-opt/building/match/array_len.const_array_len.built.after.panic-unwind.mir
@@ -0,0 +1,155 @@
+// MIR for `const_array_len` after built
+
+fn const_array_len(_1: [T; 5]) -> () {
+    debug x => _1;
+    let mut _0: ();
+    let _6: ();
+    let mut _7: T;
+    let _8: ();
+    let mut _9: T;
+    let _10: ();
+    let mut _11: [T; 2];
+    let _12: ();
+    let mut _13: T;
+    scope 1 {
+        debug a => _2;
+        debug b => _3;
+        debug rest => _4;
+        debug e => _5;
+        let _2: T;
+        let _3: T;
+        let _4: [T; 2];
+        let _5: T;
+    }
+
+    bb0: {
+        PlaceMention(_1);
+        falseEdge -> [real: bb2, imaginary: bb1];
+    }
+
+    bb1: {
+        goto -> bb7;
+    }
+
+    bb2: {
+        StorageLive(_2);
+        _2 = move _1[0 of 5];
+        StorageLive(_3);
+        _3 = move _1[1 of 5];
+        StorageLive(_4);
+        _4 = move _1[2..4];
+        StorageLive(_5);
+        _5 = move _1[4 of 5];
+        StorageLive(_6);
+        StorageLive(_7);
+        _7 = move _2;
+        _6 = opaque::<T>(move _7) -> [return: bb3, unwind: bb17];
+    }
+
+    bb3: {
+        StorageDead(_7);
+        StorageDead(_6);
+        StorageLive(_8);
+        StorageLive(_9);
+        _9 = move _3;
+        _8 = opaque::<T>(move _9) -> [return: bb4, unwind: bb16];
+    }
+
+    bb4: {
+        StorageDead(_9);
+        StorageDead(_8);
+        StorageLive(_10);
+        StorageLive(_11);
+        _11 = move _4;
+        _10 = opaque::<[T; 2]>(move _11) -> [return: bb5, unwind: bb15];
+    }
+
+    bb5: {
+        StorageDead(_11);
+        StorageDead(_10);
+        StorageLive(_12);
+        StorageLive(_13);
+        _13 = move _5;
+        _12 = opaque::<T>(move _13) -> [return: bb6, unwind: bb14];
+    }
+
+    bb6: {
+        StorageDead(_13);
+        StorageDead(_12);
+        _0 = const ();
+        drop(_5) -> [return: bb8, unwind: bb19];
+    }
+
+    bb7: {
+        _0 = const ();
+        goto -> bb12;
+    }
+
+    bb8: {
+        StorageDead(_5);
+        drop(_4) -> [return: bb9, unwind: bb20];
+    }
+
+    bb9: {
+        StorageDead(_4);
+        drop(_3) -> [return: bb10, unwind: bb21];
+    }
+
+    bb10: {
+        StorageDead(_3);
+        drop(_2) -> [return: bb11, unwind: bb22];
+    }
+
+    bb11: {
+        StorageDead(_2);
+        goto -> bb12;
+    }
+
+    bb12: {
+        drop(_1) -> [return: bb13, unwind: bb23];
+    }
+
+    bb13: {
+        return;
+    }
+
+    bb14 (cleanup): {
+        drop(_13) -> [return: bb18, unwind terminate(cleanup)];
+    }
+
+    bb15 (cleanup): {
+        drop(_11) -> [return: bb18, unwind terminate(cleanup)];
+    }
+
+    bb16 (cleanup): {
+        drop(_9) -> [return: bb18, unwind terminate(cleanup)];
+    }
+
+    bb17 (cleanup): {
+        drop(_7) -> [return: bb18, unwind terminate(cleanup)];
+    }
+
+    bb18 (cleanup): {
+        drop(_5) -> [return: bb19, unwind terminate(cleanup)];
+    }
+
+    bb19 (cleanup): {
+        drop(_4) -> [return: bb20, unwind terminate(cleanup)];
+    }
+
+    bb20 (cleanup): {
+        drop(_3) -> [return: bb21, unwind terminate(cleanup)];
+    }
+
+    bb21 (cleanup): {
+        drop(_2) -> [return: bb22, unwind terminate(cleanup)];
+    }
+
+    bb22 (cleanup): {
+        drop(_1) -> [return: bb23, unwind terminate(cleanup)];
+    }
+
+    bb23 (cleanup): {
+        resume;
+    }
+}
diff --git a/tests/mir-opt/building/match/array_len.rs b/tests/mir-opt/building/match/array_len.rs
new file mode 100644
index 00000000000..0d889ada9b6
--- /dev/null
+++ b/tests/mir-opt/building/match/array_len.rs
@@ -0,0 +1,31 @@
+// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
+//@ compile-flags: -Zmir-opt-level=0
+
+fn opaque<T>(x: T) {}
+
+// EMIT_MIR array_len.const_array_len.built.after.mir
+fn const_array_len<T>(x: [T; 5]) {
+    // CHECK-LABEL: fn const_array_len(
+    // CHECK-NOT: Len
+    // CHECK-NOT: PtrMetadata
+    // CHECK: = const 5_usize;
+    if let [a, b, rest @ .., e] = x {
+        opaque(a);
+        opaque(b);
+        opaque(rest);
+        opaque(e);
+    }
+}
+
+// EMIT_MIR array_len.slice_len.built.after.mir
+fn slice_len<T>(x: &[T]) {
+    // CHECK-LABEL: fn slice_len(
+    // CHECK-NOT: Len
+    // CHECK: = PtrMetadata(copy _1);
+    if let [a, b, rest @ .., e] = x {
+        opaque(a);
+        opaque(b);
+        opaque(rest);
+        opaque(e);
+    }
+}
diff --git a/tests/mir-opt/building/match/array_len.slice_len.built.after.panic-abort.mir b/tests/mir-opt/building/match/array_len.slice_len.built.after.panic-abort.mir
new file mode 100644
index 00000000000..d73f5a1b6f7
--- /dev/null
+++ b/tests/mir-opt/building/match/array_len.slice_len.built.after.panic-abort.mir
@@ -0,0 +1,115 @@
+// MIR for `slice_len` after built
+
+fn slice_len(_1: &[T]) -> () {
+    debug x => _1;
+    let mut _0: ();
+    let mut _2: usize;
+    let mut _3: usize;
+    let mut _4: usize;
+    let mut _5: bool;
+    let _10: ();
+    let mut _11: &T;
+    let _12: ();
+    let mut _13: &T;
+    let _14: ();
+    let mut _15: &[T];
+    let _16: ();
+    let mut _17: &T;
+    scope 1 {
+        debug a => _6;
+        debug b => _7;
+        debug rest => _8;
+        debug e => _9;
+        let _6: &T;
+        let _7: &T;
+        let _8: &[T];
+        let _9: &T;
+    }
+
+    bb0: {
+        PlaceMention(_1);
+        _3 = PtrMetadata(copy _1);
+        _2 = move _3;
+        _4 = const 3_usize;
+        _5 = Ge(move _2, move _4);
+        switchInt(move _5) -> [0: bb1, otherwise: bb2];
+    }
+
+    bb1: {
+        goto -> bb9;
+    }
+
+    bb2: {
+        falseEdge -> [real: bb4, imaginary: bb1];
+    }
+
+    bb3: {
+        goto -> bb1;
+    }
+
+    bb4: {
+        StorageLive(_6);
+        _6 = &(*_1)[0 of 3];
+        StorageLive(_7);
+        _7 = &(*_1)[1 of 3];
+        StorageLive(_8);
+        _8 = &(*_1)[2:-1];
+        StorageLive(_9);
+        _9 = &(*_1)[-1 of 3];
+        StorageLive(_10);
+        StorageLive(_11);
+        _11 = copy _6;
+        _10 = opaque::<&T>(move _11) -> [return: bb5, unwind: bb11];
+    }
+
+    bb5: {
+        StorageDead(_11);
+        StorageDead(_10);
+        StorageLive(_12);
+        StorageLive(_13);
+        _13 = copy _7;
+        _12 = opaque::<&T>(move _13) -> [return: bb6, unwind: bb11];
+    }
+
+    bb6: {
+        StorageDead(_13);
+        StorageDead(_12);
+        StorageLive(_14);
+        StorageLive(_15);
+        _15 = copy _8;
+        _14 = opaque::<&[T]>(move _15) -> [return: bb7, unwind: bb11];
+    }
+
+    bb7: {
+        StorageDead(_15);
+        StorageDead(_14);
+        StorageLive(_16);
+        StorageLive(_17);
+        _17 = copy _9;
+        _16 = opaque::<&T>(move _17) -> [return: bb8, unwind: bb11];
+    }
+
+    bb8: {
+        StorageDead(_17);
+        StorageDead(_16);
+        _0 = const ();
+        StorageDead(_9);
+        StorageDead(_8);
+        StorageDead(_7);
+        StorageDead(_6);
+        goto -> bb10;
+    }
+
+    bb9: {
+        _0 = const ();
+        goto -> bb10;
+    }
+
+    bb10: {
+        return;
+    }
+
+    bb11 (cleanup): {
+        resume;
+    }
+}
diff --git a/tests/mir-opt/building/match/array_len.slice_len.built.after.panic-unwind.mir b/tests/mir-opt/building/match/array_len.slice_len.built.after.panic-unwind.mir
new file mode 100644
index 00000000000..d73f5a1b6f7
--- /dev/null
+++ b/tests/mir-opt/building/match/array_len.slice_len.built.after.panic-unwind.mir
@@ -0,0 +1,115 @@
+// MIR for `slice_len` after built
+
+fn slice_len(_1: &[T]) -> () {
+    debug x => _1;
+    let mut _0: ();
+    let mut _2: usize;
+    let mut _3: usize;
+    let mut _4: usize;
+    let mut _5: bool;
+    let _10: ();
+    let mut _11: &T;
+    let _12: ();
+    let mut _13: &T;
+    let _14: ();
+    let mut _15: &[T];
+    let _16: ();
+    let mut _17: &T;
+    scope 1 {
+        debug a => _6;
+        debug b => _7;
+        debug rest => _8;
+        debug e => _9;
+        let _6: &T;
+        let _7: &T;
+        let _8: &[T];
+        let _9: &T;
+    }
+
+    bb0: {
+        PlaceMention(_1);
+        _3 = PtrMetadata(copy _1);
+        _2 = move _3;
+        _4 = const 3_usize;
+        _5 = Ge(move _2, move _4);
+        switchInt(move _5) -> [0: bb1, otherwise: bb2];
+    }
+
+    bb1: {
+        goto -> bb9;
+    }
+
+    bb2: {
+        falseEdge -> [real: bb4, imaginary: bb1];
+    }
+
+    bb3: {
+        goto -> bb1;
+    }
+
+    bb4: {
+        StorageLive(_6);
+        _6 = &(*_1)[0 of 3];
+        StorageLive(_7);
+        _7 = &(*_1)[1 of 3];
+        StorageLive(_8);
+        _8 = &(*_1)[2:-1];
+        StorageLive(_9);
+        _9 = &(*_1)[-1 of 3];
+        StorageLive(_10);
+        StorageLive(_11);
+        _11 = copy _6;
+        _10 = opaque::<&T>(move _11) -> [return: bb5, unwind: bb11];
+    }
+
+    bb5: {
+        StorageDead(_11);
+        StorageDead(_10);
+        StorageLive(_12);
+        StorageLive(_13);
+        _13 = copy _7;
+        _12 = opaque::<&T>(move _13) -> [return: bb6, unwind: bb11];
+    }
+
+    bb6: {
+        StorageDead(_13);
+        StorageDead(_12);
+        StorageLive(_14);
+        StorageLive(_15);
+        _15 = copy _8;
+        _14 = opaque::<&[T]>(move _15) -> [return: bb7, unwind: bb11];
+    }
+
+    bb7: {
+        StorageDead(_15);
+        StorageDead(_14);
+        StorageLive(_16);
+        StorageLive(_17);
+        _17 = copy _9;
+        _16 = opaque::<&T>(move _17) -> [return: bb8, unwind: bb11];
+    }
+
+    bb8: {
+        StorageDead(_17);
+        StorageDead(_16);
+        _0 = const ();
+        StorageDead(_9);
+        StorageDead(_8);
+        StorageDead(_7);
+        StorageDead(_6);
+        goto -> bb10;
+    }
+
+    bb9: {
+        _0 = const ();
+        goto -> bb10;
+    }
+
+    bb10: {
+        return;
+    }
+
+    bb11 (cleanup): {
+        resume;
+    }
+}
diff --git a/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-abort.mir b/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-abort.mir
index 7e033916fd3..33fbca7f77e 100644
--- a/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-abort.mir
+++ b/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-abort.mir
@@ -7,15 +7,14 @@ fn main::{closure#0}(_1: *mut {coroutine@$DIR/coroutine_drop_cleanup.rs:12:5: 12
     let _4: ();
     let mut _5: ();
     let mut _6: ();
-    let mut _7: ();
-    let mut _8: u32;
+    let mut _7: u32;
     scope 1 {
         debug _s => (((*_1) as variant#3).0: std::string::String);
     }
 
     bb0: {
-        _8 = discriminant((*_1));
-        switchInt(move _8) -> [0: bb5, 3: bb8, otherwise: bb9];
+        _7 = discriminant((*_1));
+        switchInt(move _7) -> [0: bb5, 3: bb8, otherwise: bb9];
     }
 
     bb1: {
diff --git a/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-unwind.mir b/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-unwind.mir
index 613ef2909b5..69e7219af9f 100644
--- a/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-unwind.mir
+++ b/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-unwind.mir
@@ -7,15 +7,14 @@ fn main::{closure#0}(_1: *mut {coroutine@$DIR/coroutine_drop_cleanup.rs:12:5: 12
     let _4: ();
     let mut _5: ();
     let mut _6: ();
-    let mut _7: ();
-    let mut _8: u32;
+    let mut _7: u32;
     scope 1 {
         debug _s => (((*_1) as variant#3).0: std::string::String);
     }
 
     bb0: {
-        _8 = discriminant((*_1));
-        switchInt(move _8) -> [0: bb7, 3: bb10, otherwise: bb11];
+        _7 = discriminant((*_1));
+        switchInt(move _7) -> [0: bb7, 3: bb10, otherwise: bb11];
     }
 
     bb1: {
diff --git a/tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir
index f8b3f68d21e..9905cc3e00f 100644
--- a/tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir
+++ b/tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir
@@ -1,7 +1,7 @@
 // MIR for `main::{closure#0}` 0 coroutine_resume
 /* coroutine_layout = CoroutineLayout {
     field_tys: {
-        _0: CoroutineSavedTy {
+        _s0: CoroutineSavedTy {
             ty: HasDrop,
             source_info: SourceInfo {
                 span: $DIR/coroutine_tiny.rs:22:13: 22:15 (#0),
@@ -14,15 +14,15 @@
         Unresumed(0): [],
         Returned (1): [],
         Panicked (2): [],
-        Suspend0 (3): [_0],
+        Suspend0 (3): [_s0],
     },
     storage_conflicts: BitMatrix(1x1) {
-        (_0, _0),
+        (_s0, _s0),
     },
 } */
 
 fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13}>, _2: u8) -> CoroutineState<(), ()> {
-    debug _x => _10;
+    debug _x => _2;
     let mut _0: std::ops::CoroutineState<(), ()>;
     let _3: HasDrop;
     let mut _4: !;
@@ -31,19 +31,17 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13}
     let mut _7: ();
     let _8: ();
     let mut _9: ();
-    let _10: u8;
-    let mut _11: u32;
+    let mut _10: u32;
     scope 1 {
         debug _d => (((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13})) as variant#3).0: HasDrop);
     }
 
     bb0: {
-        _11 = discriminant((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13})));
-        switchInt(move _11) -> [0: bb1, 3: bb5, otherwise: bb6];
+        _10 = discriminant((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13})));
+        switchInt(move _10) -> [0: bb1, 3: bb5, otherwise: bb6];
     }
 
     bb1: {
-        _10 = move _2;
         nop;
         (((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13})) as variant#3).0: HasDrop) = HasDrop;
         StorageLive(_4);
diff --git a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-abort.diff
new file mode 100644
index 00000000000..fd9ef54fe77
--- /dev/null
+++ b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-abort.diff
@@ -0,0 +1,77 @@
+- // MIR for `main` before DataflowConstProp
++ // MIR for `main` after DataflowConstProp
+  
+  fn main() -> () {
+      let mut _0: ();
+      let _1: u32;
+      let mut _2: &[u32];
+      let mut _3: &[u32; 3];
+      let _4: &[u32; 3];
+      let _5: [u32; 3];
+      let _6: usize;
+      let mut _7: usize;
+      let mut _8: bool;
+      let mut _10: &[u32];
+      let _11: usize;
+      let mut _12: usize;
+      let mut _13: bool;
+      let mut _14: &[u32; 3];
+      scope 1 {
+          debug local => _1;
+          let _9: u32;
+          scope 2 {
+              debug constant => _9;
+          }
+      }
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          StorageLive(_3);
+          StorageLive(_4);
+          _14 = const main::promoted[0];
+          _4 = copy _14;
+          _3 = copy _4;
+          _2 = move _3 as &[u32] (PointerCoercion(Unsize, AsCast));
+          StorageDead(_3);
+          StorageLive(_6);
+          _6 = const 1_usize;
+-         _7 = PtrMetadata(copy _2);
+-         _8 = Lt(copy _6, copy _7);
+-         assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind unreachable];
++         _7 = const 3_usize;
++         _8 = const true;
++         assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind unreachable];
+      }
+  
+      bb1: {
+-         _1 = copy (*_2)[_6];
++         _1 = copy (*_2)[1 of 2];
+          StorageDead(_6);
+          StorageDead(_4);
+          StorageDead(_2);
+          StorageLive(_9);
+          StorageLive(_10);
+          _10 = const main::SLICE;
+          StorageLive(_11);
+          _11 = const 1_usize;
+-         _12 = PtrMetadata(copy _10);
+-         _13 = Lt(copy _11, copy _12);
+-         assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb2, unwind unreachable];
++         _12 = const 3_usize;
++         _13 = const true;
++         assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb2, unwind unreachable];
+      }
+  
+      bb2: {
+-         _9 = copy (*_10)[_11];
++         _9 = copy (*_10)[1 of 2];
+          StorageDead(_11);
+          StorageDead(_10);
+          _0 = const ();
+          StorageDead(_9);
+          StorageDead(_1);
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-unwind.diff
new file mode 100644
index 00000000000..1fec08c2562
--- /dev/null
+++ b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-unwind.diff
@@ -0,0 +1,77 @@
+- // MIR for `main` before DataflowConstProp
++ // MIR for `main` after DataflowConstProp
+  
+  fn main() -> () {
+      let mut _0: ();
+      let _1: u32;
+      let mut _2: &[u32];
+      let mut _3: &[u32; 3];
+      let _4: &[u32; 3];
+      let _5: [u32; 3];
+      let _6: usize;
+      let mut _7: usize;
+      let mut _8: bool;
+      let mut _10: &[u32];
+      let _11: usize;
+      let mut _12: usize;
+      let mut _13: bool;
+      let mut _14: &[u32; 3];
+      scope 1 {
+          debug local => _1;
+          let _9: u32;
+          scope 2 {
+              debug constant => _9;
+          }
+      }
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          StorageLive(_3);
+          StorageLive(_4);
+          _14 = const main::promoted[0];
+          _4 = copy _14;
+          _3 = copy _4;
+          _2 = move _3 as &[u32] (PointerCoercion(Unsize, AsCast));
+          StorageDead(_3);
+          StorageLive(_6);
+          _6 = const 1_usize;
+-         _7 = PtrMetadata(copy _2);
+-         _8 = Lt(copy _6, copy _7);
+-         assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind continue];
++         _7 = const 3_usize;
++         _8 = const true;
++         assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind continue];
+      }
+  
+      bb1: {
+-         _1 = copy (*_2)[_6];
++         _1 = copy (*_2)[1 of 2];
+          StorageDead(_6);
+          StorageDead(_4);
+          StorageDead(_2);
+          StorageLive(_9);
+          StorageLive(_10);
+          _10 = const main::SLICE;
+          StorageLive(_11);
+          _11 = const 1_usize;
+-         _12 = PtrMetadata(copy _10);
+-         _13 = Lt(copy _11, copy _12);
+-         assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb2, unwind continue];
++         _12 = const 3_usize;
++         _13 = const true;
++         assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb2, unwind continue];
+      }
+  
+      bb2: {
+-         _9 = copy (*_10)[_11];
++         _9 = copy (*_10)[1 of 2];
+          StorageDead(_11);
+          StorageDead(_10);
+          _0 = const ();
+          StorageDead(_9);
+          StorageDead(_1);
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-abort.diff
new file mode 100644
index 00000000000..fd9ef54fe77
--- /dev/null
+++ b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-abort.diff
@@ -0,0 +1,77 @@
+- // MIR for `main` before DataflowConstProp
++ // MIR for `main` after DataflowConstProp
+  
+  fn main() -> () {
+      let mut _0: ();
+      let _1: u32;
+      let mut _2: &[u32];
+      let mut _3: &[u32; 3];
+      let _4: &[u32; 3];
+      let _5: [u32; 3];
+      let _6: usize;
+      let mut _7: usize;
+      let mut _8: bool;
+      let mut _10: &[u32];
+      let _11: usize;
+      let mut _12: usize;
+      let mut _13: bool;
+      let mut _14: &[u32; 3];
+      scope 1 {
+          debug local => _1;
+          let _9: u32;
+          scope 2 {
+              debug constant => _9;
+          }
+      }
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          StorageLive(_3);
+          StorageLive(_4);
+          _14 = const main::promoted[0];
+          _4 = copy _14;
+          _3 = copy _4;
+          _2 = move _3 as &[u32] (PointerCoercion(Unsize, AsCast));
+          StorageDead(_3);
+          StorageLive(_6);
+          _6 = const 1_usize;
+-         _7 = PtrMetadata(copy _2);
+-         _8 = Lt(copy _6, copy _7);
+-         assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind unreachable];
++         _7 = const 3_usize;
++         _8 = const true;
++         assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind unreachable];
+      }
+  
+      bb1: {
+-         _1 = copy (*_2)[_6];
++         _1 = copy (*_2)[1 of 2];
+          StorageDead(_6);
+          StorageDead(_4);
+          StorageDead(_2);
+          StorageLive(_9);
+          StorageLive(_10);
+          _10 = const main::SLICE;
+          StorageLive(_11);
+          _11 = const 1_usize;
+-         _12 = PtrMetadata(copy _10);
+-         _13 = Lt(copy _11, copy _12);
+-         assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb2, unwind unreachable];
++         _12 = const 3_usize;
++         _13 = const true;
++         assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb2, unwind unreachable];
+      }
+  
+      bb2: {
+-         _9 = copy (*_10)[_11];
++         _9 = copy (*_10)[1 of 2];
+          StorageDead(_11);
+          StorageDead(_10);
+          _0 = const ();
+          StorageDead(_9);
+          StorageDead(_1);
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-unwind.diff
new file mode 100644
index 00000000000..1fec08c2562
--- /dev/null
+++ b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-unwind.diff
@@ -0,0 +1,77 @@
+- // MIR for `main` before DataflowConstProp
++ // MIR for `main` after DataflowConstProp
+  
+  fn main() -> () {
+      let mut _0: ();
+      let _1: u32;
+      let mut _2: &[u32];
+      let mut _3: &[u32; 3];
+      let _4: &[u32; 3];
+      let _5: [u32; 3];
+      let _6: usize;
+      let mut _7: usize;
+      let mut _8: bool;
+      let mut _10: &[u32];
+      let _11: usize;
+      let mut _12: usize;
+      let mut _13: bool;
+      let mut _14: &[u32; 3];
+      scope 1 {
+          debug local => _1;
+          let _9: u32;
+          scope 2 {
+              debug constant => _9;
+          }
+      }
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          StorageLive(_3);
+          StorageLive(_4);
+          _14 = const main::promoted[0];
+          _4 = copy _14;
+          _3 = copy _4;
+          _2 = move _3 as &[u32] (PointerCoercion(Unsize, AsCast));
+          StorageDead(_3);
+          StorageLive(_6);
+          _6 = const 1_usize;
+-         _7 = PtrMetadata(copy _2);
+-         _8 = Lt(copy _6, copy _7);
+-         assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind continue];
++         _7 = const 3_usize;
++         _8 = const true;
++         assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind continue];
+      }
+  
+      bb1: {
+-         _1 = copy (*_2)[_6];
++         _1 = copy (*_2)[1 of 2];
+          StorageDead(_6);
+          StorageDead(_4);
+          StorageDead(_2);
+          StorageLive(_9);
+          StorageLive(_10);
+          _10 = const main::SLICE;
+          StorageLive(_11);
+          _11 = const 1_usize;
+-         _12 = PtrMetadata(copy _10);
+-         _13 = Lt(copy _11, copy _12);
+-         assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb2, unwind continue];
++         _12 = const 3_usize;
++         _13 = const true;
++         assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb2, unwind continue];
+      }
+  
+      bb2: {
+-         _9 = copy (*_10)[_11];
++         _9 = copy (*_10)[1 of 2];
+          StorageDead(_11);
+          StorageDead(_10);
+          _0 = const ();
+          StorageDead(_9);
+          StorageDead(_1);
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/dataflow-const-prop/slice_len.rs b/tests/mir-opt/dataflow-const-prop/slice_len.rs
new file mode 100644
index 00000000000..e0e68f9fde5
--- /dev/null
+++ b/tests/mir-opt/dataflow-const-prop/slice_len.rs
@@ -0,0 +1,34 @@
+// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
+//@ test-mir-pass: DataflowConstProp
+//@ compile-flags: -Zmir-enable-passes=+InstSimplify-after-simplifycfg
+// EMIT_MIR_FOR_EACH_BIT_WIDTH
+
+// EMIT_MIR slice_len.main.DataflowConstProp.diff
+
+// CHECK-LABEL: fn main(
+fn main() {
+    // CHECK: debug local => [[local:_.*]];
+    // CHECK: debug constant => [[constant:_.*]];
+
+    // CHECK-NOT: {{_.*}} = Len(
+    // CHECK-NOT: {{_.*}} = Lt(
+    // CHECK-NOT: assert(move _
+    // CHECK: {{_.*}} = const 3_usize;
+    // CHECK: {{_.*}} = const true;
+    // CHECK: assert(const true,
+
+    // CHECK: [[local]] = copy (*{{_.*}})[1 of 2];
+    let local = (&[1u32, 2, 3] as &[u32])[1];
+
+    // CHECK-NOT: {{_.*}} = Len(
+    // CHECK-NOT: {{_.*}} = Lt(
+    // CHECK-NOT: assert(move _
+    const SLICE: &[u32] = &[1, 2, 3];
+    // CHECK: {{_.*}} = const 3_usize;
+    // CHECK: {{_.*}} = const true;
+    // CHECK: assert(const true,
+
+    // CHECK-NOT: [[constant]] = {{copy|move}} (*{{_.*}})[_
+    // CHECK: [[constant]] = copy (*{{_.*}})[1 of 2];
+    let constant = SLICE[1];
+}
diff --git a/tests/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.panic-abort.diff b/tests/mir-opt/dest-prop/nrvo_borrowed.nrvo.DestinationPropagation.panic-abort.diff
index 6dce3ec5303..e9fbcf20a72 100644
--- a/tests/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.panic-abort.diff
+++ b/tests/mir-opt/dest-prop/nrvo_borrowed.nrvo.DestinationPropagation.panic-abort.diff
@@ -1,5 +1,5 @@
-- // MIR for `nrvo` before RenameReturnPlace
-+ // MIR for `nrvo` after RenameReturnPlace
+- // MIR for `nrvo` before DestinationPropagation
++ // MIR for `nrvo` after DestinationPropagation
   
   fn nrvo(_1: for<'a> fn(&'a mut [u8; 1024])) -> [u8; 1024] {
       debug init => _1;
@@ -10,32 +10,33 @@
       let mut _5: &mut [u8; 1024];
       let mut _6: &mut [u8; 1024];
       scope 1 {
--         debug buf => _2;
-+         debug buf => _0;
+          debug buf => _2;
       }
   
       bb0: {
--         StorageLive(_2);
--         _2 = [const 0_u8; 1024];
-+         _0 = [const 0_u8; 1024];
+          StorageLive(_2);
+          _2 = [const 0_u8; 1024];
           StorageLive(_3);
-          StorageLive(_4);
-          _4 = copy _1;
+-         StorageLive(_4);
+-         _4 = copy _1;
++         nop;
++         nop;
           StorageLive(_5);
           StorageLive(_6);
--         _6 = &mut _2;
-+         _6 = &mut _0;
+          _6 = &mut _2;
           _5 = &mut (*_6);
-          _3 = move _4(move _5) -> [return: bb1, unwind unreachable];
+-         _3 = move _4(move _5) -> [return: bb1, unwind unreachable];
++         _3 = move _1(move _5) -> [return: bb1, unwind unreachable];
       }
   
       bb1: {
           StorageDead(_5);
-          StorageDead(_4);
+-         StorageDead(_4);
++         nop;
           StorageDead(_6);
           StorageDead(_3);
--         _0 = copy _2;
--         StorageDead(_2);
+          _0 = copy _2;
+          StorageDead(_2);
           return;
       }
   }
diff --git a/tests/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.panic-unwind.diff b/tests/mir-opt/dest-prop/nrvo_borrowed.nrvo.DestinationPropagation.panic-unwind.diff
index 54cbe2871f1..95d5fe1b930 100644
--- a/tests/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.panic-unwind.diff
+++ b/tests/mir-opt/dest-prop/nrvo_borrowed.nrvo.DestinationPropagation.panic-unwind.diff
@@ -1,5 +1,5 @@
-- // MIR for `nrvo` before RenameReturnPlace
-+ // MIR for `nrvo` after RenameReturnPlace
+- // MIR for `nrvo` before DestinationPropagation
++ // MIR for `nrvo` after DestinationPropagation
   
   fn nrvo(_1: for<'a> fn(&'a mut [u8; 1024])) -> [u8; 1024] {
       debug init => _1;
@@ -10,32 +10,33 @@
       let mut _5: &mut [u8; 1024];
       let mut _6: &mut [u8; 1024];
       scope 1 {
--         debug buf => _2;
-+         debug buf => _0;
+          debug buf => _2;
       }
   
       bb0: {
--         StorageLive(_2);
--         _2 = [const 0_u8; 1024];
-+         _0 = [const 0_u8; 1024];
+          StorageLive(_2);
+          _2 = [const 0_u8; 1024];
           StorageLive(_3);
-          StorageLive(_4);
-          _4 = copy _1;
+-         StorageLive(_4);
+-         _4 = copy _1;
++         nop;
++         nop;
           StorageLive(_5);
           StorageLive(_6);
--         _6 = &mut _2;
-+         _6 = &mut _0;
+          _6 = &mut _2;
           _5 = &mut (*_6);
-          _3 = move _4(move _5) -> [return: bb1, unwind continue];
+-         _3 = move _4(move _5) -> [return: bb1, unwind continue];
++         _3 = move _1(move _5) -> [return: bb1, unwind continue];
       }
   
       bb1: {
           StorageDead(_5);
-          StorageDead(_4);
+-         StorageDead(_4);
++         nop;
           StorageDead(_6);
           StorageDead(_3);
--         _0 = copy _2;
--         StorageDead(_2);
+          _0 = copy _2;
+          StorageDead(_2);
           return;
       }
   }
diff --git a/tests/mir-opt/nrvo_simple.rs b/tests/mir-opt/dest-prop/nrvo_borrowed.rs
index df540472e1c..6f3076d4c13 100644
--- a/tests/mir-opt/nrvo_simple.rs
+++ b/tests/mir-opt/dest-prop/nrvo_borrowed.rs
@@ -1,8 +1,8 @@
 // skip-filecheck
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
-//@ test-mir-pass: RenameReturnPlace
+//@ test-mir-pass: DestinationPropagation
 
-// EMIT_MIR nrvo_simple.nrvo.RenameReturnPlace.diff
+// EMIT_MIR nrvo_borrowed.nrvo.DestinationPropagation.diff
 fn nrvo(init: fn(&mut [u8; 1024])) -> [u8; 1024] {
     let mut buf = [0; 1024];
     init(&mut buf);
diff --git a/tests/mir-opt/nrvo_miscompile_111005.rs b/tests/mir-opt/dest-prop/nrvo_miscompile_111005.rs
index 131f7b8f6f9..17e6450278a 100644
--- a/tests/mir-opt/nrvo_miscompile_111005.rs
+++ b/tests/mir-opt/dest-prop/nrvo_miscompile_111005.rs
@@ -1,18 +1,17 @@
 // This is a miscompilation, #111005 to track
 
-//@ test-mir-pass: RenameReturnPlace
+//@ test-mir-pass: DestinationPropagation
 
 #![feature(custom_mir, core_intrinsics)]
 extern crate core;
 use core::intrinsics::mir::*;
 
-// EMIT_MIR nrvo_miscompile_111005.wrong.RenameReturnPlace.diff
+// EMIT_MIR nrvo_miscompile_111005.wrong.DestinationPropagation.diff
 #[custom_mir(dialect = "runtime", phase = "initial")]
 pub fn wrong(arg: char) -> char {
     // CHECK-LABEL: fn wrong(
     // CHECK: _0 = copy _1;
-    // FIXME: This is wrong:
-    // CHECK-NEXT: _0 = const 'b';
+    // CHECK-NEXT: _1 = const 'b';
     // CHECK-NEXT: return;
     mir! {
         {
diff --git a/tests/mir-opt/nrvo_miscompile_111005.wrong.RenameReturnPlace.diff b/tests/mir-opt/dest-prop/nrvo_miscompile_111005.wrong.DestinationPropagation.diff
index d248c76f261..60cf9236f6c 100644
--- a/tests/mir-opt/nrvo_miscompile_111005.wrong.RenameReturnPlace.diff
+++ b/tests/mir-opt/dest-prop/nrvo_miscompile_111005.wrong.DestinationPropagation.diff
@@ -1,5 +1,5 @@
-- // MIR for `wrong` before RenameReturnPlace
-+ // MIR for `wrong` after RenameReturnPlace
+- // MIR for `wrong` before DestinationPropagation
++ // MIR for `wrong` after DestinationPropagation
   
   fn wrong(_1: char) -> char {
       let mut _0: char;
@@ -9,8 +9,9 @@
 -         _2 = copy _1;
 -         _0 = copy _2;
 -         _2 = const 'b';
++         nop;
 +         _0 = copy _1;
-+         _0 = const 'b';
++         _1 = const 'b';
           return;
       }
   }
diff --git a/tests/mir-opt/gvn.array_len.GVN.panic-abort.diff b/tests/mir-opt/gvn.array_len.GVN.panic-abort.diff
index 0d0477fe772..59b65a52f4e 100644
--- a/tests/mir-opt/gvn.array_len.GVN.panic-abort.diff
+++ b/tests/mir-opt/gvn.array_len.GVN.panic-abort.diff
@@ -12,8 +12,7 @@
       }
   
       bb0: {
--         StorageLive(_2);
-+         nop;
+          StorageLive(_2);
           StorageLive(_3);
           _3 = &(*_1);
           _2 = move _3 as &[i32] (PointerCoercion(Unsize, Implicit));
@@ -23,8 +22,7 @@
 -         _0 = PtrMetadata(move _4);
 +         _0 = const 42_usize;
           StorageDead(_4);
--         StorageDead(_2);
-+         nop;
+          StorageDead(_2);
           return;
       }
   }
diff --git a/tests/mir-opt/gvn.array_len.GVN.panic-unwind.diff b/tests/mir-opt/gvn.array_len.GVN.panic-unwind.diff
index 0d0477fe772..59b65a52f4e 100644
--- a/tests/mir-opt/gvn.array_len.GVN.panic-unwind.diff
+++ b/tests/mir-opt/gvn.array_len.GVN.panic-unwind.diff
@@ -12,8 +12,7 @@
       }
   
       bb0: {
--         StorageLive(_2);
-+         nop;
+          StorageLive(_2);
           StorageLive(_3);
           _3 = &(*_1);
           _2 = move _3 as &[i32] (PointerCoercion(Unsize, Implicit));
@@ -23,8 +22,7 @@
 -         _0 = PtrMetadata(move _4);
 +         _0 = const 42_usize;
           StorageDead(_4);
--         StorageDead(_2);
-+         nop;
+          StorageDead(_2);
           return;
       }
   }
diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff
index 22e6ea722dd..2ae86e2eb8b 100644
--- a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff
+++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff
@@ -39,8 +39,8 @@
 +                 let mut _28: &mut std::task::Context<'_>;
 +                 let mut _29: ();
 +                 let mut _30: ();
-+                 let mut _31: &mut std::task::Context<'_>;
-+                 let mut _32: u32;
++                 let mut _31: u32;
++                 let mut _32: &mut {async fn body of ActionPermit<'_, T>::perform()};
 +                 let mut _33: &mut {async fn body of ActionPermit<'_, T>::perform()};
 +                 let mut _34: &mut {async fn body of ActionPermit<'_, T>::perform()};
 +                 let mut _35: &mut {async fn body of ActionPermit<'_, T>::perform()};
@@ -48,7 +48,6 @@
 +                 let mut _37: &mut {async fn body of ActionPermit<'_, T>::perform()};
 +                 let mut _38: &mut {async fn body of ActionPermit<'_, T>::perform()};
 +                 let mut _39: &mut {async fn body of ActionPermit<'_, T>::perform()};
-+                 let mut _40: &mut {async fn body of ActionPermit<'_, T>::perform()};
 +                 scope 7 {
 +                     let mut _15: std::future::Ready<()>;
 +                     scope 8 {
@@ -58,14 +57,14 @@
 +                         scope 12 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) {
 +                         }
 +                         scope 13 (inlined <std::future::Ready<()> as Future>::poll) {
-+                             let mut _42: ();
-+                             let mut _43: std::option::Option<()>;
-+                             let mut _44: &mut std::option::Option<()>;
-+                             let mut _45: &mut std::future::Ready<()>;
-+                             let mut _46: &mut std::pin::Pin<&mut std::future::Ready<()>>;
++                             let mut _41: ();
++                             let mut _42: std::option::Option<()>;
++                             let mut _43: &mut std::option::Option<()>;
++                             let mut _44: &mut std::future::Ready<()>;
++                             let mut _45: &mut std::pin::Pin<&mut std::future::Ready<()>>;
 +                             scope 14 (inlined <Pin<&mut std::future::Ready<()>> as DerefMut>::deref_mut) {
 +                                 scope 15 (inlined Pin::<&mut std::future::Ready<()>>::as_mut) {
-+                                     let mut _47: &mut &mut std::future::Ready<()>;
++                                     let mut _46: &mut &mut std::future::Ready<()>;
 +                                     scope 16 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) {
 +                                     }
 +                                     scope 18 (inlined <&mut std::future::Ready<()> as DerefMut>::deref_mut) {
@@ -75,22 +74,22 @@
 +                                 }
 +                             }
 +                             scope 19 (inlined Option::<()>::take) {
-+                                 let mut _48: std::option::Option<()>;
++                                 let mut _47: std::option::Option<()>;
 +                                 scope 20 (inlined std::mem::replace::<Option<()>>) {
 +                                     scope 21 {
 +                                     }
 +                                 }
 +                             }
 +                             scope 22 (inlined #[track_caller] Option::<()>::expect) {
-+                                 let mut _49: isize;
-+                                 let mut _50: !;
++                                 let mut _48: isize;
++                                 let mut _49: !;
 +                                 scope 23 {
 +                                 }
 +                             }
 +                         }
 +                     }
 +                     scope 10 (inlined ready::<()>) {
-+                         let mut _41: std::option::Option<()>;
++                         let mut _40: std::option::Option<()>;
 +                     }
 +                     scope 11 (inlined <std::future::Ready<()> as IntoFuture>::into_future) {
 +                     }
@@ -145,10 +144,9 @@
 +         StorageLive(_37);
 +         StorageLive(_38);
 +         StorageLive(_39);
-+         StorageLive(_40);
-+         _33 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
-+         _32 = discriminant((*_33));
-+         switchInt(move _32) -> [0: bb3, 1: bb10, 3: bb9, otherwise: bb5];
++         _32 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
++         _31 = discriminant((*_32));
++         switchInt(move _31) -> [0: bb3, 1: bb10, 3: bb9, otherwise: bb5];
       }
   
 -     bb3: {
@@ -158,7 +156,6 @@
 +     }
 + 
 +     bb2: {
-+         StorageDead(_40);
 +         StorageDead(_39);
 +         StorageDead(_38);
 +         StorageDead(_37);
@@ -186,23 +183,22 @@
       }
   
 +     bb3: {
-+         _31 = move _9;
++         _33 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
 +         _34 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
-+         _35 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
-+         (((*_34) as variant#3).0: ActionPermit<'_, T>) = move ((*_35).0: ActionPermit<'_, T>);
++         (((*_33) as variant#3).0: ActionPermit<'_, T>) = move ((*_34).0: ActionPermit<'_, T>);
 +         StorageLive(_12);
 +         StorageLive(_13);
 +         StorageLive(_14);
 +         _14 = ();
-+         StorageLive(_41);
-+         _41 = Option::<()>::Some(copy _14);
-+         _13 = std::future::Ready::<()>(move _41);
-+         StorageDead(_41);
++         StorageLive(_40);
++         _40 = Option::<()>::Some(copy _14);
++         _13 = std::future::Ready::<()>(move _40);
++         StorageDead(_40);
 +         StorageDead(_14);
 +         _12 = move _13;
 +         StorageDead(_13);
-+         _36 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
-+         (((*_36) as variant#3).1: std::future::Ready<()>) = move _12;
++         _35 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
++         (((*_35) as variant#3).1: std::future::Ready<()>) = move _12;
 +         goto -> bb4;
 +     }
 + 
@@ -214,39 +210,39 @@
 +         StorageLive(_19);
 +         StorageLive(_20);
 +         StorageLive(_21);
-+         _37 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
-+         _21 = &mut (((*_37) as variant#3).1: std::future::Ready<()>);
++         _36 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
++         _21 = &mut (((*_36) as variant#3).1: std::future::Ready<()>);
 +         _20 = &mut (*_21);
 +         _19 = Pin::<&mut std::future::Ready<()>> { pointer: copy _20 };
 +         StorageDead(_20);
 +         StorageLive(_22);
 +         StorageLive(_23);
 +         StorageLive(_24);
-+         _24 = copy _31;
++         _24 = copy _9;
 +         _23 = move _24;
 +         _22 = &mut (*_23);
 +         StorageDead(_24);
++         StorageLive(_44);
 +         StorageLive(_45);
-+         StorageLive(_46);
-+         StorageLive(_50);
++         StorageLive(_49);
++         StorageLive(_41);
 +         StorageLive(_42);
 +         StorageLive(_43);
-+         StorageLive(_44);
-+         _46 = &mut _19;
++         _45 = &mut _19;
++         StorageLive(_46);
++         _46 = &mut (_19.0: &mut std::future::Ready<()>);
++         _44 = copy (_19.0: &mut std::future::Ready<()>);
++         StorageDead(_46);
++         _43 = &mut ((*_44).0: std::option::Option<()>);
 +         StorageLive(_47);
-+         _47 = &mut (_19.0: &mut std::future::Ready<()>);
-+         _45 = copy (_19.0: &mut std::future::Ready<()>);
++         _47 = Option::<()>::None;
++         _42 = copy ((*_44).0: std::option::Option<()>);
++         ((*_44).0: std::option::Option<()>) = copy _47;
 +         StorageDead(_47);
-+         _44 = &mut ((*_45).0: std::option::Option<()>);
++         StorageDead(_43);
 +         StorageLive(_48);
-+         _48 = Option::<()>::None;
-+         _43 = copy ((*_45).0: std::option::Option<()>);
-+         ((*_45).0: std::option::Option<()>) = copy _48;
-+         StorageDead(_48);
-+         StorageDead(_44);
-+         StorageLive(_49);
-+         _49 = discriminant(_43);
-+         switchInt(move _49) -> [0: bb11, 1: bb12, otherwise: bb5];
++         _48 = discriminant(_42);
++         switchInt(move _48) -> [0: bb11, 1: bb12, otherwise: bb5];
       }
 + 
 +     bb5: {
@@ -266,8 +262,8 @@
 +         StorageDead(_12);
 +         StorageDead(_28);
 +         StorageDead(_29);
-+         _38 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
-+         discriminant((*_38)) = 3;
++         _37 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
++         discriminant((*_37)) = 3;
 +         goto -> bb2;
 +     }
 + 
@@ -281,14 +277,14 @@
 +         StorageDead(_18);
 +         StorageDead(_17);
 +         StorageDead(_12);
-+         _39 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
-+         drop((((*_39) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb8, unwind unreachable];
++         _38 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
++         drop((((*_38) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb8, unwind unreachable];
 +     }
 + 
 +     bb8: {
 +         _7 = Poll::<()>::Ready(move _30);
-+         _40 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
-+         discriminant((*_40)) = 1;
++         _39 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
++         discriminant((*_39)) = 1;
 +         goto -> bb2;
 +     }
 + 
@@ -298,7 +294,7 @@
 +         StorageLive(_29);
 +         _28 = move _9;
 +         StorageDead(_29);
-+         _31 = move _28;
++         _9 = move _28;
 +         StorageDead(_28);
 +         _16 = const ();
 +         goto -> bb4;
@@ -309,18 +305,18 @@
 +     }
 + 
 +     bb11: {
-+         _50 = option::expect_failed(const "`Ready` polled after completion") -> unwind unreachable;
++         _49 = option::expect_failed(const "`Ready` polled after completion") -> unwind unreachable;
 +     }
 + 
 +     bb12: {
-+         _42 = move ((_43 as Some).0: ());
-+         StorageDead(_49);
-+         StorageDead(_43);
-+         _18 = Poll::<()>::Ready(move _42);
++         _41 = move ((_42 as Some).0: ());
++         StorageDead(_48);
 +         StorageDead(_42);
-+         StorageDead(_50);
-+         StorageDead(_46);
++         _18 = Poll::<()>::Ready(move _41);
++         StorageDead(_41);
++         StorageDead(_49);
 +         StorageDead(_45);
++         StorageDead(_44);
 +         StorageDead(_22);
 +         StorageDead(_19);
 +         _25 = discriminant(_18);
diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff
index 8b027e988b8..d7ae931aaae 100644
--- a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff
+++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff
@@ -39,8 +39,8 @@
 +                 let mut _28: &mut std::task::Context<'_>;
 +                 let mut _29: ();
 +                 let mut _30: ();
-+                 let mut _31: &mut std::task::Context<'_>;
-+                 let mut _32: u32;
++                 let mut _31: u32;
++                 let mut _32: &mut {async fn body of ActionPermit<'_, T>::perform()};
 +                 let mut _33: &mut {async fn body of ActionPermit<'_, T>::perform()};
 +                 let mut _34: &mut {async fn body of ActionPermit<'_, T>::perform()};
 +                 let mut _35: &mut {async fn body of ActionPermit<'_, T>::perform()};
@@ -50,7 +50,6 @@
 +                 let mut _39: &mut {async fn body of ActionPermit<'_, T>::perform()};
 +                 let mut _40: &mut {async fn body of ActionPermit<'_, T>::perform()};
 +                 let mut _41: &mut {async fn body of ActionPermit<'_, T>::perform()};
-+                 let mut _42: &mut {async fn body of ActionPermit<'_, T>::perform()};
 +                 scope 7 {
 +                     let mut _15: std::future::Ready<()>;
 +                     scope 8 {
@@ -60,14 +59,14 @@
 +                         scope 12 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) {
 +                         }
 +                         scope 13 (inlined <std::future::Ready<()> as Future>::poll) {
-+                             let mut _44: ();
-+                             let mut _45: std::option::Option<()>;
-+                             let mut _46: &mut std::option::Option<()>;
-+                             let mut _47: &mut std::future::Ready<()>;
-+                             let mut _48: &mut std::pin::Pin<&mut std::future::Ready<()>>;
++                             let mut _43: ();
++                             let mut _44: std::option::Option<()>;
++                             let mut _45: &mut std::option::Option<()>;
++                             let mut _46: &mut std::future::Ready<()>;
++                             let mut _47: &mut std::pin::Pin<&mut std::future::Ready<()>>;
 +                             scope 14 (inlined <Pin<&mut std::future::Ready<()>> as DerefMut>::deref_mut) {
 +                                 scope 15 (inlined Pin::<&mut std::future::Ready<()>>::as_mut) {
-+                                     let mut _49: &mut &mut std::future::Ready<()>;
++                                     let mut _48: &mut &mut std::future::Ready<()>;
 +                                     scope 16 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) {
 +                                     }
 +                                     scope 18 (inlined <&mut std::future::Ready<()> as DerefMut>::deref_mut) {
@@ -77,22 +76,22 @@
 +                                 }
 +                             }
 +                             scope 19 (inlined Option::<()>::take) {
-+                                 let mut _50: std::option::Option<()>;
++                                 let mut _49: std::option::Option<()>;
 +                                 scope 20 (inlined std::mem::replace::<Option<()>>) {
 +                                     scope 21 {
 +                                     }
 +                                 }
 +                             }
 +                             scope 22 (inlined #[track_caller] Option::<()>::expect) {
-+                                 let mut _51: isize;
-+                                 let mut _52: !;
++                                 let mut _50: isize;
++                                 let mut _51: !;
 +                                 scope 23 {
 +                                 }
 +                             }
 +                         }
 +                     }
 +                     scope 10 (inlined ready::<()>) {
-+                         let mut _43: std::option::Option<()>;
++                         let mut _42: std::option::Option<()>;
 +                     }
 +                     scope 11 (inlined <std::future::Ready<()> as IntoFuture>::into_future) {
 +                     }
@@ -149,10 +148,9 @@
 +         StorageLive(_39);
 +         StorageLive(_40);
 +         StorageLive(_41);
-+         StorageLive(_42);
-+         _33 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
-+         _32 = discriminant((*_33));
-+         switchInt(move _32) -> [0: bb5, 1: bb15, 2: bb14, 3: bb13, otherwise: bb7];
++         _32 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
++         _31 = discriminant((*_32));
++         switchInt(move _31) -> [0: bb5, 1: bb15, 2: bb14, 3: bb13, otherwise: bb7];
       }
   
 -     bb3: {
@@ -170,7 +168,6 @@
 +     }
 + 
 +     bb4: {
-+         StorageDead(_42);
 +         StorageDead(_41);
 +         StorageDead(_40);
 +         StorageDead(_39);
@@ -203,23 +200,22 @@
 -         StorageDead(_2);
 -         return;
 +     bb5: {
-+         _31 = move _9;
++         _33 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
 +         _34 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
-+         _35 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
-+         (((*_34) as variant#3).0: ActionPermit<'_, T>) = move ((*_35).0: ActionPermit<'_, T>);
++         (((*_33) as variant#3).0: ActionPermit<'_, T>) = move ((*_34).0: ActionPermit<'_, T>);
 +         StorageLive(_12);
 +         StorageLive(_13);
 +         StorageLive(_14);
 +         _14 = ();
-+         StorageLive(_43);
-+         _43 = Option::<()>::Some(copy _14);
-+         _13 = std::future::Ready::<()>(move _43);
-+         StorageDead(_43);
++         StorageLive(_42);
++         _42 = Option::<()>::Some(copy _14);
++         _13 = std::future::Ready::<()>(move _42);
++         StorageDead(_42);
 +         StorageDead(_14);
 +         _12 = move _13;
 +         StorageDead(_13);
-+         _36 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
-+         (((*_36) as variant#3).1: std::future::Ready<()>) = move _12;
++         _35 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
++         (((*_35) as variant#3).1: std::future::Ready<()>) = move _12;
 +         goto -> bb6;
       }
   
@@ -231,39 +227,39 @@
 +         StorageLive(_19);
 +         StorageLive(_20);
 +         StorageLive(_21);
-+         _37 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
-+         _21 = &mut (((*_37) as variant#3).1: std::future::Ready<()>);
++         _36 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
++         _21 = &mut (((*_36) as variant#3).1: std::future::Ready<()>);
 +         _20 = &mut (*_21);
 +         _19 = Pin::<&mut std::future::Ready<()>> { pointer: copy _20 };
 +         StorageDead(_20);
 +         StorageLive(_22);
 +         StorageLive(_23);
 +         StorageLive(_24);
-+         _24 = copy _31;
++         _24 = copy _9;
 +         _23 = move _24;
 +         _22 = &mut (*_23);
 +         StorageDead(_24);
++         StorageLive(_46);
 +         StorageLive(_47);
-+         StorageLive(_48);
-+         StorageLive(_52);
++         StorageLive(_51);
++         StorageLive(_43);
 +         StorageLive(_44);
 +         StorageLive(_45);
-+         StorageLive(_46);
-+         _48 = &mut _19;
++         _47 = &mut _19;
++         StorageLive(_48);
++         _48 = &mut (_19.0: &mut std::future::Ready<()>);
++         _46 = copy (_19.0: &mut std::future::Ready<()>);
++         StorageDead(_48);
++         _45 = &mut ((*_46).0: std::option::Option<()>);
 +         StorageLive(_49);
-+         _49 = &mut (_19.0: &mut std::future::Ready<()>);
-+         _47 = copy (_19.0: &mut std::future::Ready<()>);
++         _49 = Option::<()>::None;
++         _44 = copy ((*_46).0: std::option::Option<()>);
++         ((*_46).0: std::option::Option<()>) = copy _49;
 +         StorageDead(_49);
-+         _46 = &mut ((*_47).0: std::option::Option<()>);
++         StorageDead(_45);
 +         StorageLive(_50);
-+         _50 = Option::<()>::None;
-+         _45 = copy ((*_47).0: std::option::Option<()>);
-+         ((*_47).0: std::option::Option<()>) = copy _50;
-+         StorageDead(_50);
-+         StorageDead(_46);
-+         StorageLive(_51);
-+         _51 = discriminant(_45);
-+         switchInt(move _51) -> [0: bb16, 1: bb17, otherwise: bb7];
++         _50 = discriminant(_44);
++         switchInt(move _50) -> [0: bb16, 1: bb17, otherwise: bb7];
       }
   
 -     bb6 (cleanup): {
@@ -285,8 +281,8 @@
 +         StorageDead(_12);
 +         StorageDead(_28);
 +         StorageDead(_29);
-+         _38 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
-+         discriminant((*_38)) = 3;
++         _37 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
++         discriminant((*_37)) = 3;
 +         goto -> bb4;
 +     }
 + 
@@ -300,14 +296,14 @@
 +         StorageDead(_18);
 +         StorageDead(_17);
 +         StorageDead(_12);
-+         _39 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
-+         drop((((*_39) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb10, unwind: bb12];
++         _38 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
++         drop((((*_38) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb10, unwind: bb12];
 +     }
 + 
 +     bb10: {
 +         _7 = Poll::<()>::Ready(move _30);
-+         _40 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
-+         discriminant((*_40)) = 1;
++         _39 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
++         discriminant((*_39)) = 1;
 +         goto -> bb4;
 +     }
 + 
@@ -319,13 +315,13 @@
 +         StorageDead(_18);
 +         StorageDead(_17);
 +         StorageDead(_12);
-+         _41 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
-+         drop((((*_41) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb12, unwind terminate(cleanup)];
++         _40 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
++         drop((((*_40) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb12, unwind terminate(cleanup)];
 +     }
 + 
 +     bb12 (cleanup): {
-+         _42 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
-+         discriminant((*_42)) = 2;
++         _41 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
++         discriminant((*_41)) = 2;
 +         goto -> bb2;
 +     }
 + 
@@ -335,7 +331,7 @@
 +         StorageLive(_29);
 +         _28 = move _9;
 +         StorageDead(_29);
-+         _31 = move _28;
++         _9 = move _28;
 +         StorageDead(_28);
 +         _16 = const ();
 +         goto -> bb6;
@@ -350,18 +346,18 @@
 +     }
 + 
 +     bb16: {
-+         _52 = option::expect_failed(const "`Ready` polled after completion") -> bb11;
++         _51 = option::expect_failed(const "`Ready` polled after completion") -> bb11;
 +     }
 + 
 +     bb17: {
-+         _44 = move ((_45 as Some).0: ());
-+         StorageDead(_51);
-+         StorageDead(_45);
-+         _18 = Poll::<()>::Ready(move _44);
++         _43 = move ((_44 as Some).0: ());
++         StorageDead(_50);
 +         StorageDead(_44);
-+         StorageDead(_52);
-+         StorageDead(_48);
++         _18 = Poll::<()>::Ready(move _43);
++         StorageDead(_43);
++         StorageDead(_51);
 +         StorageDead(_47);
++         StorageDead(_46);
 +         StorageDead(_22);
 +         StorageDead(_19);
 +         _25 = discriminant(_18);
diff --git a/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-abort.diff b/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-abort.diff
new file mode 100644
index 00000000000..feba0fe7c4a
--- /dev/null
+++ b/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-abort.diff
@@ -0,0 +1,71 @@
+- // MIR for `norm2` before InstSimplify-after-simplifycfg
++ // MIR for `norm2` after InstSimplify-after-simplifycfg
+  
+  fn norm2(_1: [f32; 2]) -> f32 {
+      debug x => _1;
+      let mut _0: f32;
+      let _2: f32;
+      let _3: usize;
+      let mut _4: bool;
+      let _6: usize;
+      let mut _7: bool;
+      let mut _8: f32;
+      let mut _9: f32;
+      let mut _10: f32;
+      let mut _11: f32;
+      let mut _12: f32;
+      let mut _13: f32;
+      scope 1 {
+          debug a => _2;
+          let _5: f32;
+          scope 2 {
+              debug b => _5;
+          }
+      }
+  
+      bb0: {
+          StorageLive(_2);
+          StorageLive(_3);
+          _3 = const 0_usize;
+          _4 = Lt(copy _3, const 2_usize);
+          assert(move _4, "index out of bounds: the length is {} but the index is {}", const 2_usize, copy _3) -> [success: bb1, unwind unreachable];
+      }
+  
+      bb1: {
+          _2 = copy _1[_3];
+          StorageDead(_3);
+          StorageLive(_5);
+          StorageLive(_6);
+          _6 = const 1_usize;
+          _7 = Lt(copy _6, const 2_usize);
+          assert(move _7, "index out of bounds: the length is {} but the index is {}", const 2_usize, copy _6) -> [success: bb2, unwind unreachable];
+      }
+  
+      bb2: {
+          _5 = copy _1[_6];
+          StorageDead(_6);
+          StorageLive(_8);
+          StorageLive(_9);
+          _9 = copy _2;
+          StorageLive(_10);
+          _10 = copy _2;
+          _8 = Mul(move _9, move _10);
+          StorageDead(_10);
+          StorageDead(_9);
+          StorageLive(_11);
+          StorageLive(_12);
+          _12 = copy _5;
+          StorageLive(_13);
+          _13 = copy _5;
+          _11 = Mul(move _12, move _13);
+          StorageDead(_13);
+          StorageDead(_12);
+          _0 = Add(move _8, move _11);
+          StorageDead(_11);
+          StorageDead(_8);
+          StorageDead(_5);
+          StorageDead(_2);
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-unwind.diff b/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-unwind.diff
new file mode 100644
index 00000000000..0ccf6a825c4
--- /dev/null
+++ b/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-unwind.diff
@@ -0,0 +1,71 @@
+- // MIR for `norm2` before InstSimplify-after-simplifycfg
++ // MIR for `norm2` after InstSimplify-after-simplifycfg
+  
+  fn norm2(_1: [f32; 2]) -> f32 {
+      debug x => _1;
+      let mut _0: f32;
+      let _2: f32;
+      let _3: usize;
+      let mut _4: bool;
+      let _6: usize;
+      let mut _7: bool;
+      let mut _8: f32;
+      let mut _9: f32;
+      let mut _10: f32;
+      let mut _11: f32;
+      let mut _12: f32;
+      let mut _13: f32;
+      scope 1 {
+          debug a => _2;
+          let _5: f32;
+          scope 2 {
+              debug b => _5;
+          }
+      }
+  
+      bb0: {
+          StorageLive(_2);
+          StorageLive(_3);
+          _3 = const 0_usize;
+          _4 = Lt(copy _3, const 2_usize);
+          assert(move _4, "index out of bounds: the length is {} but the index is {}", const 2_usize, copy _3) -> [success: bb1, unwind continue];
+      }
+  
+      bb1: {
+          _2 = copy _1[_3];
+          StorageDead(_3);
+          StorageLive(_5);
+          StorageLive(_6);
+          _6 = const 1_usize;
+          _7 = Lt(copy _6, const 2_usize);
+          assert(move _7, "index out of bounds: the length is {} but the index is {}", const 2_usize, copy _6) -> [success: bb2, unwind continue];
+      }
+  
+      bb2: {
+          _5 = copy _1[_6];
+          StorageDead(_6);
+          StorageLive(_8);
+          StorageLive(_9);
+          _9 = copy _2;
+          StorageLive(_10);
+          _10 = copy _2;
+          _8 = Mul(move _9, move _10);
+          StorageDead(_10);
+          StorageDead(_9);
+          StorageLive(_11);
+          StorageLive(_12);
+          _12 = copy _5;
+          StorageLive(_13);
+          _13 = copy _5;
+          _11 = Mul(move _12, move _13);
+          StorageDead(_13);
+          StorageDead(_12);
+          _0 = Add(move _8, move _11);
+          StorageDead(_11);
+          StorageDead(_8);
+          StorageDead(_5);
+          StorageDead(_2);
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/instsimplify/combine_array_len.normN.InstSimplify-after-simplifycfg.panic-abort.diff b/tests/mir-opt/instsimplify/combine_array_len.normN.InstSimplify-after-simplifycfg.panic-abort.diff
new file mode 100644
index 00000000000..e9cb2c58177
--- /dev/null
+++ b/tests/mir-opt/instsimplify/combine_array_len.normN.InstSimplify-after-simplifycfg.panic-abort.diff
@@ -0,0 +1,71 @@
+- // MIR for `normN` before InstSimplify-after-simplifycfg
++ // MIR for `normN` after InstSimplify-after-simplifycfg
+  
+  fn normN(_1: [f32; N]) -> f32 {
+      debug x => _1;
+      let mut _0: f32;
+      let _2: f32;
+      let _3: usize;
+      let mut _4: bool;
+      let _6: usize;
+      let mut _7: bool;
+      let mut _8: f32;
+      let mut _9: f32;
+      let mut _10: f32;
+      let mut _11: f32;
+      let mut _12: f32;
+      let mut _13: f32;
+      scope 1 {
+          debug a => _2;
+          let _5: f32;
+          scope 2 {
+              debug b => _5;
+          }
+      }
+  
+      bb0: {
+          StorageLive(_2);
+          StorageLive(_3);
+          _3 = const 0_usize;
+          _4 = Lt(copy _3, const N);
+          assert(move _4, "index out of bounds: the length is {} but the index is {}", const N, copy _3) -> [success: bb1, unwind unreachable];
+      }
+  
+      bb1: {
+          _2 = copy _1[_3];
+          StorageDead(_3);
+          StorageLive(_5);
+          StorageLive(_6);
+          _6 = const 1_usize;
+          _7 = Lt(copy _6, const N);
+          assert(move _7, "index out of bounds: the length is {} but the index is {}", const N, copy _6) -> [success: bb2, unwind unreachable];
+      }
+  
+      bb2: {
+          _5 = copy _1[_6];
+          StorageDead(_6);
+          StorageLive(_8);
+          StorageLive(_9);
+          _9 = copy _2;
+          StorageLive(_10);
+          _10 = copy _2;
+          _8 = Mul(move _9, move _10);
+          StorageDead(_10);
+          StorageDead(_9);
+          StorageLive(_11);
+          StorageLive(_12);
+          _12 = copy _5;
+          StorageLive(_13);
+          _13 = copy _5;
+          _11 = Mul(move _12, move _13);
+          StorageDead(_13);
+          StorageDead(_12);
+          _0 = Add(move _8, move _11);
+          StorageDead(_11);
+          StorageDead(_8);
+          StorageDead(_5);
+          StorageDead(_2);
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/instsimplify/combine_array_len.normN.InstSimplify-after-simplifycfg.panic-unwind.diff b/tests/mir-opt/instsimplify/combine_array_len.normN.InstSimplify-after-simplifycfg.panic-unwind.diff
new file mode 100644
index 00000000000..0ddc70f2003
--- /dev/null
+++ b/tests/mir-opt/instsimplify/combine_array_len.normN.InstSimplify-after-simplifycfg.panic-unwind.diff
@@ -0,0 +1,71 @@
+- // MIR for `normN` before InstSimplify-after-simplifycfg
++ // MIR for `normN` after InstSimplify-after-simplifycfg
+  
+  fn normN(_1: [f32; N]) -> f32 {
+      debug x => _1;
+      let mut _0: f32;
+      let _2: f32;
+      let _3: usize;
+      let mut _4: bool;
+      let _6: usize;
+      let mut _7: bool;
+      let mut _8: f32;
+      let mut _9: f32;
+      let mut _10: f32;
+      let mut _11: f32;
+      let mut _12: f32;
+      let mut _13: f32;
+      scope 1 {
+          debug a => _2;
+          let _5: f32;
+          scope 2 {
+              debug b => _5;
+          }
+      }
+  
+      bb0: {
+          StorageLive(_2);
+          StorageLive(_3);
+          _3 = const 0_usize;
+          _4 = Lt(copy _3, const N);
+          assert(move _4, "index out of bounds: the length is {} but the index is {}", const N, copy _3) -> [success: bb1, unwind continue];
+      }
+  
+      bb1: {
+          _2 = copy _1[_3];
+          StorageDead(_3);
+          StorageLive(_5);
+          StorageLive(_6);
+          _6 = const 1_usize;
+          _7 = Lt(copy _6, const N);
+          assert(move _7, "index out of bounds: the length is {} but the index is {}", const N, copy _6) -> [success: bb2, unwind continue];
+      }
+  
+      bb2: {
+          _5 = copy _1[_6];
+          StorageDead(_6);
+          StorageLive(_8);
+          StorageLive(_9);
+          _9 = copy _2;
+          StorageLive(_10);
+          _10 = copy _2;
+          _8 = Mul(move _9, move _10);
+          StorageDead(_10);
+          StorageDead(_9);
+          StorageLive(_11);
+          StorageLive(_12);
+          _12 = copy _5;
+          StorageLive(_13);
+          _13 = copy _5;
+          _11 = Mul(move _12, move _13);
+          StorageDead(_13);
+          StorageDead(_12);
+          _0 = Add(move _8, move _11);
+          StorageDead(_11);
+          StorageDead(_8);
+          StorageDead(_5);
+          StorageDead(_2);
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/instsimplify/combine_array_len.rs b/tests/mir-opt/instsimplify/combine_array_len.rs
new file mode 100644
index 00000000000..1c4d42d3bbe
--- /dev/null
+++ b/tests/mir-opt/instsimplify/combine_array_len.rs
@@ -0,0 +1,25 @@
+// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
+//@ test-mir-pass: InstSimplify-after-simplifycfg
+
+// EMIT_MIR combine_array_len.norm2.InstSimplify-after-simplifycfg.diff
+fn norm2(x: [f32; 2]) -> f32 {
+    // CHECK-LABEL: fn norm2(
+    // CHECK-NOT: PtrMetadata(
+    let a = x[0];
+    let b = x[1];
+    a * a + b * b
+}
+
+// EMIT_MIR combine_array_len.normN.InstSimplify-after-simplifycfg.diff
+fn normN<const N: usize>(x: [f32; N]) -> f32 {
+    // CHECK-LABEL: fn normN(
+    // CHECK-NOT: PtrMetadata(
+    let a = x[0];
+    let b = x[1];
+    a * a + b * b
+}
+
+fn main() {
+    assert_eq!(norm2([3.0, 4.0]), 5.0 * 5.0);
+    assert_eq!(normN([3.0, 4.0]), 5.0 * 5.0);
+}
diff --git a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff
index 08dee3697e0..5cf36b9aebf 100644
--- a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff
+++ b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff
@@ -7,18 +7,16 @@
       let _2: &[T];
       let _3: &[T; 3];
       let _4: [T; 3];
-      let mut _5: usize;
-      let mut _6: bool;
-      let mut _10: !;
+      let mut _8: !;
       scope 1 {
           debug v => _2;
+          let _5: &T;
+          let _6: &T;
           let _7: &T;
-          let _8: &T;
-          let _9: &T;
           scope 2 {
-              debug v1 => _7;
-              debug v2 => _8;
-              debug v3 => _9;
+              debug v1 => _5;
+              debug v2 => _6;
+              debug v3 => _7;
           }
       }
   
@@ -27,25 +25,23 @@
           _4 = [copy _1, copy _1, copy _1];
           _3 = &_4;
           _2 = copy _3 as &[T] (PointerCoercion(Unsize, Implicit));
-          nop;
-          nop;
           goto -> bb2;
       }
   
       bb1: {
-          _10 = core::panicking::panic(const "internal error: entered unreachable code") -> unwind unreachable;
+          _8 = core::panicking::panic(const "internal error: entered unreachable code") -> unwind unreachable;
       }
   
       bb2: {
+          StorageLive(_5);
+          _5 = &(*_2)[0 of 3];
+          StorageLive(_6);
+          _6 = &(*_2)[1 of 3];
           StorageLive(_7);
-          _7 = &(*_2)[0 of 3];
-          StorageLive(_8);
-          _8 = &(*_2)[1 of 3];
-          StorageLive(_9);
-          _9 = &(*_2)[2 of 3];
-          StorageDead(_9);
-          StorageDead(_8);
+          _7 = &(*_2)[2 of 3];
           StorageDead(_7);
+          StorageDead(_6);
+          StorageDead(_5);
           StorageDead(_4);
           return;
       }
diff --git a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff
index aa44a2ad532..0598a3aa3f1 100644
--- a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff
+++ b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff
@@ -7,18 +7,16 @@
       let _2: &[T];
       let _3: &[T; 3];
       let _4: [T; 3];
-      let mut _5: usize;
-      let mut _6: bool;
-      let mut _10: !;
+      let mut _8: !;
       scope 1 {
           debug v => _2;
+          let _5: &T;
+          let _6: &T;
           let _7: &T;
-          let _8: &T;
-          let _9: &T;
           scope 2 {
-              debug v1 => _7;
-              debug v2 => _8;
-              debug v3 => _9;
+              debug v1 => _5;
+              debug v2 => _6;
+              debug v3 => _7;
           }
       }
   
@@ -27,25 +25,23 @@
           _4 = [copy _1, copy _1, copy _1];
           _3 = &_4;
           _2 = copy _3 as &[T] (PointerCoercion(Unsize, Implicit));
-          nop;
-          nop;
           goto -> bb2;
       }
   
       bb1: {
-          _10 = core::panicking::panic(const "internal error: entered unreachable code") -> unwind continue;
+          _8 = core::panicking::panic(const "internal error: entered unreachable code") -> unwind continue;
       }
   
       bb2: {
+          StorageLive(_5);
+          _5 = &(*_2)[0 of 3];
+          StorageLive(_6);
+          _6 = &(*_2)[1 of 3];
           StorageLive(_7);
-          _7 = &(*_2)[0 of 3];
-          StorageLive(_8);
-          _8 = &(*_2)[1 of 3];
-          StorageLive(_9);
-          _9 = &(*_2)[2 of 3];
-          StorageDead(_9);
-          StorageDead(_8);
+          _7 = &(*_2)[2 of 3];
           StorageDead(_7);
+          StorageDead(_6);
+          StorageDead(_5);
           StorageDead(_4);
           return;
       }
diff --git a/tests/mir-opt/lower_array_len.array_len_raw.GVN.panic-abort.diff b/tests/mir-opt/lower_array_len.array_len_raw.GVN.panic-abort.diff
index 180a7db0297..714a12804e6 100644
--- a/tests/mir-opt/lower_array_len.array_len_raw.GVN.panic-abort.diff
+++ b/tests/mir-opt/lower_array_len.array_len_raw.GVN.panic-abort.diff
@@ -18,8 +18,7 @@
       }
   
       bb0: {
--         StorageLive(_2);
-+         nop;
+          StorageLive(_2);
           StorageLive(_3);
           StorageLive(_4);
           _4 = &_1;
@@ -41,8 +40,7 @@
       bb1: {
           StorageDead(_6);
           StorageDead(_5);
--         StorageDead(_2);
-+         nop;
+          StorageDead(_2);
           StorageDead(_7);
           return;
       }
diff --git a/tests/mir-opt/lower_array_len.array_len_raw.GVN.panic-unwind.diff b/tests/mir-opt/lower_array_len.array_len_raw.GVN.panic-unwind.diff
index 180a7db0297..714a12804e6 100644
--- a/tests/mir-opt/lower_array_len.array_len_raw.GVN.panic-unwind.diff
+++ b/tests/mir-opt/lower_array_len.array_len_raw.GVN.panic-unwind.diff
@@ -18,8 +18,7 @@
       }
   
       bb0: {
--         StorageLive(_2);
-+         nop;
+          StorageLive(_2);
           StorageLive(_3);
           StorageLive(_4);
           _4 = &_1;
@@ -41,8 +40,7 @@
       bb1: {
           StorageDead(_6);
           StorageDead(_5);
--         StorageDead(_2);
-+         nop;
+          StorageDead(_2);
           StorageDead(_7);
           return;
       }
diff --git a/tests/mir-opt/lower_array_len.array_len_reborrow.GVN.panic-abort.diff b/tests/mir-opt/lower_array_len.array_len_reborrow.GVN.panic-abort.diff
index 49964f8b49e..b236b22f067 100644
--- a/tests/mir-opt/lower_array_len.array_len_reborrow.GVN.panic-abort.diff
+++ b/tests/mir-opt/lower_array_len.array_len_reborrow.GVN.panic-abort.diff
@@ -17,8 +17,7 @@
       }
   
       bb0: {
--         StorageLive(_2);
-+         nop;
+          StorageLive(_2);
           StorageLive(_3);
           StorageLive(_4);
           _4 = &mut _1;
@@ -38,8 +37,7 @@
       bb1: {
           StorageDead(_6);
           StorageDead(_5);
--         StorageDead(_2);
-+         nop;
+          StorageDead(_2);
           return;
       }
   }
diff --git a/tests/mir-opt/lower_array_len.array_len_reborrow.GVN.panic-unwind.diff b/tests/mir-opt/lower_array_len.array_len_reborrow.GVN.panic-unwind.diff
index 49964f8b49e..b236b22f067 100644
--- a/tests/mir-opt/lower_array_len.array_len_reborrow.GVN.panic-unwind.diff
+++ b/tests/mir-opt/lower_array_len.array_len_reborrow.GVN.panic-unwind.diff
@@ -17,8 +17,7 @@
       }
   
       bb0: {
--         StorageLive(_2);
-+         nop;
+          StorageLive(_2);
           StorageLive(_3);
           StorageLive(_4);
           _4 = &mut _1;
@@ -38,8 +37,7 @@
       bb1: {
           StorageDead(_6);
           StorageDead(_5);
--         StorageDead(_2);
-+         nop;
+          StorageDead(_2);
           return;
       }
   }
diff --git a/tests/mir-opt/pre-codegen/checked_ops.rs b/tests/mir-opt/pre-codegen/checked_ops.rs
index 8fd340503f5..dfbc0f4a110 100644
--- a/tests/mir-opt/pre-codegen/checked_ops.rs
+++ b/tests/mir-opt/pre-codegen/checked_ops.rs
@@ -44,8 +44,7 @@ pub fn saturating_sub_at_home(lhs: u32, rhs: u32) -> u32 {
     // CHECK-LABEL: fn saturating_sub_at_home
     // CHECK: [[DELTA:_[0-9]+]] = SubUnchecked(copy _1, copy _2)
     // CHECK: [[TEMP1:_.+]] = Option::<u32>::Some({{move|copy}} [[DELTA]]);
-    // CHECK: [[TEMP2:_.+]] = {{move|copy}} (([[TEMP1]] as Some).0: u32);
-    // CHECK: _0 = {{move|copy}} [[TEMP2]];
+    // CHECK: _0 = {{move|copy}} (([[TEMP1]] as Some).0: u32);
     u32::checked_sub(lhs, rhs).unwrap_or(0)
 }
 
diff --git a/tests/mir-opt/pre-codegen/checked_ops.saturating_sub_at_home.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/checked_ops.saturating_sub_at_home.PreCodegen.after.panic-abort.mir
index 5b4fdeda857..dc7567b57e7 100644
--- a/tests/mir-opt/pre-codegen/checked_ops.saturating_sub_at_home.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/checked_ops.saturating_sub_at_home.PreCodegen.after.panic-abort.mir
@@ -10,7 +10,6 @@ fn saturating_sub_at_home(_1: u32, _2: u32) -> u32 {
         let mut _4: u32;
     }
     scope 2 (inlined Option::<u32>::unwrap_or) {
-        let _6: u32;
         scope 3 {
         }
     }
@@ -28,10 +27,7 @@ fn saturating_sub_at_home(_1: u32, _2: u32) -> u32 {
         _5 = Option::<u32>::Some(move _4);
         StorageDead(_4);
         StorageDead(_3);
-        StorageLive(_6);
-        _6 = move ((_5 as Some).0: u32);
-        _0 = move _6;
-        StorageDead(_6);
+        _0 = move ((_5 as Some).0: u32);
         goto -> bb3;
     }
 
diff --git a/tests/mir-opt/pre-codegen/checked_ops.saturating_sub_at_home.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/checked_ops.saturating_sub_at_home.PreCodegen.after.panic-unwind.mir
index 5b4fdeda857..dc7567b57e7 100644
--- a/tests/mir-opt/pre-codegen/checked_ops.saturating_sub_at_home.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/checked_ops.saturating_sub_at_home.PreCodegen.after.panic-unwind.mir
@@ -10,7 +10,6 @@ fn saturating_sub_at_home(_1: u32, _2: u32) -> u32 {
         let mut _4: u32;
     }
     scope 2 (inlined Option::<u32>::unwrap_or) {
-        let _6: u32;
         scope 3 {
         }
     }
@@ -28,10 +27,7 @@ fn saturating_sub_at_home(_1: u32, _2: u32) -> u32 {
         _5 = Option::<u32>::Some(move _4);
         StorageDead(_4);
         StorageDead(_3);
-        StorageLive(_6);
-        _6 = move ((_5 as Some).0: u32);
-        _0 = move _6;
-        StorageDead(_6);
+        _0 = move ((_5 as Some).0: u32);
         goto -> bb3;
     }
 
diff --git a/tests/mir-opt/pre-codegen/derived_ord.demo_le.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/derived_ord.demo_le.PreCodegen.after.mir
index 8746cb08991..e235fa35c02 100644
--- a/tests/mir-opt/pre-codegen/derived_ord.demo_le.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/derived_ord.demo_le.PreCodegen.after.mir
@@ -5,8 +5,9 @@ fn demo_le(_1: &MultiField, _2: &MultiField) -> bool {
     debug b => _2;
     let mut _0: bool;
     scope 1 (inlined <MultiField as PartialOrd>::le) {
-        let mut _11: std::option::Option<std::cmp::Ordering>;
+        let mut _6: std::option::Option<std::cmp::Ordering>;
         scope 2 (inlined Option::<std::cmp::Ordering>::is_some_and::<fn(std::cmp::Ordering) -> bool {std::cmp::Ordering::is_le}>) {
+            let mut _11: isize;
             let _12: std::cmp::Ordering;
             scope 3 {
                 scope 4 (inlined <fn(std::cmp::Ordering) -> bool {std::cmp::Ordering::is_le} as FnOnce<(std::cmp::Ordering,)>>::call_once - shim(fn(std::cmp::Ordering) -> bool {std::cmp::Ordering::is_le})) {
@@ -19,7 +20,6 @@ fn demo_le(_1: &MultiField, _2: &MultiField) -> bool {
             }
         }
         scope 7 (inlined <MultiField as PartialOrd>::partial_cmp) {
-            let mut _6: std::option::Option<std::cmp::Ordering>;
             let mut _7: i8;
             scope 8 {
             }
@@ -38,9 +38,8 @@ fn demo_le(_1: &MultiField, _2: &MultiField) -> bool {
 
     bb0: {
         StorageLive(_12);
-        StorageLive(_11);
-        StorageLive(_5);
         StorageLive(_6);
+        StorageLive(_5);
         StorageLive(_7);
         StorageLive(_3);
         _3 = copy ((*_1).0: char);
@@ -63,30 +62,44 @@ fn demo_le(_1: &MultiField, _2: &MultiField) -> bool {
         _10 = Cmp(move _8, move _9);
         StorageDead(_9);
         StorageDead(_8);
-        _11 = Option::<std::cmp::Ordering>::Some(move _10);
+        _6 = Option::<std::cmp::Ordering>::Some(move _10);
         StorageDead(_10);
         StorageDead(_7);
-        StorageDead(_6);
         StorageDead(_5);
-        goto -> bb3;
+        StorageLive(_11);
+        goto -> bb4;
     }
 
     bb2: {
-        _11 = copy _6;
         StorageDead(_7);
-        StorageDead(_6);
         StorageDead(_5);
-        goto -> bb3;
+        StorageLive(_11);
+        _11 = discriminant(_6);
+        switchInt(move _11) -> [0: bb3, 1: bb4, otherwise: bb6];
     }
 
     bb3: {
-        _12 = move ((_11 as Some).0: std::cmp::Ordering);
+        _0 = const false;
+        goto -> bb5;
+    }
+
+    bb4: {
+        _12 = move ((_6 as Some).0: std::cmp::Ordering);
         StorageLive(_13);
         _13 = discriminant(_12);
         _0 = Le(move _13, const 0_i8);
         StorageDead(_13);
+        goto -> bb5;
+    }
+
+    bb5: {
         StorageDead(_11);
+        StorageDead(_6);
         StorageDead(_12);
         return;
     }
+
+    bb6: {
+        unreachable;
+    }
 }
diff --git a/tests/mir-opt/pre-codegen/derived_ord.rs b/tests/mir-opt/pre-codegen/derived_ord.rs
index 73ae923a6cb..823e0f6d09c 100644
--- a/tests/mir-opt/pre-codegen/derived_ord.rs
+++ b/tests/mir-opt/pre-codegen/derived_ord.rs
@@ -25,7 +25,10 @@ pub fn demo_le(a: &MultiField, b: &MultiField) -> bool {
     // CHECK: Cmp(move [[A1]], move [[B1]]);
 
     // CHECK: [[D1:_[0-9]+]] = discriminant({{.+}});
-    // CHECK: _0 = Le(move [[D1]], const 0_i8);
+    // CHECK: switchInt(move [[D1]]) -> [0: bb{{[0-9]+}}, 1: bb{{[0-9]+}}, otherwise: bb{{[0-9]+}}];
+
+    // CHECK: [[D2:_[0-9]+]] = discriminant({{.+}});
+    // CHECK: _0 = Le(move [[D2]], const 0_i8);
     *a <= *b
 }
 
diff --git a/tests/mir-opt/pre-codegen/derived_ord.{impl#0}-partial_cmp.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/derived_ord.{impl#0}-partial_cmp.PreCodegen.after.mir
index de25eebee77..5993bd79d27 100644
--- a/tests/mir-opt/pre-codegen/derived_ord.{impl#0}-partial_cmp.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/derived_ord.{impl#0}-partial_cmp.PreCodegen.after.mir
@@ -4,10 +4,9 @@ fn <impl at $DIR/derived_ord.rs:5:10: 5:20>::partial_cmp(_1: &MultiField, _2: &M
     debug self => _1;
     debug other => _2;
     let mut _0: std::option::Option<std::cmp::Ordering>;
-    let mut _6: std::option::Option<std::cmp::Ordering>;
-    let mut _7: i8;
+    let mut _6: i8;
     scope 1 {
-        debug cmp => _6;
+        debug cmp => _0;
     }
     scope 2 (inlined std::cmp::impls::<impl PartialOrd for char>::partial_cmp) {
         let mut _3: char;
@@ -15,9 +14,9 @@ fn <impl at $DIR/derived_ord.rs:5:10: 5:20>::partial_cmp(_1: &MultiField, _2: &M
         let mut _5: std::cmp::Ordering;
     }
     scope 3 (inlined std::cmp::impls::<impl PartialOrd for i16>::partial_cmp) {
+        let mut _7: i16;
         let mut _8: i16;
-        let mut _9: i16;
-        let mut _10: std::cmp::Ordering;
+        let mut _9: std::cmp::Ordering;
     }
 
     bb0: {
@@ -28,27 +27,26 @@ fn <impl at $DIR/derived_ord.rs:5:10: 5:20>::partial_cmp(_1: &MultiField, _2: &M
         _5 = Cmp(move _3, move _4);
         StorageDead(_4);
         StorageDead(_3);
-        _6 = Option::<std::cmp::Ordering>::Some(copy _5);
-        _7 = discriminant(_5);
-        switchInt(move _7) -> [0: bb1, otherwise: bb2];
+        _0 = Option::<std::cmp::Ordering>::Some(copy _5);
+        _6 = discriminant(_5);
+        switchInt(move _6) -> [0: bb1, otherwise: bb2];
     }
 
     bb1: {
-        StorageLive(_10);
-        StorageLive(_8);
-        _8 = copy ((*_1).1: i16);
         StorageLive(_9);
-        _9 = copy ((*_2).1: i16);
-        _10 = Cmp(move _8, move _9);
-        StorageDead(_9);
+        StorageLive(_7);
+        _7 = copy ((*_1).1: i16);
+        StorageLive(_8);
+        _8 = copy ((*_2).1: i16);
+        _9 = Cmp(move _7, move _8);
         StorageDead(_8);
-        _0 = Option::<std::cmp::Ordering>::Some(move _10);
-        StorageDead(_10);
+        StorageDead(_7);
+        _0 = Option::<std::cmp::Ordering>::Some(move _9);
+        StorageDead(_9);
         goto -> bb3;
     }
 
     bb2: {
-        _0 = copy _6;
         goto -> bb3;
     }
 
diff --git a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir
index dfe618612ab..03a52b82b49 100644
--- a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir
@@ -5,23 +5,21 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
     debug end => _2;
     debug f => _3;
     let mut _0: ();
-    let mut _4: u32;
-    let mut _9: std::option::Option<u32>;
-    let mut _11: &impl Fn(u32);
-    let mut _12: (u32,);
-    let _13: ();
+    let mut _7: std::option::Option<u32>;
+    let mut _9: &impl Fn(u32);
+    let mut _10: (u32,);
+    let _11: ();
     scope 1 {
-        debug ((iter: std::ops::Range<u32>).0: u32) => _4;
+        debug ((iter: std::ops::Range<u32>).0: u32) => _1;
         debug ((iter: std::ops::Range<u32>).1: u32) => _2;
-        let _10: u32;
+        let _8: u32;
         scope 2 {
-            debug x => _10;
+            debug x => _8;
         }
         scope 4 (inlined iter::range::<impl Iterator for std::ops::Range<u32>>::next) {
             scope 5 (inlined <std::ops::Range<u32> as iter::range::RangeIteratorImpl>::spec_next) {
-                let mut _6: bool;
-                let _7: u32;
-                let mut _8: u32;
+                let mut _5: bool;
+                let _6: u32;
                 scope 6 {
                     scope 8 (inlined <u32 as Step>::forward_unchecked) {
                         scope 9 (inlined #[track_caller] core::num::<impl u32>::unchecked_add) {
@@ -33,7 +31,7 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
                     }
                 }
                 scope 7 (inlined std::cmp::impls::<impl PartialOrd for u32>::lt) {
-                    let mut _5: u32;
+                    let mut _4: u32;
                 }
             }
         }
@@ -42,25 +40,22 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
     }
 
     bb0: {
-        StorageLive(_4);
-        _4 = copy _1;
         goto -> bb1;
     }
 
     bb1: {
-        StorageLive(_9);
-        StorageLive(_6);
+        StorageLive(_7);
         StorageLive(_5);
-        _5 = copy _4;
-        _6 = Lt(move _5, copy _2);
-        StorageDead(_5);
-        switchInt(move _6) -> [0: bb2, otherwise: bb4];
+        StorageLive(_4);
+        _4 = copy _1;
+        _5 = Lt(move _4, copy _2);
+        StorageDead(_4);
+        switchInt(move _5) -> [0: bb2, otherwise: bb4];
     }
 
     bb2: {
-        StorageDead(_6);
-        StorageDead(_9);
-        StorageDead(_4);
+        StorageDead(_5);
+        StorageDead(_7);
         drop(_3) -> [return: bb3, unwind unreachable];
     }
 
@@ -69,25 +64,22 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
     }
 
     bb4: {
-        _7 = copy _4;
-        StorageLive(_8);
-        _8 = AddUnchecked(copy _7, const 1_u32);
-        _4 = move _8;
-        StorageDead(_8);
-        _9 = Option::<u32>::Some(copy _7);
-        StorageDead(_6);
-        _10 = copy ((_9 as Some).0: u32);
-        StorageLive(_11);
-        _11 = &_3;
-        StorageLive(_12);
-        _12 = (copy _10,);
-        _13 = <impl Fn(u32) as Fn<(u32,)>>::call(move _11, move _12) -> [return: bb5, unwind unreachable];
+        _6 = copy _1;
+        _1 = AddUnchecked(copy _6, const 1_u32);
+        _7 = Option::<u32>::Some(copy _6);
+        StorageDead(_5);
+        _8 = copy ((_7 as Some).0: u32);
+        StorageLive(_9);
+        _9 = &_3;
+        StorageLive(_10);
+        _10 = (copy _8,);
+        _11 = <impl Fn(u32) as Fn<(u32,)>>::call(move _9, move _10) -> [return: bb5, unwind unreachable];
     }
 
     bb5: {
-        StorageDead(_12);
-        StorageDead(_11);
+        StorageDead(_10);
         StorageDead(_9);
+        StorageDead(_7);
         goto -> bb1;
     }
 }
diff --git a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir
index e0fcfcaffc5..3b09f33e733 100644
--- a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir
@@ -5,23 +5,21 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
     debug end => _2;
     debug f => _3;
     let mut _0: ();
-    let mut _4: u32;
-    let mut _9: std::option::Option<u32>;
-    let mut _11: &impl Fn(u32);
-    let mut _12: (u32,);
-    let _13: ();
+    let mut _7: std::option::Option<u32>;
+    let mut _9: &impl Fn(u32);
+    let mut _10: (u32,);
+    let _11: ();
     scope 1 {
-        debug ((iter: std::ops::Range<u32>).0: u32) => _4;
+        debug ((iter: std::ops::Range<u32>).0: u32) => _1;
         debug ((iter: std::ops::Range<u32>).1: u32) => _2;
-        let _10: u32;
+        let _8: u32;
         scope 2 {
-            debug x => _10;
+            debug x => _8;
         }
         scope 4 (inlined iter::range::<impl Iterator for std::ops::Range<u32>>::next) {
             scope 5 (inlined <std::ops::Range<u32> as iter::range::RangeIteratorImpl>::spec_next) {
-                let mut _6: bool;
-                let _7: u32;
-                let mut _8: u32;
+                let mut _5: bool;
+                let _6: u32;
                 scope 6 {
                     scope 8 (inlined <u32 as Step>::forward_unchecked) {
                         scope 9 (inlined #[track_caller] core::num::<impl u32>::unchecked_add) {
@@ -33,7 +31,7 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
                     }
                 }
                 scope 7 (inlined std::cmp::impls::<impl PartialOrd for u32>::lt) {
-                    let mut _5: u32;
+                    let mut _4: u32;
                 }
             }
         }
@@ -42,25 +40,22 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
     }
 
     bb0: {
-        StorageLive(_4);
-        _4 = copy _1;
         goto -> bb1;
     }
 
     bb1: {
-        StorageLive(_9);
-        StorageLive(_6);
+        StorageLive(_7);
         StorageLive(_5);
-        _5 = copy _4;
-        _6 = Lt(move _5, copy _2);
-        StorageDead(_5);
-        switchInt(move _6) -> [0: bb2, otherwise: bb4];
+        StorageLive(_4);
+        _4 = copy _1;
+        _5 = Lt(move _4, copy _2);
+        StorageDead(_4);
+        switchInt(move _5) -> [0: bb2, otherwise: bb4];
     }
 
     bb2: {
-        StorageDead(_6);
-        StorageDead(_9);
-        StorageDead(_4);
+        StorageDead(_5);
+        StorageDead(_7);
         drop(_3) -> [return: bb3, unwind continue];
     }
 
@@ -69,25 +64,22 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
     }
 
     bb4: {
-        _7 = copy _4;
-        StorageLive(_8);
-        _8 = AddUnchecked(copy _7, const 1_u32);
-        _4 = move _8;
-        StorageDead(_8);
-        _9 = Option::<u32>::Some(copy _7);
-        StorageDead(_6);
-        _10 = copy ((_9 as Some).0: u32);
-        StorageLive(_11);
-        _11 = &_3;
-        StorageLive(_12);
-        _12 = (copy _10,);
-        _13 = <impl Fn(u32) as Fn<(u32,)>>::call(move _11, move _12) -> [return: bb5, unwind: bb6];
+        _6 = copy _1;
+        _1 = AddUnchecked(copy _6, const 1_u32);
+        _7 = Option::<u32>::Some(copy _6);
+        StorageDead(_5);
+        _8 = copy ((_7 as Some).0: u32);
+        StorageLive(_9);
+        _9 = &_3;
+        StorageLive(_10);
+        _10 = (copy _8,);
+        _11 = <impl Fn(u32) as Fn<(u32,)>>::call(move _9, move _10) -> [return: bb5, unwind: bb6];
     }
 
     bb5: {
-        StorageDead(_12);
-        StorageDead(_11);
+        StorageDead(_10);
         StorageDead(_9);
+        StorageDead(_7);
         goto -> bb1;
     }
 
diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir
index 72b39a7f6a8..104987b0fdd 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir
@@ -4,30 +4,28 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     debug slice => _1;
     debug f => _2;
     let mut _0: ();
-    let mut _11: std::ptr::NonNull<T>;
-    let mut _12: *const T;
-    let mut _13: usize;
-    let mut _32: std::option::Option<(usize, &T)>;
-    let mut _35: &impl Fn(usize, &T);
-    let mut _36: (usize, &T);
-    let _37: ();
+    let mut _10: usize;
+    let mut _28: std::option::Option<(usize, &T)>;
+    let mut _31: &impl Fn(usize, &T);
+    let mut _32: (usize, &T);
+    let _33: ();
     scope 1 {
-        debug (((iter: Enumerate<std::slice::Iter<'_, T>>).0: std::slice::Iter<'_, T>).0: std::ptr::NonNull<T>) => _11;
-        debug (((iter: Enumerate<std::slice::Iter<'_, T>>).0: std::slice::Iter<'_, T>).1: *const T) => _12;
+        debug (((iter: Enumerate<std::slice::Iter<'_, T>>).0: std::slice::Iter<'_, T>).0: std::ptr::NonNull<T>) => _6;
+        debug (((iter: Enumerate<std::slice::Iter<'_, T>>).0: std::slice::Iter<'_, T>).1: *const T) => _9;
         debug (((iter: Enumerate<std::slice::Iter<'_, T>>).0: std::slice::Iter<'_, T>).2: std::marker::PhantomData<&T>) => const ZeroSized: PhantomData<&T>;
-        debug ((iter: Enumerate<std::slice::Iter<'_, T>>).1: usize) => _13;
-        let _33: usize;
-        let _34: &T;
+        debug ((iter: Enumerate<std::slice::Iter<'_, T>>).1: usize) => _10;
+        let _29: usize;
+        let _30: &T;
         scope 2 {
-            debug i => _33;
-            debug x => _34;
+            debug i => _29;
+            debug x => _30;
         }
         scope 18 (inlined <Enumerate<std::slice::Iter<'_, T>> as Iterator>::next) {
-            let mut _27: std::option::Option<&T>;
-            let mut _30: (usize, bool);
-            let mut _31: (usize, &T);
+            let mut _23: std::option::Option<&T>;
+            let mut _26: (usize, bool);
+            let mut _27: (usize, &T);
             scope 19 {
-                let _29: usize;
+                let _25: usize;
                 scope 24 {
                 }
             }
@@ -42,21 +40,21 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
                 }
             }
             scope 25 (inlined <Option<&T> as Try>::branch) {
-                let _28: &T;
+                let _24: &T;
                 scope 26 {
                 }
             }
             scope 28 (inlined <std::slice::Iter<'_, T> as Iterator>::next) {
-                let _14: std::ptr::NonNull<T>;
-                let _16: std::ptr::NonNull<T>;
-                let mut _19: bool;
-                let mut _22: std::ptr::NonNull<T>;
-                let mut _24: usize;
-                let _26: &T;
+                let mut _6: std::ptr::NonNull<T>;
+                let _11: std::ptr::NonNull<T>;
+                let _13: std::ptr::NonNull<T>;
+                let mut _16: bool;
+                let mut _20: usize;
+                let _22: &T;
                 scope 29 {
-                    let _15: *const T;
+                    let _12: *const T;
                     scope 30 {
-                        let _23: usize;
+                        let _19: usize;
                         scope 31 {
                             scope 34 (inlined #[track_caller] core::num::<impl usize>::unchecked_sub) {
                                 scope 35 (inlined core::ub_checks::check_language_ub) {
@@ -72,21 +70,21 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
                             }
                         }
                         scope 38 (inlined <NonNull<T> as PartialEq>::eq) {
-                            let mut _17: *mut T;
-                            let mut _18: *mut T;
+                            let mut _14: *mut T;
+                            let mut _15: *mut T;
                             scope 39 (inlined NonNull::<T>::as_ptr) {
                             }
                             scope 40 (inlined NonNull::<T>::as_ptr) {
                             }
                         }
                         scope 41 (inlined NonNull::<T>::add) {
-                            let mut _20: *const T;
-                            let mut _21: *const T;
+                            let mut _17: *const T;
+                            let mut _18: *const T;
                             scope 42 (inlined NonNull::<T>::as_ptr) {
                             }
                         }
                         scope 43 (inlined NonNull::<T>::as_ref::<'_>) {
-                            let _25: *const T;
+                            let _21: *const T;
                             scope 44 (inlined NonNull::<T>::as_ptr) {
                             }
                             scope 45 (inlined std::ptr::mut_ptr::<impl *mut T>::cast_const) {
@@ -102,9 +100,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
             let _3: usize;
             let mut _7: *mut T;
             let mut _8: *mut T;
-            let mut _10: *const T;
             scope 5 {
-                let _6: std::ptr::NonNull<T>;
                 scope 6 {
                     let _9: *const T;
                     scope 7 {
@@ -145,7 +141,6 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
         _5 = copy _4 as *const T (PtrToPtr);
         _6 = NonNull::<T> { pointer: copy _5 };
         StorageDead(_5);
-        StorageLive(_9);
         switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb1, otherwise: bb2];
     }
 
@@ -166,97 +161,86 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     }
 
     bb3: {
-        _10 = copy _9;
-        StorageDead(_9);
         StorageDead(_4);
         StorageDead(_3);
-        StorageLive(_11);
-        StorageLive(_12);
-        StorageLive(_13);
-        _11 = copy _6;
-        _12 = copy _10;
-        _13 = const 0_usize;
+        StorageLive(_10);
+        _10 = const 0_usize;
         goto -> bb4;
     }
 
     bb4: {
-        StorageLive(_32);
-        StorageLive(_29);
-        StorageLive(_30);
-        StorageLive(_27);
-        StorageLive(_14);
-        StorageLive(_15);
-        StorageLive(_23);
-        StorageLive(_24);
-        StorageLive(_16);
+        StorageLive(_28);
+        StorageLive(_25);
         StorageLive(_26);
-        _14 = copy _11;
-        _15 = copy _12;
+        StorageLive(_23);
+        StorageLive(_11);
+        StorageLive(_12);
+        StorageLive(_19);
+        StorageLive(_20);
+        StorageLive(_13);
+        StorageLive(_22);
+        _11 = copy _6;
+        _12 = copy _9;
         switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb5, otherwise: bb8];
     }
 
     bb5: {
-        StorageLive(_19);
-        _16 = copy _15 as std::ptr::NonNull<T> (Transmute);
-        StorageLive(_17);
-        _17 = copy _14 as *mut T (Transmute);
-        StorageLive(_18);
-        _18 = copy _16 as *mut T (Transmute);
-        _19 = Eq(copy _17, copy _18);
-        StorageDead(_18);
-        StorageDead(_17);
-        switchInt(move _19) -> [0: bb6, otherwise: bb7];
+        StorageLive(_16);
+        _13 = copy _12 as std::ptr::NonNull<T> (Transmute);
+        StorageLive(_14);
+        _14 = copy _11 as *mut T (Transmute);
+        StorageLive(_15);
+        _15 = copy _13 as *mut T (Transmute);
+        _16 = Eq(copy _14, copy _15);
+        StorageDead(_15);
+        StorageDead(_14);
+        switchInt(move _16) -> [0: bb6, otherwise: bb7];
     }
 
     bb6: {
-        StorageDead(_19);
-        StorageLive(_22);
-        StorageLive(_21);
-        StorageLive(_20);
-        _20 = copy _14 as *const T (Transmute);
-        _21 = Offset(copy _20, const 1_usize);
-        StorageDead(_20);
-        _22 = NonNull::<T> { pointer: copy _21 };
-        StorageDead(_21);
-        _11 = move _22;
-        StorageDead(_22);
+        StorageDead(_16);
+        StorageLive(_18);
+        StorageLive(_17);
+        _17 = copy _11 as *const T (Transmute);
+        _18 = Offset(copy _17, const 1_usize);
+        StorageDead(_17);
+        _6 = NonNull::<T> { pointer: copy _18 };
+        StorageDead(_18);
         goto -> bb13;
     }
 
     bb7: {
-        StorageDead(_19);
-        StorageDead(_26);
         StorageDead(_16);
-        StorageDead(_24);
-        StorageDead(_23);
-        StorageDead(_15);
-        StorageDead(_14);
+        StorageDead(_22);
+        StorageDead(_13);
+        StorageDead(_20);
+        StorageDead(_19);
+        StorageDead(_12);
+        StorageDead(_11);
         goto -> bb10;
     }
 
     bb8: {
-        _23 = copy _15 as usize (Transmute);
-        switchInt(copy _23) -> [0: bb9, otherwise: bb12];
+        _19 = copy _12 as usize (Transmute);
+        switchInt(copy _19) -> [0: bb9, otherwise: bb12];
     }
 
     bb9: {
-        StorageDead(_26);
-        StorageDead(_16);
-        StorageDead(_24);
-        StorageDead(_23);
-        StorageDead(_15);
-        StorageDead(_14);
+        StorageDead(_22);
+        StorageDead(_13);
+        StorageDead(_20);
+        StorageDead(_19);
+        StorageDead(_12);
+        StorageDead(_11);
         goto -> bb10;
     }
 
     bb10: {
-        StorageDead(_27);
-        StorageDead(_30);
-        StorageDead(_29);
-        StorageDead(_32);
-        StorageDead(_11);
-        StorageDead(_12);
-        StorageDead(_13);
+        StorageDead(_23);
+        StorageDead(_26);
+        StorageDead(_25);
+        StorageDead(_28);
+        StorageDead(_10);
         drop(_2) -> [return: bb11, unwind unreachable];
     }
 
@@ -265,51 +249,51 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     }
 
     bb12: {
-        _24 = SubUnchecked(copy _23, const 1_usize);
-        _12 = copy _24 as *const T (Transmute);
+        _20 = SubUnchecked(copy _19, const 1_usize);
+        _9 = copy _20 as *const T (Transmute);
         goto -> bb13;
     }
 
     bb13: {
-        StorageLive(_25);
-        _25 = copy _14 as *const T (Transmute);
-        _26 = &(*_25);
-        StorageDead(_25);
-        _27 = Option::<&T>::Some(copy _26);
-        StorageDead(_26);
-        StorageDead(_16);
-        StorageDead(_24);
+        StorageLive(_21);
+        _21 = copy _11 as *const T (Transmute);
+        _22 = &(*_21);
+        StorageDead(_21);
+        _23 = Option::<&T>::Some(copy _22);
+        StorageDead(_22);
+        StorageDead(_13);
+        StorageDead(_20);
+        StorageDead(_19);
+        StorageDead(_12);
+        StorageDead(_11);
+        _24 = copy ((_23 as Some).0: &T);
         StorageDead(_23);
-        StorageDead(_15);
-        StorageDead(_14);
-        _28 = copy ((_27 as Some).0: &T);
-        StorageDead(_27);
-        _29 = copy _13;
-        _30 = AddWithOverflow(copy _13, const 1_usize);
-        assert(!move (_30.1: bool), "attempt to compute `{} + {}`, which would overflow", copy _13, const 1_usize) -> [success: bb14, unwind unreachable];
+        _25 = copy _10;
+        _26 = AddWithOverflow(copy _10, const 1_usize);
+        assert(!move (_26.1: bool), "attempt to compute `{} + {}`, which would overflow", copy _10, const 1_usize) -> [success: bb14, unwind unreachable];
     }
 
     bb14: {
-        _13 = move (_30.0: usize);
+        _10 = move (_26.0: usize);
+        StorageLive(_27);
+        _27 = (copy _25, copy _24);
+        _28 = Option::<(usize, &T)>::Some(move _27);
+        StorageDead(_27);
+        StorageDead(_26);
+        StorageDead(_25);
+        _29 = copy (((_28 as Some).0: (usize, &T)).0: usize);
+        _30 = copy (((_28 as Some).0: (usize, &T)).1: &T);
         StorageLive(_31);
-        _31 = (copy _29, copy _28);
-        _32 = Option::<(usize, &T)>::Some(move _31);
-        StorageDead(_31);
-        StorageDead(_30);
-        StorageDead(_29);
-        _33 = copy (((_32 as Some).0: (usize, &T)).0: usize);
-        _34 = copy (((_32 as Some).0: (usize, &T)).1: &T);
-        StorageLive(_35);
-        _35 = &_2;
-        StorageLive(_36);
-        _36 = (copy _33, copy _34);
-        _37 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _35, move _36) -> [return: bb15, unwind unreachable];
+        _31 = &_2;
+        StorageLive(_32);
+        _32 = (copy _29, copy _30);
+        _33 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _31, move _32) -> [return: bb15, unwind unreachable];
     }
 
     bb15: {
-        StorageDead(_36);
-        StorageDead(_35);
         StorageDead(_32);
+        StorageDead(_31);
+        StorageDead(_28);
         goto -> bb4;
     }
 }
diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir
index 42aa152ec99..28b12cdf367 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir
@@ -4,22 +4,22 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     debug slice => _1;
     debug f => _2;
     let mut _0: ();
-    let mut _11: std::slice::Iter<'_, T>;
+    let mut _10: std::slice::Iter<'_, T>;
+    let mut _11: std::iter::Enumerate<std::slice::Iter<'_, T>>;
     let mut _12: std::iter::Enumerate<std::slice::Iter<'_, T>>;
-    let mut _13: std::iter::Enumerate<std::slice::Iter<'_, T>>;
-    let mut _14: &mut std::iter::Enumerate<std::slice::Iter<'_, T>>;
-    let mut _15: std::option::Option<(usize, &T)>;
-    let mut _16: isize;
-    let mut _19: &impl Fn(usize, &T);
-    let mut _20: (usize, &T);
-    let _21: ();
+    let mut _13: &mut std::iter::Enumerate<std::slice::Iter<'_, T>>;
+    let mut _14: std::option::Option<(usize, &T)>;
+    let mut _15: isize;
+    let mut _18: &impl Fn(usize, &T);
+    let mut _19: (usize, &T);
+    let _20: ();
     scope 1 {
-        debug iter => _13;
-        let _17: usize;
-        let _18: &T;
+        debug iter => _12;
+        let _16: usize;
+        let _17: &T;
         scope 2 {
-            debug i => _17;
-            debug x => _18;
+            debug i => _16;
+            debug x => _17;
         }
     }
     scope 3 (inlined core::slice::<impl [T]>::iter) {
@@ -27,7 +27,6 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
             let _3: usize;
             let mut _7: *mut T;
             let mut _8: *mut T;
-            let mut _10: *const T;
             scope 5 {
                 let _6: std::ptr::NonNull<T>;
                 scope 6 {
@@ -62,9 +61,10 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     }
 
     bb0: {
-        StorageLive(_11);
+        StorageLive(_10);
         StorageLive(_3);
         StorageLive(_6);
+        StorageLive(_9);
         StorageLive(_4);
         _3 = PtrMetadata(copy _1);
         _4 = &raw const (*_1);
@@ -72,7 +72,6 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
         _5 = copy _4 as *const T (PtrToPtr);
         _6 = NonNull::<T> { pointer: copy _5 };
         StorageDead(_5);
-        StorageLive(_9);
         switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb1, otherwise: bb2];
     }
 
@@ -93,33 +92,30 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     }
 
     bb3: {
-        StorageLive(_10);
-        _10 = copy _9;
-        _11 = std::slice::Iter::<'_, T> { ptr: copy _6, end_or_len: copy _10, _marker: const ZeroSized: PhantomData<&T> };
-        StorageDead(_10);
-        StorageDead(_9);
+        _10 = std::slice::Iter::<'_, T> { ptr: copy _6, end_or_len: copy _9, _marker: const ZeroSized: PhantomData<&T> };
         StorageDead(_4);
+        StorageDead(_9);
         StorageDead(_6);
         StorageDead(_3);
-        _12 = Enumerate::<std::slice::Iter<'_, T>> { iter: copy _11, count: const 0_usize };
-        StorageDead(_11);
-        StorageLive(_13);
-        _13 = copy _12;
+        _11 = Enumerate::<std::slice::Iter<'_, T>> { iter: copy _10, count: const 0_usize };
+        StorageDead(_10);
+        StorageLive(_12);
+        _12 = copy _11;
         goto -> bb4;
     }
 
     bb4: {
-        _14 = &mut _13;
-        _15 = <Enumerate<std::slice::Iter<'_, T>> as Iterator>::next(move _14) -> [return: bb5, unwind: bb11];
+        _13 = &mut _12;
+        _14 = <Enumerate<std::slice::Iter<'_, T>> as Iterator>::next(move _13) -> [return: bb5, unwind: bb11];
     }
 
     bb5: {
-        _16 = discriminant(_15);
-        switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10];
+        _15 = discriminant(_14);
+        switchInt(move _15) -> [0: bb6, 1: bb8, otherwise: bb10];
     }
 
     bb6: {
-        StorageDead(_13);
+        StorageDead(_12);
         drop(_2) -> [return: bb7, unwind continue];
     }
 
@@ -128,18 +124,18 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     }
 
     bb8: {
-        _17 = copy (((_15 as Some).0: (usize, &T)).0: usize);
-        _18 = copy (((_15 as Some).0: (usize, &T)).1: &T);
+        _16 = copy (((_14 as Some).0: (usize, &T)).0: usize);
+        _17 = copy (((_14 as Some).0: (usize, &T)).1: &T);
+        StorageLive(_18);
+        _18 = &_2;
         StorageLive(_19);
-        _19 = &_2;
-        StorageLive(_20);
-        _20 = copy ((_15 as Some).0: (usize, &T));
-        _21 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _19, move _20) -> [return: bb9, unwind: bb11];
+        _19 = copy ((_14 as Some).0: (usize, &T));
+        _20 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _18, move _19) -> [return: bb9, unwind: bb11];
     }
 
     bb9: {
-        StorageDead(_20);
         StorageDead(_19);
+        StorageDead(_18);
         goto -> bb4;
     }
 
diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir
index 0d65640ec9b..4d0e3548e7d 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir
@@ -4,31 +4,29 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     debug slice => _1;
     debug f => _2;
     let mut _0: ();
-    let mut _11: std::ptr::NonNull<T>;
-    let mut _12: *const T;
-    let mut _26: std::option::Option<&T>;
-    let mut _28: &impl Fn(&T);
-    let mut _29: (&T,);
-    let _30: ();
+    let mut _22: std::option::Option<&T>;
+    let mut _24: &impl Fn(&T);
+    let mut _25: (&T,);
+    let _26: ();
     scope 1 {
-        debug ((iter: std::slice::Iter<'_, T>).0: std::ptr::NonNull<T>) => _11;
-        debug ((iter: std::slice::Iter<'_, T>).1: *const T) => _12;
+        debug ((iter: std::slice::Iter<'_, T>).0: std::ptr::NonNull<T>) => _6;
+        debug ((iter: std::slice::Iter<'_, T>).1: *const T) => _9;
         debug ((iter: std::slice::Iter<'_, T>).2: std::marker::PhantomData<&T>) => const ZeroSized: PhantomData<&T>;
-        let _27: &T;
+        let _23: &T;
         scope 2 {
-            debug x => _27;
+            debug x => _23;
         }
         scope 16 (inlined <std::slice::Iter<'_, T> as Iterator>::next) {
-            let _13: std::ptr::NonNull<T>;
-            let _15: std::ptr::NonNull<T>;
-            let mut _18: bool;
-            let mut _21: std::ptr::NonNull<T>;
-            let mut _23: usize;
-            let _25: &T;
+            let mut _6: std::ptr::NonNull<T>;
+            let _10: std::ptr::NonNull<T>;
+            let _12: std::ptr::NonNull<T>;
+            let mut _15: bool;
+            let mut _19: usize;
+            let _21: &T;
             scope 17 {
-                let _14: *const T;
+                let _11: *const T;
                 scope 18 {
-                    let _22: usize;
+                    let _18: usize;
                     scope 19 {
                         scope 22 (inlined #[track_caller] core::num::<impl usize>::unchecked_sub) {
                             scope 23 (inlined core::ub_checks::check_language_ub) {
@@ -44,21 +42,21 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
                         }
                     }
                     scope 26 (inlined <NonNull<T> as PartialEq>::eq) {
-                        let mut _16: *mut T;
-                        let mut _17: *mut T;
+                        let mut _13: *mut T;
+                        let mut _14: *mut T;
                         scope 27 (inlined NonNull::<T>::as_ptr) {
                         }
                         scope 28 (inlined NonNull::<T>::as_ptr) {
                         }
                     }
                     scope 29 (inlined NonNull::<T>::add) {
-                        let mut _19: *const T;
-                        let mut _20: *const T;
+                        let mut _16: *const T;
+                        let mut _17: *const T;
                         scope 30 (inlined NonNull::<T>::as_ptr) {
                         }
                     }
                     scope 31 (inlined NonNull::<T>::as_ref::<'_>) {
-                        let _24: *const T;
+                        let _20: *const T;
                         scope 32 (inlined NonNull::<T>::as_ptr) {
                         }
                         scope 33 (inlined std::ptr::mut_ptr::<impl *mut T>::cast_const) {
@@ -73,9 +71,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
             let _3: usize;
             let mut _7: *mut T;
             let mut _8: *mut T;
-            let mut _10: *const T;
             scope 5 {
-                let _6: std::ptr::NonNull<T>;
                 scope 6 {
                     let _9: *const T;
                     scope 7 {
@@ -112,7 +108,6 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
         _5 = copy _4 as *const T (PtrToPtr);
         _6 = NonNull::<T> { pointer: copy _5 };
         StorageDead(_5);
-        StorageLive(_9);
         switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb1, otherwise: bb2];
     }
 
@@ -133,88 +128,77 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     }
 
     bb3: {
-        _10 = copy _9;
-        StorageDead(_9);
         StorageDead(_4);
         StorageDead(_3);
-        StorageLive(_11);
-        StorageLive(_12);
-        _11 = copy _6;
-        _12 = copy _10;
         goto -> bb4;
     }
 
     bb4: {
-        StorageLive(_26);
-        StorageLive(_13);
-        StorageLive(_14);
         StorageLive(_22);
-        StorageLive(_23);
-        StorageLive(_15);
-        StorageLive(_25);
-        _13 = copy _11;
-        _14 = copy _12;
+        StorageLive(_10);
+        StorageLive(_11);
+        StorageLive(_18);
+        StorageLive(_19);
+        StorageLive(_12);
+        StorageLive(_21);
+        _10 = copy _6;
+        _11 = copy _9;
         switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb5, otherwise: bb8];
     }
 
     bb5: {
-        StorageLive(_18);
-        _15 = copy _14 as std::ptr::NonNull<T> (Transmute);
-        StorageLive(_16);
-        _16 = copy _13 as *mut T (Transmute);
-        StorageLive(_17);
-        _17 = copy _15 as *mut T (Transmute);
-        _18 = Eq(copy _16, copy _17);
-        StorageDead(_17);
-        StorageDead(_16);
-        switchInt(move _18) -> [0: bb6, otherwise: bb7];
+        StorageLive(_15);
+        _12 = copy _11 as std::ptr::NonNull<T> (Transmute);
+        StorageLive(_13);
+        _13 = copy _10 as *mut T (Transmute);
+        StorageLive(_14);
+        _14 = copy _12 as *mut T (Transmute);
+        _15 = Eq(copy _13, copy _14);
+        StorageDead(_14);
+        StorageDead(_13);
+        switchInt(move _15) -> [0: bb6, otherwise: bb7];
     }
 
     bb6: {
-        StorageDead(_18);
-        StorageLive(_21);
-        StorageLive(_20);
-        StorageLive(_19);
-        _19 = copy _13 as *const T (Transmute);
-        _20 = Offset(copy _19, const 1_usize);
-        StorageDead(_19);
-        _21 = NonNull::<T> { pointer: copy _20 };
-        StorageDead(_20);
-        _11 = move _21;
-        StorageDead(_21);
+        StorageDead(_15);
+        StorageLive(_17);
+        StorageLive(_16);
+        _16 = copy _10 as *const T (Transmute);
+        _17 = Offset(copy _16, const 1_usize);
+        StorageDead(_16);
+        _6 = NonNull::<T> { pointer: copy _17 };
+        StorageDead(_17);
         goto -> bb13;
     }
 
     bb7: {
-        StorageDead(_18);
-        StorageDead(_25);
         StorageDead(_15);
-        StorageDead(_23);
-        StorageDead(_22);
-        StorageDead(_14);
-        StorageDead(_13);
+        StorageDead(_21);
+        StorageDead(_12);
+        StorageDead(_19);
+        StorageDead(_18);
+        StorageDead(_11);
+        StorageDead(_10);
         goto -> bb10;
     }
 
     bb8: {
-        _22 = copy _14 as usize (Transmute);
-        switchInt(copy _22) -> [0: bb9, otherwise: bb12];
+        _18 = copy _11 as usize (Transmute);
+        switchInt(copy _18) -> [0: bb9, otherwise: bb12];
     }
 
     bb9: {
-        StorageDead(_25);
-        StorageDead(_15);
-        StorageDead(_23);
-        StorageDead(_22);
-        StorageDead(_14);
-        StorageDead(_13);
+        StorageDead(_21);
+        StorageDead(_12);
+        StorageDead(_19);
+        StorageDead(_18);
+        StorageDead(_11);
+        StorageDead(_10);
         goto -> bb10;
     }
 
     bb10: {
-        StorageDead(_26);
-        StorageDead(_11);
-        StorageDead(_12);
+        StorageDead(_22);
         drop(_2) -> [return: bb11, unwind unreachable];
     }
 
@@ -223,35 +207,35 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     }
 
     bb12: {
-        _23 = SubUnchecked(copy _22, const 1_usize);
-        _12 = copy _23 as *const T (Transmute);
+        _19 = SubUnchecked(copy _18, const 1_usize);
+        _9 = copy _19 as *const T (Transmute);
         goto -> bb13;
     }
 
     bb13: {
+        StorageLive(_20);
+        _20 = copy _10 as *const T (Transmute);
+        _21 = &(*_20);
+        StorageDead(_20);
+        _22 = Option::<&T>::Some(copy _21);
+        StorageDead(_21);
+        StorageDead(_12);
+        StorageDead(_19);
+        StorageDead(_18);
+        StorageDead(_11);
+        StorageDead(_10);
+        _23 = copy ((_22 as Some).0: &T);
         StorageLive(_24);
-        _24 = copy _13 as *const T (Transmute);
-        _25 = &(*_24);
-        StorageDead(_24);
-        _26 = Option::<&T>::Some(copy _25);
-        StorageDead(_25);
-        StorageDead(_15);
-        StorageDead(_23);
-        StorageDead(_22);
-        StorageDead(_14);
-        StorageDead(_13);
-        _27 = copy ((_26 as Some).0: &T);
-        StorageLive(_28);
-        _28 = &_2;
-        StorageLive(_29);
-        _29 = (copy _27,);
-        _30 = <impl Fn(&T) as Fn<(&T,)>>::call(move _28, move _29) -> [return: bb14, unwind unreachable];
+        _24 = &_2;
+        StorageLive(_25);
+        _25 = (copy _23,);
+        _26 = <impl Fn(&T) as Fn<(&T,)>>::call(move _24, move _25) -> [return: bb14, unwind unreachable];
     }
 
     bb14: {
-        StorageDead(_29);
-        StorageDead(_28);
-        StorageDead(_26);
+        StorageDead(_25);
+        StorageDead(_24);
+        StorageDead(_22);
         goto -> bb4;
     }
 }
diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir
index 02efb193474..2b5d8c27d71 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir
@@ -4,31 +4,29 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     debug slice => _1;
     debug f => _2;
     let mut _0: ();
-    let mut _11: std::ptr::NonNull<T>;
-    let mut _12: *const T;
-    let mut _26: std::option::Option<&T>;
-    let mut _28: &impl Fn(&T);
-    let mut _29: (&T,);
-    let _30: ();
+    let mut _22: std::option::Option<&T>;
+    let mut _24: &impl Fn(&T);
+    let mut _25: (&T,);
+    let _26: ();
     scope 1 {
-        debug ((iter: std::slice::Iter<'_, T>).0: std::ptr::NonNull<T>) => _11;
-        debug ((iter: std::slice::Iter<'_, T>).1: *const T) => _12;
+        debug ((iter: std::slice::Iter<'_, T>).0: std::ptr::NonNull<T>) => _6;
+        debug ((iter: std::slice::Iter<'_, T>).1: *const T) => _9;
         debug ((iter: std::slice::Iter<'_, T>).2: std::marker::PhantomData<&T>) => const ZeroSized: PhantomData<&T>;
-        let _27: &T;
+        let _23: &T;
         scope 2 {
-            debug x => _27;
+            debug x => _23;
         }
         scope 16 (inlined <std::slice::Iter<'_, T> as Iterator>::next) {
-            let _13: std::ptr::NonNull<T>;
-            let _15: std::ptr::NonNull<T>;
-            let mut _18: bool;
-            let mut _21: std::ptr::NonNull<T>;
-            let mut _23: usize;
-            let _25: &T;
+            let mut _6: std::ptr::NonNull<T>;
+            let _10: std::ptr::NonNull<T>;
+            let _12: std::ptr::NonNull<T>;
+            let mut _15: bool;
+            let mut _19: usize;
+            let _21: &T;
             scope 17 {
-                let _14: *const T;
+                let _11: *const T;
                 scope 18 {
-                    let _22: usize;
+                    let _18: usize;
                     scope 19 {
                         scope 22 (inlined #[track_caller] core::num::<impl usize>::unchecked_sub) {
                             scope 23 (inlined core::ub_checks::check_language_ub) {
@@ -44,21 +42,21 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
                         }
                     }
                     scope 26 (inlined <NonNull<T> as PartialEq>::eq) {
-                        let mut _16: *mut T;
-                        let mut _17: *mut T;
+                        let mut _13: *mut T;
+                        let mut _14: *mut T;
                         scope 27 (inlined NonNull::<T>::as_ptr) {
                         }
                         scope 28 (inlined NonNull::<T>::as_ptr) {
                         }
                     }
                     scope 29 (inlined NonNull::<T>::add) {
-                        let mut _19: *const T;
-                        let mut _20: *const T;
+                        let mut _16: *const T;
+                        let mut _17: *const T;
                         scope 30 (inlined NonNull::<T>::as_ptr) {
                         }
                     }
                     scope 31 (inlined NonNull::<T>::as_ref::<'_>) {
-                        let _24: *const T;
+                        let _20: *const T;
                         scope 32 (inlined NonNull::<T>::as_ptr) {
                         }
                         scope 33 (inlined std::ptr::mut_ptr::<impl *mut T>::cast_const) {
@@ -73,9 +71,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
             let _3: usize;
             let mut _7: *mut T;
             let mut _8: *mut T;
-            let mut _10: *const T;
             scope 5 {
-                let _6: std::ptr::NonNull<T>;
                 scope 6 {
                     let _9: *const T;
                     scope 7 {
@@ -112,7 +108,6 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
         _5 = copy _4 as *const T (PtrToPtr);
         _6 = NonNull::<T> { pointer: copy _5 };
         StorageDead(_5);
-        StorageLive(_9);
         switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb1, otherwise: bb2];
     }
 
@@ -133,88 +128,77 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     }
 
     bb3: {
-        _10 = copy _9;
-        StorageDead(_9);
         StorageDead(_4);
         StorageDead(_3);
-        StorageLive(_11);
-        StorageLive(_12);
-        _11 = copy _6;
-        _12 = copy _10;
         goto -> bb4;
     }
 
     bb4: {
-        StorageLive(_26);
-        StorageLive(_13);
-        StorageLive(_14);
         StorageLive(_22);
-        StorageLive(_23);
-        StorageLive(_15);
-        StorageLive(_25);
-        _13 = copy _11;
-        _14 = copy _12;
+        StorageLive(_10);
+        StorageLive(_11);
+        StorageLive(_18);
+        StorageLive(_19);
+        StorageLive(_12);
+        StorageLive(_21);
+        _10 = copy _6;
+        _11 = copy _9;
         switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb5, otherwise: bb8];
     }
 
     bb5: {
-        StorageLive(_18);
-        _15 = copy _14 as std::ptr::NonNull<T> (Transmute);
-        StorageLive(_16);
-        _16 = copy _13 as *mut T (Transmute);
-        StorageLive(_17);
-        _17 = copy _15 as *mut T (Transmute);
-        _18 = Eq(copy _16, copy _17);
-        StorageDead(_17);
-        StorageDead(_16);
-        switchInt(move _18) -> [0: bb6, otherwise: bb7];
+        StorageLive(_15);
+        _12 = copy _11 as std::ptr::NonNull<T> (Transmute);
+        StorageLive(_13);
+        _13 = copy _10 as *mut T (Transmute);
+        StorageLive(_14);
+        _14 = copy _12 as *mut T (Transmute);
+        _15 = Eq(copy _13, copy _14);
+        StorageDead(_14);
+        StorageDead(_13);
+        switchInt(move _15) -> [0: bb6, otherwise: bb7];
     }
 
     bb6: {
-        StorageDead(_18);
-        StorageLive(_21);
-        StorageLive(_20);
-        StorageLive(_19);
-        _19 = copy _13 as *const T (Transmute);
-        _20 = Offset(copy _19, const 1_usize);
-        StorageDead(_19);
-        _21 = NonNull::<T> { pointer: copy _20 };
-        StorageDead(_20);
-        _11 = move _21;
-        StorageDead(_21);
+        StorageDead(_15);
+        StorageLive(_17);
+        StorageLive(_16);
+        _16 = copy _10 as *const T (Transmute);
+        _17 = Offset(copy _16, const 1_usize);
+        StorageDead(_16);
+        _6 = NonNull::<T> { pointer: copy _17 };
+        StorageDead(_17);
         goto -> bb13;
     }
 
     bb7: {
-        StorageDead(_18);
-        StorageDead(_25);
         StorageDead(_15);
-        StorageDead(_23);
-        StorageDead(_22);
-        StorageDead(_14);
-        StorageDead(_13);
+        StorageDead(_21);
+        StorageDead(_12);
+        StorageDead(_19);
+        StorageDead(_18);
+        StorageDead(_11);
+        StorageDead(_10);
         goto -> bb10;
     }
 
     bb8: {
-        _22 = copy _14 as usize (Transmute);
-        switchInt(copy _22) -> [0: bb9, otherwise: bb12];
+        _18 = copy _11 as usize (Transmute);
+        switchInt(copy _18) -> [0: bb9, otherwise: bb12];
     }
 
     bb9: {
-        StorageDead(_25);
-        StorageDead(_15);
-        StorageDead(_23);
-        StorageDead(_22);
-        StorageDead(_14);
-        StorageDead(_13);
+        StorageDead(_21);
+        StorageDead(_12);
+        StorageDead(_19);
+        StorageDead(_18);
+        StorageDead(_11);
+        StorageDead(_10);
         goto -> bb10;
     }
 
     bb10: {
-        StorageDead(_26);
-        StorageDead(_11);
-        StorageDead(_12);
+        StorageDead(_22);
         drop(_2) -> [return: bb11, unwind continue];
     }
 
@@ -223,35 +207,35 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     }
 
     bb12: {
-        _23 = SubUnchecked(copy _22, const 1_usize);
-        _12 = copy _23 as *const T (Transmute);
+        _19 = SubUnchecked(copy _18, const 1_usize);
+        _9 = copy _19 as *const T (Transmute);
         goto -> bb13;
     }
 
     bb13: {
+        StorageLive(_20);
+        _20 = copy _10 as *const T (Transmute);
+        _21 = &(*_20);
+        StorageDead(_20);
+        _22 = Option::<&T>::Some(copy _21);
+        StorageDead(_21);
+        StorageDead(_12);
+        StorageDead(_19);
+        StorageDead(_18);
+        StorageDead(_11);
+        StorageDead(_10);
+        _23 = copy ((_22 as Some).0: &T);
         StorageLive(_24);
-        _24 = copy _13 as *const T (Transmute);
-        _25 = &(*_24);
-        StorageDead(_24);
-        _26 = Option::<&T>::Some(copy _25);
-        StorageDead(_25);
-        StorageDead(_15);
-        StorageDead(_23);
-        StorageDead(_22);
-        StorageDead(_14);
-        StorageDead(_13);
-        _27 = copy ((_26 as Some).0: &T);
-        StorageLive(_28);
-        _28 = &_2;
-        StorageLive(_29);
-        _29 = (copy _27,);
-        _30 = <impl Fn(&T) as Fn<(&T,)>>::call(move _28, move _29) -> [return: bb14, unwind: bb15];
+        _24 = &_2;
+        StorageLive(_25);
+        _25 = (copy _23,);
+        _26 = <impl Fn(&T) as Fn<(&T,)>>::call(move _24, move _25) -> [return: bb14, unwind: bb15];
     }
 
     bb14: {
-        StorageDead(_29);
-        StorageDead(_28);
-        StorageDead(_26);
+        StorageDead(_25);
+        StorageDead(_24);
+        StorageDead(_22);
         goto -> bb4;
     }
 
diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir
index 41e273151ec..14537599071 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir
@@ -5,28 +5,27 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     debug f => _2;
     let mut _0: ();
     let mut _3: usize;
-    let mut _4: usize;
-    let mut _9: std::option::Option<usize>;
-    let mut _11: bool;
-    let mut _13: &impl Fn(usize, &T);
-    let mut _14: (usize, &T);
-    let _15: ();
+    let mut _8: std::option::Option<usize>;
+    let mut _10: bool;
+    let mut _12: &impl Fn(usize, &T);
+    let mut _13: (usize, &T);
+    let _14: ();
     scope 1 {
         debug ((iter: std::ops::Range<usize>).0: usize) => _4;
         debug ((iter: std::ops::Range<usize>).1: usize) => _3;
-        let _10: usize;
+        let _9: usize;
         scope 2 {
-            debug i => _10;
-            let _12: &T;
+            debug i => _9;
+            let _11: &T;
             scope 3 {
-                debug x => _12;
+                debug x => _11;
             }
         }
         scope 5 (inlined iter::range::<impl Iterator for std::ops::Range<usize>>::next) {
             scope 6 (inlined <std::ops::Range<usize> as iter::range::RangeIteratorImpl>::spec_next) {
+                let mut _4: usize;
                 let mut _6: bool;
                 let _7: usize;
-                let mut _8: usize;
                 scope 7 {
                     scope 9 (inlined <usize as Step>::forward_unchecked) {
                         scope 10 (inlined #[track_caller] core::num::<impl usize>::unchecked_add) {
@@ -48,13 +47,12 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
 
     bb0: {
         _3 = PtrMetadata(copy _1);
-        StorageLive(_4);
         _4 = const 0_usize;
         goto -> bb1;
     }
 
     bb1: {
-        StorageLive(_9);
+        StorageLive(_8);
         StorageLive(_6);
         StorageLive(_5);
         _5 = copy _4;
@@ -65,8 +63,7 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
 
     bb2: {
         StorageDead(_6);
-        StorageDead(_9);
-        StorageDead(_4);
+        StorageDead(_8);
         drop(_2) -> [return: bb3, unwind unreachable];
     }
 
@@ -76,30 +73,27 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
 
     bb4: {
         _7 = copy _4;
-        StorageLive(_8);
-        _8 = AddUnchecked(copy _7, const 1_usize);
-        _4 = move _8;
-        StorageDead(_8);
-        _9 = Option::<usize>::Some(copy _7);
+        _4 = AddUnchecked(copy _7, const 1_usize);
+        _8 = Option::<usize>::Some(copy _7);
         StorageDead(_6);
-        _10 = copy ((_9 as Some).0: usize);
-        _11 = Lt(copy _10, copy _3);
-        assert(move _11, "index out of bounds: the length is {} but the index is {}", copy _3, copy _10) -> [success: bb5, unwind unreachable];
+        _9 = copy ((_8 as Some).0: usize);
+        _10 = Lt(copy _9, copy _3);
+        assert(move _10, "index out of bounds: the length is {} but the index is {}", copy _3, copy _9) -> [success: bb5, unwind unreachable];
     }
 
     bb5: {
-        _12 = &(*_1)[_10];
+        _11 = &(*_1)[_9];
+        StorageLive(_12);
+        _12 = &_2;
         StorageLive(_13);
-        _13 = &_2;
-        StorageLive(_14);
-        _14 = (copy _10, copy _12);
-        _15 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _13, move _14) -> [return: bb6, unwind unreachable];
+        _13 = (copy _9, copy _11);
+        _14 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _12, move _13) -> [return: bb6, unwind unreachable];
     }
 
     bb6: {
-        StorageDead(_14);
         StorageDead(_13);
-        StorageDead(_9);
+        StorageDead(_12);
+        StorageDead(_8);
         goto -> bb1;
     }
 }
diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir
index ec781c1480c..8e573ef488f 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir
@@ -5,28 +5,27 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     debug f => _2;
     let mut _0: ();
     let mut _3: usize;
-    let mut _4: usize;
-    let mut _9: std::option::Option<usize>;
-    let mut _11: bool;
-    let mut _13: &impl Fn(usize, &T);
-    let mut _14: (usize, &T);
-    let _15: ();
+    let mut _8: std::option::Option<usize>;
+    let mut _10: bool;
+    let mut _12: &impl Fn(usize, &T);
+    let mut _13: (usize, &T);
+    let _14: ();
     scope 1 {
         debug ((iter: std::ops::Range<usize>).0: usize) => _4;
         debug ((iter: std::ops::Range<usize>).1: usize) => _3;
-        let _10: usize;
+        let _9: usize;
         scope 2 {
-            debug i => _10;
-            let _12: &T;
+            debug i => _9;
+            let _11: &T;
             scope 3 {
-                debug x => _12;
+                debug x => _11;
             }
         }
         scope 5 (inlined iter::range::<impl Iterator for std::ops::Range<usize>>::next) {
             scope 6 (inlined <std::ops::Range<usize> as iter::range::RangeIteratorImpl>::spec_next) {
+                let mut _4: usize;
                 let mut _6: bool;
                 let _7: usize;
-                let mut _8: usize;
                 scope 7 {
                     scope 9 (inlined <usize as Step>::forward_unchecked) {
                         scope 10 (inlined #[track_caller] core::num::<impl usize>::unchecked_add) {
@@ -48,13 +47,12 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
 
     bb0: {
         _3 = PtrMetadata(copy _1);
-        StorageLive(_4);
         _4 = const 0_usize;
         goto -> bb1;
     }
 
     bb1: {
-        StorageLive(_9);
+        StorageLive(_8);
         StorageLive(_6);
         StorageLive(_5);
         _5 = copy _4;
@@ -65,8 +63,7 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
 
     bb2: {
         StorageDead(_6);
-        StorageDead(_9);
-        StorageDead(_4);
+        StorageDead(_8);
         drop(_2) -> [return: bb3, unwind continue];
     }
 
@@ -76,30 +73,27 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
 
     bb4: {
         _7 = copy _4;
-        StorageLive(_8);
-        _8 = AddUnchecked(copy _7, const 1_usize);
-        _4 = move _8;
-        StorageDead(_8);
-        _9 = Option::<usize>::Some(copy _7);
+        _4 = AddUnchecked(copy _7, const 1_usize);
+        _8 = Option::<usize>::Some(copy _7);
         StorageDead(_6);
-        _10 = copy ((_9 as Some).0: usize);
-        _11 = Lt(copy _10, copy _3);
-        assert(move _11, "index out of bounds: the length is {} but the index is {}", copy _3, copy _10) -> [success: bb5, unwind: bb7];
+        _9 = copy ((_8 as Some).0: usize);
+        _10 = Lt(copy _9, copy _3);
+        assert(move _10, "index out of bounds: the length is {} but the index is {}", copy _3, copy _9) -> [success: bb5, unwind: bb7];
     }
 
     bb5: {
-        _12 = &(*_1)[_10];
+        _11 = &(*_1)[_9];
+        StorageLive(_12);
+        _12 = &_2;
         StorageLive(_13);
-        _13 = &_2;
-        StorageLive(_14);
-        _14 = (copy _10, copy _12);
-        _15 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _13, move _14) -> [return: bb6, unwind: bb7];
+        _13 = (copy _9, copy _11);
+        _14 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _12, move _13) -> [return: bb6, unwind: bb7];
     }
 
     bb6: {
-        StorageDead(_14);
         StorageDead(_13);
-        StorageDead(_9);
+        StorageDead(_12);
+        StorageDead(_8);
         goto -> bb1;
     }
 
diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir
index ee638be7d7a..0adf268d766 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir
@@ -4,22 +4,22 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     debug slice => _1;
     debug f => _2;
     let mut _0: ();
-    let mut _11: std::slice::Iter<'_, T>;
+    let mut _10: std::slice::Iter<'_, T>;
+    let mut _11: std::iter::Rev<std::slice::Iter<'_, T>>;
     let mut _12: std::iter::Rev<std::slice::Iter<'_, T>>;
-    let mut _13: std::iter::Rev<std::slice::Iter<'_, T>>;
-    let mut _15: std::option::Option<&T>;
-    let mut _16: isize;
-    let mut _18: &impl Fn(&T);
-    let mut _19: (&T,);
-    let _20: ();
+    let mut _14: std::option::Option<&T>;
+    let mut _15: isize;
+    let mut _17: &impl Fn(&T);
+    let mut _18: (&T,);
+    let _19: ();
     scope 1 {
-        debug iter => _13;
-        let _17: &T;
+        debug iter => _12;
+        let _16: &T;
         scope 2 {
-            debug x => _17;
+            debug x => _16;
         }
         scope 18 (inlined <Rev<std::slice::Iter<'_, T>> as Iterator>::next) {
-            let mut _14: &mut std::slice::Iter<'_, T>;
+            let mut _13: &mut std::slice::Iter<'_, T>;
         }
     }
     scope 3 (inlined core::slice::<impl [T]>::iter) {
@@ -27,7 +27,6 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
             let _3: usize;
             let mut _7: *mut T;
             let mut _8: *mut T;
-            let mut _10: *const T;
             scope 5 {
                 let _6: std::ptr::NonNull<T>;
                 scope 6 {
@@ -62,9 +61,10 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     }
 
     bb0: {
-        StorageLive(_11);
+        StorageLive(_10);
         StorageLive(_3);
         StorageLive(_6);
+        StorageLive(_9);
         StorageLive(_4);
         _3 = PtrMetadata(copy _1);
         _4 = &raw const (*_1);
@@ -72,7 +72,6 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
         _5 = copy _4 as *const T (PtrToPtr);
         _6 = NonNull::<T> { pointer: copy _5 };
         StorageDead(_5);
-        StorageLive(_9);
         switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb1, otherwise: bb2];
     }
 
@@ -93,37 +92,34 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     }
 
     bb3: {
-        StorageLive(_10);
-        _10 = copy _9;
-        _11 = std::slice::Iter::<'_, T> { ptr: copy _6, end_or_len: copy _10, _marker: const ZeroSized: PhantomData<&T> };
-        StorageDead(_10);
-        StorageDead(_9);
+        _10 = std::slice::Iter::<'_, T> { ptr: copy _6, end_or_len: copy _9, _marker: const ZeroSized: PhantomData<&T> };
         StorageDead(_4);
+        StorageDead(_9);
         StorageDead(_6);
         StorageDead(_3);
-        _12 = Rev::<std::slice::Iter<'_, T>> { iter: copy _11 };
-        StorageDead(_11);
-        StorageLive(_13);
-        _13 = copy _12;
+        _11 = Rev::<std::slice::Iter<'_, T>> { iter: copy _10 };
+        StorageDead(_10);
+        StorageLive(_12);
+        _12 = copy _11;
         goto -> bb4;
     }
 
     bb4: {
-        StorageLive(_15);
         StorageLive(_14);
-        _14 = &mut (_13.0: std::slice::Iter<'_, T>);
-        _15 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _14) -> [return: bb5, unwind unreachable];
+        StorageLive(_13);
+        _13 = &mut (_12.0: std::slice::Iter<'_, T>);
+        _14 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _13) -> [return: bb5, unwind unreachable];
     }
 
     bb5: {
-        StorageDead(_14);
-        _16 = discriminant(_15);
-        switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10];
+        StorageDead(_13);
+        _15 = discriminant(_14);
+        switchInt(move _15) -> [0: bb6, 1: bb8, otherwise: bb10];
     }
 
     bb6: {
-        StorageDead(_15);
-        StorageDead(_13);
+        StorageDead(_14);
+        StorageDead(_12);
         drop(_2) -> [return: bb7, unwind unreachable];
     }
 
@@ -132,18 +128,18 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     }
 
     bb8: {
-        _17 = copy ((_15 as Some).0: &T);
+        _16 = copy ((_14 as Some).0: &T);
+        StorageLive(_17);
+        _17 = &_2;
         StorageLive(_18);
-        _18 = &_2;
-        StorageLive(_19);
-        _19 = (copy _17,);
-        _20 = <impl Fn(&T) as Fn<(&T,)>>::call(move _18, move _19) -> [return: bb9, unwind unreachable];
+        _18 = (copy _16,);
+        _19 = <impl Fn(&T) as Fn<(&T,)>>::call(move _17, move _18) -> [return: bb9, unwind unreachable];
     }
 
     bb9: {
-        StorageDead(_19);
         StorageDead(_18);
-        StorageDead(_15);
+        StorageDead(_17);
+        StorageDead(_14);
         goto -> bb4;
     }
 
diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir
index aee29d4d4fe..cb0d640d445 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir
@@ -4,22 +4,22 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     debug slice => _1;
     debug f => _2;
     let mut _0: ();
-    let mut _11: std::slice::Iter<'_, T>;
+    let mut _10: std::slice::Iter<'_, T>;
+    let mut _11: std::iter::Rev<std::slice::Iter<'_, T>>;
     let mut _12: std::iter::Rev<std::slice::Iter<'_, T>>;
-    let mut _13: std::iter::Rev<std::slice::Iter<'_, T>>;
-    let mut _15: std::option::Option<&T>;
-    let mut _16: isize;
-    let mut _18: &impl Fn(&T);
-    let mut _19: (&T,);
-    let _20: ();
+    let mut _14: std::option::Option<&T>;
+    let mut _15: isize;
+    let mut _17: &impl Fn(&T);
+    let mut _18: (&T,);
+    let _19: ();
     scope 1 {
-        debug iter => _13;
-        let _17: &T;
+        debug iter => _12;
+        let _16: &T;
         scope 2 {
-            debug x => _17;
+            debug x => _16;
         }
         scope 18 (inlined <Rev<std::slice::Iter<'_, T>> as Iterator>::next) {
-            let mut _14: &mut std::slice::Iter<'_, T>;
+            let mut _13: &mut std::slice::Iter<'_, T>;
         }
     }
     scope 3 (inlined core::slice::<impl [T]>::iter) {
@@ -27,7 +27,6 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
             let _3: usize;
             let mut _7: *mut T;
             let mut _8: *mut T;
-            let mut _10: *const T;
             scope 5 {
                 let _6: std::ptr::NonNull<T>;
                 scope 6 {
@@ -62,9 +61,10 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     }
 
     bb0: {
-        StorageLive(_11);
+        StorageLive(_10);
         StorageLive(_3);
         StorageLive(_6);
+        StorageLive(_9);
         StorageLive(_4);
         _3 = PtrMetadata(copy _1);
         _4 = &raw const (*_1);
@@ -72,7 +72,6 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
         _5 = copy _4 as *const T (PtrToPtr);
         _6 = NonNull::<T> { pointer: copy _5 };
         StorageDead(_5);
-        StorageLive(_9);
         switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb1, otherwise: bb2];
     }
 
@@ -93,37 +92,34 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     }
 
     bb3: {
-        StorageLive(_10);
-        _10 = copy _9;
-        _11 = std::slice::Iter::<'_, T> { ptr: copy _6, end_or_len: copy _10, _marker: const ZeroSized: PhantomData<&T> };
-        StorageDead(_10);
-        StorageDead(_9);
+        _10 = std::slice::Iter::<'_, T> { ptr: copy _6, end_or_len: copy _9, _marker: const ZeroSized: PhantomData<&T> };
         StorageDead(_4);
+        StorageDead(_9);
         StorageDead(_6);
         StorageDead(_3);
-        _12 = Rev::<std::slice::Iter<'_, T>> { iter: copy _11 };
-        StorageDead(_11);
-        StorageLive(_13);
-        _13 = copy _12;
+        _11 = Rev::<std::slice::Iter<'_, T>> { iter: copy _10 };
+        StorageDead(_10);
+        StorageLive(_12);
+        _12 = copy _11;
         goto -> bb4;
     }
 
     bb4: {
-        StorageLive(_15);
         StorageLive(_14);
-        _14 = &mut (_13.0: std::slice::Iter<'_, T>);
-        _15 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _14) -> [return: bb5, unwind: bb11];
+        StorageLive(_13);
+        _13 = &mut (_12.0: std::slice::Iter<'_, T>);
+        _14 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _13) -> [return: bb5, unwind: bb11];
     }
 
     bb5: {
-        StorageDead(_14);
-        _16 = discriminant(_15);
-        switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10];
+        StorageDead(_13);
+        _15 = discriminant(_14);
+        switchInt(move _15) -> [0: bb6, 1: bb8, otherwise: bb10];
     }
 
     bb6: {
-        StorageDead(_15);
-        StorageDead(_13);
+        StorageDead(_14);
+        StorageDead(_12);
         drop(_2) -> [return: bb7, unwind continue];
     }
 
@@ -132,18 +128,18 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     }
 
     bb8: {
-        _17 = copy ((_15 as Some).0: &T);
+        _16 = copy ((_14 as Some).0: &T);
+        StorageLive(_17);
+        _17 = &_2;
         StorageLive(_18);
-        _18 = &_2;
-        StorageLive(_19);
-        _19 = (copy _17,);
-        _20 = <impl Fn(&T) as Fn<(&T,)>>::call(move _18, move _19) -> [return: bb9, unwind: bb11];
+        _18 = (copy _16,);
+        _19 = <impl Fn(&T) as Fn<(&T,)>>::call(move _17, move _18) -> [return: bb9, unwind: bb11];
     }
 
     bb9: {
-        StorageDead(_19);
         StorageDead(_18);
-        StorageDead(_15);
+        StorageDead(_17);
+        StorageDead(_14);
         goto -> bb4;
     }
 
diff --git a/tests/mir-opt/pre-codegen/tuple_ord.demo_ge_partial.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/tuple_ord.demo_ge_partial.PreCodegen.after.mir
index c4d0e318b58..29bfe962974 100644
--- a/tests/mir-opt/pre-codegen/tuple_ord.demo_ge_partial.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/tuple_ord.demo_ge_partial.PreCodegen.after.mir
@@ -7,7 +7,6 @@ fn demo_ge_partial(_1: &(f32, f32), _2: &(f32, f32)) -> bool {
     scope 1 (inlined std::cmp::impls::<impl PartialOrd for &(f32, f32)>::ge) {
         scope 2 (inlined core::tuple::<impl PartialOrd for (f32, f32)>::ge) {
             let mut _7: std::ops::ControlFlow<bool>;
-            let _8: bool;
             scope 3 {
             }
             scope 4 (inlined std::cmp::impls::<impl PartialOrd for f32>::__chaining_ge) {
@@ -19,8 +18,8 @@ fn demo_ge_partial(_1: &(f32, f32), _2: &(f32, f32)) -> bool {
                 }
             }
             scope 6 (inlined std::cmp::impls::<impl PartialOrd for f32>::ge) {
+                let mut _8: f32;
                 let mut _9: f32;
-                let mut _10: f32;
             }
         }
     }
@@ -44,10 +43,7 @@ fn demo_ge_partial(_1: &(f32, f32), _2: &(f32, f32)) -> bool {
         StorageDead(_5);
         StorageDead(_4);
         StorageDead(_3);
-        StorageLive(_8);
-        _8 = copy ((_7 as Break).0: bool);
-        _0 = copy _8;
-        StorageDead(_8);
+        _0 = copy ((_7 as Break).0: bool);
         goto -> bb3;
     }
 
@@ -55,13 +51,13 @@ fn demo_ge_partial(_1: &(f32, f32), _2: &(f32, f32)) -> bool {
         StorageDead(_5);
         StorageDead(_4);
         StorageDead(_3);
+        StorageLive(_8);
+        _8 = copy ((*_1).1: f32);
         StorageLive(_9);
-        _9 = copy ((*_1).1: f32);
-        StorageLive(_10);
-        _10 = copy ((*_2).1: f32);
-        _0 = Ge(move _9, move _10);
-        StorageDead(_10);
+        _9 = copy ((*_2).1: f32);
+        _0 = Ge(move _8, move _9);
         StorageDead(_9);
+        StorageDead(_8);
         goto -> bb3;
     }
 
diff --git a/tests/mir-opt/pre-codegen/tuple_ord.demo_le_total.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/tuple_ord.demo_le_total.PreCodegen.after.mir
index 44df8b27993..7678c92a1f0 100644
--- a/tests/mir-opt/pre-codegen/tuple_ord.demo_le_total.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/tuple_ord.demo_le_total.PreCodegen.after.mir
@@ -7,7 +7,6 @@ fn demo_le_total(_1: &(u16, i16), _2: &(u16, i16)) -> bool {
     scope 1 (inlined std::cmp::impls::<impl PartialOrd for &(u16, i16)>::le) {
         scope 2 (inlined core::tuple::<impl PartialOrd for (u16, i16)>::le) {
             let mut _7: std::ops::ControlFlow<bool>;
-            let _8: bool;
             scope 3 {
             }
             scope 4 (inlined std::cmp::impls::<impl PartialOrd for u16>::__chaining_le) {
@@ -19,8 +18,8 @@ fn demo_le_total(_1: &(u16, i16), _2: &(u16, i16)) -> bool {
                 }
             }
             scope 6 (inlined std::cmp::impls::<impl PartialOrd for i16>::le) {
+                let mut _8: i16;
                 let mut _9: i16;
-                let mut _10: i16;
             }
         }
     }
@@ -44,10 +43,7 @@ fn demo_le_total(_1: &(u16, i16), _2: &(u16, i16)) -> bool {
         StorageDead(_5);
         StorageDead(_4);
         StorageDead(_3);
-        StorageLive(_8);
-        _8 = copy ((_7 as Break).0: bool);
-        _0 = copy _8;
-        StorageDead(_8);
+        _0 = copy ((_7 as Break).0: bool);
         goto -> bb3;
     }
 
@@ -55,13 +51,13 @@ fn demo_le_total(_1: &(u16, i16), _2: &(u16, i16)) -> bool {
         StorageDead(_5);
         StorageDead(_4);
         StorageDead(_3);
+        StorageLive(_8);
+        _8 = copy ((*_1).1: i16);
         StorageLive(_9);
-        _9 = copy ((*_1).1: i16);
-        StorageLive(_10);
-        _10 = copy ((*_2).1: i16);
-        _0 = Le(move _9, move _10);
-        StorageDead(_10);
+        _9 = copy ((*_2).1: i16);
+        _0 = Le(move _8, move _9);
         StorageDead(_9);
+        StorageDead(_8);
         goto -> bb3;
     }
 
diff --git a/tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff b/tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff
index 3da795b61f9..375b6096d88 100644
--- a/tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff
+++ b/tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff
@@ -17,14 +17,15 @@
       let mut _15: std::ops::RangeFull;
       let mut _16: usize;
       let mut _17: usize;
-      let mut _18: bool;
-      let _23: &&mut u8;
-      let _24: &mut u8;
-      let mut _25: debuginfo::T;
+      let mut _18: usize;
+      let mut _19: bool;
+      let _24: &&mut u8;
+      let _25: &mut u8;
+      let mut _26: debuginfo::T;
       scope 1 {
           debug ref_mut_u8 => _1;
           let _3: &u8;
-          let mut _28: &debuginfo::T;
+          let mut _29: &debuginfo::T;
           scope 2 {
               debug field => _3;
               let _5: &u8;
@@ -32,22 +33,22 @@
 -                 debug reborrow => _5;
 +                 debug reborrow => _1;
                   let _9: &i32;
-                  let _22: &&&mut u8;
-                  let mut _27: &std::option::Option<i32>;
+                  let _23: &&&mut u8;
+                  let mut _28: &std::option::Option<i32>;
                   scope 4 {
                       debug variant_field => _9;
                   }
                   scope 5 {
-                      debug constant_index => _19;
-                      debug subslice => _20;
-                      debug constant_index_from_end => _21;
-                      let _19: &i32;
-                      let _20: &[i32];
-                      let _21: &i32;
-                      let mut _26: &[i32; 10];
+                      debug constant_index => _20;
+                      debug subslice => _21;
+                      debug constant_index_from_end => _22;
+                      let _20: &i32;
+                      let _21: &[i32];
+                      let _22: &i32;
+                      let mut _27: &[i32; 10];
                   }
                   scope 6 {
-                      debug multiple_borrow => _22;
+                      debug multiple_borrow => _23;
                   }
               }
           }
@@ -59,8 +60,8 @@
           _2 = const 5_u8;
           _1 = &mut _2;
           StorageLive(_3);
-          _28 = const debuginfo::promoted[2];
-          _3 = &((*_28).0: u8);
+          _29 = const debuginfo::promoted[2];
+          _3 = &((*_29).0: u8);
 -         StorageLive(_5);
 -         _5 = &(*_1);
 -         StorageLive(_6);
@@ -76,8 +77,8 @@
   
       bb2: {
           StorageLive(_9);
-          _27 = const debuginfo::promoted[1];
-          _9 = &(((*_27) as Some).0: i32);
+          _28 = const debuginfo::promoted[1];
+          _9 = &(((*_28) as Some).0: i32);
 -         _6 = const ();
           StorageDead(_9);
           goto -> bb4;
@@ -92,11 +93,11 @@
           StorageDead(_7);
 -         StorageDead(_6);
 -         StorageLive(_10);
--         StorageLive(_11);
+          StorageLive(_11);
 -         StorageLive(_12);
           StorageLive(_13);
-          _26 = const debuginfo::promoted[0];
-          _13 = &(*_26);
+          _27 = const debuginfo::promoted[0];
+          _13 = &(*_27);
           StorageLive(_15);
           _15 = RangeFull;
 -         _12 = <[i32; 10] as Index<RangeFull>>::index(move _13, move _15) -> [return: bb5, unwind continue];
@@ -106,28 +107,28 @@
       bb5: {
           StorageDead(_15);
           StorageDead(_13);
--         _11 = &(*_12);
--         _16 = Len((*_11));
-+         _16 = Len((*_12));
-          _17 = const 3_usize;
-          _18 = Ge(move _16, move _17);
-          switchInt(move _18) -> [0: bb7, otherwise: bb6];
+          _11 = &(*_12);
+          _17 = PtrMetadata(copy _11);
+          _16 = move _17;
+          _18 = const 3_usize;
+          _19 = Ge(move _16, move _18);
+          switchInt(move _19) -> [0: bb7, otherwise: bb6];
       }
   
       bb6: {
-          StorageLive(_19);
--         _19 = &(*_11)[1 of 3];
-+         _19 = &(*_12)[1 of 3];
           StorageLive(_20);
--         _20 = &(*_11)[2:-1];
-+         _20 = &(*_12)[2:-1];
+-         _20 = &(*_11)[1 of 3];
++         _20 = &(*_12)[1 of 3];
           StorageLive(_21);
--         _21 = &(*_11)[-1 of 3];
+-         _21 = &(*_11)[2:-1];
++         _21 = &(*_12)[2:-1];
+          StorageLive(_22);
+-         _22 = &(*_11)[-1 of 3];
 -         _10 = const ();
-+         _21 = &(*_12)[-1 of 3];
++         _22 = &(*_12)[-1 of 3];
+          StorageDead(_22);
           StorageDead(_21);
           StorageDead(_20);
-          StorageDead(_19);
           goto -> bb8;
       }
   
@@ -138,21 +139,21 @@
   
       bb8: {
 -         StorageDead(_12);
--         StorageDead(_11);
+          StorageDead(_11);
 -         StorageDead(_10);
-          StorageLive(_22);
           StorageLive(_23);
           StorageLive(_24);
           StorageLive(_25);
-          _25 = T(const 6_u8);
-          _24 = &mut (_25.0: u8);
+          StorageLive(_26);
+          _26 = T(const 6_u8);
+          _25 = &mut (_26.0: u8);
+          _24 = &_25;
           _23 = &_24;
-          _22 = &_23;
           _0 = const ();
+          StorageDead(_26);
           StorageDead(_25);
           StorageDead(_24);
           StorageDead(_23);
-          StorageDead(_22);
 -         StorageDead(_5);
           StorageDead(_3);
           StorageDead(_2);
diff --git a/tests/run-make/musl-default-linking/rmake.rs b/tests/run-make/musl-default-linking/rmake.rs
index 7bb54e2739c..1b30c538b5e 100644
--- a/tests/run-make/musl-default-linking/rmake.rs
+++ b/tests/run-make/musl-default-linking/rmake.rs
@@ -4,7 +4,7 @@ use run_make_support::{rustc, serde_json};
 // Per https://github.com/rust-lang/compiler-team/issues/422,
 // we should be trying to move these targets to dynamically link
 // musl libc by default.
-//@ needs-llvm-components: aarch64 arm mips powerpc riscv systemz x86
+//@ needs-llvm-components: aarch64 arm mips powerpc x86
 static LEGACY_STATIC_LINKING_TARGETS: &[&'static str] = &[
     "aarch64-unknown-linux-musl",
     "arm-unknown-linux-musleabi",
@@ -14,16 +14,8 @@ static LEGACY_STATIC_LINKING_TARGETS: &[&'static str] = &[
     "armv7-unknown-linux-musleabihf",
     "i586-unknown-linux-musl",
     "i686-unknown-linux-musl",
-    "mips64-unknown-linux-musl",
-    "mips64-unknown-linux-muslabi64",
     "mips64el-unknown-linux-muslabi64",
-    "powerpc-unknown-linux-musl",
-    "powerpc-unknown-linux-muslspe",
-    "powerpc64-unknown-linux-musl",
     "powerpc64le-unknown-linux-musl",
-    "riscv32gc-unknown-linux-musl",
-    "s390x-unknown-linux-musl",
-    "thumbv7neon-unknown-linux-musleabihf",
     "x86_64-unknown-linux-musl",
 ];
 
diff --git a/tests/ui/README.md b/tests/ui/README.md
index 66c1bb905a7..3b28ef694dd 100644
--- a/tests/ui/README.md
+++ b/tests/ui/README.md
@@ -350,6 +350,12 @@ Tests for FFI with C varargs (`va_list`).
 
 Tests for detection and handling of cyclic trait dependencies.
 
+## `tests/ui/darwin-objc/`: Darwin Objective-C
+
+Tests exercising `#![feature(darwin_objc)]`.
+
+See [Tracking Issue for `darwin_objc` #145496](https://github.com/rust-lang/rust/issues/145496).
+
 ## `tests/ui/dataflow_const_prop/`
 
 Contains a single regression test for const prop in `SwitchInt` pass crashing when `ptr2int` transmute is involved.
diff --git a/tests/ui/abi/sparcv8plus-llvm19.rs b/tests/ui/abi/sparcv8plus-llvm19.rs
deleted file mode 100644
index 3d6d8568b6e..00000000000
--- a/tests/ui/abi/sparcv8plus-llvm19.rs
+++ /dev/null
@@ -1,42 +0,0 @@
-//@ add-core-stubs
-//@ revisions: sparc sparcv8plus sparc_cpu_v9 sparc_feature_v8plus sparc_cpu_v9_feature_v8plus
-//@[sparc] compile-flags: --target sparc-unknown-none-elf
-//@[sparc] needs-llvm-components: sparc
-//@[sparcv8plus] compile-flags: --target sparc-unknown-linux-gnu
-//@[sparcv8plus] needs-llvm-components: sparc
-//@[sparc_cpu_v9] compile-flags: --target sparc-unknown-none-elf -C target-cpu=v9
-//@[sparc_cpu_v9] needs-llvm-components: sparc
-//@[sparc_feature_v8plus] compile-flags: --target sparc-unknown-none-elf -C target-feature=+v8plus
-//@[sparc_feature_v8plus] needs-llvm-components: sparc
-//@[sparc_cpu_v9_feature_v8plus] compile-flags: --target sparc-unknown-none-elf -C target-cpu=v9 -C target-feature=+v8plus
-//@[sparc_cpu_v9_feature_v8plus] needs-llvm-components: sparc
-//@ exact-llvm-major-version: 19
-
-#![crate_type = "rlib"]
-#![feature(no_core, rustc_attrs, lang_items)]
-#![no_core]
-
-extern crate minicore;
-use minicore::*;
-
-#[rustc_builtin_macro]
-macro_rules! compile_error {
-    () => {};
-}
-
-#[cfg(all(not(target_feature = "v8plus"), not(target_feature = "v9")))]
-compile_error!("-v8plus,-v9");
-//[sparc]~^ ERROR -v8plus,-v9
-
-// FIXME: sparc_cpu_v9 should be in "-v8plus,+v9" group (fixed in LLVM 20)
-#[cfg(all(target_feature = "v8plus", target_feature = "v9"))]
-compile_error!("+v8plus,+v9");
-//[sparcv8plus,sparc_cpu_v9_feature_v8plus,sparc_cpu_v9]~^ ERROR +v8plus,+v9
-
-// FIXME: should be rejected
-#[cfg(all(target_feature = "v8plus", not(target_feature = "v9")))]
-compile_error!("+v8plus,-v9 (FIXME)");
-//[sparc_feature_v8plus]~^ ERROR +v8plus,-v9 (FIXME)
-
-#[cfg(all(not(target_feature = "v8plus"), target_feature = "v9"))]
-compile_error!("-v8plus,+v9");
diff --git a/tests/ui/abi/sparcv8plus-llvm19.sparc.stderr b/tests/ui/abi/sparcv8plus-llvm19.sparc.stderr
deleted file mode 100644
index d3462ae87d3..00000000000
--- a/tests/ui/abi/sparcv8plus-llvm19.sparc.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: -v8plus,-v9
-  --> $DIR/sparcv8plus-llvm19.rs:28:1
-   |
-LL | compile_error!("-v8plus,-v9");
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/abi/sparcv8plus-llvm19.sparc_cpu_v9.stderr b/tests/ui/abi/sparcv8plus-llvm19.sparc_cpu_v9.stderr
deleted file mode 100644
index 9891aec94b8..00000000000
--- a/tests/ui/abi/sparcv8plus-llvm19.sparc_cpu_v9.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: +v8plus,+v9
-  --> $DIR/sparcv8plus-llvm19.rs:33:1
-   |
-LL | compile_error!("+v8plus,+v9");
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/abi/sparcv8plus-llvm19.sparc_cpu_v9_feature_v8plus.stderr b/tests/ui/abi/sparcv8plus-llvm19.sparc_cpu_v9_feature_v8plus.stderr
deleted file mode 100644
index 9891aec94b8..00000000000
--- a/tests/ui/abi/sparcv8plus-llvm19.sparc_cpu_v9_feature_v8plus.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: +v8plus,+v9
-  --> $DIR/sparcv8plus-llvm19.rs:33:1
-   |
-LL | compile_error!("+v8plus,+v9");
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/abi/sparcv8plus-llvm19.sparc_feature_v8plus.stderr b/tests/ui/abi/sparcv8plus-llvm19.sparc_feature_v8plus.stderr
deleted file mode 100644
index dbcdb8ed121..00000000000
--- a/tests/ui/abi/sparcv8plus-llvm19.sparc_feature_v8plus.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: +v8plus,-v9 (FIXME)
-  --> $DIR/sparcv8plus-llvm19.rs:38:1
-   |
-LL | compile_error!("+v8plus,-v9 (FIXME)");
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/abi/sparcv8plus-llvm19.sparcv8plus.stderr b/tests/ui/abi/sparcv8plus-llvm19.sparcv8plus.stderr
deleted file mode 100644
index 9891aec94b8..00000000000
--- a/tests/ui/abi/sparcv8plus-llvm19.sparcv8plus.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: +v8plus,+v9
-  --> $DIR/sparcv8plus-llvm19.rs:33:1
-   |
-LL | compile_error!("+v8plus,+v9");
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/abi/sparcv8plus.rs b/tests/ui/abi/sparcv8plus.rs
index 6c17f721838..ba4fb6f7108 100644
--- a/tests/ui/abi/sparcv8plus.rs
+++ b/tests/ui/abi/sparcv8plus.rs
@@ -10,7 +10,6 @@
 //@[sparc_feature_v8plus] needs-llvm-components: sparc
 //@[sparc_cpu_v9_feature_v8plus] compile-flags: --target sparc-unknown-none-elf -C target-cpu=v9 -C target-feature=+v8plus
 //@[sparc_cpu_v9_feature_v8plus] needs-llvm-components: sparc
-//@ min-llvm-version: 20
 
 #![crate_type = "rlib"]
 #![feature(no_core, rustc_attrs, lang_items)]
diff --git a/tests/ui/abi/sparcv8plus.sparc.stderr b/tests/ui/abi/sparcv8plus.sparc.stderr
index e2aa89a9273..e31dbd344d6 100644
--- a/tests/ui/abi/sparcv8plus.sparc.stderr
+++ b/tests/ui/abi/sparcv8plus.sparc.stderr
@@ -1,5 +1,5 @@
 error: -v8plus,-v9
-  --> $DIR/sparcv8plus.rs:28:1
+  --> $DIR/sparcv8plus.rs:27:1
    |
 LL | compile_error!("-v8plus,-v9");
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/abi/sparcv8plus.sparc_cpu_v9.stderr b/tests/ui/abi/sparcv8plus.sparc_cpu_v9.stderr
index 2c5699f2dec..a1a8383cbe7 100644
--- a/tests/ui/abi/sparcv8plus.sparc_cpu_v9.stderr
+++ b/tests/ui/abi/sparcv8plus.sparc_cpu_v9.stderr
@@ -1,5 +1,5 @@
 error: -v8plus,+v9
-  --> $DIR/sparcv8plus.rs:41:1
+  --> $DIR/sparcv8plus.rs:40:1
    |
 LL | compile_error!("-v8plus,+v9");
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/abi/sparcv8plus.sparc_cpu_v9_feature_v8plus.stderr b/tests/ui/abi/sparcv8plus.sparc_cpu_v9_feature_v8plus.stderr
index 4b96e4421f9..c633ee26c51 100644
--- a/tests/ui/abi/sparcv8plus.sparc_cpu_v9_feature_v8plus.stderr
+++ b/tests/ui/abi/sparcv8plus.sparc_cpu_v9_feature_v8plus.stderr
@@ -1,5 +1,5 @@
 error: +v8plus,+v9
-  --> $DIR/sparcv8plus.rs:32:1
+  --> $DIR/sparcv8plus.rs:31:1
    |
 LL | compile_error!("+v8plus,+v9");
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/abi/sparcv8plus.sparc_feature_v8plus.stderr b/tests/ui/abi/sparcv8plus.sparc_feature_v8plus.stderr
index dfdec88961b..bad8adc1599 100644
--- a/tests/ui/abi/sparcv8plus.sparc_feature_v8plus.stderr
+++ b/tests/ui/abi/sparcv8plus.sparc_feature_v8plus.stderr
@@ -1,5 +1,5 @@
 error: +v8plus,-v9 (FIXME)
-  --> $DIR/sparcv8plus.rs:37:1
+  --> $DIR/sparcv8plus.rs:36:1
    |
 LL | compile_error!("+v8plus,-v9 (FIXME)");
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/abi/sparcv8plus.sparcv8plus.stderr b/tests/ui/abi/sparcv8plus.sparcv8plus.stderr
index 4b96e4421f9..c633ee26c51 100644
--- a/tests/ui/abi/sparcv8plus.sparcv8plus.stderr
+++ b/tests/ui/abi/sparcv8plus.sparcv8plus.stderr
@@ -1,5 +1,5 @@
 error: +v8plus,+v9
-  --> $DIR/sparcv8plus.rs:32:1
+  --> $DIR/sparcv8plus.rs:31:1
    |
 LL | compile_error!("+v8plus,+v9");
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/asm/loongarch/bad-reg.loongarch32_ilp32d.stderr b/tests/ui/asm/loongarch/bad-reg.loongarch32_ilp32d.stderr
index 8742d4bd82c..c67c913d2a6 100644
--- a/tests/ui/asm/loongarch/bad-reg.loongarch32_ilp32d.stderr
+++ b/tests/ui/asm/loongarch/bad-reg.loongarch32_ilp32d.stderr
@@ -1,35 +1,35 @@
 error: invalid register `$r0`: constant zero cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:27:18
+  --> $DIR/bad-reg.rs:26:18
    |
 LL |         asm!("", out("$r0") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `$tp`: reserved for TLS
-  --> $DIR/bad-reg.rs:29:18
+  --> $DIR/bad-reg.rs:28:18
    |
 LL |         asm!("", out("$tp") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `$sp`: the stack pointer cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:31:18
+  --> $DIR/bad-reg.rs:30:18
    |
 LL |         asm!("", out("$sp") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `$r21`: reserved by the ABI
-  --> $DIR/bad-reg.rs:33:18
+  --> $DIR/bad-reg.rs:32:18
    |
 LL |         asm!("", out("$r21") _);
    |                  ^^^^^^^^^^^^^
 
 error: invalid register `$fp`: the frame pointer cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:35:18
+  --> $DIR/bad-reg.rs:34:18
    |
 LL |         asm!("", out("$fp") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `$r31`: $r31 is used internally by LLVM and cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:37:18
+  --> $DIR/bad-reg.rs:36:18
    |
 LL |         asm!("", out("$r31") _);
    |                  ^^^^^^^^^^^^^
diff --git a/tests/ui/asm/loongarch/bad-reg.loongarch32_ilp32s.stderr b/tests/ui/asm/loongarch/bad-reg.loongarch32_ilp32s.stderr
index e6cb6e40c70..99c071919ac 100644
--- a/tests/ui/asm/loongarch/bad-reg.loongarch32_ilp32s.stderr
+++ b/tests/ui/asm/loongarch/bad-reg.loongarch32_ilp32s.stderr
@@ -1,59 +1,59 @@
 error: invalid register `$r0`: constant zero cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:27:18
+  --> $DIR/bad-reg.rs:26:18
    |
 LL |         asm!("", out("$r0") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `$tp`: reserved for TLS
-  --> $DIR/bad-reg.rs:29:18
+  --> $DIR/bad-reg.rs:28:18
    |
 LL |         asm!("", out("$tp") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `$sp`: the stack pointer cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:31:18
+  --> $DIR/bad-reg.rs:30:18
    |
 LL |         asm!("", out("$sp") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `$r21`: reserved by the ABI
-  --> $DIR/bad-reg.rs:33:18
+  --> $DIR/bad-reg.rs:32:18
    |
 LL |         asm!("", out("$r21") _);
    |                  ^^^^^^^^^^^^^
 
 error: invalid register `$fp`: the frame pointer cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:35:18
+  --> $DIR/bad-reg.rs:34:18
    |
 LL |         asm!("", out("$fp") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `$r31`: $r31 is used internally by LLVM and cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:37:18
+  --> $DIR/bad-reg.rs:36:18
    |
 LL |         asm!("", out("$r31") _);
    |                  ^^^^^^^^^^^^^
 
 error: register class `freg` requires at least one of the following target features: d, f
-  --> $DIR/bad-reg.rs:41:26
+  --> $DIR/bad-reg.rs:40:26
    |
 LL |         asm!("/* {} */", in(freg) f);
    |                          ^^^^^^^^^^
 
 error: register class `freg` requires at least one of the following target features: d, f
-  --> $DIR/bad-reg.rs:43:26
+  --> $DIR/bad-reg.rs:42:26
    |
 LL |         asm!("/* {} */", out(freg) _);
    |                          ^^^^^^^^^^^
 
 error: register class `freg` requires at least one of the following target features: d, f
-  --> $DIR/bad-reg.rs:45:26
+  --> $DIR/bad-reg.rs:44:26
    |
 LL |         asm!("/* {} */", in(freg) d);
    |                          ^^^^^^^^^^
 
 error: register class `freg` requires at least one of the following target features: d, f
-  --> $DIR/bad-reg.rs:47:26
+  --> $DIR/bad-reg.rs:46:26
    |
 LL |         asm!("/* {} */", out(freg) d);
    |                          ^^^^^^^^^^^
diff --git a/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64d.stderr b/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64d.stderr
index 8742d4bd82c..c67c913d2a6 100644
--- a/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64d.stderr
+++ b/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64d.stderr
@@ -1,35 +1,35 @@
 error: invalid register `$r0`: constant zero cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:27:18
+  --> $DIR/bad-reg.rs:26:18
    |
 LL |         asm!("", out("$r0") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `$tp`: reserved for TLS
-  --> $DIR/bad-reg.rs:29:18
+  --> $DIR/bad-reg.rs:28:18
    |
 LL |         asm!("", out("$tp") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `$sp`: the stack pointer cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:31:18
+  --> $DIR/bad-reg.rs:30:18
    |
 LL |         asm!("", out("$sp") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `$r21`: reserved by the ABI
-  --> $DIR/bad-reg.rs:33:18
+  --> $DIR/bad-reg.rs:32:18
    |
 LL |         asm!("", out("$r21") _);
    |                  ^^^^^^^^^^^^^
 
 error: invalid register `$fp`: the frame pointer cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:35:18
+  --> $DIR/bad-reg.rs:34:18
    |
 LL |         asm!("", out("$fp") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `$r31`: $r31 is used internally by LLVM and cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:37:18
+  --> $DIR/bad-reg.rs:36:18
    |
 LL |         asm!("", out("$r31") _);
    |                  ^^^^^^^^^^^^^
diff --git a/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64s.stderr b/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64s.stderr
index e6cb6e40c70..99c071919ac 100644
--- a/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64s.stderr
+++ b/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64s.stderr
@@ -1,59 +1,59 @@
 error: invalid register `$r0`: constant zero cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:27:18
+  --> $DIR/bad-reg.rs:26:18
    |
 LL |         asm!("", out("$r0") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `$tp`: reserved for TLS
-  --> $DIR/bad-reg.rs:29:18
+  --> $DIR/bad-reg.rs:28:18
    |
 LL |         asm!("", out("$tp") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `$sp`: the stack pointer cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:31:18
+  --> $DIR/bad-reg.rs:30:18
    |
 LL |         asm!("", out("$sp") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `$r21`: reserved by the ABI
-  --> $DIR/bad-reg.rs:33:18
+  --> $DIR/bad-reg.rs:32:18
    |
 LL |         asm!("", out("$r21") _);
    |                  ^^^^^^^^^^^^^
 
 error: invalid register `$fp`: the frame pointer cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:35:18
+  --> $DIR/bad-reg.rs:34:18
    |
 LL |         asm!("", out("$fp") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `$r31`: $r31 is used internally by LLVM and cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:37:18
+  --> $DIR/bad-reg.rs:36:18
    |
 LL |         asm!("", out("$r31") _);
    |                  ^^^^^^^^^^^^^
 
 error: register class `freg` requires at least one of the following target features: d, f
-  --> $DIR/bad-reg.rs:41:26
+  --> $DIR/bad-reg.rs:40:26
    |
 LL |         asm!("/* {} */", in(freg) f);
    |                          ^^^^^^^^^^
 
 error: register class `freg` requires at least one of the following target features: d, f
-  --> $DIR/bad-reg.rs:43:26
+  --> $DIR/bad-reg.rs:42:26
    |
 LL |         asm!("/* {} */", out(freg) _);
    |                          ^^^^^^^^^^^
 
 error: register class `freg` requires at least one of the following target features: d, f
-  --> $DIR/bad-reg.rs:45:26
+  --> $DIR/bad-reg.rs:44:26
    |
 LL |         asm!("/* {} */", in(freg) d);
    |                          ^^^^^^^^^^
 
 error: register class `freg` requires at least one of the following target features: d, f
-  --> $DIR/bad-reg.rs:47:26
+  --> $DIR/bad-reg.rs:46:26
    |
 LL |         asm!("/* {} */", out(freg) d);
    |                          ^^^^^^^^^^^
diff --git a/tests/ui/asm/loongarch/bad-reg.rs b/tests/ui/asm/loongarch/bad-reg.rs
index 0d3eba07f14..cca37dd2e8e 100644
--- a/tests/ui/asm/loongarch/bad-reg.rs
+++ b/tests/ui/asm/loongarch/bad-reg.rs
@@ -1,7 +1,6 @@
 //@ add-core-stubs
 //@ needs-asm-support
 //@ revisions: loongarch32_ilp32d loongarch32_ilp32s loongarch64_lp64d loongarch64_lp64s
-//@ min-llvm-version: 20
 //@[loongarch32_ilp32d] compile-flags: --target loongarch32-unknown-none
 //@[loongarch32_ilp32d] needs-llvm-components: loongarch
 //@[loongarch32_ilp32s] compile-flags: --target loongarch32-unknown-none-softfloat
diff --git a/tests/ui/associated-types/associated-types-for-unimpl-trait.fixed b/tests/ui/associated-types/associated-types-for-unimpl-trait.fixed
index bce6148f9e1..ae4d0107aee 100644
--- a/tests/ui/associated-types/associated-types-for-unimpl-trait.fixed
+++ b/tests/ui/associated-types/associated-types-for-unimpl-trait.fixed
@@ -8,7 +8,7 @@ trait Get {
 }
 
 trait Other {
-    fn uhoh<U: Get>(&self, foo: U, bar: <Self as Get>::Value) where Self: Sized, Self: Get, Self: Get {}
+    fn uhoh<U: Get>(&self, foo: U, bar: <Self as Get>::Value) where Self: Sized, Self: Get {}
     //~^ ERROR the trait bound `Self: Get` is not satisfied
     //~| ERROR the trait bound `Self: Get` is not satisfied
 }
diff --git a/tests/ui/borrowck/format-args-temporary-scopes.e2024.stderr b/tests/ui/borrowck/format-args-temporary-scopes.e2024.stderr
new file mode 100644
index 00000000000..506fc6e0965
--- /dev/null
+++ b/tests/ui/borrowck/format-args-temporary-scopes.e2024.stderr
@@ -0,0 +1,27 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/format-args-temporary-scopes.rs:13:25
+   |
+LL |     println!("{:?}", { &temp() });
+   |                      ---^^^^^---
+   |                      |  |    |
+   |                      |  |    temporary value is freed at the end of this statement
+   |                      |  creates a temporary value which is freed while still in use
+   |                      borrow later used here
+   |
+   = note: consider using a `let` binding to create a longer lived value
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/format-args-temporary-scopes.rs:19:29
+   |
+LL |     println!("{:?}{:?}", { &temp() }, ());
+   |                          ---^^^^^---
+   |                          |  |    |
+   |                          |  |    temporary value is freed at the end of this statement
+   |                          |  creates a temporary value which is freed while still in use
+   |                          borrow later used here
+   |
+   = note: consider using a `let` binding to create a longer lived value
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/tests/ui/borrowck/format-args-temporary-scopes.rs b/tests/ui/borrowck/format-args-temporary-scopes.rs
new file mode 100644
index 00000000000..2641058accb
--- /dev/null
+++ b/tests/ui/borrowck/format-args-temporary-scopes.rs
@@ -0,0 +1,21 @@
+//! Test for #145784 as it relates to format arguments: arguments to macros such as `println!`
+//! should obey normal temporary scoping rules.
+//@ revisions: e2021 e2024
+//@ [e2021] check-pass
+//@ [e2021] edition: 2021
+//@ [e2024] edition: 2024
+
+fn temp() {}
+
+fn main() {
+    // In Rust 2024, block tail expressions are temporary scopes, so the result of `temp()` is
+    // dropped after evaluating `&temp()`.
+    println!("{:?}", { &temp() });
+    //[e2024]~^ ERROR: temporary value dropped while borrowed [E0716]
+
+    // In Rust 1.89, `format_args!` extended the lifetime of all extending expressions in its
+    // arguments when provided with two or more arguments. This caused the result of `temp()` to
+    // outlive the result of the block, making this compile.
+    println!("{:?}{:?}", { &temp() }, ());
+    //[e2024]~^ ERROR: temporary value dropped while borrowed [E0716]
+}
diff --git a/tests/ui/c-variadic/no-closure.rs b/tests/ui/c-variadic/no-closure.rs
index c0b77786e8b..830ed962a8c 100644
--- a/tests/ui/c-variadic/no-closure.rs
+++ b/tests/ui/c-variadic/no-closure.rs
@@ -4,14 +4,17 @@
 // Check that `...` in closures is rejected.
 
 const F: extern "C" fn(...) = |_: ...| {};
-//~^ ERROR C-variadic type `...` may not be nested inside another type
+//~^ ERROR: unexpected `...`
+//~| NOTE: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
 
 fn foo() {
     let f = |...| {};
-    //~^ ERROR: `..` patterns are not allowed here
-    //~| ERROR: unexpected `...`
+    //~^ ERROR: unexpected `...`
+    //~| NOTE: not a valid pattern
+    //~| NOTE: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
 
     let f = |_: ...| {};
-    //~^ ERROR C-variadic type `...` may not be nested inside another type
+    //~^ ERROR: unexpected `...`
+    //~| NOTE: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
     f(1i64)
 }
diff --git a/tests/ui/c-variadic/no-closure.stderr b/tests/ui/c-variadic/no-closure.stderr
index 77bd106bb95..0946c4632e6 100644
--- a/tests/ui/c-variadic/no-closure.stderr
+++ b/tests/ui/c-variadic/no-closure.stderr
@@ -1,35 +1,26 @@
-error[E0743]: C-variadic type `...` may not be nested inside another type
+error: unexpected `...`
   --> $DIR/no-closure.rs:6:35
    |
 LL | const F: extern "C" fn(...) = |_: ...| {};
    |                                   ^^^
+   |
+   = note: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
 
 error: unexpected `...`
-  --> $DIR/no-closure.rs:10:14
+  --> $DIR/no-closure.rs:11:14
    |
 LL |     let f = |...| {};
    |              ^^^ not a valid pattern
    |
-help: for a rest pattern, use `..` instead of `...`
-   |
-LL -     let f = |...| {};
-LL +     let f = |..| {};
-   |
+   = note: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
 
-error[E0743]: C-variadic type `...` may not be nested inside another type
-  --> $DIR/no-closure.rs:14:17
+error: unexpected `...`
+  --> $DIR/no-closure.rs:16:17
    |
 LL |     let f = |_: ...| {};
    |                 ^^^
-
-error: `..` patterns are not allowed here
-  --> $DIR/no-closure.rs:10:14
-   |
-LL |     let f = |...| {};
-   |              ^^^
    |
-   = note: only allowed in tuple, tuple struct, and slice patterns
+   = note: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
 
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0743`.
diff --git a/tests/ui/coercion/coerce-block-tail.stderr b/tests/ui/coercion/coerce-block-tail.stderr
index 1301f3b7813..b358401b706 100644
--- a/tests/ui/coercion/coerce-block-tail.stderr
+++ b/tests/ui/coercion/coerce-block-tail.stderr
@@ -6,10 +6,11 @@ LL |     let _: &i32 = & { Box::new(1i32) };
    |
    = note: expected type `i32`
             found struct `Box<i32>`
-help: consider unboxing the value
+help: consider removing the Box
+   |
+LL -     let _: &i32 = & { Box::new(1i32) };
+LL +     let _: &i32 = & { 1i32 };
    |
-LL |     let _: &i32 = & { *Box::new(1i32) };
-   |                       +
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/coercion/coerce-box-new-to-unboxed.rs b/tests/ui/coercion/coerce-box-new-to-unboxed.rs
new file mode 100644
index 00000000000..63ff0fc4e23
--- /dev/null
+++ b/tests/ui/coercion/coerce-box-new-to-unboxed.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let _: String = Box::new(String::new());
+    //~^ ERROR mismatched types
+}
diff --git a/tests/ui/coercion/coerce-box-new-to-unboxed.stderr b/tests/ui/coercion/coerce-box-new-to-unboxed.stderr
new file mode 100644
index 00000000000..bdd962686e4
--- /dev/null
+++ b/tests/ui/coercion/coerce-box-new-to-unboxed.stderr
@@ -0,0 +1,19 @@
+error[E0308]: mismatched types
+  --> $DIR/coerce-box-new-to-unboxed.rs:2:21
+   |
+LL |     let _: String = Box::new(String::new());
+   |            ------   ^^^^^^^^^^^^^^^^^^^^^^^ expected `String`, found `Box<String>`
+   |            |
+   |            expected due to this
+   |
+   = note: expected struct `String`
+              found struct `Box<String>`
+help: consider removing the Box
+   |
+LL -     let _: String = Box::new(String::new());
+LL +     let _: String = String::new();
+   |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/darwin-objc/darwin-objc-bad-arg.rs b/tests/ui/darwin-objc/darwin-objc-bad-arg.rs
new file mode 100644
index 00000000000..70eb83aa052
--- /dev/null
+++ b/tests/ui/darwin-objc/darwin-objc-bad-arg.rs
@@ -0,0 +1,36 @@
+// Test that `objc::class!` and `objc::selector!` only take string literals.
+
+//@ edition: 2024
+//@ only-apple
+
+#![feature(darwin_objc)]
+
+use std::os::darwin::objc;
+
+pub fn main() {
+    let s = "NSObject";
+    objc::class!(s);
+    //~^ ERROR attribute value must be a literal
+
+    objc::class!(NSObject);
+    //~^ ERROR attribute value must be a literal
+
+    objc::class!(123);
+    //~^ ERROR `objc::class!` expected a string literal
+
+    objc::class!("NSObject\0");
+    //~^ ERROR `objc::class!` may not contain null characters
+
+    let s = "alloc";
+    objc::selector!(s);
+    //~^ ERROR attribute value must be a literal
+
+    objc::selector!(alloc);
+    //~^ ERROR attribute value must be a literal
+
+    objc::selector!(123);
+    //~^ ERROR `objc::selector!` expected a string literal
+
+    objc::selector!("alloc\0");
+    //~^ ERROR `objc::selector!` may not contain null characters
+}
diff --git a/tests/ui/darwin-objc/darwin-objc-bad-arg.stderr b/tests/ui/darwin-objc/darwin-objc-bad-arg.stderr
new file mode 100644
index 00000000000..99eeb27e30c
--- /dev/null
+++ b/tests/ui/darwin-objc/darwin-objc-bad-arg.stderr
@@ -0,0 +1,50 @@
+error: attribute value must be a literal
+  --> $DIR/darwin-objc-bad-arg.rs:12:18
+   |
+LL |     objc::class!(s);
+   |                  ^
+
+error: attribute value must be a literal
+  --> $DIR/darwin-objc-bad-arg.rs:15:18
+   |
+LL |     objc::class!(NSObject);
+   |                  ^^^^^^^^
+
+error: `objc::class!` expected a string literal
+  --> $DIR/darwin-objc-bad-arg.rs:18:18
+   |
+LL |     objc::class!(123);
+   |                  ^^^
+
+error: `objc::class!` may not contain null characters
+  --> $DIR/darwin-objc-bad-arg.rs:21:18
+   |
+LL |     objc::class!("NSObject\0");
+   |                  ^^^^^^^^^^^^
+
+error: attribute value must be a literal
+  --> $DIR/darwin-objc-bad-arg.rs:25:21
+   |
+LL |     objc::selector!(s);
+   |                     ^
+
+error: attribute value must be a literal
+  --> $DIR/darwin-objc-bad-arg.rs:28:21
+   |
+LL |     objc::selector!(alloc);
+   |                     ^^^^^
+
+error: `objc::selector!` expected a string literal
+  --> $DIR/darwin-objc-bad-arg.rs:31:21
+   |
+LL |     objc::selector!(123);
+   |                     ^^^
+
+error: `objc::selector!` may not contain null characters
+  --> $DIR/darwin-objc-bad-arg.rs:34:21
+   |
+LL |     objc::selector!("alloc\0");
+   |                     ^^^^^^^^^
+
+error: aborting due to 8 previous errors
+
diff --git a/tests/ui/darwin-objc/darwin-objc-bad-const.rs b/tests/ui/darwin-objc/darwin-objc-bad-const.rs
new file mode 100644
index 00000000000..ccf28697b48
--- /dev/null
+++ b/tests/ui/darwin-objc/darwin-objc-bad-const.rs
@@ -0,0 +1,17 @@
+// Test that `objc::class!` and `objc::selector!` aren't `const` expressions.
+// The system gives them their final values at dynamic load time.
+
+//@ edition: 2024
+//@ only-apple
+
+#![feature(darwin_objc)]
+
+use std::os::darwin::objc;
+
+pub const CLASS: objc::Class = objc::class!("NSObject");
+//~^ ERROR cannot access extern static `CLASS::VAL` [E0080]
+
+pub const SELECTOR: objc::SEL = objc::selector!("alloc");
+//~^ ERROR cannot access extern static `SELECTOR::VAL` [E0080]
+
+pub fn main() {}
diff --git a/tests/ui/darwin-objc/darwin-objc-bad-const.stderr b/tests/ui/darwin-objc/darwin-objc-bad-const.stderr
new file mode 100644
index 00000000000..43d0b7d761f
--- /dev/null
+++ b/tests/ui/darwin-objc/darwin-objc-bad-const.stderr
@@ -0,0 +1,19 @@
+error[E0080]: cannot access extern static `CLASS::VAL`
+  --> $DIR/darwin-objc-bad-const.rs:11:32
+   |
+LL | pub const CLASS: objc::Class = objc::class!("NSObject");
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `CLASS` failed here
+   |
+   = note: this error originates in the macro `objc::class` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0080]: cannot access extern static `SELECTOR::VAL`
+  --> $DIR/darwin-objc-bad-const.rs:14:33
+   |
+LL | pub const SELECTOR: objc::SEL = objc::selector!("alloc");
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `SELECTOR` failed here
+   |
+   = note: this error originates in the macro `objc::selector` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/darwin-objc/darwin-objc-bad-ref.rs b/tests/ui/darwin-objc/darwin-objc-bad-ref.rs
new file mode 100644
index 00000000000..fb1437366dd
--- /dev/null
+++ b/tests/ui/darwin-objc/darwin-objc-bad-ref.rs
@@ -0,0 +1,31 @@
+// Test that `objc::class!` and `objc::selector!` can't be returned by reference.
+// A single instance may have multiple addresses (e.g. across dylib boundaries).
+
+//@ edition: 2024
+//@ only-apple
+
+#![feature(darwin_objc)]
+
+use std::os::darwin::objc;
+
+pub fn class_ref<'a>() -> &'a objc::Class {
+    &objc::class!("NSObject")
+    //~^ ERROR cannot return reference to temporary value [E0515]
+}
+
+pub fn class_ref_static() -> &'static objc::Class {
+    &objc::class!("NSObject")
+    //~^ ERROR cannot return reference to temporary value [E0515]
+}
+
+pub fn selector_ref<'a>() -> &'a objc::SEL {
+    &objc::selector!("alloc")
+    //~^ ERROR cannot return reference to temporary value [E0515]
+}
+
+pub fn selector_ref_static() -> &'static objc::SEL {
+    &objc::selector!("alloc")
+    //~^ ERROR cannot return reference to temporary value [E0515]
+}
+
+pub fn main() {}
diff --git a/tests/ui/darwin-objc/darwin-objc-bad-ref.stderr b/tests/ui/darwin-objc/darwin-objc-bad-ref.stderr
new file mode 100644
index 00000000000..b09e6a75c84
--- /dev/null
+++ b/tests/ui/darwin-objc/darwin-objc-bad-ref.stderr
@@ -0,0 +1,39 @@
+error[E0515]: cannot return reference to temporary value
+  --> $DIR/darwin-objc-bad-ref.rs:12:5
+   |
+LL |     &objc::class!("NSObject")
+   |     ^------------------------
+   |     ||
+   |     |temporary value created here
+   |     returns a reference to data owned by the current function
+
+error[E0515]: cannot return reference to temporary value
+  --> $DIR/darwin-objc-bad-ref.rs:17:5
+   |
+LL |     &objc::class!("NSObject")
+   |     ^------------------------
+   |     ||
+   |     |temporary value created here
+   |     returns a reference to data owned by the current function
+
+error[E0515]: cannot return reference to temporary value
+  --> $DIR/darwin-objc-bad-ref.rs:22:5
+   |
+LL |     &objc::selector!("alloc")
+   |     ^------------------------
+   |     ||
+   |     |temporary value created here
+   |     returns a reference to data owned by the current function
+
+error[E0515]: cannot return reference to temporary value
+  --> $DIR/darwin-objc-bad-ref.rs:27:5
+   |
+LL |     &objc::selector!("alloc")
+   |     ^------------------------
+   |     ||
+   |     |temporary value created here
+   |     returns a reference to data owned by the current function
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/tests/ui/darwin-objc/darwin-objc-class-selector.rs b/tests/ui/darwin-objc/darwin-objc-class-selector.rs
new file mode 100644
index 00000000000..b9a2fc3634f
--- /dev/null
+++ b/tests/ui/darwin-objc/darwin-objc-class-selector.rs
@@ -0,0 +1,31 @@
+// Call `[NSObject class]` using `objc::class!` and `objc::selector!`.
+
+//@ edition: 2024
+//@ only-apple
+//@ run-pass
+
+#![feature(darwin_objc)]
+
+use std::mem::transmute;
+use std::os::darwin::objc;
+
+#[link(name = "Foundation", kind = "framework")]
+unsafe extern "C" {}
+
+#[link(name = "objc", kind = "dylib")]
+unsafe extern "C" {
+    unsafe fn objc_msgSend();
+}
+
+fn main() {
+    let msg_send_fn = unsafe {
+        transmute::<
+            unsafe extern "C" fn(),
+            unsafe extern "C" fn(objc::Class, objc::SEL) -> objc::Class,
+        >(objc_msgSend)
+    };
+    let static_sel = objc::selector!("class");
+    let static_class = objc::class!("NSObject");
+    let runtime_class = unsafe { msg_send_fn(static_class, static_sel) };
+    assert_eq!(static_class, runtime_class);
+}
diff --git a/tests/ui/darwin-objc/darwin-objc-class.rs b/tests/ui/darwin-objc/darwin-objc-class.rs
new file mode 100644
index 00000000000..851149d8726
--- /dev/null
+++ b/tests/ui/darwin-objc/darwin-objc-class.rs
@@ -0,0 +1,39 @@
+// Test that `objc::class!` returns the same thing as `objc_lookUpClass`.
+
+//@ edition: 2024
+//@ only-apple
+//@ run-pass
+
+#![feature(darwin_objc)]
+
+use std::ffi::c_char;
+use std::os::darwin::objc;
+
+#[link(name = "Foundation", kind = "framework")]
+unsafe extern "C" {}
+
+#[link(name = "objc")]
+unsafe extern "C" {
+    fn objc_lookUpClass(methname: *const c_char) -> objc::Class;
+}
+
+fn get_object_class() -> objc::Class {
+    objc::class!("NSObject")
+}
+
+fn lookup_object_class() -> objc::Class {
+    unsafe { objc_lookUpClass(c"NSObject".as_ptr()) }
+}
+
+fn get_string_class() -> objc::Class {
+    objc::class!("NSString")
+}
+
+fn lookup_string_class() -> objc::Class {
+    unsafe { objc_lookUpClass(c"NSString".as_ptr()) }
+}
+
+fn main() {
+    assert_eq!(get_object_class(), lookup_object_class());
+    assert_eq!(get_string_class(), lookup_string_class());
+}
diff --git a/tests/ui/darwin-objc/darwin-objc-selector.rs b/tests/ui/darwin-objc/darwin-objc-selector.rs
new file mode 100644
index 00000000000..008ae4c4ca4
--- /dev/null
+++ b/tests/ui/darwin-objc/darwin-objc-selector.rs
@@ -0,0 +1,36 @@
+// Test that `objc::selector!` returns the same thing as `sel_registerName`.
+
+//@ edition: 2024
+//@ only-apple
+//@ run-pass
+
+#![feature(darwin_objc)]
+
+use std::ffi::c_char;
+use std::os::darwin::objc;
+
+#[link(name = "objc")]
+unsafe extern "C" {
+    fn sel_registerName(methname: *const c_char) -> objc::SEL;
+}
+
+fn get_alloc_selector() -> objc::SEL {
+    objc::selector!("alloc")
+}
+
+fn register_alloc_selector() -> objc::SEL {
+    unsafe { sel_registerName(c"alloc".as_ptr()) }
+}
+
+fn get_init_selector() -> objc::SEL {
+    objc::selector!("initWithCString:encoding:")
+}
+
+fn register_init_selector() -> objc::SEL {
+    unsafe { sel_registerName(c"initWithCString:encoding:".as_ptr()) }
+}
+
+fn main() {
+    assert_eq!(get_alloc_selector(), register_alloc_selector());
+    assert_eq!(get_init_selector(), register_init_selector());
+}
diff --git a/tests/ui/drop/super-let-tail-expr-drop-order.rs b/tests/ui/drop/super-let-tail-expr-drop-order.rs
new file mode 100644
index 00000000000..5b2ecfbb320
--- /dev/null
+++ b/tests/ui/drop/super-let-tail-expr-drop-order.rs
@@ -0,0 +1,192 @@
+//! Test for #145784: the argument to `pin!` should be treated as an extending expression if and
+//! only if the whole `pin!` invocation is an extending expression. Likewise, since `pin!` is
+//! implemented in terms of `super let`, test the same for `super let` initializers. Since the
+//! argument to `pin!` and the initializer of `super let` are not temporary drop scopes, this only
+//! affects lifetimes in two cases:
+//!
+//! - Block tail expressions in Rust 2024, which are both extending expressions and temporary drop
+//! scopes; treating them as extending expressions within a non-extending `pin!` resulted in borrow
+//! expression operands living past the end of the block.
+//!
+//! - Nested `super let` statements, which can have their binding and temporary lifetimes extended
+//! when the block they're in is an extending expression.
+//!
+//! For more information on extending expressions, see
+//! https://doc.rust-lang.org/reference/destructors.html#extending-based-on-expressions
+//!
+//! For tests that `super let` initializers aren't temporary drop scopes, and tests for
+//! lifetime-extended `super let`, see tests/ui/borrowck/super-let-lifetime-and-drop.rs
+//@ run-pass
+//@ revisions: e2021 e2024
+//@ [e2021] edition: 2021
+//@ [e2024] edition: 2024
+
+#![feature(super_let)]
+#![allow(unused_braces)]
+
+use std::cell::RefCell;
+use std::pin::pin;
+
+fn f<T>(_: LogDrop<'_>, x: T) -> T { x }
+
+fn main() {
+    // Test block arguments to `pin!` in non-extending expressions.
+    // In Rust 2021, block tail expressions aren't temporary drop scopes, so their temporaries
+    // should outlive the `pin!` invocation.
+    // In Rust 2024, block tail expressions are temporary drop scopes, so their temporaries should
+    // be dropped after evaluating the tail expression within the `pin!` invocation.
+    // By nesting two `pin!` calls, this ensures non-extended `pin!` doesn't extend an inner `pin!`.
+    assert_drop_order(1..=3, |o| {
+        #[cfg(e2021)]
+        (
+            pin!((
+                pin!({ &o.log(3) as *const LogDrop<'_> }),
+                drop(o.log(1)),
+            )),
+            drop(o.log(2)),
+        );
+        #[cfg(e2024)]
+        (
+            pin!((
+                pin!({ &o.log(1) as *const LogDrop<'_> }),
+                drop(o.log(2)),
+            )),
+            drop(o.log(3)),
+        );
+    });
+
+    // The same holds for `super let` initializers in non-extending expressions.
+    assert_drop_order(1..=4, |o| {
+        #[cfg(e2021)]
+        (
+            {
+                super let _ = {
+                    super let _ = { &o.log(4) as *const LogDrop<'_> };
+                    drop(o.log(1))
+                };
+                drop(o.log(2))
+            },
+            drop(o.log(3)),
+        );
+        #[cfg(e2024)]
+        (
+            {
+                super let _ = {
+                    super let _ = { &o.log(1) as *const LogDrop<'_> };
+                    drop(o.log(2))
+                };
+                drop(o.log(3))
+            },
+            drop(o.log(4)),
+        );
+    });
+
+    // Within an extending expression, the argument to `pin!` is also an extending expression,
+    // allowing borrow operands in block tail expressions to have extended lifetimes.
+    assert_drop_order(1..=2, |o| {
+        let _ = pin!({ &o.log(2) as *const LogDrop<'_> });
+        drop(o.log(1));
+    });
+
+    // The same holds for `super let` initializers in extending expressions.
+    assert_drop_order(1..=2, |o| {
+        let _ =  { super let _ = { &o.log(2) as *const LogDrop<'_> }; };
+        drop(o.log(1));
+    });
+
+    // We have extending borrow expressions within an extending block
+    // expression (within an extending borrow expression) within a
+    // non-extending expresion within the initializer expression.
+    #[cfg(e2021)]
+    {
+        // These two should be the same.
+        assert_drop_order(1..=3, |e| {
+            let _v = f(e.log(1), &{ &raw const *&e.log(2) });
+            drop(e.log(3));
+        });
+        assert_drop_order(1..=3, |e| {
+            let _v = f(e.log(1), {
+                super let v = &{ &raw const *&e.log(2) };
+                v
+            });
+            drop(e.log(3));
+        });
+    }
+    #[cfg(e2024)]
+    {
+        // These two should be the same.
+        assert_drop_order(1..=3, |e| {
+            let _v = f(e.log(2), &{ &raw const *&e.log(1) });
+            drop(e.log(3));
+        });
+        assert_drop_order(1..=3, |e| {
+            let _v = f(e.log(2), {
+                super let v = &{ &raw const *&e.log(1) };
+                v
+            });
+            drop(e.log(3));
+        });
+    }
+
+    // We have extending borrow expressions within a non-extending
+    // expression within the initializer expression.
+    //
+    // These two should be the same.
+    assert_drop_order(1..=3, |e| {
+        let _v = f(e.log(1), &&raw const *&e.log(2));
+        drop(e.log(3));
+    });
+    assert_drop_order(1..=3, |e| {
+        let _v = f(e.log(1), {
+            super let v = &&raw const *&e.log(2);
+            v
+        });
+        drop(e.log(3));
+    });
+
+    // We have extending borrow expressions within an extending block
+    // expression (within an extending borrow expression) within the
+    // initializer expression.
+    //
+    // These two should be the same.
+    assert_drop_order(1..=2, |e| {
+        let _v = &{ &raw const *&e.log(2) };
+        drop(e.log(1));
+    });
+    assert_drop_order(1..=2, |e| {
+        let _v = {
+            super let v = &{ &raw const *&e.log(2) };
+            v
+        };
+        drop(e.log(1));
+    });
+}
+
+// # Test scaffolding...
+
+struct DropOrder(RefCell<Vec<u64>>);
+struct LogDrop<'o>(&'o DropOrder, u64);
+
+impl DropOrder {
+    fn log(&self, n: u64) -> LogDrop<'_> {
+        LogDrop(self, n)
+    }
+}
+
+impl<'o> Drop for LogDrop<'o> {
+    fn drop(&mut self) {
+        self.0.0.borrow_mut().push(self.1);
+    }
+}
+
+#[track_caller]
+fn assert_drop_order(
+    ex: impl IntoIterator<Item = u64>,
+    f: impl Fn(&DropOrder),
+) {
+    let order = DropOrder(RefCell::new(Vec::new()));
+    f(&order);
+    let order = order.0.into_inner();
+    let expected: Vec<u64> = ex.into_iter().collect();
+    assert_eq!(order, expected);
+}
diff --git a/tests/ui/issues/issue-18088.rs b/tests/ui/issues/issue-18088.rs
deleted file mode 100644
index ba198884c63..00000000000
--- a/tests/ui/issues/issue-18088.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-//@ check-pass
-
-pub trait Indexable<T>: std::ops::Index<usize, Output = T> {
-    fn index2(&self, i: usize) -> &T {
-        &self[i]
-    }
-}
-fn main() {}
diff --git a/tests/ui/issues/issue-21950.rs b/tests/ui/issues/issue-21950.rs
deleted file mode 100644
index 7a85ac91bca..00000000000
--- a/tests/ui/issues/issue-21950.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-trait Add<Rhs=Self> {
-    type Output;
-}
-
-impl Add for i32 {
-    type Output = i32;
-}
-
-fn main() {
-    let x = &10 as &dyn Add;
-    //~^ ERROR E0191
-}
diff --git a/tests/ui/issues/issue-2284.rs b/tests/ui/issues/issue-2284.rs
deleted file mode 100644
index 358331ecd9a..00000000000
--- a/tests/ui/issues/issue-2284.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-//@ run-pass
-#![allow(dead_code)]
-
-trait Send {
-    fn f(&self);
-}
-
-fn f<T:Send>(t: T) {
-    t.f();
-}
-
-pub fn main() {
-}
diff --git a/tests/ui/lifetimes/issue-105507.fixed b/tests/ui/lifetimes/issue-105507.fixed
index 46d4f14a245..a3c4e5784b8 100644
--- a/tests/ui/lifetimes/issue-105507.fixed
+++ b/tests/ui/lifetimes/issue-105507.fixed
@@ -31,7 +31,7 @@ impl<T> ProjectedMyTrait for T
 
 fn require_trait<T: MyTrait>(_: T) {}
 
-fn foo<T : MyTrait + 'static + 'static, U : MyTrait + 'static + 'static>(wrap: Wrapper<'_, Option<T>>, wrap1: Wrapper<'_, Option<U>>) {
+fn foo<T : MyTrait + 'static, U : MyTrait + 'static>(wrap: Wrapper<'_, Option<T>>, wrap1: Wrapper<'_, Option<U>>) {
     //~^ HELP consider restricting the type parameter to the `'static` lifetime
     //~| HELP consider restricting the type parameter to the `'static` lifetime
     require_trait(wrap);
diff --git a/tests/ui/lint/unused_parens_follow_ident.fixed b/tests/ui/lint/unused_parens_follow_ident.fixed
new file mode 100644
index 00000000000..e61b287e5a6
--- /dev/null
+++ b/tests/ui/lint/unused_parens_follow_ident.fixed
@@ -0,0 +1,17 @@
+//@ run-rustfix
+
+#![deny(unused_parens)]
+
+macro_rules! wrap {
+    ($name:ident $arg:expr) => {
+        $name($arg);
+    };
+}
+
+fn main() {
+    wrap!(unary routine()); //~ ERROR unnecessary parentheses around function argument
+    wrap!(unary routine()); //~ ERROR unnecessary parentheses around function argument
+}
+
+fn unary(_: ()) {}
+fn routine() {}
diff --git a/tests/ui/lint/unused_parens_follow_ident.rs b/tests/ui/lint/unused_parens_follow_ident.rs
new file mode 100644
index 00000000000..32a163345b2
--- /dev/null
+++ b/tests/ui/lint/unused_parens_follow_ident.rs
@@ -0,0 +1,17 @@
+//@ run-rustfix
+
+#![deny(unused_parens)]
+
+macro_rules! wrap {
+    ($name:ident $arg:expr) => {
+        $name($arg);
+    };
+}
+
+fn main() {
+    wrap!(unary(routine())); //~ ERROR unnecessary parentheses around function argument
+    wrap!(unary (routine())); //~ ERROR unnecessary parentheses around function argument
+}
+
+fn unary(_: ()) {}
+fn routine() {}
diff --git a/tests/ui/lint/unused_parens_follow_ident.stderr b/tests/ui/lint/unused_parens_follow_ident.stderr
new file mode 100644
index 00000000000..ce7bb26778c
--- /dev/null
+++ b/tests/ui/lint/unused_parens_follow_ident.stderr
@@ -0,0 +1,31 @@
+error: unnecessary parentheses around function argument
+  --> $DIR/unused_parens_follow_ident.rs:12:16
+   |
+LL |     wrap!(unary(routine()));
+   |                ^         ^
+   |
+note: the lint level is defined here
+  --> $DIR/unused_parens_follow_ident.rs:3:9
+   |
+LL | #![deny(unused_parens)]
+   |         ^^^^^^^^^^^^^
+help: remove these parentheses
+   |
+LL -     wrap!(unary(routine()));
+LL +     wrap!(unary routine());
+   |
+
+error: unnecessary parentheses around function argument
+  --> $DIR/unused_parens_follow_ident.rs:13:17
+   |
+LL |     wrap!(unary (routine()));
+   |                 ^         ^
+   |
+help: remove these parentheses
+   |
+LL -     wrap!(unary (routine()));
+LL +     wrap!(unary routine());
+   |
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/mir/lint/assignment-overlap.rs b/tests/ui/mir/lint/assignment-overlap.rs
index bbc14090467..5d1213a7758 100644
--- a/tests/ui/mir/lint/assignment-overlap.rs
+++ b/tests/ui/mir/lint/assignment-overlap.rs
@@ -13,7 +13,7 @@ pub fn main() {
         let a: [u8; 1024];
         {
             a = a; //~ ERROR broken MIR
-                   //~^ ERROR encountered `Assign` statement with overlapping memory
+                   //~^ ERROR encountered `_1 = copy _1` statement with overlapping memory
             Return()
         }
     }
diff --git a/tests/ui/parser/expr-as-stmt.fixed b/tests/ui/parser/expr-as-stmt.fixed
index bfae55047ed..b3a491200ed 100644
--- a/tests/ui/parser/expr-as-stmt.fixed
+++ b/tests/ui/parser/expr-as-stmt.fixed
@@ -66,7 +66,7 @@ fn asteroids() -> impl FnOnce() -> bool {
 
 // https://github.com/rust-lang/rust/issues/105179
 fn r#match() -> i32 {
-    ((match () { () => 1 })) + match () { () => 1 } //~ ERROR expected expression, found `+`
+    (match () { () => 1 }) + match () { () => 1 } //~ ERROR expected expression, found `+`
     //~^ ERROR mismatched types
 }
 
@@ -82,7 +82,7 @@ fn matches() -> bool {
     (match () { _ => true }) && match () { _ => true }; //~ ERROR mismatched types
     //~^ ERROR expected `;`, found keyword `match`
     (match () { _ => true }) && true; //~ ERROR mismatched types
-    ((match () { _ => true })) && true //~ ERROR mismatched types
+    (match () { _ => true }) && true //~ ERROR mismatched types
     //~^ ERROR mismatched types
 }
 fn main() {}
diff --git a/tests/ui/rustc_public-ir-print/async-closure.rs b/tests/ui/rustc_public-ir-print/async-closure.rs
index 80f96e09cfc..bd8c7e888a3 100644
--- a/tests/ui/rustc_public-ir-print/async-closure.rs
+++ b/tests/ui/rustc_public-ir-print/async-closure.rs
@@ -1,6 +1,6 @@
 //@ compile-flags: -Z unpretty=stable-mir --crate-type lib -C panic=abort -Zmir-opt-level=0
 //@ check-pass
-//@ only-x86_64
+//@ only-64bit
 //@ edition: 2024
 //@ needs-unwind unwind edges are different with panic=abort
 
diff --git a/tests/ui/rustc_public-ir-print/async-closure.stdout b/tests/ui/rustc_public-ir-print/async-closure.stdout
index 73e9b8fc097..5113dc5048b 100644
--- a/tests/ui/rustc_public-ir-print/async-closure.stdout
+++ b/tests/ui/rustc_public-ir-print/async-closure.stdout
@@ -40,30 +40,28 @@ fn foo::{closure#0}::{closure#0}(_1: Pin<&mut {async closure body@$DIR/async-clo
     let  _3: i32;
     let mut _4: &i32;
     let mut _5: ();
-    let mut _6: &mut Context<'_>;
-    let mut _7: u32;
+    let mut _6: u32;
+    let mut _7: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6};
     let mut _8: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6};
     let mut _9: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6};
-    let mut _10: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6};
-    debug _task_context => _6;
+    debug _task_context => _2;
     debug y => (*((*(_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6})).0: &i32));
     debug y => _3;
     bb0: {
-        _8 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}));
-        _7 = discriminant((*_8));
-        switchInt(move _7) -> [0: bb1, 1: bb2, otherwise: bb3];
+        _7 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}));
+        _6 = discriminant((*_7));
+        switchInt(move _6) -> [0: bb1, 1: bb2, otherwise: bb3];
     }
     bb1: {
-        _6 = move _2;
         StorageLive(_3);
-        _9 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}));
-        _4 = CopyForDeref(((*_9).0: &i32));
+        _8 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}));
+        _4 = CopyForDeref(((*_8).0: &i32));
         _3 = (*_4);
         _5 = ();
         StorageDead(_3);
         _0 = std::task::Poll::Ready(move _5);
-        _10 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}));
-        discriminant((*_10)) = 1;
+        _9 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}));
+        discriminant((*_9)) = 1;
         return;
     }
     bb2: {
@@ -78,30 +76,28 @@ fn foo::{closure#0}::{synthetic#0}(_1: Pin<&mut {async closure body@$DIR/async-c
     let  _3: i32;
     let mut _4: &i32;
     let mut _5: ();
-    let mut _6: &mut Context<'_>;
-    let mut _7: u32;
+    let mut _6: u32;
+    let mut _7: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6};
     let mut _8: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6};
     let mut _9: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6};
-    let mut _10: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6};
-    debug _task_context => _6;
+    debug _task_context => _2;
     debug y => (*((*(_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6})).0: &i32));
     debug y => _3;
     bb0: {
-        _8 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}));
-        _7 = discriminant((*_8));
-        switchInt(move _7) -> [0: bb1, 1: bb2, otherwise: bb3];
+        _7 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}));
+        _6 = discriminant((*_7));
+        switchInt(move _6) -> [0: bb1, 1: bb2, otherwise: bb3];
     }
     bb1: {
-        _6 = move _2;
         StorageLive(_3);
-        _9 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}));
-        _4 = CopyForDeref(((*_9).0: &i32));
+        _8 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}));
+        _4 = CopyForDeref(((*_8).0: &i32));
         _3 = (*_4);
         _5 = ();
         StorageDead(_3);
         _0 = std::task::Poll::Ready(move _5);
-        _10 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}));
-        discriminant((*_10)) = 1;
+        _9 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}));
+        discriminant((*_9)) = 1;
         return;
     }
     bb2: {
diff --git a/tests/ui/suggestions/apitit-unimplemented-method.rs b/tests/ui/suggestions/apitit-unimplemented-method.rs
index b182e1939b3..c0cd709e230 100644
--- a/tests/ui/suggestions/apitit-unimplemented-method.rs
+++ b/tests/ui/suggestions/apitit-unimplemented-method.rs
@@ -4,9 +4,12 @@ extern crate dep;
 use dep::*;
 
 struct Local;
+
 impl Trait for Local {}
 //~^ ERROR not all trait items implemented
 //~| HELP implement the missing item: `fn foo(_: impl Sized) { todo!() }`
-//~| HELP implement the missing item: `fn bar<T>(_: impl Sized) { todo!() }`
+//~| HELP implement the missing item: `fn bar<T>(_: impl Sized) where Foo<T>: MetaSized { todo!() }`
+//~| HELP implement the missing item: `fn baz<const N: usize>() { todo!() }`
+//~| HELP implement the missing item: `fn quux<'a: 'b, 'b, T>() where T: ?Sized { todo!() }`
 
 fn main() {}
diff --git a/tests/ui/suggestions/apitit-unimplemented-method.stderr b/tests/ui/suggestions/apitit-unimplemented-method.stderr
index b309a64e958..1f2e0ea2cad 100644
--- a/tests/ui/suggestions/apitit-unimplemented-method.stderr
+++ b/tests/ui/suggestions/apitit-unimplemented-method.stderr
@@ -1,11 +1,13 @@
-error[E0046]: not all trait items implemented, missing: `foo`, `bar`
-  --> $DIR/apitit-unimplemented-method.rs:7:1
+error[E0046]: not all trait items implemented, missing: `foo`, `bar`, `baz`, `quux`
+  --> $DIR/apitit-unimplemented-method.rs:8:1
    |
 LL | impl Trait for Local {}
-   | ^^^^^^^^^^^^^^^^^^^^ missing `foo`, `bar` in implementation
+   | ^^^^^^^^^^^^^^^^^^^^ missing `foo`, `bar`, `baz`, `quux` in implementation
    |
    = help: implement the missing item: `fn foo(_: impl Sized) { todo!() }`
-   = help: implement the missing item: `fn bar<T>(_: impl Sized) { todo!() }`
+   = help: implement the missing item: `fn bar<T>(_: impl Sized) where Foo<T>: MetaSized { todo!() }`
+   = help: implement the missing item: `fn baz<const N: usize>() { todo!() }`
+   = help: implement the missing item: `fn quux<'a: 'b, 'b, T>() where T: ?Sized { todo!() }`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/suggestions/auxiliary/dep.rs b/tests/ui/suggestions/auxiliary/dep.rs
index ac0de418313..c28c8b8a52f 100644
--- a/tests/ui/suggestions/auxiliary/dep.rs
+++ b/tests/ui/suggestions/auxiliary/dep.rs
@@ -1,4 +1,16 @@
+#![feature(sized_hierarchy)]
+
+use std::marker::MetaSized;
+
+pub struct Foo<T> {
+    inner: T,
+}
+
 pub trait Trait {
     fn foo(_: impl Sized);
-    fn bar<T>(_: impl Sized);
+    fn bar<T>(_: impl Sized)
+    where
+        Foo<T>: MetaSized;
+    fn baz<'a, const N: usize>();
+    fn quux<'a: 'b, 'b, T: ?Sized>();
 }
diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.fixed b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.fixed
index 99433f73320..8a2be310e0d 100644
--- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.fixed
+++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.fixed
@@ -8,7 +8,7 @@ pub struct Vector2<T: Debug + Copy + Clone> {
 }
 
 #[derive(Debug, Copy, Clone)]
-pub struct AABB<K: Debug + std::marker::Copy + std::marker::Copy + std::marker::Copy + std::marker::Copy> {
+pub struct AABB<K: Debug + std::marker::Copy> {
     pub loc: Vector2<K>, //~ ERROR the trait bound `K: Copy` is not satisfied
     //~^ ERROR the trait bound `K: Copy` is not satisfied
     //~| ERROR the trait bound `K: Copy` is not satisfied
diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed
index 6da3e351ffb..74df1d7c7cf 100644
--- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed
+++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed
@@ -8,7 +8,7 @@ pub struct Vector2<T: Debug + Copy + Clone>{
 }
 
 #[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` cannot be implemented for this type
-pub struct AABB<K: Copy + Debug + std::fmt::Debug + std::fmt::Debug + std::fmt::Debug>{
+pub struct AABB<K: Copy + Debug + std::fmt::Debug>{
     pub loc: Vector2<K>, //~ ERROR `K` doesn't implement `Debug`
     //~^ ERROR `K` doesn't implement `Debug`
     pub size: Vector2<K> //~ ERROR `K` doesn't implement `Debug`
diff --git a/tests/ui/suggestions/trait-impl-bound-suggestions.fixed b/tests/ui/suggestions/trait-impl-bound-suggestions.fixed
index 9d3168f5acd..49793b4b6f4 100644
--- a/tests/ui/suggestions/trait-impl-bound-suggestions.fixed
+++ b/tests/ui/suggestions/trait-impl-bound-suggestions.fixed
@@ -10,7 +10,7 @@ struct ConstrainedStruct<X: Copy> {
 }
 
 #[allow(dead_code)]
-trait InsufficientlyConstrainedGeneric<X=()> where Self: Sized, X: std::marker::Copy, X: std::marker::Copy {
+trait InsufficientlyConstrainedGeneric<X=()> where Self: Sized, X: std::marker::Copy {
     fn return_the_constrained_type(&self, x: X) -> ConstrainedStruct<X> {
         //~^ ERROR the trait bound `X: Copy` is not satisfied
         ConstrainedStruct { x }
@@ -20,7 +20,7 @@ trait InsufficientlyConstrainedGeneric<X=()> where Self: Sized, X: std::marker::
 
 // Regression test for #120838
 #[allow(dead_code)]
-trait InsufficientlyConstrainedGenericWithEmptyWhere<X=()> where Self: Sized, X: std::marker::Copy, X: std::marker::Copy {
+trait InsufficientlyConstrainedGenericWithEmptyWhere<X=()> where Self: Sized, X: std::marker::Copy {
     fn return_the_constrained_type(&self, x: X) -> ConstrainedStruct<X> {
         //~^ ERROR the trait bound `X: Copy` is not satisfied
         ConstrainedStruct { x }
diff --git a/tests/ui/issues/issue-19479.rs b/tests/ui/traits/associated_type_bound/assoc-type-via-another-trait-issue-19479.rs
index ed586b76550..f17a89bcb5f 100644
--- a/tests/ui/issues/issue-19479.rs
+++ b/tests/ui/traits/associated_type_bound/assoc-type-via-another-trait-issue-19479.rs
@@ -1,5 +1,11 @@
 //@ check-pass
 
+//! Tests that it's possible to define an associated type in a trait
+//! using an associated type from type parameter bound trait in a blanket implementation.
+//!
+//! # Context
+//! Original issue: https://github.com/rust-lang/rust/issues/19479
+
 trait Base {
     fn dummy(&self) { }
 }
diff --git a/tests/ui/traits/cast-as-dyn-trait-wo-assoc-type-issue-21950.rs b/tests/ui/traits/cast-as-dyn-trait-wo-assoc-type-issue-21950.rs
new file mode 100644
index 00000000000..3c381505450
--- /dev/null
+++ b/tests/ui/traits/cast-as-dyn-trait-wo-assoc-type-issue-21950.rs
@@ -0,0 +1,19 @@
+//! Tests that compiler yields error E0191 when value with existing trait implementation
+//! is cast as same `dyn` trait without specifying associated type at the cast.
+//!
+//! # Context
+//! Original issue: https://github.com/rust-lang/rust/issues/21950
+
+trait Add<Rhs=Self> {
+    type Output;
+}
+
+impl Add for i32 {
+    type Output = i32;
+}
+
+fn main() {
+    let x = &10 as &dyn Add<i32, Output = i32>; //OK
+    let x = &10 as &dyn Add;
+    //~^ ERROR E0191
+}
diff --git a/tests/ui/issues/issue-21950.stderr b/tests/ui/traits/cast-as-dyn-trait-wo-assoc-type-issue-21950.stderr
index 24230cfe17f..5f4974e6f23 100644
--- a/tests/ui/issues/issue-21950.stderr
+++ b/tests/ui/traits/cast-as-dyn-trait-wo-assoc-type-issue-21950.stderr
@@ -1,5 +1,5 @@
 error[E0191]: the value of the associated type `Output` in `Add` must be specified
-  --> $DIR/issue-21950.rs:10:25
+  --> $DIR/cast-as-dyn-trait-wo-assoc-type-issue-21950.rs:17:25
    |
 LL |     type Output;
    |     ----------- `Output` defined here
diff --git a/tests/ui/traits/core-marker-name-shadowing-issue-2284.rs b/tests/ui/traits/core-marker-name-shadowing-issue-2284.rs
new file mode 100644
index 00000000000..e5d083ac8c3
--- /dev/null
+++ b/tests/ui/traits/core-marker-name-shadowing-issue-2284.rs
@@ -0,0 +1,21 @@
+//@ run-pass
+#![allow(dead_code)]
+
+//! Tests that user-defined trait is prioritized in compile time over
+//! the core::marker trait with the same name, allowing shadowing core traits.
+//!
+//! # Context
+//! Original issue: https://github.com/rust-lang/rust/issues/2284
+//! Original fix pull request: https://github.com/rust-lang/rust/pull/3792
+
+
+trait Send {
+    fn f(&self);
+}
+
+fn f<T:Send>(t: T) {
+    t.f();
+}
+
+pub fn main() {
+}
diff --git a/tests/ui/traits/inheritance/supertrait-operator-issue-18088.rs b/tests/ui/traits/inheritance/supertrait-operator-issue-18088.rs
new file mode 100644
index 00000000000..8bd45cd54a4
--- /dev/null
+++ b/tests/ui/traits/inheritance/supertrait-operator-issue-18088.rs
@@ -0,0 +1,13 @@
+//@ check-pass
+
+//! Tests that operators from supertrait are available directly on `self` for an inheritor trait.
+//!
+//! # Context
+//! Original issue: https://github.com/rust-lang/rust/issues/18088
+
+pub trait Indexable<T>: std::ops::Index<usize, Output = T> {
+    fn index2(&self, i: usize) -> &T {
+        &self[i]
+    }
+}
+fn main() {}
diff --git a/tests/ui/type-inference/has_sigdrop.rs b/tests/ui/type-inference/has_sigdrop.rs
new file mode 100644
index 00000000000..c3d835cfe16
--- /dev/null
+++ b/tests/ui/type-inference/has_sigdrop.rs
@@ -0,0 +1,18 @@
+//@ run-pass
+// Inference, canonicalization, and significant drops should work nicely together.
+// Related issue: #86868
+
+#[clippy::has_significant_drop]
+struct DropGuy {}
+
+fn creator() -> DropGuy {
+    DropGuy {}
+}
+
+fn dropper() {
+    let _ = creator();
+}
+
+fn main() {
+    dropper();
+}