Skip to content

Conversation

rluvaton
Copy link

@rluvaton rluvaton commented Sep 20, 2025

I noticed that this was not inlined when trying to push and probably the reason why the compiler lose the information about the capacity (fixes #82801) - is there a way I can test that to make sure the issue is fixed?

BTW The original PR that added it (#91352) wrote:

[...] I tried lots of minor variations on this, e.g. different inlining
attributes. This was the best one I could find. [...]

I never contributed to Rust so I did not know how to test that it actually fixes the problem, but I'm fairly certain it is.

Consider the very basic example (Godbolt rustc 1.90.0 -C opt-level=3 -C target-feature=+avx2 -C codegen-units=1)

#[no_mangle]
fn extend_offsets(offsets: &[usize]) -> Vec::<usize> {
    let mut intermediate = Vec::<usize>::with_capacity(offsets.len());

    for &offset in offsets {
        intermediate.push(offset + 1)
    }

    intermediate
}

it does not inline grow_one which make it not use SIMD.

If however we are using push_within_capacity:

#![feature(vec_push_within_capacity)]

#[no_mangle]
fn extend_offsets(offsets: &[usize]) -> Vec::<usize> {
    let mut intermediate = Vec::<usize>::with_capacity(offsets.len());

    for &offset in offsets {
        intermediate.push_within_capacity(offset + 1).unwrap()
    }

    intermediate
}

it will use SIMD

I noticed that this was not inlined when trying to `push` and probably the reason why the compiler lose the information about the capacity (fixes rust-lang#82801)

BTW The original PR that added it (rust-lang#91352) wrote:
> [...] I tried lots of minor variations on this, e.g. different inlining
attributes. This was the best one I could find. [...]

I never contributed to Rust so I did not know how to test that it actually fixes the problem, but I'm fairly certain it is.

Consider the very basic example (Godbolt rustc 1.90.0 `-C opt-level=3 -C target-feature=+avx2 -C codegen-units=1`) 
```rust
#[no_mangle]
fn extend_offsets(offsets: &[usize]) -> Vec::<usize> {
    let mut intermediate = Vec::<usize>::with_capacity(offsets.len());

    for &offset in offsets {
        intermediate.push(offset)
    }

    intermediate
}
```

it does not inline `grow_one` which make it not use SIMD.

If however we are using [`push_within_capacity`](rust-lang#100486):

```rust
#![feature(vec_push_within_capacity)]

#[no_mangle]
fn extend_offsets(offsets: &[usize]) -> Vec::<usize> {
    let mut intermediate = Vec::<usize>::with_capacity(offsets.len());

    for &offset in offsets {
        intermediate.push_within_capacity(offset).unwrap()
    }

    intermediate
}
```

it will use SIMD
@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 20, 2025
@rustbot
Copy link
Collaborator

rustbot commented Sep 20, 2025

r? @tgross35

rustbot has assigned @tgross35.
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

@saethlin
Copy link
Member

@bors try @rust-timer queue

@rust-timer

This comment has been minimized.

@rust-bors

This comment has been minimized.

rust-bors bot added a commit that referenced this pull request Sep 20, 2025
perf: change `RawVec` `grow_one` from `#[inline(never)]` to `#[inline]`
@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Sep 20, 2025
@rust-log-analyzer
Copy link
Collaborator

The job aarch64-gnu-llvm-20-1 failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)

---- [codegen] tests/codegen-llvm/vec-len-invariant.rs stdout ----
------FileCheck stdout------------------------------

------FileCheck stderr------------------------------
/checkout/tests/codegen-llvm/vec-len-invariant.rs:12:12: error: CHECK: expected string not found in input
 // CHECK: call {{.*}}grow_one
           ^
/checkout/obj/build/aarch64-unknown-linux-gnu/test/codegen-llvm/vec-len-invariant/vec-len-invariant.ll:123:19: note: scanning from here
 %len.i = load i64, ptr %0, align 8, !alias.scope !6, !noundef !3
                  ^
/checkout/obj/build/aarch64-unknown-linux-gnu/test/codegen-llvm/vec-len-invariant/vec-len-invariant.ll:157:6: note: possible intended match here
; call alloc::raw_vec::finish_grow
     ^

Input file: /checkout/obj/build/aarch64-unknown-linux-gnu/test/codegen-llvm/vec-len-invariant/vec-len-invariant.ll
Check file: /checkout/tests/codegen-llvm/vec-len-invariant.rs

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

Input was:
<<<<<<
            .
            .
            .
           23:  %2 = getelementptr inbounds nuw i8, ptr %current_memory, i64 8 
           24:  %3 = load i64, ptr %2, align 8, !range !2, !noundef !3 
           25:  %.not = icmp eq i64 %3, 0 
           26:  br i1 %.not, label %bb5, label %bb1 
           27:  
           28: bb1: ; preds = %start 
           29:  %ptr = load ptr, ptr %current_memory, align 8, !nonnull !3, !noundef !3 
           30:  %4 = getelementptr inbounds nuw i8, ptr %current_memory, i64 16 
           31:  %5 = load i64, ptr %4, align 8, !noundef !3 
           32:  store i64 %3, ptr %_9, align 8 
           33:  store i64 %0, ptr %_12, align 8 
           34:  %_14 = icmp eq i64 %3, %0 
           35:  br i1 %_14, label %bb2, label %bb3, !prof !4 
           36:  
           37: bb5: ; preds = %start 
           38:  %6 = icmp eq i64 %1, 0 
           39:  br i1 %6, label %bb2.i.i, label %bb4.i.i 
           40:  
           41: bb2.i.i: ; preds = %bb5 
           42:  %_19.i.i = getelementptr i8, ptr null, i64 %0 
           43:  br label %bb7 
           44:  
           45: bb4.i.i: ; preds = %bb5 
           46: ; call __rustc::__rust_no_alloc_shim_is_unstable_v2 
           47:  tail call void @_RNvCsluNeYmp3Xm3_7___rustc35___rust_no_alloc_shim_is_unstable_v2() #11 
           48: ; call __rustc::__rust_alloc 
           49:  %7 = tail call noundef ptr @_RNvCsluNeYmp3Xm3_7___rustc12___rust_alloc(i64 noundef %1, i64 noundef range(i64 1, -9223372036854775807) %0) #11 
           50:  br label %bb7 
           51:  
           52: bb3: ; preds = %bb1 
           53:  call void @llvm.lifetime.start.p0(i64 48, ptr nonnull %_16) 
           54:  store ptr null, ptr %_16, align 8 
           55: ; call core::panicking::assert_failed 
           56:  call void @_ZN4core9panicking13assert_failed17hc671a3ed0aea6677E(i8 noundef 0, ptr noalias noundef nonnull readonly align 8 dereferenceable(8) %_9, ptr noalias noundef nonnull readonly align 8 dereferenceable(8) %_12, ptr noalias noundef nonnull align 8 dereferenceable(48) %_16, ptr noalias noundef nonnull readonly align 8 dereferenceable(24) @alloc_60b3217ab254a473df4c758b54d2e808) #12 
           57:  unreachable 
           58:  
           59: bb2: ; preds = %bb1 
           60:  %_6.not.i.i = icmp ult i64 %1, %5 
           61:  br i1 %_6.not.i.i, label %bb2.i.i13, label %bb1.i.i, !prof !5 
           62:  
           63: bb2.i.i13: ; preds = %bb2 
           64:  call void @llvm.lifetime.start.p0(i64 48, ptr nonnull %_12.i.i) 
           65:  store ptr @alloc_04056f6d76887c0653320aca2f1cbe49, ptr %_12.i.i, align 8 
           66:  %8 = getelementptr inbounds nuw i8, ptr %_12.i.i, i64 8 
           67:  store i64 1, ptr %8, align 8 
           68:  %9 = getelementptr inbounds nuw i8, ptr %_12.i.i, i64 16 
           69:  store ptr null, ptr %9, align 8 
           70:  %10 = getelementptr inbounds nuw i8, ptr %_12.i.i, i64 32 
           71:  store ptr inttoptr (i64 8 to ptr), ptr %10, align 8 
           72:  %11 = getelementptr inbounds nuw i8, ptr %_12.i.i, i64 40 
           73:  store i64 0, ptr %11, align 8 
           74: ; call core::panicking::panic_fmt 
           75:  call void @_ZN4core9panicking9panic_fmt17hc0fa719bc544a225E(ptr noalias noundef nonnull readonly align 8 dereferenceable(48) %_12.i.i, ptr noalias noundef nonnull readonly align 8 dereferenceable(24) @alloc_f8c5c844aa69054ab9d96ab1c41933fc) #12 
           76:  unreachable 
           77:  
           78: bb1.i.i: ; preds = %bb2 
           79:  %12 = icmp eq i64 %5, 0 
           80:  br i1 %12, label %bb4.i.i12, label %bb5.i.i 
           81:  
           82: bb4.i.i12: ; preds = %bb1.i.i 
           83:  %13 = icmp eq i64 %1, 0 
           84:  br i1 %13, label %bb2.i.i.i, label %bb4.i.i.i 
           85:  
           86: bb2.i.i.i: ; preds = %bb4.i.i12 
           87:  %_19.i.i.i = getelementptr i8, ptr null, i64 %0 
           88:  br label %bb7 
           89:  
           90: bb4.i.i.i: ; preds = %bb4.i.i12 
           91: ; call __rustc::__rust_no_alloc_shim_is_unstable_v2 
           92:  tail call void @_RNvCsluNeYmp3Xm3_7___rustc35___rust_no_alloc_shim_is_unstable_v2() #11 
           93: ; call __rustc::__rust_alloc 
           94:  %14 = tail call noundef ptr @_RNvCsluNeYmp3Xm3_7___rustc12___rust_alloc(i64 noundef %1, i64 noundef range(i64 1, -9223372036854775807) %0) #11 
           95:  br label %bb7 
           96:  
           97: bb5.i.i: ; preds = %bb1.i.i 
           98: ; call __rustc::__rust_realloc 
           99:  %15 = tail call noundef ptr @_RNvCsluNeYmp3Xm3_7___rustc14___rust_realloc(ptr noundef nonnull %ptr, i64 noundef %5, i64 noundef range(i64 1, -9223372036854775807) %0, i64 noundef %1) #11 
          100:  br label %bb7 
          101:  
          102: bb7: ; preds = %bb5.i.i, %bb4.i.i.i, %bb2.i.i.i, %bb4.i.i, %bb2.i.i 
          103:  %_0.sroa.0.0.i.i11.pn = phi ptr [ %_19.i.i, %bb2.i.i ], [ %7, %bb4.i.i ], [ %15, %bb5.i.i ], [ %_19.i.i.i, %bb2.i.i.i ], [ %14, %bb4.i.i.i ] 
          104:  %16 = icmp eq ptr %_0.sroa.0.0.i.i11.pn, null 
          105:  %17 = inttoptr i64 %0 to ptr 
          106:  %spec.select = select i1 %16, ptr %17, ptr %_0.sroa.0.0.i.i11.pn 
          107:  %spec.select4 = zext i1 %16 to i64 
          108:  %18 = getelementptr inbounds nuw i8, ptr %_0, i64 8 
          109:  store ptr %spec.select, ptr %18, align 8 
          110:  %19 = getelementptr inbounds nuw i8, ptr %_0, i64 16 
          111:  store i64 %1, ptr %19, align 8 
          112:  store i64 %spec.select4, ptr %_0, align 8 
          113:  ret void 
          114: } 
          115:  
          116: ; Function Attrs: uwtable 
          117: define void @should_load_once(ptr noalias nocapture noundef align 8 dereferenceable(24) %v) unnamed_addr #1 personality ptr @rust_eh_personality { 
          118: start: 
          119:  %_29.i.i = alloca [24 x i8], align 8 
          120:  %self5.i.i = alloca [24 x i8], align 8 
          121:  tail call void @llvm.experimental.noalias.scope.decl(metadata !6) 
          122:  %0 = getelementptr inbounds nuw i8, ptr %v, i64 16 
          123:  %len.i = load i64, ptr %0, align 8, !alias.scope !6, !noundef !3 
check:12'0                       X~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: no match found
          124:  %1 = getelementptr inbounds nuw i8, ptr %v, i64 8 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          125:  %self1.i = load i64, ptr %1, align 8, !range !9, !alias.scope !6, !noundef !3 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          126:  %_4.i = icmp eq i64 %len.i, %self1.i 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          127:  br i1 %_4.i, label %bb1.i, label %start.bb3_crit_edge.i 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          128:  
check:12'0     ~
          129: start.bb3_crit_edge.i: ; preds = %start 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          130:  %_24.pre.i = load ptr, ptr %v, align 8, !alias.scope !6 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          131:  br label %"_ZN5alloc3vec16Vec$LT$T$C$A$GT$8push_mut17h2c3392560117356eE.exit" 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          132:  
check:12'0     ~
          133: bb1.i: ; preds = %start 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~
          134:  tail call void @llvm.experimental.noalias.scope.decl(metadata !10) 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          135:  %2 = shl nuw i64 %len.i, 1 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          136:  %3 = tail call i64 @llvm.umax.i64(i64 %2, i64 8) 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          137:  %_26.i.i.i = icmp slt i64 %3, 0 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          138:  br i1 %_26.i.i.i, label %bb12.i, label %bb25.i.i, !prof !13 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          139:  
check:12'0     ~
          140: bb25.i.i: ; preds = %bb1.i 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
          141:  call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %self5.i.i), !noalias !14 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          142:  call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %_29.i.i), !noalias !14 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          143:  %4 = icmp eq i64 %len.i, 0 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          144:  br i1 %4, label %"_ZN5alloc7raw_vec20RawVecInner$LT$A$GT$14current_memory17h84d95bdf5b34909dE.exit.i.i", label %bb4.i.i.i 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          145:  
check:12'0     ~
          146: bb4.i.i.i: ; preds = %bb25.i.i 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          147:  %self.val.i.i = load ptr, ptr %v, align 8, !alias.scope !14, !nonnull !3, !noundef !3 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          148:  store ptr %self.val.i.i, ptr %_29.i.i, align 8, !alias.scope !15, !noalias !14 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          149:  %_15.sroa.5.0._0.sroa_idx.i.i.i = getelementptr inbounds nuw i8, ptr %_29.i.i, i64 16 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          150:  store i64 %len.i, ptr %_15.sroa.5.0._0.sroa_idx.i.i.i, align 8, !alias.scope !15, !noalias !14 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          151:  br label %"_ZN5alloc7raw_vec20RawVecInner$LT$A$GT$14current_memory17h84d95bdf5b34909dE.exit.i.i" 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          152:  
check:12'0     ~
          153: "_ZN5alloc7raw_vec20RawVecInner$LT$A$GT$14current_memory17h84d95bdf5b34909dE.exit.i.i": ; preds = %bb4.i.i.i, %bb25.i.i 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          154:  %.sink.i.i.i = phi i64 [ 1, %bb4.i.i.i ], [ 0, %bb25.i.i ] 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          155:  %5 = getelementptr inbounds nuw i8, ptr %_29.i.i, i64 8 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          156:  store i64 %.sink.i.i.i, ptr %5, align 8, !alias.scope !15, !noalias !14 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          157: ; call alloc::raw_vec::finish_grow 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
check:12'1          ?                              possible intended match
          158:  call fastcc void @_ZN5alloc7raw_vec11finish_grow17h598902a8a8510760E(ptr noalias noundef align 8 dereferenceable(24) %self5.i.i, i64 noundef 1, i64 noundef %3, ptr noalias noundef readonly align 8 dereferenceable(24) %_29.i.i), !noalias !14 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          159:  call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %_29.i.i), !noalias !14 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          160:  %_56.i.i = load i64, ptr %self5.i.i, align 8, !range !18, !noalias !14, !noundef !3 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          161:  %6 = trunc nuw i64 %_56.i.i to i1 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          162:  %7 = getelementptr inbounds nuw i8, ptr %self5.i.i, i64 8 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          163:  br i1 %6, label %bb26.i.i, label %"_ZN5alloc7raw_vec20RawVecInner$LT$A$GT$14grow_amortized17h6d61f7b4f2838582E.exit.i" 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          164:  
check:12'0     ~
          165: bb26.i.i: ; preds = %"_ZN5alloc7raw_vec20RawVecInner$LT$A$GT$14current_memory17h84d95bdf5b34909dE.exit.i.i" 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          166:  %e.0.i.i = load i64, ptr %7, align 8, !range !2, !noalias !14, !noundef !3 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          167:  %8 = getelementptr inbounds nuw i8, ptr %self5.i.i, i64 16 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          168:  %e.1.i.i = load i64, ptr %8, align 8, !noalias !14 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          169:  call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %self5.i.i), !noalias !14 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          170:  br label %bb12.i 
check:12'0     ~~~~~~~~~~~~~~~~~~
          171:  
check:12'0     ~
          172: "_ZN5alloc7raw_vec20RawVecInner$LT$A$GT$14grow_amortized17h6d61f7b4f2838582E.exit.i": ; preds = %"_ZN5alloc7raw_vec20RawVecInner$LT$A$GT$14current_memory17h84d95bdf5b34909dE.exit.i.i" 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          173:  %v.013.i.i = load ptr, ptr %7, align 8, !noalias !14, !nonnull !3, !noundef !3 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          174:  call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %self5.i.i), !noalias !14 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          175:  store ptr %v.013.i.i, ptr %v, align 8, !alias.scope !14 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          176:  store i64 %3, ptr %1, align 8, !alias.scope !14 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          177:  br label %"_ZN5alloc3vec16Vec$LT$T$C$A$GT$8push_mut17h2c3392560117356eE.exit" 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          178:  
check:12'0     ~
          179: bb12.i: ; preds = %bb26.i.i, %bb1.i 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          180:  %_0.sroa.6.0.i.ph.i = phi i64 [ undef, %bb1.i ], [ %e.1.i.i, %bb26.i.i ] 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          181:  %_0.sroa.0.0.i.ph.i = phi i64 [ 0, %bb1.i ], [ %e.0.i.i, %bb26.i.i ] 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          182: ; call alloc::raw_vec::handle_error 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          183:  tail call void @_ZN5alloc7raw_vec12handle_error17h3a1325aef5fdff61E(i64 noundef %_0.sroa.0.0.i.ph.i, i64 %_0.sroa.6.0.i.ph.i, ptr noalias noundef nonnull readonly align 8 dereferenceable(24) @alloc_39d7e98511a1d7398aea42ce8d330a58) #12, !noalias !6 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          184:  unreachable 
check:12'0     ~~~~~~~~~~~~~
          185:  
check:12'0     ~
          186: "_ZN5alloc3vec16Vec$LT$T$C$A$GT$8push_mut17h2c3392560117356eE.exit": ; preds = %start.bb3_crit_edge.i, %"_ZN5alloc7raw_vec20RawVecInner$LT$A$GT$14grow_amortized17h6d61f7b4f2838582E.exit.i" 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          187:  %_24.i = phi ptr [ %_24.pre.i, %start.bb3_crit_edge.i ], [ %v.013.i.i, %"_ZN5alloc7raw_vec20RawVecInner$LT$A$GT$14grow_amortized17h6d61f7b4f2838582E.exit.i" ] 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          188:  %9 = getelementptr inbounds nuw i8, ptr %_24.i, i64 %len.i 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          189:  store i8 1, ptr %9, align 1, !noalias !6 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          190:  %_12.0.i = add i64 %len.i, 1 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          191:  store i64 %_12.0.i, ptr %0, align 8, !alias.scope !6 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          192:  ret void 
check:12'0     ~~~~~~~~~~
          193: } 
check:12'0     ~~
          194:  
check:12'0     ~
          195: ; Function Attrs: nounwind uwtable 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          196: declare noundef range(i32 0, 10) i32 @rust_eh_personality(i32 noundef, i32 noundef, i64 noundef, ptr noundef, ptr noundef) unnamed_addr #2 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          197:  
check:12'0     ~
          198: ; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          199: declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #3 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          200:  
check:12'0     ~
          201: ; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          202: declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #3 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          203:  
check:12'0     ~
          204: ; core::panicking::panic_fmt 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          205: ; Function Attrs: cold noinline noreturn uwtable 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          206: declare void @_ZN4core9panicking9panic_fmt17hc0fa719bc544a225E(ptr noalias noundef readonly align 8 dereferenceable(48), ptr noalias noundef readonly align 8 dereferenceable(24)) unnamed_addr #4 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          207:  
check:12'0     ~
          208: ; alloc::raw_vec::handle_error 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          209: ; Function Attrs: cold minsize noreturn optsize uwtable 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          210: declare void @_ZN5alloc7raw_vec12handle_error17h3a1325aef5fdff61E(i64 noundef range(i64 0, -9223372036854775807), i64, ptr noalias noundef readonly align 8 dereferenceable(24)) unnamed_addr #5 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          211:  
check:12'0     ~
          212: ; __rustc::__rust_no_alloc_shim_is_unstable_v2 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          213: ; Function Attrs: nounwind uwtable 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          214: declare void @_RNvCsluNeYmp3Xm3_7___rustc35___rust_no_alloc_shim_is_unstable_v2() unnamed_addr #2 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          215:  
check:12'0     ~
          216: ; __rustc::__rust_alloc 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~
          217: ; Function Attrs: nounwind allockind("alloc,uninitialized,aligned") allocsize(0) uwtable 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          218: declare noalias noundef ptr @_RNvCsluNeYmp3Xm3_7___rustc12___rust_alloc(i64 noundef, i64 allocalign noundef) unnamed_addr #6 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          219:  
check:12'0     ~
          220: ; __rustc::__rust_realloc 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~
          221: ; Function Attrs: nounwind allockind("realloc,aligned") allocsize(3) uwtable 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          222: declare noalias noundef ptr @_RNvCsluNeYmp3Xm3_7___rustc14___rust_realloc(ptr allocptr noundef, i64 noundef, i64 allocalign noundef, i64 noundef) unnamed_addr #7 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          223:  
check:12'0     ~
          224: ; core::panicking::assert_failed 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          225: ; Function Attrs: cold minsize noinline noreturn optsize uwtable 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          226: declare void @_ZN4core9panicking13assert_failed17hc671a3ed0aea6677E(i8 noundef range(i8 0, 3), ptr noalias noundef readonly align 8 dereferenceable(8), ptr noalias noundef readonly align 8 dereferenceable(8), ptr noalias noundef align 8 dereferenceable(48), ptr noalias noundef readonly align 8 dereferenceable(24)) unnamed_addr #8 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          227:  
check:12'0     ~
          228: ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: readwrite) 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          229: declare void @llvm.experimental.noalias.scope.decl(metadata) #9 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          230:  
check:12'0     ~
          231: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none) 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          232: declare i64 @llvm.umax.i64(i64, i64) #10 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          233:  
check:12'0     ~
          234: attributes #0 = { cold uwtable "frame-pointer"="non-leaf" "probe-stack"="inline-asm" "target-cpu"="generic" "target-features"="+v8a,+outline-atomics" } 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          235: attributes #1 = { uwtable "frame-pointer"="non-leaf" "probe-stack"="inline-asm" "target-cpu"="generic" "target-features"="+v8a,+outline-atomics" } 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          236: attributes #2 = { nounwind uwtable "frame-pointer"="non-leaf" "probe-stack"="inline-asm" "target-cpu"="generic" "target-features"="+v8a,+outline-atomics" } 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          237: attributes #3 = { mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          238: attributes #4 = { cold noinline noreturn uwtable "frame-pointer"="non-leaf" "probe-stack"="inline-asm" "target-cpu"="generic" "target-features"="+v8a,+outline-atomics" } 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          239: attributes #5 = { cold minsize noreturn optsize uwtable "frame-pointer"="non-leaf" "probe-stack"="inline-asm" "target-cpu"="generic" "target-features"="+v8a,+outline-atomics" } 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          240: attributes #6 = { nounwind allockind("alloc,uninitialized,aligned") allocsize(0) uwtable "alloc-family"="__rust_alloc" "alloc-variant-zeroed"="_RNvCsluNeYmp3Xm3_7___rustc19___rust_alloc_zeroed" "frame-pointer"="non-leaf" "probe-stack"="inline-asm" "target-cpu"="generic" "target-features"="+v8a,+outline-atomics" } 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          241: attributes #7 = { nounwind allockind("realloc,aligned") allocsize(3) uwtable "alloc-family"="__rust_alloc" "frame-pointer"="non-leaf" "probe-stack"="inline-asm" "target-cpu"="generic" "target-features"="+v8a,+outline-atomics" } 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          242: attributes #8 = { cold minsize noinline noreturn optsize uwtable "frame-pointer"="non-leaf" "probe-stack"="inline-asm" "target-cpu"="generic" "target-features"="+v8a,+outline-atomics" } 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          243: attributes #9 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: readwrite) } 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          244: attributes #10 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          245: attributes #11 = { nounwind } 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          246: attributes #12 = { noreturn } 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          247:  
check:12'0     ~
          248: !llvm.module.flags = !{!0} 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
          249: !llvm.ident = !{!1} 
check:12'0     ~~~~~~~~~~~~~~~~~~~~
          250:  
check:12'0     ~
          251: !0 = !{i32 8, !"PIC Level", i32 2} 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          252: !1 = !{!"rustc version 1.92.0-nightly (ac01e0523 2025-09-20)"} 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          253: !2 = !{i64 0, i64 -9223372036854775807} 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          254: !3 = !{} 
check:12'0     ~~~~~~~~~
          255: !4 = !{!"branch_weights", !"expected", i32 2000, i32 1} 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          256: !5 = !{!"branch_weights", !"expected", i32 1, i32 2000} 
check:12'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          257: !6 = !{!7} 
check:12'0     ~~~~~~~~~~~
            .
            .
            .
>>>>>>

------------------------------------------

error: verification with 'FileCheck' failed
status: exit status: 1
command: "/usr/lib/llvm-20/bin/FileCheck" "--input-file" "/checkout/obj/build/aarch64-unknown-linux-gnu/test/codegen-llvm/vec-len-invariant/vec-len-invariant.ll" "/checkout/tests/codegen-llvm/vec-len-invariant.rs" "--check-prefix=CHECK" "--allow-unused-prefixes" "--dump-input-context" "100"
stdout: none
--- stderr -------------------------------
/checkout/tests/codegen-llvm/vec-len-invariant.rs:12:12: error: CHECK: expected string not found in input
 // CHECK: call {{.*}}grow_one
           ^
/checkout/obj/build/aarch64-unknown-linux-gnu/test/codegen-llvm/vec-len-invariant/vec-len-invariant.ll:123:19: note: scanning from here
 %len.i = load i64, ptr %0, align 8, !alias.scope !6, !noundef !3
                  ^
/checkout/obj/build/aarch64-unknown-linux-gnu/test/codegen-llvm/vec-len-invariant/vec-len-invariant.ll:157:6: note: possible intended match here
; call alloc::raw_vec::finish_grow
     ^

Input file: /checkout/obj/build/aarch64-unknown-linux-gnu/test/codegen-llvm/vec-len-invariant/vec-len-invariant.ll
Check file: /checkout/tests/codegen-llvm/vec-len-invariant.rs

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

Input was:
<<<<<<
            .
            .
            .
           23:  %2 = getelementptr inbounds nuw i8, ptr %current_memory, i64 8 
           24:  %3 = load i64, ptr %2, align 8, !range !2, !noundef !3 
           25:  %.not = icmp eq i64 %3, 0 
           26:  br i1 %.not, label %bb5, label %bb1 
           27:  
           28: bb1: ; preds = %start 
           29:  %ptr = load ptr, ptr %current_memory, align 8, !nonnull !3, !noundef !3 
           30:  %4 = getelementptr inbounds nuw i8, ptr %current_memory, i64 16 
           31:  %5 = load i64, ptr %4, align 8, !noundef !3 
           32:  store i64 %3, ptr %_9, align 8 
           33:  store i64 %0, ptr %_12, align 8 
           34:  %_14 = icmp eq i64 %3, %0 
           35:  br i1 %_14, label %bb2, label %bb3, !prof !4 
           36:  
           37: bb5: ; preds = %start 
           38:  %6 = icmp eq i64 %1, 0 
           39:  br i1 %6, label %bb2.i.i, label %bb4.i.i 
           40:  
           41: bb2.i.i: ; preds = %bb5 
           42:  %_19.i.i = getelementptr i8, ptr null, i64 %0 
           43:  br label %bb7 
           44:  
           45: bb4.i.i: ; preds = %bb5 
           46: ; call __rustc::__rust_no_alloc_shim_is_unstable_v2 
           47:  tail call void @_RNvCsluNeYmp3Xm3_7___rustc35___rust_no_alloc_shim_is_unstable_v2() #11 
           48: ; call __rustc::__rust_alloc 
           49:  %7 = tail call noundef ptr @_RNvCsluNeYmp3Xm3_7___rustc12___rust_alloc(i64 noundef %1, i64 noundef range(i64 1, -9223372036854775807) %0) #11 
           50:  br label %bb7 
           51:  
           52: bb3: ; preds = %bb1 
           53:  call void @llvm.lifetime.start.p0(i64 48, ptr nonnull %_16) 
           54:  store ptr null, ptr %_16, align 8 
           55: ; call core::panicking::assert_failed 
           56:  call void @_ZN4core9panicking13assert_failed17hc671a3ed0aea6677E(i8 noundef 0, ptr noalias noundef nonnull readonly align 8 dereferenceable(8) %_9, ptr noalias noundef nonnull readonly align 8 dereferenceable(8) %_12, ptr noalias noundef nonnull align 8 dereferenceable(48) %_16, ptr noalias noundef nonnull readonly align 8 dereferenceable(24) @alloc_60b3217ab254a473df4c758b54d2e808) #12 
           57:  unreachable 
           58:  
           59: bb2: ; preds = %bb1 
           60:  %_6.not.i.i = icmp ult i64 %1, %5 
           61:  br i1 %_6.not.i.i, label %bb2.i.i13, label %bb1.i.i, !prof !5 
           62:  
           63: bb2.i.i13: ; preds = %bb2 
           64:  call void @llvm.lifetime.start.p0(i64 48, ptr nonnull %_12.i.i) 
           65:  store ptr @alloc_04056f6d76887c0653320aca2f1cbe49, ptr %_12.i.i, align 8 
           66:  %8 = getelementptr inbounds nuw i8, ptr %_12.i.i, i64 8 
           67:  store i64 1, ptr %8, align 8 
           68:  %9 = getelementptr inbounds nuw i8, ptr %_12.i.i, i64 16 
           69:  store ptr null, ptr %9, align 8 
           70:  %10 = getelementptr inbounds nuw i8, ptr %_12.i.i, i64 32 
           71:  store ptr inttoptr (i64 8 to ptr), ptr %10, align 8 
           72:  %11 = getelementptr inbounds nuw i8, ptr %_12.i.i, i64 40 
           73:  store i64 0, ptr %11, align 8 
           74: ; call core::panicking::panic_fmt 
           75:  call void @_ZN4core9panicking9panic_fmt17hc0fa719bc544a225E(ptr noalias noundef nonnull readonly align 8 dereferenceable(48) %_12.i.i, ptr noalias noundef nonnull readonly align 8 dereferenceable(24) @alloc_f8c5c844aa69054ab9d96ab1c41933fc) #12 
           76:  unreachable 
           77:  
           78: bb1.i.i: ; preds = %bb2 
           79:  %12 = icmp eq i64 %5, 0 
           80:  br i1 %12, label %bb4.i.i12, label %bb5.i.i 
           81:  
           82: bb4.i.i12: ; preds = %bb1.i.i 
           83:  %13 = icmp eq i64 %1, 0 
           84:  br i1 %13, label %bb2.i.i.i, label %bb4.i.i.i 
           85:  
           86: bb2.i.i.i: ; preds = %bb4.i.i12 
           87:  %_19.i.i.i = getelementptr i8, ptr null, i64 %0 
           88:  br label %bb7 
           89:  
           90: bb4.i.i.i: ; preds = %bb4.i.i12 
           91: ; call __rustc::__rust_no_alloc_shim_is_unstable_v2 
           92:  tail call void @_RNvCsluNeYmp3Xm3_7___rustc35___rust_no_alloc_shim_is_unstable_v2() #11 
           93: ; call __rustc::__rust_alloc 
           94:  %14 = tail call noundef ptr @_RNvCsluNeYmp3Xm3_7___rustc12___rust_alloc(i64 noundef %1, i64 noundef range(i64 1, -9223372036854775807) %0) #11 

@rust-bors
Copy link

rust-bors bot commented Sep 20, 2025

☀️ Try build successful (CI)
Build commit: 2b1a9e5 (2b1a9e56c785e5abe128db3331df10395fb85de5, parent: 9f2ef0f14d6028c5108643cafa6e2c617834594b)

@rust-timer

This comment has been minimized.

@tgross35
Copy link
Contributor

and probably the reason why the compiler lose the information about the capacity (fixes #82801) - is there a way I can test that to make sure the issue is fixed?

The way to do this would be a codegen test. I think you could add a new function at tests/codegen-llvm/vec-len-invariant.rs (the failing test here) based on the top post of #82801 that has a CHECK-NOT: handle_error to ensure that the function doesn't contain a call to alloc::raw_vec::handle_error. Please make sure the test actually fails without the fix here.

You should also add another function that doesn't have the capacity information and passes with CHECK: handle_error, to make sure the test gets flagged if handle_error is renamed or something.

(not sure how familiar you are with filecheck but CHECK: foo means there has to be a line in the LLVM IR containing "foo", CHECK-NOT: foo means no lines can contain "foo". Some more at https://llvm.org/docs/CommandGuide/FileCheck.html)

BTW The original PR that added it (#91352) wrote:

[...] I tried lots of minor variations on this, e.g. different inlining
attributes. This was the best one I could find. [...]

@nnethercote it's been forever so I doubt it, but any idea what metrics you were going for here?

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (2b1a9e5): comparison URL.

Overall result: ❌✅ regressions and improvements - please read the text below

Benchmarking this pull request means it may be perf-sensitive – we'll automatically label it not fit for rolling up. You can override this, but we strongly advise not to, due to possible changes in compiler perf.

Next Steps: If you can justify the regressions found in this try perf run, please do so in sufficient writing along with @rustbot label: +perf-regression-triaged. If not, please fix the regressions and do another perf run. If its results are neutral or positive, the label will be automatically removed.

@bors rollup=never
@rustbot label: -S-waiting-on-perf +perf-regression

Instruction count

Our most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.

mean range count
Regressions ❌
(primary)
1.0% [0.1%, 3.8%] 40
Regressions ❌
(secondary)
0.5% [0.2%, 1.8%] 29
Improvements ✅
(primary)
-0.3% [-0.6%, -0.1%] 56
Improvements ✅
(secondary)
-0.4% [-2.0%, -0.1%] 80
All ❌✅ (primary) 0.3% [-0.6%, 3.8%] 96

Max RSS (memory usage)

Results (primary 3.4%, secondary -3.0%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
4.7% [2.0%, 9.9%] 4
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
-1.8% [-1.8%, -1.8%] 1
Improvements ✅
(secondary)
-3.0% [-3.0%, -3.0%] 1
All ❌✅ (primary) 3.4% [-1.8%, 9.9%] 5

Cycles

Results (primary 2.6%, secondary 1.9%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
2.6% [1.3%, 4.4%] 13
Regressions ❌
(secondary)
1.9% [1.7%, 2.2%] 2
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 2.6% [1.3%, 4.4%] 13

Binary size

Results (primary 0.1%, secondary 0.2%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
0.4% [0.0%, 1.2%] 40
Regressions ❌
(secondary)
0.3% [0.0%, 0.7%] 43
Improvements ✅
(primary)
-0.2% [-0.3%, -0.0%] 34
Improvements ✅
(secondary)
-0.3% [-0.3%, -0.3%] 3
All ❌✅ (primary) 0.1% [-0.3%, 1.2%] 74

Bootstrap: 471.07s -> 478.071s (1.49%)
Artifact size: 389.99 MiB -> 390.06 MiB (0.02%)

@rustbot rustbot added perf-regression Performance regression. and removed S-waiting-on-perf Status: Waiting on a perf run to be completed. labels Sep 20, 2025
@rluvaton
Copy link
Author

Debugging locally for the last 3 hours, the problem for not optimizing into SIMD is not because of the grow_one, the grow_one should never be called in our case, but instead the compiler don't understand that if len == self.buf.capacity() inside push_mut will never be taken.

@rluvaton
Copy link
Author

How do you help the optimizer in this case

@tgross35
Copy link
Contributor

I haven't dug into it but you may be able to play with using assert_unchecked (aka assume) in some places. We have this once at

// Make it more obvious that a subsequent Vec::reserve(capacity) will not allocate.
hint::assert_unchecked(!this.needs_to_grow(0, capacity, elem_layout));
, see #126793. Note that there's a bit of a fine line to balance, overuse of assert_unchecked can make compile times worse.

The usual process here usually involves playing with the implementations and looking at the result of --emit=llvm-ir or do that on godbolt (under "add new"). Probably no need to look at the actual asm since an error condition removal should be platform-agnostic and happen at the LLVM IR level.

If you're getting really deep into things, godbolt also has "add new"->"opt pipeline" for looking at optimizations done by each LLVM pass one at a time. Can be helpful for looking at things more incrementally, rather than just the coarse diff between -Copt-level=1 and -Copt-level=2 output.

@rluvaton rluvaton marked this pull request as draft September 21, 2025 00:31
@rustbot rustbot 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 Sep 21, 2025
@rluvaton
Copy link
Author

So I found the problem.

LLVM does not eliminate dead code in some cases:
consider this example:

const COUNT: usize = 10000;

#[no_mangle]
pub fn run() -> usize {
    let mut inter = 0;
    let mut my_cap = COUNT;

    for _ in 0..COUNT {
        let len = inter;

        if len == my_cap {
            something(len);
        }

        inter += 1;
    }

    return inter;
}

#[inline(never)]
fn something(len: usize) {
    std::hint::black_box(len as i128);
}

pub fn main() {
    std::hint::black_box(run());
}

it will eliminate:

if len == my_cap {
  something(len);
}

but if you change the code of the if to modify my_cap it will not remove that:

if len == my_cap {
    something(len);
	my_cap += 1;
}

it will not eliminate the if.

looking at Rust MIR, the if exists in both cases, but in LLVM IR it does not exists - meaning that LLVM have the problem.

will try to look inside LLVM (Ugh, CPP)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
perf-regression Performance regression. 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.

The compiler loses vector capacity information
6 participants