Skip to content

Safer implementation of RepeatN #130887

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

Safer implementation of RepeatN #130887

wants to merge 1 commit into from

Conversation

Soveu
Copy link
Contributor

@Soveu Soveu commented Sep 26, 2024

I've seen the "Use MaybeUninit for RepeatN" commit while reading This Week In Rust and immediately thought about something I've written some time ago - https://github.com/Soveu/repeat_finite/blob/master/src/lib.rs.

Using the fact, that Option will find niche in (T, NonZeroUsize), we can construct something that has the same size as (T, usize) while completely getting rid of MaybeUninit.
This leaves only unsafe on TrustedLen, which is pretty neat.

try-job: x86_64-gnu-distcheck

@rustbot
Copy link
Collaborator

rustbot commented Sep 26, 2024

r? @Amanieu

rustbot has assigned @Amanieu.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Sep 26, 2024
@rust-log-analyzer

This comment has been minimized.

@Soveu
Copy link
Contributor Author

Soveu commented Sep 26, 2024

huh, I'm no llvm expert, buuut...

          8: ; Function Attrs: mustprogress nofree norecurse nosync nounwind nonlazybind willreturn memory(argmem: readwrite) uwtable 
           9: define { i16, i16 } @iter_repeat_n_next(ptr noalias nocapture noundef align 8 dereferenceable(16) %it) unnamed_addr #0 { 
          10: start: 
          11:  %0 = load i64, ptr %it, align 8, !alias.scope !3, !noundef !6 
          12:  %1 = icmp eq i64 %0, 0 
          13:  br i1 %1, label %"_ZN106_$LT$core..iter..sources..repeat_n..RepeatN$LT$A$GT$$u20$as$u20$core..iter..traits..iterator..Iterator$GT$4next17hd614a6386f3f6a14E.exit", label %bb8.i 
          14:  
          15: bb8.i: ; preds = %start 
          16:  %_10.0.i = add i64 %0, -1 
          17:  %2 = icmp eq i64 %_10.0.i, 0 
          18:  br i1 %2, label %bb5.i, label %bb3.i 
          19:  
          20: bb3.i: ; preds = %bb8.i 
          21:  store i64 %_10.0.i, ptr %it, align 8, !alias.scope !3 
  next:29      !~~~~~~~~~~~~~~~~~                                     error: match on wrong line
          22:  %_14.i = getelementptr inbounds i8, ptr %it, i64 8 
          23:  %_14.val.i = load i16, ptr %_14.i, align 8, !alias.scope !3, !noundef !6 
          24:  br label %"_ZN106_$LT$core..iter..sources..repeat_n..RepeatN$LT$A$GT$$u20$as$u20$core..iter..traits..iterator..Iterator$GT$4next17hd614a6386f3f6a14E.exit" 
          25:  
          26: bb5.i: ; preds = %bb8.i 
          27:  %3 = getelementptr inbounds i8, ptr %it, i64 8 
          28:  %4 = load i16, ptr %3, align 8, !alias.scope !7 
          29:  store i64 0, ptr %it, align 8, !alias.scope !7 
          30:  br label %"_ZN106_$LT$core..iter..sources..repeat_n..RepeatN$LT$A$GT$$u20$as$u20$core..iter..traits..iterator..Iterator$GT$4next17hd614a6386f3f6a14E.exit" 
          31:  
          32: "_ZN106_$LT$core..iter..sources..repeat_n..RepeatN$LT$A$GT$$u20$as$u20$core..iter..traits..iterator..Iterator$GT$4next17hd614a6386f3f6a14E.exit": ; preds = %start, %bb3.i, %bb5.i 
          33:  %_0.sroa.5.0.i = phi i16 [ %4, %bb5.i ], [ %_14.val.i, %bb3.i ], [ undef, %start ] 
          34:  %_0.sroa.0.0.i = phi i16 [ 1, %bb5.i ], [ 1, %bb3.i ], [ 0, %start ] 
          35:  %5 = insertvalue { i16, i16 } poison, i16 %_0.sroa.0.0.i, 0 
          36:  %6 = insertvalue { i16, i16 } %5, i16 %_0.sroa.5.0.i, 1 
          37:  ret { i16, i16 } %6 
          38: } 

bb3.i and bb5.i if not for the store i64 they would look identical.

The other functions (vec_extend_via_repeat_n and array_repeat_not_copy) look ok.

@slanterns
Copy link
Contributor

Maybe you can ping scottmcm (test author) to see if the change in codegen result is acceptable (then adjust the test.)

@Dylan-DPC
Copy link
Member

@Soveu any updates on the failed test? thanks

@Dylan-DPC Dylan-DPC added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Nov 28, 2024
@Soveu
Copy link
Contributor Author

Soveu commented Nov 29, 2024

@Soveu any updates on the failed test? thanks

I guess we don't want to introduce additional branches in the generated code, so for "production" code this implementation would be unfit. @scottmcm could comment on that.

@scottmcm
Copy link
Member

It is pretty neat, and in fact it's the implementation I originally wrote for this.

The biggest issue I had with it then, though, is that it makes the iterator be potentially-undef, but because of the #130141 bug (which reminds me to go push on rust-lang/rfcs#3712 ) we're stuck with that problem anyway, so there's probably a way you could make this work.


Looks like the problem is that it's having trouble figuring out that the store of zero and the store of count-1 can be merged, because otherwise there'd be no difference.

Basically, what this test is testing is that for !needs_drop types we don't need to consider the last iteration separately, because the difference between them is whether we need to call drop, but since we don't need to do that for !needs_drop it's not an issue, and thus we should be able to avoid that second branch. (We of course need the "is the iterator empty?" branch, but once we know it's not empty there should be no further branches needed for !needs_drop types.)

Nothing immediately jumps to mind for how to get LLVM to know that, though. Maybe try a separate if const { mem::needs_drop::<T>() } path that could avoid the take, and see if that helps? Or maybe there's a way to phrase this such that you compute the value to write in a local, then there's just one write of it back to self so LLVM just needs to merge the values instead of merging the stores?

I'd suggest copying the implementation to godbolt and playing around a bit there until you find an incantation that works.

@Soveu
Copy link
Contributor Author

Soveu commented Nov 29, 2024

I have tried some things when first writing this code, with no effect, but the idea with mem::needs_drop made me try again. I was able to make the branches very similar, making LLVM merge them :) Technically there is still a case, where clone is more expensive than move, but the type does not have drop(). Probably it doesn't happen often, but might need consideration.

    fn next(&mut self) -> Option<A> {
        let inner = self.inner.as_mut()?;
        let count = inner.count.get();

        if let Some(new_count) = NonZero::<usize>::new(count - 1) {
            let tmp = inner.element.clone();
            inner.count = new_count;
            return Some(tmp);
        }

        return if core::mem::needs_drop::<A>() {
            self.take_element()
        } else {
            let tmp = inner.element.clone();
            self.inner = None;
            Some(tmp)
        };
    }

Godbolt: https://rust.godbolt.org/z/Kr198x635

LLVM output:

define { i16, i16 } @iter_repeat_n_next(ptr noalias nocapture noundef align 8 dereferenceable(16) %it) unnamed_addr personality ptr @rust_eh_personality {
start:
  %0 = getelementptr inbounds i8, ptr %it, i64 8
  %1 = load i64, ptr %0, align 8
  %2 = icmp eq i64 %1, 0
  br i1 %2, label %"_ZN84_$LT$example..RepeatN$LT$A$GT$$u20$as$u20$core..iter..traits..iterator..Iterator$GT$4next17hbed8c0f5d41a7103E.exit", label %bb13.i

bb13.i:
  %count.i = add i64 %1, -1
  %3 = load i16, ptr %it, align 8
  store i64 %count.i, ptr %0, align 8
  br label %"_ZN84_$LT$example..RepeatN$LT$A$GT$$u20$as$u20$core..iter..traits..iterator..Iterator$GT$4next17hbed8c0f5d41a7103E.exit"

"_ZN84_$LT$example..RepeatN$LT$A$GT$$u20$as$u20$core..iter..traits..iterator..Iterator$GT$4next17hbed8c0f5d41a7103E.exit":
  %_0.sroa.6.0.i = phi i16 [ undef, %start ], [ %3, %bb13.i ]
  %_0.sroa.0.0.i = phi i16 [ 0, %start ], [ 1, %bb13.i ]
  %4 = insertvalue { i16, i16 } poison, i16 %_0.sroa.0.0.i, 0
  %5 = insertvalue { i16, i16 } %4, i16 %_0.sroa.6.0.i, 1
  ret { i16, i16 } %5
}

declare noundef range(i32 0, 10) i32 @rust_eh_personality(i32 noundef, i32 noundef range(i32 1, 17), i64 noundef, ptr noundef, ptr noundef) unnamed_addr #1

LLVM output for the current std implementation:

define { i16, i16 } @iter_repeat_n_next(ptr noalias nocapture noundef align 8 dereferenceable(16) %it) unnamed_addr {
start:
  %_3 = load i64, ptr %it, align 8
  %_2.not = icmp eq i64 %_3, 0
  br i1 %_2.not, label %bb4, label %bb1

bb1:
  %_2.i = add i64 %_3, -1
  store i64 %_2.i, ptr %it, align 8
  %0 = getelementptr inbounds i8, ptr %it, i64 8
  %result.i = load i16, ptr %0, align 8
  br label %bb4

bb4:
  %_0.sroa.3.0 = phi i16 [ %result.i, %bb1 ], [ undef, %start ]
  %_0.sroa.0.0 = phi i16 [ 1, %bb1 ], [ 0, %start ]
  %1 = insertvalue { i16, i16 } poison, i16 %_0.sroa.0.0, 0
  %2 = insertvalue { i16, i16 } %1, i16 %_0.sroa.3.0, 1
  ret { i16, i16 } %2
}

From what I see, %0 = getelementptr inbounds i8, ptr %it, i64 8 gets moved to the top

@Soveu
Copy link
Contributor Author

Soveu commented Nov 29, 2024

That is interesting, just switching variables made it work 🤔

    fn next(&mut self) -> Option<A> {
        let inner = self.inner.as_mut()?;
        let count = inner.count.get();

        if let Some(new_count) = NonZero::<usize>::new(count - 1) {
            // This must be in this order!
            let tmp = inner.element.clone();
            inner.count = new_count;
            return Some(tmp);
        }

        return self.take_element();
    }

@scottmcm
Copy link
Member

just switching variables made it work 🤔

Definitely odd, but that's why we have codegen tests :P

@rust-log-analyzer

This comment has been minimized.

@scottmcm
Copy link
Member

From what I see, %0 = getelementptr inbounds i8, ptr %it, i64 8 gets moved to the top

What that means is that it ended up getting a different layout -- originally it was storing the count at address, but apparently it flipped the order.

I don't have a strong feeling about which order is better, but if you want you could put #[repr(C)] // not stable just keeps the layout consistent for codegen tests on RepeatNInner to make it give you the order you want.

bors added a commit to rust-lang-ci/rust that referenced this pull request Nov 30, 2024
…epeatn, r=<try>

Use `iter::repeat_n` to implement `Vec::extend_with`

This replaces the `Vec::extend_with` manual implementation, which is used by `Vec::resize` and `Vec` `SpecFromElem`, with `iter::repeat_n`.

I've compared the codegen output between:

1. the current `Vec::resize` impl
2. this branch
3. this branch + rust-lang#130887

3 gives the closest codegen output to 1, with some output improvements. 2 doesn't look good: https://rust.godbolt.org/z/Yrc83EhjY.
May also help rust-lang#120050?
@Soveu
Copy link
Contributor Author

Soveu commented Nov 30, 2024

@scottmcm @Amanieu its ready

@Soveu
Copy link
Contributor Author

Soveu commented Nov 30, 2024

@rustbot label +S-waiting-on-review -S-waiting-on-author

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Nov 30, 2024
bors added a commit to rust-lang-ci/rust that referenced this pull request Dec 1, 2024
…epeatn, r=<try>

Use `iter::repeat_n` to implement `Vec::extend_with`

This replaces the `Vec::extend_with` manual implementation, which is used by `Vec::resize` and `Vec` `SpecFromElem`, with `iter::repeat_n`.

I've compared the codegen output between:

1. the current `Vec::resize` impl
2. this branch
3. this branch + rust-lang#130887

3 gives the closest codegen output to 1, with some output improvements. 2 doesn't look good: https://rust.godbolt.org/z/Yrc83EhjY.
May also help rust-lang#120050?

---

WARNING: DO NOT MERGE - in order to run the perf run in rust-lang#133662 (comment) this PR currently also contains commits from rust-lang#130887
@paolobarbolini
Copy link
Contributor

FYI we're also playing around with this change at #133662 since Compiler Explorer showed that the two MRs combined made Vec::resize slightly better. We'll see how the perf run goes.

@Folyd
Copy link
Contributor

Folyd commented Dec 1, 2024

Nice, this reminds me of my article on Rust Magazine: VecDeque::resize() optimization
.

@scottmcm
Copy link
Member

Thanks! I still hope that one day we have have a never-undef version of this, but this sounds good until then.

@bors r+ rollup=iffy (just because codegen tests can always be finickity)

@bors
Copy link
Collaborator

bors commented May 16, 2025

📌 Commit 5202d41 has been approved by scottmcm

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 16, 2025
bors added a commit to rust-lang-ci/rust that referenced this pull request May 16, 2025
Safer implementation of RepeatN

I've seen the "Use MaybeUninit for RepeatN" commit while reading This Week In Rust and immediately thought about something I've written some time ago - https://github.com/Soveu/repeat_finite/blob/master/src/lib.rs.

Using the fact, that `Option` will find niche in `(T, NonZeroUsize)`, we can construct something that has the same size as `(T, usize)` while completely getting rid of `MaybeUninit`.
This leaves only `unsafe` on `TrustedLen`, which is pretty neat.
@bors
Copy link
Collaborator

bors commented May 16, 2025

⌛ Testing commit 5202d41 with merge 1c48265...

@rust-log-analyzer

This comment has been minimized.

@bors
Copy link
Collaborator

bors commented May 16, 2025

💔 Test failed - checks-actions

@bors bors added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels May 16, 2025
@Soveu
Copy link
Contributor Author

Soveu commented May 17, 2025

@scottmcm sorry, I did not notice, that codegen does not run on stage 0 tests (ran only ./x.py test --stage 0 library)... but on the good side, it was only a reorder of one instruction.

@scottmcm
Copy link
Member

Ah, no CHECK changes in the test is even better :)

@bors r+

@bors
Copy link
Collaborator

bors commented May 18, 2025

📌 Commit 20608d9 has been approved by scottmcm

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 18, 2025
@scottmcm
Copy link
Member

that codegen does not run on stage 0 tests (ran only ./x.py test --stage 0 library)

This is not a stage 0 problem, this is a problem that the codegen tests are x.py test tests/codegen.

fmease added a commit to fmease/rust that referenced this pull request May 18, 2025
Safer implementation of RepeatN

I've seen the "Use MaybeUninit for RepeatN" commit while reading This Week In Rust and immediately thought about something I've written some time ago - https://github.com/Soveu/repeat_finite/blob/master/src/lib.rs.

Using the fact, that `Option` will find niche in `(T, NonZeroUsize)`, we can construct something that has the same size as `(T, usize)` while completely getting rid of `MaybeUninit`.
This leaves only `unsafe` on `TrustedLen`, which is pretty neat.
bors added a commit to rust-lang-ci/rust that referenced this pull request May 18, 2025
Rollup of 6 pull requests

Successful merges:

 - rust-lang#127013 (Add `f16` formatting and parsing)
 - rust-lang#130887 (Safer implementation of RepeatN)
 - rust-lang#140154 (Cygwin support in rustc)
 - rust-lang#140874 (make `rustc_attr_parsing` less dominant in the rustc crate graph)
 - rust-lang#141094 (add regression test for rust-lang#101650)
 - rust-lang#141110 ([std] fix the presentation of `split_off_mut` and `split_off` documentation)

r? `@ghost`
`@rustbot` modify labels: rollup
@fmease
Copy link
Member

fmease commented May 18, 2025

Failed in rollup: #141233 (comment) (x86_64-gnu-distcheck)
@bors r-

@bors bors added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels May 18, 2025
@fmease
Copy link
Member

fmease commented May 18, 2025

(x86_64-gnu-distcheck) @bors try

@bors
Copy link
Collaborator

bors commented May 18, 2025

⌛ Trying commit 20608d9 with merge e3450c6...

bors added a commit to rust-lang-ci/rust that referenced this pull request May 18, 2025
Safer implementation of RepeatN

I've seen the "Use MaybeUninit for RepeatN" commit while reading This Week In Rust and immediately thought about something I've written some time ago - https://github.com/Soveu/repeat_finite/blob/master/src/lib.rs.

Using the fact, that `Option` will find niche in `(T, NonZeroUsize)`, we can construct something that has the same size as `(T, usize)` while completely getting rid of `MaybeUninit`.
This leaves only `unsafe` on `TrustedLen`, which is pretty neat.

try-job: x86_64-gnu-distcheck
@rust-log-analyzer
Copy link
Collaborator

The job x86_64-gnu-distcheck failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
file:.git/config remote.origin.url=https://github.com/rust-lang-ci/rust
file:.git/config remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
file:.git/config gc.auto=0
file:.git/config http.https://github.com/.extraheader=AUTHORIZATION: basic ***
file:.git/config branch.try.remote=origin
file:.git/config branch.try.merge=refs/heads/try
file:.git/config submodule.library/backtrace.active=true
file:.git/config submodule.library/backtrace.url=https://github.com/rust-lang/backtrace-rs.git
file:.git/config submodule.library/stdarch.active=true
file:.git/config submodule.library/stdarch.url=https://github.com/rust-lang/stdarch.git
file:.git/config submodule.src/doc/book.active=true
---
failures:

---- [codegen] tests/codegen/iter-repeat-n-trivial-drop.rs stdout ----

error: verification with 'FileCheck' failed
status: exit status: 1
command: "/checkout/obj/build/tmp/distcheck/build/x86_64-unknown-linux-gnu/llvm/build/bin/FileCheck" "--input-file" "/checkout/obj/build/tmp/distcheck/build/x86_64-unknown-linux-gnu/test/codegen/iter-repeat-n-trivial-drop/iter-repeat-n-trivial-drop.ll" "/checkout/tests/codegen/iter-repeat-n-trivial-drop.rs" "--check-prefix=CHECK" "--allow-unused-prefixes" "--dump-input-context" "100"
stdout: none
--- stderr -------------------------------
/checkout/tests/codegen/iter-repeat-n-trivial-drop.rs:29:17: error: CHECK-NEXT: is not on the line after the previous match
 // CHECK-NEXT: %[[DEC:.+]] = add i64 %[[COUNT]], -1
                ^
/checkout/obj/build/tmp/distcheck/build/x86_64-unknown-linux-gnu/test/codegen/iter-repeat-n-trivial-drop/iter-repeat-n-trivial-drop.ll:19:2: note: 'next' match was here
 %2 = add i64 %0, -1
 ^
/checkout/obj/build/tmp/distcheck/build/x86_64-unknown-linux-gnu/test/codegen/iter-repeat-n-trivial-drop/iter-repeat-n-trivial-drop.ll:17:7: note: previous match ended here
bb8.i: ; preds = %start
      ^
/checkout/obj/build/tmp/distcheck/build/x86_64-unknown-linux-gnu/test/codegen/iter-repeat-n-trivial-drop/iter-repeat-n-trivial-drop.ll:18:1: note: non-matching line after previous match is here
 %1 = getelementptr inbounds nuw i8, ptr %it, i64 8
^

Input file: /checkout/obj/build/tmp/distcheck/build/x86_64-unknown-linux-gnu/test/codegen/iter-repeat-n-trivial-drop/iter-repeat-n-trivial-drop.ll
Check file: /checkout/tests/codegen/iter-repeat-n-trivial-drop.rs

-dump-input=help explains the following input dump.

Input was:
<<<<<<
         1: ; ModuleID = 'iter_repeat_n_trivial_drop.80fa96dad9145ebd-cgu.0' 
         2: source_filename = "iter_repeat_n_trivial_drop.80fa96dad9145ebd-cgu.0" 
         3: target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" 
         4: target triple = "x86_64-unknown-linux-gnu" 
         5:  
         6: @__rust_no_alloc_shim_is_unstable = external global i8 
         7: @alloc_3e3222eab6a509f29fa54d8acd188f56 = private unnamed_addr constant [53 x i8] c"/checkout/tests/codegen/iter-repeat-n-trivial-drop.rs", align 1 
         8: @alloc_8e75433513d2c9e77591417f09572823 = private unnamed_addr constant <{ ptr, [16 x i8] }> <{ ptr @alloc_3e3222eab6a509f29fa54d8acd188f56, [16 x i8] c"5\00\00\00\00\00\00\007\00\00\00\11\00\00\00" }>, align 8 
         9:  
        10: ; Function Attrs: mustprogress nofree norecurse nosync nounwind nonlazybind willreturn memory(argmem: readwrite) uwtable 
        11: define { i16, i16 } @iter_repeat_n_next(ptr noalias nocapture noundef align 8 dereferenceable(16) %it) unnamed_addr #0 { 
        12: start: 
        13:  %0 = load i64, ptr %it, align 8, !alias.scope !3, !noundef !6 
        14:  %.not.i = icmp eq i64 %0, 0 
        15:  br i1 %.not.i, label %"_ZN106_$LT$core..iter..sources..repeat_n..RepeatN$LT$A$GT$$u20$as$u20$core..iter..traits..iterator..Iterator$GT$4next17heba7fa00778d1756E.exit", label %bb8.i 
        16:  
        17: bb8.i: ; preds = %start 
        18:  %1 = getelementptr inbounds nuw i8, ptr %it, i64 8 
        19:  %2 = add i64 %0, -1 
next:29      !~~~~~~~~~~~~~~~~~~  error: match on wrong line
        20:  %3 = load i16, ptr %1, align 8, !alias.scope !3 
        21:  store i64 %2, ptr %it, align 8, !alias.scope !3 
        22:  br label %"_ZN106_$LT$core..iter..sources..repeat_n..RepeatN$LT$A$GT$$u20$as$u20$core..iter..traits..iterator..Iterator$GT$4next17heba7fa00778d1756E.exit" 
        23:  
        24: "_ZN106_$LT$core..iter..sources..repeat_n..RepeatN$LT$A$GT$$u20$as$u20$core..iter..traits..iterator..Iterator$GT$4next17heba7fa00778d1756E.exit": ; preds = %start, %bb8.i 
        25:  %_0.sroa.5.0.i = phi i16 [ undef, %start ], [ %3, %bb8.i ] 
        26:  %_0.sroa.0.0.i = phi i16 [ 0, %start ], [ 1, %bb8.i ] 
        27:  %4 = insertvalue { i16, i16 } poison, i16 %_0.sroa.0.0.i, 0 
        28:  %5 = insertvalue { i16, i16 } %4, i16 %_0.sroa.5.0.i, 1 
        29:  ret { i16, i16 } %5 
        30: } 
        31:  
        32: ; Function Attrs: nonlazybind uwtable 
        33: define void @vec_extend_via_iter_repeat_n(ptr dead_on_unwind noalias nocapture noundef writable writeonly sret([24 x i8]) align 8 dereferenceable(24) %_0) unnamed_addr #1 personality ptr @rust_eh_personality { 
        34: start: 
        35:  %0 = load volatile i8, ptr @__rust_no_alloc_shim_is_unstable, align 1, !noalias !7 
        36: ; call __rustc::__rust_alloc 
        37:  %_0.i.i.i.i.i = tail call noalias noundef dereferenceable_or_null(1234) ptr @_RNvCsjo78DlXnSdE_7___rustc12___rust_alloc(i64 noundef range(i64 1, 0) 1234, i64 noundef range(i64 1, -9223372036854775807) 1) #7, !noalias !7 
        38:  %1 = icmp eq ptr %_0.i.i.i.i.i, null 
        39:  br i1 %1, label %bb3.i, label %"_ZN5alloc7raw_vec20RawVecInner$LT$A$GT$16with_capacity_in17h498ad11235a8f418E.exit", !prof !10 
        40:  
        41: bb3.i: ; preds = %start 
        42: ; call alloc::raw_vec::handle_error 
        43:  tail call void @_ZN5alloc7raw_vec12handle_error17hd59783746b703129E(i64 noundef 1, i64 1234, ptr noalias noundef nonnull readonly align 8 dereferenceable(24) @alloc_8e75433513d2c9e77591417f09572823) #8 
        44:  unreachable 
        45:  
        46: "_ZN5alloc7raw_vec20RawVecInner$LT$A$GT$16with_capacity_in17h498ad11235a8f418E.exit": ; preds = %start 
        47:  tail call void @llvm.memset.p0.i64(ptr noundef nonnull align 1 dereferenceable(1234) %_0.i.i.i.i.i, i8 42, i64 1234, i1 false), !noalias !11 
        48:  store i64 1234, ptr %_0, align 8 
        49:  %v.sroa.4.0._0.sroa_idx = getelementptr inbounds nuw i8, ptr %_0, i64 8 
        50:  store ptr %_0.i.i.i.i.i, ptr %v.sroa.4.0._0.sroa_idx, align 8 
        51:  %v.sroa.5.0._0.sroa_idx = getelementptr inbounds nuw i8, ptr %_0, i64 16 
        52:  store i64 1234, ptr %v.sroa.5.0._0.sroa_idx, align 8 
        53:  ret void 
        54: } 
        55:  
        56: ; Function Attrs: mustprogress nofree norecurse nosync nounwind nonlazybind willreturn memory(argmem: write) uwtable 
        57: define void @array_repeat_not_copy(ptr dead_on_unwind noalias nocapture noundef writable writeonly sret([16 x i8]) align 2 dereferenceable(16) initializes((0, 16)) %_0, i16 noundef %item) unnamed_addr #2 personality ptr @rust_eh_personality { 
        58: start: 
        59:  %0 = insertelement <8 x i16> poison, i16 %item, i64 0 
        60:  %1 = shufflevector <8 x i16> %0, <8 x i16> poison, <8 x i32> zeroinitializer 
        61:  store <8 x i16> %1, ptr %_0, align 2, !alias.scope !22 
        62:  ret void 
        63: } 
        64:  
        65: ; Function Attrs: nounwind nonlazybind uwtable 
        66: declare noundef range(i32 0, 10) i32 @rust_eh_personality(i32 noundef, i32 noundef, i64 noundef, ptr noundef, ptr noundef) unnamed_addr #3 
        67:  
        68: ; Function Attrs: mustprogress nocallback nofree nounwind willreturn memory(argmem: write) 
        69: declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #4 
        70:  
        71: ; __rustc::__rust_alloc 
        72: ; Function Attrs: nounwind nonlazybind allockind("alloc,uninitialized,aligned") allocsize(0) uwtable 
        73: declare noalias noundef ptr @_RNvCsjo78DlXnSdE_7___rustc12___rust_alloc(i64 noundef, i64 allocalign noundef) unnamed_addr #5 
        74:  
        75: ; alloc::raw_vec::handle_error 
        76: ; Function Attrs: cold minsize noreturn nonlazybind optsize uwtable 
        77: declare void @_ZN5alloc7raw_vec12handle_error17hd59783746b703129E(i64 noundef range(i64 0, -9223372036854775807), i64, ptr noalias noundef readonly align 8 dereferenceable(24)) unnamed_addr #6 
        78:  
        79: attributes #0 = { mustprogress nofree norecurse nosync nounwind nonlazybind willreturn memory(argmem: readwrite) uwtable "probe-stack"="inline-asm" "target-cpu"="x86-64" } 
        80: attributes #1 = { nonlazybind uwtable "probe-stack"="inline-asm" "target-cpu"="x86-64" } 
        81: attributes #2 = { mustprogress nofree norecurse nosync nounwind nonlazybind willreturn memory(argmem: write) uwtable "probe-stack"="inline-asm" "target-cpu"="x86-64" } 
        82: attributes #3 = { nounwind nonlazybind uwtable "probe-stack"="inline-asm" "target-cpu"="x86-64" } 
        83: attributes #4 = { mustprogress nocallback nofree nounwind willreturn memory(argmem: write) } 
        84: attributes #5 = { nounwind nonlazybind allockind("alloc,uninitialized,aligned") allocsize(0) uwtable "alloc-family"="__rust_alloc" "probe-stack"="inline-asm" "target-cpu"="x86-64" } 
        85: attributes #6 = { cold minsize noreturn nonlazybind optsize uwtable "probe-stack"="inline-asm" "target-cpu"="x86-64" } 
        86: attributes #7 = { nounwind } 
        87: attributes #8 = { noreturn } 
        88:  
        89: !llvm.module.flags = !{!0, !1} 
        90: !llvm.ident = !{!2} 
        91:  
        92: !0 = !{i32 8, !"PIC Level", i32 2} 
        93: !1 = !{i32 2, !"RtLibUseGOT", i32 1} 
        94: !2 = !{!"rustc version 1.89.0-nightly (e3450c663 2025-05-18)"} 
        95: !3 = !{!4} 
        96: !4 = distinct !{!4, !5, !"_ZN106_$LT$core..iter..sources..repeat_n..RepeatN$LT$A$GT$$u20$as$u20$core..iter..traits..iterator..Iterator$GT$4next17heba7fa00778d1756E: %self"} 
        97: !5 = distinct !{!5, !"_ZN106_$LT$core..iter..sources..repeat_n..RepeatN$LT$A$GT$$u20$as$u20$core..iter..traits..iterator..Iterator$GT$4next17heba7fa00778d1756E"} 
        98: !6 = !{} 
        99: !7 = !{!8} 
       100: !8 = distinct !{!8, !9, !"_ZN5alloc7raw_vec20RawVecInner$LT$A$GT$15try_allocate_in17h1d0abe0eaac5cb74E: %_0"} 
       101: !9 = distinct !{!9, !"_ZN5alloc7raw_vec20RawVecInner$LT$A$GT$15try_allocate_in17h1d0abe0eaac5cb74E"} 
       102: !10 = !{!"branch_weights", !"expected", i32 1, i32 2000} 
       103: !11 = !{!12, !14, !16, !18, !20} 
       104: !12 = distinct !{!12, !13, !"_ZN5alloc3vec16Vec$LT$T$C$A$GT$14extend_trusted28_$u7b$$u7b$closure$u7d$$u7d$17h14916368b119472bE: %_1"} 
       105: !13 = distinct !{!13, !"_ZN5alloc3vec16Vec$LT$T$C$A$GT$14extend_trusted28_$u7b$$u7b$closure$u7d$$u7d$17h14916368b119472bE"} 
       106: !14 = distinct !{!14, !15, !"_ZN4core4iter6traits8iterator8Iterator8for_each4call28_$u7b$$u7b$closure$u7d$$u7d$17h5cebcb0e7eac5245E: %_1"} 
       107: !15 = distinct !{!15, !"_ZN4core4iter6traits8iterator8Iterator8for_each4call28_$u7b$$u7b$closure$u7d$$u7d$17h5cebcb0e7eac5245E"} 
       108: !16 = distinct !{!16, !17, !"_ZN4core4iter6traits8iterator8Iterator4fold17h9c2cd72caea4a765E: %f"} 
       109: !17 = distinct !{!17, !"_ZN4core4iter6traits8iterator8Iterator4fold17h9c2cd72caea4a765E"} 
       110: !18 = distinct !{!18, !19, !"_ZN4core4iter6traits8iterator8Iterator8for_each17h6ce1cc66fb1a96dcE: %f"} 
       111: !19 = distinct !{!19, !"_ZN4core4iter6traits8iterator8Iterator8for_each17h6ce1cc66fb1a96dcE"} 
       112: !20 = distinct !{!20, !21, !"_ZN5alloc3vec16Vec$LT$T$C$A$GT$14extend_trusted17hd89c82a637bae73fE: %self"} 
       113: !21 = distinct !{!21, !"_ZN5alloc3vec16Vec$LT$T$C$A$GT$14extend_trusted17hd89c82a637bae73fE"} 
       114: !22 = !{!23} 
       115: !23 = distinct !{!23, !24, !"_ZN4core5array6repeat17h812607a4e0a9affaE: %_0"} 
       116: !24 = distinct !{!24, !"_ZN4core5array6repeat17h812607a4e0a9affaE"} 
>>>>>>
------------------------------------------



failures:
    [codegen] tests/codegen/iter-repeat-n-trivial-drop.rs

test result: FAILED. 764 passed; 1 failed; 85 ignored; 0 measured; 0 filtered out; finished in 9.38s

Some tests failed in compiletest suite=codegen mode=codegen host=x86_64-unknown-linux-gnu target=x86_64-unknown-linux-gnu
Build completed unsuccessfully in 0:38:01
make: *** [Makefile:49: check] Error 1
Command has failed. Rerun with -v to see more details.
Build completed unsuccessfully in 0:43:43
  local time: Sun May 18 22:28:39 UTC 2025
  network time: Sun, 18 May 2025 22:28:40 GMT
##[error]Process completed with exit code 1.
Post job cleanup.

@bors
Copy link
Collaborator

bors commented May 18, 2025

💔 Test failed - checks-actions

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-libs Relevant to the library team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.