Auto merge of #91512 - scottmcm:array-intoiter-advance, r=Mark-Simulacrum
Override `Iterator::advance(_back)_by` for `array::IntoIter`
Because I happened to notice that `nth` is currently getting codegen'd as a loop even for `Copy` types: <https://rust.godbolt.org/z/fPqv7Gvs7>
<details>
<summary>LLVM before and after</summary>
Rust:
```rust
#[no_mangle]
pub fn array_intoiter_nth(it: &mut std::array::IntoIter<i32, 100>, n: usize) -> Option<i32> {
it.nth(n)
}
```
Current nightly:
```llvmir
define { i32, i32 } `@array_intoiter_nth(%"core::array::iter::IntoIter<i32,` 100_usize>"* noalias nocapture align 8 dereferenceable(416) %it, i64 %n) unnamed_addr #0 personality i32 (i32, i32, i64, %"unwind::libunwind::_Unwind_Exception"*, %"unwind::libunwind::_Unwind_Context"*)* `@rust_eh_personality` !dbg !6 {
start:
%_3.i.i.i4.i.i = getelementptr inbounds %"core::array::iter::IntoIter<i32, 100_usize>", %"core::array::iter::IntoIter<i32, 100_usize>"* %it, i64 0, i32 0, i32 0
%_4.i.i.i5.i.i = getelementptr inbounds %"core::array::iter::IntoIter<i32, 100_usize>", %"core::array::iter::IntoIter<i32, 100_usize>"* %it, i64 0, i32 0, i32 1
%_4.i.i.i.i.i.i = load i64, i64* %_4.i.i.i5.i.i, align 8, !alias.scope !10
%.not.i.i = icmp eq i64 %n, 0, !dbg !15
%_3.i.i.i.i.pre.i = load i64, i64* %_3.i.i.i4.i.i, align 8, !dbg !40, !alias.scope !41
br i1 %.not.i.i, label %bb4.i, label %bb4.preheader.i.i, !dbg !42
bb4.preheader.i.i: ; preds = %start
%umax.i = tail call i64 `@llvm.umax.i64(i64` %_3.i.i.i.i.pre.i, i64 %_4.i.i.i.i.i.i) #3, !dbg !43
%0 = sub i64 %umax.i, %_3.i.i.i.i.pre.i, !dbg !43
br label %bb4.i.i, !dbg !43
bb4.i.i: ; preds = %bb3.i.i.i.i, %bb4.preheader.i.i
%_3.i.i.i.i.i.i = phi i64 [ %2, %bb3.i.i.i.i ], [ %_3.i.i.i.i.pre.i, %bb4.preheader.i.i ], !dbg !52
%iter.sroa.0.016.i.i = phi i64 [ %1, %bb3.i.i.i.i ], [ 0, %bb4.preheader.i.i ]
%1 = add nuw i64 %iter.sroa.0.016.i.i, 1, !dbg !54
%exitcond.not.i = icmp eq i64 %iter.sroa.0.016.i.i, %0, !dbg !52
br i1 %exitcond.not.i, label %core::iter::traits::iterator::Iterator::nth.exit, label %bb3.i.i.i.i, !dbg !43
bb3.i.i.i.i: ; preds = %bb4.i.i
%2 = add nuw i64 %_3.i.i.i.i.i.i, 1, !dbg !63
store i64 %2, i64* %_3.i.i.i4.i.i, align 8, !dbg !66, !alias.scope !75
%exitcond.not.i.i = icmp eq i64 %1, %n, !dbg !15
br i1 %exitcond.not.i.i, label %bb4.i, label %bb4.i.i, !dbg !42
bb4.i: ; preds = %bb3.i.i.i.i, %start
%_3.i.i.i.i.i = phi i64 [ %_3.i.i.i.i.pre.i, %start ], [ %2, %bb3.i.i.i.i ], !dbg !84
%3 = icmp ult i64 %_3.i.i.i.i.i, %_4.i.i.i.i.i.i, !dbg !84
br i1 %3, label %bb3.i.i.i, label %core::iter::traits::iterator::Iterator::nth.exit, !dbg !89
bb3.i.i.i: ; preds = %bb4.i
%4 = add nuw i64 %_3.i.i.i.i.i, 1, !dbg !90
store i64 %4, i64* %_3.i.i.i4.i.i, align 8, !dbg !93, !alias.scope !96
%5 = getelementptr inbounds %"core::array::iter::IntoIter<i32, 100_usize>", %"core::array::iter::IntoIter<i32, 100_usize>"* %it, i64 0, i32 1, i64 %_3.i.i.i.i.i, !dbg !105
%6 = load i32, i32* %5, align 4, !dbg !131, !alias.scope !141, !noalias !144
br label %core::iter::traits::iterator::Iterator::nth.exit, !dbg !149
core::iter::traits::iterator::Iterator::nth.exit: ; preds = %bb4.i.i, %bb4.i, %bb3.i.i.i
%.sroa.3.0.i = phi i32 [ %6, %bb3.i.i.i ], [ undef, %bb4.i ], [ undef, %bb4.i.i ], !dbg !40
%.sroa.0.0.i = phi i32 [ 1, %bb3.i.i.i ], [ 0, %bb4.i ], [ 0, %bb4.i.i ], !dbg !40
%7 = insertvalue { i32, i32 } undef, i32 %.sroa.0.0.i, 0, !dbg !150
%8 = insertvalue { i32, i32 } %7, i32 %.sroa.3.0.i, 1, !dbg !150
ret { i32, i32 } %8, !dbg !151
}
```
With this PR:
```llvmir
define { i32, i32 } `@array_intoiter_nth(%"core::array::iter::IntoIter<i32,` 100_usize>"* noalias nocapture align 8 dereferenceable(416) %it, i64 %n) unnamed_addr #0 personality i32 (...)* `@__CxxFrameHandler3` {
start:
%0 = getelementptr inbounds %"core::array::iter::IntoIter<i32, 100_usize>", %"core::array::iter::IntoIter<i32, 100_usize>"* %it, i64 0, i32 0, i32 1
%_2.i.i.i.i = load i64, i64* %0, align 8, !alias.scope !6, !noalias !13
%1 = getelementptr inbounds %"core::array::iter::IntoIter<i32, 100_usize>", %"core::array::iter::IntoIter<i32, 100_usize>"* %it, i64 0, i32 0, i32 0
%_3.i.i.i.i = load i64, i64* %1, align 8, !alias.scope !16
%2 = sub i64 %_2.i.i.i.i, %_3.i.i.i.i
%3 = icmp ult i64 %2, %n
%.0.sroa.speculated.i.i.i.i.i = select i1 %3, i64 %2, i64 %n
%_10.i.i = add i64 %.0.sroa.speculated.i.i.i.i.i, %_3.i.i.i.i
store i64 %_10.i.i, i64* %1, align 8, !alias.scope !16
%.not.i = xor i1 %3, true
%4 = icmp ult i64 %_10.i.i, %_2.i.i.i.i
%or.cond.i = select i1 %.not.i, i1 %4, i1 false
br i1 %or.cond.i, label %bb3.i.i.i, label %_ZN4core4iter6traits8iterator8Iterator3nth17hcbc727011e9e2a3bE.exit
bb3.i.i.i: ; preds = %start
%5 = add nuw i64 %_10.i.i, 1
store i64 %5, i64* %1, align 8, !alias.scope !17
%6 = getelementptr inbounds %"core::array::iter::IntoIter<i32, 100_usize>", %"core::array::iter::IntoIter<i32, 100_usize>"* %it, i64 0, i32 1, i64 %_10.i.i
%7 = load i32, i32* %6, align 4, !alias.scope !26, !noalias !29
br label %_ZN4core4iter6traits8iterator8Iterator3nth17hcbc727011e9e2a3bE.exit
_ZN4core4iter6traits8iterator8Iterator3nth17hcbc727011e9e2a3bE.exit: ; preds = %start, %bb3.i.i.i
%.sroa.3.0.i = phi i32 [ undef, %start ], [ %7, %bb3.i.i.i ]
%.sroa.0.0.i = phi i32 [ 0, %start ], [ 1, %bb3.i.i.i ]
%8 = insertvalue { i32, i32 } undef, i32 %.sroa.0.0.i, 0
%9 = insertvalue { i32, i32 } %8, i32 %.sroa.3.0.i, 1
ret { i32, i32 } %9
}
```
</details>