Skip to content

Optimization fails to reduce a loop when AVX is enabled #134735

Closed as duplicate of#134513
@cuviper

Description

@cuviper

Rust's issue-101082.rs test case has a simple sum over an array:

#[no_mangle]
pub fn test() -> usize {
    // CHECK-LABEL: @test(
    // CHECK: ret {{i64|i32}} 165
    let values = [23, 16, 54, 3, 60, 9];
    let mut acc = 0;
    for item in values {
        acc += item;
    }
    acc
}

I captured the IR (included at the end of this report), and confirmed that opt -S -O2 reduces the function to a single instruction returning the answer, as our CHECK lines expect:

define noundef i64 @test() unnamed_addr #0 personality ptr @rust_eh_personality {
bb1.i.i.preheader:
  ret i64 165
}

However, with -mcpu=x86-64-v3, it produces a vectorized calculation:

define noundef i64 @test() unnamed_addr #0 personality ptr @rust_eh_personality {
bb1.i.i.preheader:
  %iter = alloca [64 x i8], align 8
  call void @llvm.lifetime.start.p0(i64 64, ptr nonnull %iter)
  %_3.sroa.5.0.iter.sroa_idx = getelementptr inbounds nuw i8, ptr %iter, i64 16
  store <4 x i64> <i64 23, i64 16, i64 54, i64 3>, ptr %_3.sroa.5.0.iter.sroa_idx, align 8
  %_3.sroa.5.sroa.7.0._3.sroa.5.0.iter.sroa_idx.sroa_idx = getelementptr inbounds nuw i8, ptr %iter, i64 48
  store i64 60, ptr %_3.sroa.5.sroa.7.0._3.sroa.5.0.iter.sroa_idx.sroa_idx, align 8
  %_3.sroa.5.sroa.8.0._3.sroa.5.0.iter.sroa_idx.sroa_idx = getelementptr inbounds nuw i8, ptr %iter, i64 56
  store i64 9, ptr %_3.sroa.5.sroa.8.0._3.sroa.5.0.iter.sroa_idx.sroa_idx, align 8
  %unmaskedload = load <4 x i64>, ptr %_3.sroa.5.0.iter.sroa_idx, align 8, !alias.scope !3
  %0 = getelementptr inbounds nuw i8, ptr %iter, i64 48
  %wide.masked.load.1 = call <4 x i64> @llvm.masked.load.v4i64.p0(ptr nonnull %0, i32 8, <4 x i1> <i1 true, i1 true, i1 false, i1 false>, <4 x i64> poison), !alias.scope !3
  %1 = add <4 x i64> %wide.masked.load.1, %unmaskedload
  %2 = shufflevector <4 x i64> %1, <4 x i64> %unmaskedload, <4 x i32> <i32 0, i32 1, i32 6, i32 7>
  %3 = tail call i64 @llvm.vector.reduce.add.v4i64(<4 x i64> %2)
  call void @llvm.lifetime.end.p0(i64 64, ptr nonnull %iter)
  ret i64 %3
}

It's also vectorized with the default CPU and just enabling -mattr=+avx:

define noundef i64 @test() unnamed_addr #0 personality ptr @rust_eh_personality {
bb1.i.i.preheader:
  %iter = alloca [64 x i8], align 8
  call void @llvm.lifetime.start.p0(i64 64, ptr nonnull %iter)
  %_3.sroa.5.0.iter.sroa_idx = getelementptr inbounds nuw i8, ptr %iter, i64 16
  store <4 x i64> <i64 23, i64 16, i64 54, i64 3>, ptr %_3.sroa.5.0.iter.sroa_idx, align 8
  %_3.sroa.5.sroa.7.0._3.sroa.5.0.iter.sroa_idx.sroa_idx = getelementptr inbounds nuw i8, ptr %iter, i64 48
  store i64 60, ptr %_3.sroa.5.sroa.7.0._3.sroa.5.0.iter.sroa_idx.sroa_idx, align 8
  %_3.sroa.5.sroa.8.0._3.sroa.5.0.iter.sroa_idx.sroa_idx = getelementptr inbounds nuw i8, ptr %iter, i64 56
  store i64 9, ptr %_3.sroa.5.sroa.8.0._3.sroa.5.0.iter.sroa_idx.sroa_idx, align 8
  %unmaskedload = load <2 x i64>, ptr %_3.sroa.5.0.iter.sroa_idx, align 8, !alias.scope !3
  %0 = getelementptr inbounds nuw i8, ptr %iter, i64 32
  %unmaskedload16 = load <2 x i64>, ptr %0, align 8, !alias.scope !3
  %1 = add <2 x i64> %unmaskedload16, %unmaskedload
  %2 = getelementptr inbounds nuw i8, ptr %iter, i64 48
  %unmaskedload17 = load <2 x i64>, ptr %2, align 8, !alias.scope !3
  %3 = add <2 x i64> %unmaskedload17, %1
  %4 = tail call i64 @llvm.vector.reduce.add.v2i64(<2 x i64> %3)
  call void @llvm.lifetime.end.p0(i64 64, ptr nonnull %iter)
  ret i64 %4
}

My context is rust-lang/rust#138380, where this testcase is failing to optimize as expected with Ubuntu's llvm-20, and I have confirmed the reproducer with LLVM main. Oddly, that test has had no problem with x86-64-v3 when using Rust's bundled LLVM 20 in CI, but I suspect other factors are perturbing the input in that case, because the CI-built opt still fails the same way on this exact reproducer IR.

LLVM IR reproducer
; ModuleID = '<stdin>'
source_filename = "issue_101082.775d9ed26ae14e6e-cgu.0"
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"
target triple = "x86_64-unknown-linux-gnu"

@alloc_ed8641ebea8e5515740d4eb49a916ff5 = private unnamed_addr constant [218 x i8] c"unsafe precondition(s) violated: ptr::read requires that the pointer argument is aligned and non-null\0A\0AThis indicates a bug in the program. This Undefined Behavior check is optional, and cannot be relied on for safety.", align 1
@alloc_fad0cd83b7d1858a846a172eb260e593 = private unnamed_addr constant [42 x i8] c"is_aligned_to: align is not a power-of-two", align 1
@alloc_e92e94d0ff530782b571cfd99ec66aef = private unnamed_addr constant <{ ptr, [8 x i8] }> <{ ptr @alloc_fad0cd83b7d1858a846a172eb260e593, [8 x i8] c"*\00\00\00\00\00\00\00" }>, align 8
@0 = private unnamed_addr constant <{ [8 x i8], [8 x i8] }> <{ [8 x i8] zeroinitializer, [8 x i8] undef }>, align 8
@alloc_57f39e09f7c9ad4245f74159f6bbb2c2 = private unnamed_addr constant [52 x i8] c"/rustc/FAKE_PREFIX/library/core/src/ptr/const_ptr.rs", align 1
@alloc_55a78c643ac9851d3ad8dc871da622ba = private unnamed_addr constant <{ ptr, [16 x i8] }> <{ ptr @alloc_57f39e09f7c9ad4245f74159f6bbb2c2, [16 x i8] c"4\00\00\00\00\00\00\00\0D\00\00\00\C3\05\00\00" }>, align 8
@alloc_ea57c52ffecfc6f596231aa6e610f772 = private unnamed_addr constant [39 x i8] c"assertion failed: self.start < self.end", align 1
@alloc_6fbb54c7cb7260f04218cc51e19e04e4 = private unnamed_addr constant [54 x i8] c"/rustc/FAKE_PREFIX/library/core/src/ops/index_range.rs", align 1
@alloc_a35bb76379a3b55fc8cbe20b8dab1d46 = private unnamed_addr constant <{ ptr, [16 x i8] }> <{ ptr @alloc_6fbb54c7cb7260f04218cc51e19e04e4, [16 x i8] c"6\00\00\00\00\00\00\00\09\00\00\008\00\00\00" }>, align 8

; Function Attrs: inlinehint nounwind nonlazybind uwtable
define internal void @_ZN4core3ptr4read18precondition_check17he50e497260f5c5aaE(ptr noundef %addr, i64 noundef %align, i1 noundef zeroext %is_zst) unnamed_addr #0 personality ptr @rust_eh_personality {
start:
  %_6 = invoke noundef zeroext i1 @"_ZN4core3ptr9const_ptr33_$LT$impl$u20$$BP$const$u20$T$GT$13is_aligned_to17hee3b7393df819147E"(ptr noundef %addr, i64 noundef %align)
          to label %bb3 unwind label %terminate

terminate:                                        ; preds = %start
  %0 = landingpad { ptr, i32 }
          filter [0 x ptr] zeroinitializer
  %1 = extractvalue { ptr, i32 } %0, 0
  %2 = extractvalue { ptr, i32 } %0, 1
  call void @_ZN4core9panicking19panic_cannot_unwind17hf77d1d116ce25e3bE() #12
  unreachable

bb3:                                              ; preds = %start
  %3 = call i1 @llvm.expect.i1(i1 %_6, i1 true)
  br i1 %3, label %bb4, label %bb5

bb5:                                              ; preds = %bb3
  br label %bb2

bb4:                                              ; preds = %bb3
  br i1 %is_zst, label %bb6, label %bb7

bb2:                                              ; preds = %bb7, %bb5
  call void @_ZN4core9panicking14panic_nounwind17h7b81d1449a5f4f5aE(ptr noalias noundef nonnull readonly align 1 @alloc_ed8641ebea8e5515740d4eb49a916ff5, i64 noundef 218) #13
  unreachable

bb7:                                              ; preds = %bb4
  %_8 = ptrtoint ptr %addr to i64
  %_7 = icmp eq i64 %_8, 0
  %_4 = xor i1 %_7, true
  %4 = call i1 @llvm.expect.i1(i1 %_4, i1 true)
  br i1 %4, label %bb1, label %bb2

bb6:                                              ; preds = %bb4
  br label %bb1

bb1:                                              ; preds = %bb6, %bb7
  ret void
}

; Function Attrs: nonlazybind uwtable
define internal void @"_ZN4core3ptr71drop_in_place$LT$core..array..iter..IntoIter$LT$usize$C$6_usize$GT$$GT$17hd85b6451ff2beb57E"(ptr noalias noundef align 8 dereferenceable(64) %_1) unnamed_addr #1 {
start:
  call void @"_ZN82_$LT$core..array..iter..IntoIter$LT$T$C$_$GT$$u20$as$u20$core..ops..drop..Drop$GT$4drop17h3e57fc25945276b8E"(ptr noalias noundef align 8 dereferenceable(64) %_1)
  ret void
}

; Function Attrs: inlinehint nonlazybind uwtable
define internal noundef zeroext i1 @"_ZN4core3ptr9const_ptr33_$LT$impl$u20$$BP$const$u20$T$GT$13is_aligned_to17hee3b7393df819147E"(ptr noundef %self, i64 noundef %align) unnamed_addr #2 {
start:
  %0 = alloca [4 x i8], align 4
  %_4 = alloca [48 x i8], align 8
  call void @llvm.lifetime.start.p0(i64 4, ptr %0)
  %1 = call i64 @llvm.ctpop.i64(i64 %align)
  %2 = trunc i64 %1 to i32
  store i32 %2, ptr %0, align 4
  %_9 = load i32, ptr %0, align 4, !noundef !3
  call void @llvm.lifetime.end.p0(i64 4, ptr %0)
  %3 = icmp eq i32 %_9, 1
  %4 = call i1 @llvm.expect.i1(i1 %3, i1 true)
  br i1 %4, label %bb1, label %bb2

bb1:                                              ; preds = %start
  %_6 = ptrtoint ptr %self to i64
  %_8.0 = sub i64 %align, 1
  %_8.1 = icmp ult i64 %align, 1
  %_5 = and i64 %_6, %_8.0
  %_0 = icmp eq i64 %_5, 0
  ret i1 %_0

bb2:                                              ; preds = %start
  call void @llvm.lifetime.start.p0(i64 48, ptr %_4)
  %5 = getelementptr inbounds i8, ptr %_4, i64 32
  store ptr @alloc_e92e94d0ff530782b571cfd99ec66aef, ptr %5, align 8
  %6 = getelementptr inbounds i8, ptr %5, i64 8
  store i64 1, ptr %6, align 8
  %7 = load ptr, ptr @0, align 8, !align !4, !noundef !3
  %8 = load i64, ptr getelementptr inbounds (i8, ptr @0, i64 8), align 8
  %9 = getelementptr inbounds i8, ptr %_4, i64 16
  store ptr %7, ptr %9, align 8
  %10 = getelementptr inbounds i8, ptr %9, i64 8
  store i64 %8, ptr %10, align 8
  store ptr inttoptr (i64 8 to ptr), ptr %_4, align 8
  %11 = getelementptr inbounds i8, ptr %_4, i64 8
  store i64 0, ptr %11, align 8
  call void @_ZN4core9panicking9panic_fmt17hacfb58ec817221c8E(ptr noalias nocapture noundef readonly align 8 dereferenceable(48) %_4, ptr noalias noundef readonly align 8 dereferenceable(24) @alloc_55a78c643ac9851d3ad8dc871da622ba) #14
  unreachable
}

; Function Attrs: nonlazybind uwtable
define internal { ptr, i64 } @"_ZN4core5array4iter21IntoIter$LT$T$C$_$GT$12as_mut_slice17h1cd4fd74799a8d07E"(ptr noalias noundef align 8 dereferenceable(64) %self) unnamed_addr #1 {
start:
  %index = alloca [16 x i8], align 8
  %_3 = getelementptr inbounds i8, ptr %self, i64 16
  call void @llvm.lifetime.start.p0(i64 16, ptr %index)
  %0 = load i64, ptr %self, align 8, !noundef !3
  %1 = getelementptr inbounds i8, ptr %self, i64 8
  %2 = load i64, ptr %1, align 8, !noundef !3
  store i64 %0, ptr %index, align 8
  %3 = getelementptr inbounds i8, ptr %index, i64 8
  store i64 %2, ptr %3, align 8
  br label %bb3

bb3:                                              ; preds = %start
  %4 = getelementptr inbounds i8, ptr %index, i64 8
  %offset = load i64, ptr %4, align 8, !noundef !3
  %_16 = load i64, ptr %index, align 8, !noundef !3
  %len = sub nuw i64 %_16, %offset
  %_17 = getelementptr inbounds nuw i64, ptr %_3, i64 %offset
  call void @llvm.lifetime.end.p0(i64 16, ptr %index)
  %5 = insertvalue { ptr, i64 } poison, ptr %_17, 0
  %6 = insertvalue { ptr, i64 } %5, i64 %len, 1
  ret { ptr, i64 } %6

bb1:                                              ; No predecessors!
  unreachable

bb2:                                              ; No predecessors!
  unreachable
}

; Function Attrs: nonlazybind uwtable
define internal void @"_ZN82_$LT$core..array..iter..IntoIter$LT$T$C$_$GT$$u20$as$u20$core..ops..drop..Drop$GT$4drop17h3e57fc25945276b8E"(ptr noalias noundef align 8 dereferenceable(64) %self) unnamed_addr #1 {
start:
  %0 = call { ptr, i64 } @"_ZN4core5array4iter21IntoIter$LT$T$C$_$GT$12as_mut_slice17h1cd4fd74799a8d07E"(ptr noalias noundef align 8 dereferenceable(64) %self)
  %_3.0 = extractvalue { ptr, i64 } %0, 0
  %_3.1 = extractvalue { ptr, i64 } %0, 1
  ret void
}

; Function Attrs: inlinehint nonlazybind uwtable
define internal { i64, i64 } @"_ZN93_$LT$core..ops..index_range..IndexRange$u20$as$u20$core..iter..traits..iterator..Iterator$GT$4next17h4e21b39aae59a907E"(ptr noalias noundef align 8 dereferenceable(16) %0) unnamed_addr #2 {
start:
  %_0 = alloca [16 x i8], align 8
  %self = alloca [8 x i8], align 8
  store ptr %0, ptr %self, align 8
  %1 = load ptr, ptr %self, align 8, !nonnull !3, !align !4, !noundef !3
  %_6 = load i64, ptr %1, align 8, !noundef !3
  %2 = load ptr, ptr %self, align 8, !nonnull !3, !align !4, !noundef !3
  %3 = getelementptr inbounds i8, ptr %2, i64 8
  %_7 = load i64, ptr %3, align 8, !noundef !3
  %_3 = sub nuw i64 %_6, %_7
  %_2 = icmp ugt i64 %_3, 0
  br i1 %_2, label %bb1, label %bb2

bb2:                                              ; preds = %start
  %4 = load i64, ptr @0, align 8, !range !5, !noundef !3
  %5 = load i64, ptr getelementptr inbounds (i8, ptr @0, i64 8), align 8
  store i64 %4, ptr %_0, align 8
  %6 = getelementptr inbounds i8, ptr %_0, i64 8
  store i64 %5, ptr %6, align 8
  br label %bb3

bb1:                                              ; preds = %start
  %7 = load ptr, ptr %self, align 8, !nonnull !3, !align !4, !noundef !3
  %8 = getelementptr inbounds i8, ptr %7, i64 8
  %_9 = load i64, ptr %8, align 8, !noundef !3
  %9 = load ptr, ptr %self, align 8, !nonnull !3, !align !4, !noundef !3
  %_10 = load i64, ptr %9, align 8, !noundef !3
  %_8 = icmp ult i64 %_9, %_10
  %10 = call i1 @llvm.expect.i1(i1 %_8, i1 true)
  br i1 %10, label %bb4, label %bb5

bb3:                                              ; preds = %bb7, %bb2
  %11 = load i64, ptr %_0, align 8, !range !5, !noundef !3
  %12 = getelementptr inbounds i8, ptr %_0, i64 8
  %13 = load i64, ptr %12, align 8
  %14 = insertvalue { i64, i64 } poison, i64 %11, 0
  %15 = insertvalue { i64, i64 } %14, i64 %13, 1
  ret { i64, i64 } %15

bb5:                                              ; preds = %bb1
  call void @_ZN4core9panicking5panic17heec94013e0df98e3E(ptr noalias noundef nonnull readonly align 1 @alloc_ea57c52ffecfc6f596231aa6e610f772, i64 noundef 39, ptr noalias noundef readonly align 8 dereferenceable(24) @alloc_a35bb76379a3b55fc8cbe20b8dab1d46) #14
  unreachable

bb4:                                              ; preds = %bb1
  %16 = load ptr, ptr %self, align 8, !nonnull !3, !align !4, !noundef !3
  %17 = getelementptr inbounds i8, ptr %16, i64 8
  %value = load i64, ptr %17, align 8, !noundef !3
  br label %bb7

bb7:                                              ; preds = %bb4
  %_12 = add nuw i64 %value, 1
  %18 = load ptr, ptr %self, align 8, !nonnull !3, !align !4, !noundef !3
  %19 = getelementptr inbounds i8, ptr %18, i64 8
  store i64 %_12, ptr %19, align 8
  %20 = getelementptr inbounds i8, ptr %_0, i64 8
  store i64 %value, ptr %20, align 8
  store i64 1, ptr %_0, align 8
  br label %bb3

bb6:                                              ; No predecessors!
  unreachable
}

; Function Attrs: nonlazybind uwtable
define internal { i64, i64 } @"_ZN99_$LT$core..array..iter..IntoIter$LT$T$C$_$GT$$u20$as$u20$core..iter..traits..iterator..Iterator$GT$4next17h8bcf71c7ab2e62d8E"(ptr noalias noundef align 8 dereferenceable(64) %self) unnamed_addr #1 {
start:
  %self1 = alloca [16 x i8], align 8
  %_0 = alloca [16 x i8], align 8
  call void @llvm.lifetime.start.p0(i64 16, ptr %self1)
  %0 = call { i64, i64 } @"_ZN93_$LT$core..ops..index_range..IndexRange$u20$as$u20$core..iter..traits..iterator..Iterator$GT$4next17h4e21b39aae59a907E"(ptr noalias noundef align 8 dereferenceable(16) %self)
  %1 = extractvalue { i64, i64 } %0, 0
  %2 = extractvalue { i64, i64 } %0, 1
  store i64 %1, ptr %self1, align 8
  %3 = getelementptr inbounds i8, ptr %self1, i64 8
  store i64 %2, ptr %3, align 8
  %_5 = getelementptr inbounds i8, ptr %self, i64 16
  %_6 = load i64, ptr %self1, align 8, !range !5, !noundef !3
  %4 = getelementptr inbounds i8, ptr %self1, i64 8
  %5 = load i64, ptr %4, align 8
  %6 = trunc nuw i64 %_6 to i1
  br i1 %6, label %bb5, label %bb4

bb5:                                              ; preds = %start
  %7 = getelementptr inbounds i8, ptr %self1, i64 8
  %x = load i64, ptr %7, align 8, !noundef !3
  %_8 = call noundef i64 @"_ZN99_$LT$core..array..iter..IntoIter$LT$T$C$_$GT$$u20$as$u20$core..iter..traits..iterator..Iterator$GT$4next28_$u7b$$u7b$closure$u7d$$u7d$17ha5bbe4f336906f6aE"(ptr noalias noundef readonly align 8 dereferenceable(48) %_5, i64 noundef %x)
  %8 = getelementptr inbounds i8, ptr %_0, i64 8
  store i64 %_8, ptr %8, align 8
  store i64 1, ptr %_0, align 8
  br label %bb2

bb4:                                              ; preds = %start
  store i64 0, ptr %_0, align 8
  br label %bb2

bb2:                                              ; preds = %bb4, %bb5
  call void @llvm.lifetime.end.p0(i64 16, ptr %self1)
  %9 = load i64, ptr %_0, align 8, !range !5, !noundef !3
  %10 = getelementptr inbounds i8, ptr %_0, i64 8
  %11 = load i64, ptr %10, align 8
  %12 = insertvalue { i64, i64 } poison, i64 %9, 0
  %13 = insertvalue { i64, i64 } %12, i64 %11, 1
  ret { i64, i64 } %13

bb3:                                              ; No predecessors!
  unreachable
}

; Function Attrs: inlinehint nonlazybind uwtable
define internal noundef i64 @"_ZN99_$LT$core..array..iter..IntoIter$LT$T$C$_$GT$$u20$as$u20$core..iter..traits..iterator..Iterator$GT$4next28_$u7b$$u7b$closure$u7d$$u7d$17ha5bbe4f336906f6aE"(ptr noalias noundef readonly align 8 dereferenceable(48) %_1, i64 noundef %idx) unnamed_addr #2 {
start:
  %self1 = alloca [8 x i8], align 8
  %self = alloca [8 x i8], align 8
  br label %bb2

bb2:                                              ; preds = %start
  %_9 = icmp ult i64 %idx, 6
  call void @llvm.assume(i1 %_9)
  %0 = getelementptr inbounds nuw i64, ptr %_1, i64 %idx
  store ptr %0, ptr %self, align 8
  call void @llvm.lifetime.start.p0(i64 8, ptr %self1)
  %1 = load ptr, ptr %self, align 8, !noundef !3
  store ptr %1, ptr %self1, align 8
  br label %bb6

bb6:                                              ; preds = %bb4, %bb2
  %2 = load ptr, ptr %self1, align 8, !noundef !3
  %_0 = load i64, ptr %2, align 8, !noundef !3
  call void @llvm.lifetime.end.p0(i64 8, ptr %self1)
  ret i64 %_0

bb4:                                              ; No predecessors!
  %_14 = load ptr, ptr %self, align 8, !noundef !3
  call void @_ZN4core3ptr4read18precondition_check17he50e497260f5c5aaE(ptr noundef %_14, i64 noundef 8, i1 noundef zeroext false) #15
  br label %bb6

bb1:                                              ; No predecessors!
  unreachable

bb7:                                              ; No predecessors!
  unreachable

bb8:                                              ; No predecessors!
  unreachable
}

; Function Attrs: nonlazybind uwtable
define noundef i64 @test() unnamed_addr #1 personality ptr @rust_eh_personality {
start:
  %0 = alloca [16 x i8], align 8
  %_9 = alloca [48 x i8], align 8
  %_5 = alloca [16 x i8], align 8
  %iter = alloca [64 x i8], align 8
  %_3 = alloca [64 x i8], align 8
  %acc = alloca [8 x i8], align 8
  %values = alloca [48 x i8], align 8
  %1 = getelementptr inbounds nuw i64, ptr %values, i64 0
  store i64 23, ptr %1, align 8
  %2 = getelementptr inbounds nuw i64, ptr %values, i64 1
  store i64 16, ptr %2, align 8
  %3 = getelementptr inbounds nuw i64, ptr %values, i64 2
  store i64 54, ptr %3, align 8
  %4 = getelementptr inbounds nuw i64, ptr %values, i64 3
  store i64 3, ptr %4, align 8
  %5 = getelementptr inbounds nuw i64, ptr %values, i64 4
  store i64 60, ptr %5, align 8
  %6 = getelementptr inbounds nuw i64, ptr %values, i64 5
  store i64 9, ptr %6, align 8
  call void @llvm.lifetime.start.p0(i64 8, ptr %acc)
  store i64 0, ptr %acc, align 8
  call void @llvm.lifetime.start.p0(i64 64, ptr %_3)
  call void @llvm.lifetime.start.p0(i64 48, ptr %_9)
  call void @llvm.memcpy.p0.p0.i64(ptr align 8 %_9, ptr align 8 %values, i64 48, i1 false)
  %7 = getelementptr inbounds i8, ptr %_3, i64 16
  call void @llvm.memcpy.p0.p0.i64(ptr align 8 %7, ptr align 8 %_9, i64 48, i1 false)
  store i64 6, ptr %_3, align 8
  %8 = getelementptr inbounds i8, ptr %_3, i64 8
  store i64 0, ptr %8, align 8
  call void @llvm.lifetime.end.p0(i64 48, ptr %_9)
  call void @llvm.lifetime.start.p0(i64 64, ptr %iter)
  call void @llvm.memcpy.p0.p0.i64(ptr align 8 %iter, ptr align 8 %_3, i64 64, i1 false)
  br label %bb1

bb1:                                              ; preds = %bb4, %start
  call void @llvm.lifetime.start.p0(i64 16, ptr %_5)
  %9 = invoke { i64, i64 } @"_ZN99_$LT$core..array..iter..IntoIter$LT$T$C$_$GT$$u20$as$u20$core..iter..traits..iterator..Iterator$GT$4next17h8bcf71c7ab2e62d8E"(ptr noalias noundef align 8 dereferenceable(64) %iter)
          to label %bb2 unwind label %cleanup

bb7:                                              ; preds = %cleanup
  invoke void @"_ZN4core3ptr71drop_in_place$LT$core..array..iter..IntoIter$LT$usize$C$6_usize$GT$$GT$17hd85b6451ff2beb57E"(ptr noalias noundef align 8 dereferenceable(64) %iter) #16
          to label %bb8 unwind label %terminate

cleanup:                                          ; preds = %bb1
  %10 = landingpad { ptr, i32 }
          cleanup
  %11 = extractvalue { ptr, i32 } %10, 0
  %12 = extractvalue { ptr, i32 } %10, 1
  call void @llvm.lifetime.start.p0(i64 16, ptr %0)
  store ptr %11, ptr %0, align 8
  %13 = getelementptr inbounds i8, ptr %0, i64 8
  store i32 %12, ptr %13, align 8
  br label %bb7

bb2:                                              ; preds = %bb1
  %14 = extractvalue { i64, i64 } %9, 0
  %15 = extractvalue { i64, i64 } %9, 1
  store i64 %14, ptr %_5, align 8
  %16 = getelementptr inbounds i8, ptr %_5, i64 8
  store i64 %15, ptr %16, align 8
  %_7 = load i64, ptr %_5, align 8, !range !5, !noundef !3
  %17 = getelementptr inbounds i8, ptr %_5, i64 8
  %18 = load i64, ptr %17, align 8
  %19 = trunc nuw i64 %_7 to i1
  br i1 %19, label %bb4, label %bb5

bb4:                                              ; preds = %bb2
  %20 = getelementptr inbounds i8, ptr %_5, i64 8
  %item = load i64, ptr %20, align 8, !noundef !3
  %21 = load i64, ptr %acc, align 8, !noundef !3
  %22 = add i64 %21, %item
  store i64 %22, ptr %acc, align 8
  call void @llvm.lifetime.end.p0(i64 16, ptr %_5)
  br label %bb1

bb5:                                              ; preds = %bb2
  call void @llvm.lifetime.end.p0(i64 16, ptr %_5)
  call void @"_ZN4core3ptr71drop_in_place$LT$core..array..iter..IntoIter$LT$usize$C$6_usize$GT$$GT$17hd85b6451ff2beb57E"(ptr noalias noundef align 8 dereferenceable(64) %iter)
  call void @llvm.lifetime.end.p0(i64 64, ptr %iter)
  call void @llvm.lifetime.end.p0(i64 64, ptr %_3)
  %_0 = load i64, ptr %acc, align 8, !noundef !3
  call void @llvm.lifetime.end.p0(i64 8, ptr %acc)
  ret i64 %_0

bb3:                                              ; No predecessors!
  unreachable

terminate:                                        ; preds = %bb7
  %23 = landingpad { ptr, i32 }
          filter [0 x ptr] zeroinitializer
  %24 = extractvalue { ptr, i32 } %23, 0
  %25 = extractvalue { ptr, i32 } %23, 1
  call void @_ZN4core9panicking16panic_in_cleanup17hcae40d8735d0599eE() #12
  unreachable

bb8:                                              ; preds = %bb7
  %26 = load ptr, ptr %0, align 8, !noundef !3
  %27 = getelementptr inbounds i8, ptr %0, i64 8
  %28 = load i32, ptr %27, align 8, !noundef !3
  call void @llvm.lifetime.end.p0(i64 16, ptr %0)
  %29 = insertvalue { ptr, i32 } poison, ptr %26, 0
  %30 = insertvalue { ptr, i32 } %29, i32 %28, 1
  resume { ptr, i32 } %30
}

; Function Attrs: nounwind nonlazybind uwtable
declare noundef range(i32 0, 10) i32 @rust_eh_personality(i32 noundef, i32 noundef, i64 noundef, ptr noundef, ptr noundef) unnamed_addr #3

; Function Attrs: cold minsize noinline noreturn nounwind nonlazybind optsize uwtable
declare void @_ZN4core9panicking19panic_cannot_unwind17hf77d1d116ce25e3bE() unnamed_addr #4

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(none)
declare i1 @llvm.expect.i1(i1, i1) #5

; Function Attrs: cold noinline noreturn nounwind nonlazybind uwtable
declare void @_ZN4core9panicking14panic_nounwind17h7b81d1449a5f4f5aE(ptr noalias noundef nonnull readonly align 1, i64 noundef) unnamed_addr #6

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i64 @llvm.ctpop.i64(i64) #7

; Function Attrs: cold noinline noreturn nonlazybind uwtable
declare void @_ZN4core9panicking9panic_fmt17hacfb58ec817221c8E(ptr noalias nocapture noundef readonly align 8 dereferenceable(48), ptr noalias noundef readonly align 8 dereferenceable(24)) unnamed_addr #8

; Function Attrs: cold noinline noreturn nonlazybind uwtable
declare void @_ZN4core9panicking5panic17heec94013e0df98e3E(ptr noalias noundef nonnull readonly align 1, i64 noundef, ptr noalias noundef readonly align 8 dereferenceable(24)) unnamed_addr #8

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write)
declare void @llvm.assume(i1 noundef) #9

; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite)
declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg) #10

; Function Attrs: cold minsize noinline noreturn nounwind nonlazybind optsize uwtable
declare void @_ZN4core9panicking16panic_in_cleanup17hcae40d8735d0599eE() unnamed_addr #4

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #11

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #11

attributes #0 = { inlinehint nounwind nonlazybind uwtable "probe-stack"="inline-asm" }
attributes #1 = { nonlazybind uwtable "probe-stack"="inline-asm" }
attributes #2 = { inlinehint nonlazybind uwtable "probe-stack"="inline-asm" }
attributes #3 = { nounwind nonlazybind uwtable "probe-stack"="inline-asm" }
attributes #4 = { cold minsize noinline noreturn nounwind nonlazybind optsize uwtable "probe-stack"="inline-asm" }
attributes #5 = { nocallback nofree nosync nounwind willreturn memory(none) }
attributes #6 = { cold noinline noreturn nounwind nonlazybind uwtable "probe-stack"="inline-asm" }
attributes #7 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
attributes #8 = { cold noinline noreturn nonlazybind uwtable "probe-stack"="inline-asm" }
attributes #9 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }
attributes #10 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
attributes #11 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
attributes #12 = { cold noreturn nounwind }
attributes #13 = { noreturn nounwind }
attributes #14 = { noreturn }
attributes #15 = { nounwind }
attributes #16 = { cold }

!llvm.module.flags = !{!0, !1}
!llvm.ident = !{!2}

!0 = !{i32 8, !"PIC Level", i32 2}
!1 = !{i32 2, !"RtLibUseGOT", i32 1}
!2 = !{!"rustc version 1.88.0-nightly"}
!3 = !{}
!4 = !{i64 8}
!5 = !{i64 0, i64 2}

(The original IR also had explicit target-cpu attributes, which I had to remove to let command-line options take effect.)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions