Skip to content
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

Optimization for types implementing drop seems broken on LLVM 19 #125373

Closed
durin42 opened this issue May 21, 2024 · 7 comments
Closed

Optimization for types implementing drop seems broken on LLVM 19 #125373

durin42 opened this issue May 21, 2024 · 7 comments
Assignees
Labels
A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. llvm-fixed-upstream Issue expected to be fixed by the next major LLVM upgrade, or backported fixes T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@durin42
Copy link
Contributor

durin42 commented May 21, 2024

This was only recently fixed by #123878 (bug was #120493), but the test fails on LLVM 19 like this:

failures:

---- [codegen] tests/codegen/vec-in-place.rs stdout ----

error: verification with 'FileCheck' failed
status: exit status: 1
command: "/var/lib/buildkite-agent/builds/rust-llvm-integrate/llvm-project/rust-llvm-integrate-prototype/llvm-installed/bin/FileCheck" "--input-file" "/var/lib/buildkite-agent/builds/rust-llvm-integrate/llvm-project/rust-llvm-integrate-prototype/build/x86_64-unknown-linux-gnu/test/codegen/vec-in-place/vec-in-place.ll" "/var/lib/buildkite-agent/builds/rust-llvm-integrate/llvm-project/rust-llvm-integrate-prototype/tests/codegen/vec-in-place.rs" "--check-prefix=CHECK" "--check-prefix" "NONMSVC" "--allow-unused-prefixes" "--dump-input-context" "100"
stdout: none
--- stderr -------------------------------
/var/lib/buildkite-agent/builds/rust-llvm-integrate/llvm-project/rust-llvm-integrate-prototype/tests/codegen/vec-in-place.rs:97:16: error: CHECK-NOT: excluded string found in input
 // CHECK-NOT: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
               ^
/var/lib/buildkite-agent/builds/rust-llvm-integrate/llvm-project/rust-llvm-integrate-prototype/build/x86_64-unknown-linux-gnu/test/codegen/vec-in-place/vec-in-place.ll:122:2: note: found here
 br i1 %_47.not8.i.i.i.i.i, label %bb6.i.i, label %bb11.i.i.i.i.i
 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/var/lib/buildkite-agent/builds/rust-llvm-integrate/llvm-project/rust-llvm-integrate-prototype/tests/codegen/vec-in-place.rs:98:16: error: CHECK-NOT: excluded string found in input
 // CHECK-NOT: call
               ^
/var/lib/buildkite-agent/builds/rust-llvm-integrate/llvm-project/rust-llvm-integrate-prototype/build/x86_64-unknown-linux-gnu/test/codegen/vec-in-place/vec-in-place.ll:119:7: note: found here
 tail call void @llvm.experimental.noalias.scope.decl(metadata !87)
      ^~~~
/var/lib/buildkite-agent/builds/rust-llvm-integrate/llvm-project/rust-llvm-integrate-prototype/tests/codegen/vec-in-place.rs:100:16: error: CHECK-NOT: excluded string found in input
 // CHECK-NOT: %{{.*}} = udiv
               ^
/var/lib/buildkite-agent/builds/rust-llvm-integrate/llvm-project/rust-llvm-integrate-prototype/build/x86_64-unknown-linux-gnu/test/codegen/vec-in-place/vec-in-place.ll:136:2: note: found here
 %3 = udiv exact i64 %2, 24
 ^~~~~~~~~
/var/lib/buildkite-agent/builds/rust-llvm-integrate/llvm-project/rust-llvm-integrate-prototype/tests/codegen/vec-in-place.rs:108:16: error: CHECK-NOT: excluded string found in input
 // CHECK-NOT: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
               ^
/var/lib/buildkite-agent/builds/rust-llvm-integrate/llvm-project/rust-llvm-integrate-prototype/build/x86_64-unknown-linux-gnu/test/codegen/vec-in-place/vec-in-place.ll:189:2: note: found here
 br i1 %_47.not8.i.i.i.i.i, label %bb6.i.i, label %bb11.i.i.i.i.i
 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/var/lib/buildkite-agent/builds/rust-llvm-integrate/llvm-project/rust-llvm-integrate-prototype/tests/codegen/vec-in-place.rs:109:16: error: CHECK-NOT: excluded string found in input
 // CHECK-NOT: call
               ^
/var/lib/buildkite-agent/builds/rust-llvm-integrate/llvm-project/rust-llvm-integrate-prototype/build/x86_64-unknown-linux-gnu/test/codegen/vec-in-place/vec-in-place.ll:186:7: note: found here
 tail call void @llvm.experimental.noalias.scope.decl(metadata !128)
      ^~~~
/var/lib/buildkite-agent/builds/rust-llvm-integrate/llvm-project/rust-llvm-integrate-prototype/tests/codegen/vec-in-place.rs:111:16: error: CHECK-NOT: excluded string found in input
 // CHECK-NOT: %{{.*}} = udiv
               ^
/var/lib/buildkite-agent/builds/rust-llvm-integrate/llvm-project/rust-llvm-integrate-prototype/build/x86_64-unknown-linux-gnu/test/codegen/vec-in-place/vec-in-place.ll:203:2: note: found here
 %3 = udiv exact i64 %2, 24
 ^~~~~~~~~

Input file: /var/lib/buildkite-agent/builds/rust-llvm-integrate/llvm-project/rust-llvm-integrate-prototype/build/x86_64-unknown-linux-gnu/test/codegen/vec-in-place/vec-in-place.ll
Check file: /var/lib/buildkite-agent/builds/rust-llvm-integrate/llvm-project/rust-llvm-integrate-prototype/tests/codegen/vec-in-place.rs

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

Input was:
<<<<<<
         .
         .
         .
        19:  %me.sroa.5.0.copyload.i = load i64, ptr %me.sroa.5.0.self.sroa_idx.i, align 8, !alias.scope !3, !noalias !6
        20:  store i64 %me.sroa.0.0.copyload.i, ptr %_0, align 8, !alias.scope !9, !noalias !14
        21:  %0 = getelementptr inbounds i8, ptr %_0, i64 8
        22:  store ptr %me.sroa.4.0.copyload.i, ptr %0, align 8, !alias.scope !9, !noalias !14
        23:  %1 = getelementptr inbounds i8, ptr %_0, i64 16
        24:  store i64 %me.sroa.5.0.copyload.i, ptr %1, align 8, !alias.scope !9, !noalias !14
        25:  ret void
        26: }
        27:
        28: ; Function Attrs: mustprogress nofree norecurse nosync nounwind nonlazybind willreturn memory(argmem: readwrite) uwtable
        29: define void @vec_iterator_cast_wrapper(ptr dead_on_unwind noalias nocapture noundef writable writeonly sret([24 x i8]) align 8 dereferenceable(24) %_0, ptr noalias nocapture noundef readonly align 8 dereferenceable(24) %vec) unnamed_addr #0 personality ptr @rust_eh_personality {
        30: start:
        31:  %me.sroa.0.0.copyload.i = load i64, ptr %vec, align 8, !alias.scope !17, !noalias !20
        32:  %me.sroa.4.0.self.sroa_idx.i = getelementptr inbounds i8, ptr %vec, i64 8
        33:  %me.sroa.4.0.copyload.i = load ptr, ptr %me.sroa.4.0.self.sroa_idx.i, align 8, !alias.scope !17, !noalias !20, !nonnull !8, !noundef !8
        34:  %me.sroa.5.0.self.sroa_idx.i = getelementptr inbounds i8, ptr %vec, i64 16
        35:  %me.sroa.5.0.copyload.i = load i64, ptr %me.sroa.5.0.self.sroa_idx.i, align 8, !alias.scope !17, !noalias !20
        36:  store i64 %me.sroa.0.0.copyload.i, ptr %_0, align 8, !alias.scope !22, !noalias !27
        37:  %0 = getelementptr inbounds i8, ptr %_0, i64 8
        38:  store ptr %me.sroa.4.0.copyload.i, ptr %0, align 8, !alias.scope !22, !noalias !27
        39:  %1 = getelementptr inbounds i8, ptr %_0, i64 16
        40:  store i64 %me.sroa.5.0.copyload.i, ptr %1, align 8, !alias.scope !22, !noalias !27
        41:  ret void
        42: }
        43:
        44: ; Function Attrs: nofree norecurse nosync nounwind nonlazybind memory(argmem: readwrite) uwtable
        45: define void @vec_iterator_cast_unwrap(ptr dead_on_unwind noalias nocapture noundef writable writeonly sret([24 x i8]) align 8 dereferenceable(24) %_0, ptr noalias nocapture noundef readonly align 8 dereferenceable(24) %vec) unnamed_addr #1 personality ptr @rust_eh_personality {
        46: start:
        47:  %me.sroa.0.0.copyload.i = load i64, ptr %vec, align 8, !alias.scope !30, !noalias !33
        48:  %me.sroa.4.0.self.sroa_idx.i = getelementptr inbounds i8, ptr %vec, i64 8
        49:  %me.sroa.4.0.copyload.i = load ptr, ptr %me.sroa.4.0.self.sroa_idx.i, align 8, !alias.scope !30, !noalias !33, !nonnull !8, !noundef !8
        50:  %me.sroa.5.0.self.sroa_idx.i = getelementptr inbounds i8, ptr %vec, i64 16
        51:  %me.sroa.5.0.copyload.i = load i64, ptr %me.sroa.5.0.self.sroa_idx.i, align 8, !alias.scope !30, !noalias !33
        52:  store i64 %me.sroa.0.0.copyload.i, ptr %_0, align 8, !alias.scope !35, !noalias !40
        53:  %0 = getelementptr inbounds i8, ptr %_0, i64 8
        54:  store ptr %me.sroa.4.0.copyload.i, ptr %0, align 8, !alias.scope !35, !noalias !40
        55:  %1 = getelementptr inbounds i8, ptr %_0, i64 16
        56:  store i64 %me.sroa.5.0.copyload.i, ptr %1, align 8, !alias.scope !35, !noalias !40
        57:  ret void
        58: }
        59:
        60: ; Function Attrs: nofree norecurse nosync nounwind nonlazybind memory(argmem: readwrite) uwtable
        61: define void @vec_iterator_cast_aggregate(ptr dead_on_unwind noalias nocapture noundef writable writeonly sret([24 x i8]) align 8 dereferenceable(24) %_0, ptr noalias nocapture noundef readonly align 8 dereferenceable(24) %vec) unnamed_addr #1 personality ptr @rust_eh_personality {
        62: start:
        63:  %me.sroa.0.0.copyload.i = load i64, ptr %vec, align 8, !alias.scope !43, !noalias !46
        64:  %me.sroa.4.0.self.sroa_idx.i = getelementptr inbounds i8, ptr %vec, i64 8
        65:  %me.sroa.4.0.copyload.i = load ptr, ptr %me.sroa.4.0.self.sroa_idx.i, align 8, !alias.scope !43, !noalias !46, !nonnull !8, !noundef !8
        66:  %me.sroa.5.0.self.sroa_idx.i = getelementptr inbounds i8, ptr %vec, i64 16
        67:  %me.sroa.5.0.copyload.i = load i64, ptr %me.sroa.5.0.self.sroa_idx.i, align 8, !alias.scope !43, !noalias !46
        68:  %_18.i.idx = and i64 %me.sroa.5.0.copyload.i, 576460752303423487
        69:  store i64 %me.sroa.0.0.copyload.i, ptr %_0, align 8, !alias.scope !48, !noalias !53
        70:  %0 = getelementptr inbounds i8, ptr %_0, i64 8
        71:  store ptr %me.sroa.4.0.copyload.i, ptr %0, align 8, !alias.scope !48, !noalias !53
        72:  %1 = getelementptr inbounds i8, ptr %_0, i64 16
        73:  store i64 %_18.i.idx, ptr %1, align 8, !alias.scope !48, !noalias !53
        74:  ret void
        75: }
        76:
        77: ; Function Attrs: nofree norecurse nosync nounwind nonlazybind memory(argmem: readwrite) uwtable
        78: define void @vec_iterator_cast_deaggregate_tra(ptr dead_on_unwind noalias nocapture noundef writable writeonly sret([24 x i8]) align 8 dereferenceable(24) %_0, ptr noalias nocapture noundef readonly align 8 dereferenceable(24) %vec) unnamed_addr #1 personality ptr @rust_eh_personality {
        79: start:
        80:  %me.sroa.0.0.copyload.i = load i64, ptr %vec, align 8, !alias.scope !56, !noalias !59
        81:  %me.sroa.4.0.self.sroa_idx.i = getelementptr inbounds i8, ptr %vec, i64 8
        82:  %me.sroa.4.0.copyload.i = load ptr, ptr %me.sroa.4.0.self.sroa_idx.i, align 8, !alias.scope !56, !noalias !59, !nonnull !8, !noundef !8
        83:  %me.sroa.5.0.self.sroa_idx.i = getelementptr inbounds i8, ptr %vec, i64 16
        84:  %me.sroa.5.0.copyload.i = load i64, ptr %me.sroa.5.0.self.sroa_idx.i, align 8, !alias.scope !56, !noalias !59
        85:  %_18.i.idx = and i64 %me.sroa.5.0.copyload.i, 576460752303423487
        86:  store i64 %me.sroa.0.0.copyload.i, ptr %_0, align 8, !alias.scope !61, !noalias !66
        87:  %0 = getelementptr inbounds i8, ptr %_0, i64 8
        88:  store ptr %me.sroa.4.0.copyload.i, ptr %0, align 8, !alias.scope !61, !noalias !66
        89:  %1 = getelementptr inbounds i8, ptr %_0, i64 16
        90:  store i64 %_18.i.idx, ptr %1, align 8, !alias.scope !61, !noalias !66
        91:  ret void
        92: }
        93:
        94: ; Function Attrs: nofree norecurse nosync nounwind nonlazybind memory(argmem: readwrite) uwtable
        95: define void @vec_iterator_cast_deaggregate_fold(ptr dead_on_unwind noalias nocapture noundef writable writeonly sret([24 x i8]) align 8 dereferenceable(24) %_0, ptr noalias nocapture noundef readonly align 8 dereferenceable(24) %vec) unnamed_addr #1 personality ptr @rust_eh_personality {
        96: start:
        97:  %me.sroa.0.0.copyload.i = load i64, ptr %vec, align 8, !alias.scope !69, !noalias !72
        98:  %me.sroa.4.0.self.sroa_idx.i = getelementptr inbounds i8, ptr %vec, i64 8
        99:  %me.sroa.4.0.copyload.i = load ptr, ptr %me.sroa.4.0.self.sroa_idx.i, align 8, !alias.scope !69, !noalias !72, !nonnull !8, !noundef !8
       100:  %me.sroa.5.0.self.sroa_idx.i = getelementptr inbounds i8, ptr %vec, i64 16
       101:  %me.sroa.5.0.copyload.i = load i64, ptr %me.sroa.5.0.self.sroa_idx.i, align 8, !alias.scope !69, !noalias !72
       102:  store i64 %me.sroa.0.0.copyload.i, ptr %_0, align 8, !alias.scope !74, !noalias !79
       103:  %0 = getelementptr inbounds i8, ptr %_0, i64 8
       104:  store ptr %me.sroa.4.0.copyload.i, ptr %0, align 8, !alias.scope !74, !noalias !79
       105:  %1 = getelementptr inbounds i8, ptr %_0, i64 16
       106:  store i64 %me.sroa.5.0.copyload.i, ptr %1, align 8, !alias.scope !74, !noalias !79
       107:  ret void
       108: }
       109:
       110: ; Function Attrs: nounwind nonlazybind uwtable
       111: define void @vec_iterator_cast_unwrap_drop(ptr dead_on_unwind noalias nocapture noundef writable writeonly sret([24 x i8]) align 8 dereferenceable(24) %_0, ptr noalias nocapture noundef readonly align 8 dereferenceable(24) %vec) unnamed_addr #2 personality ptr @rust_eh_personality {
       112: start:
       113:  %me.sroa.0.0.copyload.i = load i64, ptr %vec, align 8, !alias.scope !82, !noalias !85
       114:  %me.sroa.4.0.self.sroa_idx.i = getelementptr inbounds i8, ptr %vec, i64 8
       115:  %me.sroa.4.0.copyload.i = load ptr, ptr %me.sroa.4.0.self.sroa_idx.i, align 8, !alias.scope !82, !noalias !85, !nonnull !8, !noundef !8
       116:  %me.sroa.5.0.self.sroa_idx.i = getelementptr inbounds i8, ptr %vec, i64 16
       117:  %me.sroa.5.0.copyload.i = load i64, ptr %me.sroa.5.0.self.sroa_idx.i, align 8, !alias.scope !82, !noalias !85
       118:  %_18.i = getelementptr inbounds %"Wrapper<alloc::string::String>", ptr %me.sroa.4.0.copyload.i, i64 %me.sroa.5.0.copyload.i
       119:  tail call void @llvm.experimental.noalias.scope.decl(metadata !87)
not:98            !~~~                                                           error: no match expected
       120:  tail call void @llvm.experimental.noalias.scope.decl(metadata !90)
       121:  %_47.not8.i.i.i.i.i = icmp eq i64 %me.sroa.5.0.copyload.i, 0
       122:  br i1 %_47.not8.i.i.i.i.i, label %bb6.i.i, label %bb11.i.i.i.i.i
not:97       !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  error: no match expected
       123:
       124: bb11.i.i.i.i.i: ; preds = %start, %bb11.i.i.i.i.i
       125:  %accum.sroa.4.010.i.i.i.i.i = phi ptr [ %_6.i.i.i.i.i.i.i, %bb11.i.i.i.i.i ], [ %me.sroa.4.0.copyload.i, %start ]
       126:  %_6.i.i.i.i.i.i.i = getelementptr i8, ptr %accum.sroa.4.010.i.i.i.i.i, i64 24
       127:  %_47.not.i.i.i.i.i = icmp eq ptr %_6.i.i.i.i.i.i.i, %_18.i
       128:  br i1 %_47.not.i.i.i.i.i, label %bb6.i.i, label %bb11.i.i.i.i.i
       129:
       130: bb6.i.i: ; preds = %bb11.i.i.i.i.i, %start
       131:  %self2.i.i.i = phi ptr [ %me.sroa.4.0.copyload.i, %start ], [ %_6.i.i.i.i.i.i.i, %bb11.i.i.i.i.i ]
       132:  %accum.sroa.4.0.lcssa.i.i.i.i.i = phi ptr [ %me.sroa.4.0.copyload.i, %start ], [ %_18.i, %bb11.i.i.i.i.i ]
       133:  %0 = ptrtoint ptr %_18.i to i64
       134:  %1 = ptrtoint ptr %self2.i.i.i to i64
       135:  %2 = sub nuw i64 %0, %1
       136:  %3 = udiv exact i64 %2, 24
not:100      !~~~~~~~~                   error: no match expected
       137:  tail call void @llvm.experimental.noalias.scope.decl(metadata !93)
       138:  %_710.i.i.i.i = icmp eq ptr %_18.i, %self2.i.i.i
       139:  br i1 %_710.i.i.i.i, label %"_ZN5alloc3vec16in_place_collect108_$LT$impl$u20$alloc..vec..spec_from_iter..SpecFromIter$LT$T$C$I$GT$$u20$for$u20$alloc..vec..Vec$LT$T$GT$$GT$9from_iter17heaba35c2218b2756E.exit", label %bb5.i.i.i.i
       140:
       141: bb5.i.i.i.i: ; preds = %bb6.i.i, %"_ZN4core3ptr71drop_in_place$LT$vec_in_place..Wrapper$LT$alloc..string..String$GT$$GT$17he9d1d0763a5e7e3bE.exit.i.i.i.i"
       142:  %_3.sroa.0.011.i.i.i.i = phi i64 [ %4, %"_ZN4core3ptr71drop_in_place$LT$vec_in_place..Wrapper$LT$alloc..string..String$GT$$GT$17he9d1d0763a5e7e3bE.exit.i.i.i.i" ], [ 0, %bb6.i.i ]
       143:  %_6.i.i.i.i = getelementptr inbounds [0 x %"Wrapper<alloc::string::String>"], ptr %self2.i.i.i, i64 0, i64 %_3.sroa.0.011.i.i.i.i
       144:  %4 = add nuw i64 %_3.sroa.0.011.i.i.i.i, 1
       145:  tail call void @llvm.experimental.noalias.scope.decl(metadata !96)
       146:  tail call void @llvm.experimental.noalias.scope.decl(metadata !99)
       147:  tail call void @llvm.experimental.noalias.scope.decl(metadata !102)
       148:  tail call void @llvm.experimental.noalias.scope.decl(metadata !105)
       149:  tail call void @llvm.experimental.noalias.scope.decl(metadata !108)
       150:  %_3.i.i.i1.i.i.i.i.i.i.i = load i64, ptr %_6.i.i.i.i, align 8, !alias.scope !111, !noalias !114, !noundef !8
       151:  %5 = icmp eq i64 %_3.i.i.i1.i.i.i.i.i.i.i, 0
       152:  br i1 %5, label %"_ZN4core3ptr71drop_in_place$LT$vec_in_place..Wrapper$LT$alloc..string..String$GT$$GT$17he9d1d0763a5e7e3bE.exit.i.i.i.i", label %"_ZN63_$LT$alloc..alloc..Global$u20$as$u20$core..alloc..Allocator$GT$10deallocate17h0f2d39528d187dc6E.exit.i.i2.i.i.i.i.i.i.i"
       153:
       154: "_ZN63_$LT$alloc..alloc..Global$u20$as$u20$core..alloc..Allocator$GT$10deallocate17h0f2d39528d187dc6E.exit.i.i2.i.i.i.i.i.i.i": ; preds = %bb5.i.i.i.i
       155:  %6 = getelementptr inbounds i8, ptr %_6.i.i.i.i, i64 8
       156:  %self1.i.i.i3.i.i.i.i.i.i.i = load ptr, ptr %6, align 8, !alias.scope !111, !noalias !114, !nonnull !8, !noundef !8
       157:  tail call void @__rust_dealloc(ptr noundef nonnull %self1.i.i.i3.i.i.i.i.i.i.i, i64 noundef %_3.i.i.i1.i.i.i.i.i.i.i, i64 noundef 1) #6, !noalias !120
       158:  br label %"_ZN4core3ptr71drop_in_place$LT$vec_in_place..Wrapper$LT$alloc..string..String$GT$$GT$17he9d1d0763a5e7e3bE.exit.i.i.i.i"
       159:
       160: "_ZN4core3ptr71drop_in_place$LT$vec_in_place..Wrapper$LT$alloc..string..String$GT$$GT$17he9d1d0763a5e7e3bE.exit.i.i.i.i": ; preds = %"_ZN63_$LT$alloc..alloc..Global$u20$as$u20$core..alloc..Allocator$GT$10deallocate17h0f2d39528d187dc6E.exit.i.i2.i.i.i.i.i.i.i", %bb5.i.i.i.i
       161:  %_7.i.i.i.i = icmp eq i64 %4, %3
       162:  br i1 %_7.i.i.i.i, label %"_ZN5alloc3vec16in_place_collect108_$LT$impl$u20$alloc..vec..spec_from_iter..SpecFromIter$LT$T$C$I$GT$$u20$for$u20$alloc..vec..Vec$LT$T$GT$$GT$9from_iter17heaba35c2218b2756E.exit", label %bb5.i.i.i.i
       163:
       164: "_ZN5alloc3vec16in_place_collect108_$LT$impl$u20$alloc..vec..spec_from_iter..SpecFromIter$LT$T$C$I$GT$$u20$for$u20$alloc..vec..Vec$LT$T$GT$$GT$9from_iter17heaba35c2218b2756E.exit": ; preds = %"_ZN4core3ptr71drop_in_place$LT$vec_in_place..Wrapper$LT$alloc..string..String$GT$$GT$17he9d1d0763a5e7e3bE.exit.i.i.i.i", %bb6.i.i
       165:  %7 = ptrtoint ptr %accum.sroa.4.0.lcssa.i.i.i.i.i to i64
       166:  %8 = ptrtoint ptr %me.sroa.4.0.copyload.i to i64
       167:  %9 = sub nuw i64 %7, %8
       168:  %10 = udiv exact i64 %9, 24
       169:  store i64 %me.sroa.0.0.copyload.i, ptr %_0, align 8, !alias.scope !121, !noalias !122
       170:  %11 = getelementptr inbounds i8, ptr %_0, i64 8
       171:  store ptr %me.sroa.4.0.copyload.i, ptr %11, align 8, !alias.scope !121, !noalias !122
       172:  %12 = getelementptr inbounds i8, ptr %_0, i64 16
       173:  store i64 %10, ptr %12, align 8, !alias.scope !121, !noalias !122
       174:  ret void
       175: }
       176:
       177: ; Function Attrs: nounwind nonlazybind uwtable
       178: define void @vec_iterator_cast_wrap_drop(ptr dead_on_unwind noalias nocapture noundef writable writeonly sret([24 x i8]) align 8 dereferenceable(24) %_0, ptr noalias nocapture noundef readonly align 8 dereferenceable(24) %vec) unnamed_addr #2 personality ptr @rust_eh_personality {
       179: start:
       180:  %me.sroa.0.0.copyload.i = load i64, ptr %vec, align 8, !alias.scope !123, !noalias !126
       181:  %me.sroa.4.0.self.sroa_idx.i = getelementptr inbounds i8, ptr %vec, i64 8
       182:  %me.sroa.4.0.copyload.i = load ptr, ptr %me.sroa.4.0.self.sroa_idx.i, align 8, !alias.scope !123, !noalias !126, !nonnull !8, !noundef !8
       183:  %me.sroa.5.0.self.sroa_idx.i = getelementptr inbounds i8, ptr %vec, i64 16
       184:  %me.sroa.5.0.copyload.i = load i64, ptr %me.sroa.5.0.self.sroa_idx.i, align 8, !alias.scope !123, !noalias !126
       185:  %_18.i = getelementptr inbounds %"alloc::string::String", ptr %me.sroa.4.0.copyload.i, i64 %me.sroa.5.0.copyload.i
       186:  tail call void @llvm.experimental.noalias.scope.decl(metadata !128)
not:109           !~~~                                                            error: no match expected
       187:  tail call void @llvm.experimental.noalias.scope.decl(metadata !131)
       188:  %_47.not8.i.i.i.i.i = icmp eq i64 %me.sroa.5.0.copyload.i, 0
       189:  br i1 %_47.not8.i.i.i.i.i, label %bb6.i.i, label %bb11.i.i.i.i.i
not:108      !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  error: no match expected
       190:
       191: bb11.i.i.i.i.i: ; preds = %start, %bb11.i.i.i.i.i
       192:  %accum.sroa.4.010.i.i.i.i.i = phi ptr [ %_6.i.i.i.i.i.i.i, %bb11.i.i.i.i.i ], [ %me.sroa.4.0.copyload.i, %start ]
       193:  %_6.i.i.i.i.i.i.i = getelementptr i8, ptr %accum.sroa.4.010.i.i.i.i.i, i64 24
       194:  %_47.not.i.i.i.i.i = icmp eq ptr %_6.i.i.i.i.i.i.i, %_18.i
       195:  br i1 %_47.not.i.i.i.i.i, label %bb6.i.i, label %bb11.i.i.i.i.i
       196:
       197: bb6.i.i: ; preds = %bb11.i.i.i.i.i, %start
       198:  %self2.i.i.i = phi ptr [ %me.sroa.4.0.copyload.i, %start ], [ %_6.i.i.i.i.i.i.i, %bb11.i.i.i.i.i ]
       199:  %accum.sroa.4.0.lcssa.i.i.i.i.i = phi ptr [ %me.sroa.4.0.copyload.i, %start ], [ %_18.i, %bb11.i.i.i.i.i ]
       200:  %0 = ptrtoint ptr %_18.i to i64
       201:  %1 = ptrtoint ptr %self2.i.i.i to i64
       202:  %2 = sub nuw i64 %0, %1
       203:  %3 = udiv exact i64 %2, 24
not:111      !~~~~~~~~                   error: no match expected
       204:  tail call void @llvm.experimental.noalias.scope.decl(metadata !134)
       205:  %_710.i.i.i.i = icmp eq ptr %_18.i, %self2.i.i.i
       206:  br i1 %_710.i.i.i.i, label %"_ZN5alloc3vec16in_place_collect108_$LT$impl$u20$alloc..vec..spec_from_iter..SpecFromIter$LT$T$C$I$GT$$u20$for$u20$alloc..vec..Vec$LT$T$GT$$GT$9from_iter17h2f243e1fd049e2c3E.exit", label %bb5.i.i.i.i
       207:
       208: bb5.i.i.i.i: ; preds = %bb6.i.i, %"_ZN4core3ptr42drop_in_place$LT$alloc..string..String$GT$17ha0ebea32be7a5449E.exit.i.i.i.i"
       209:  %_3.sroa.0.011.i.i.i.i = phi i64 [ %4, %"_ZN4core3ptr42drop_in_place$LT$alloc..string..String$GT$17ha0ebea32be7a5449E.exit.i.i.i.i" ], [ 0, %bb6.i.i ]
       210:  %_6.i.i.i.i = getelementptr inbounds [0 x %"alloc::string::String"], ptr %self2.i.i.i, i64 0, i64 %_3.sroa.0.011.i.i.i.i
       211:  %4 = add nuw i64 %_3.sroa.0.011.i.i.i.i, 1
       212:  tail call void @llvm.experimental.noalias.scope.decl(metadata !137)
       213:  tail call void @llvm.experimental.noalias.scope.decl(metadata !140)
       214:  tail call void @llvm.experimental.noalias.scope.decl(metadata !143)
       215:  tail call void @llvm.experimental.noalias.scope.decl(metadata !146)
       216:  %_3.i.i.i1.i.i.i.i.i.i = load i64, ptr %_6.i.i.i.i, align 8, !alias.scope !149, !noalias !152, !noundef !8
       217:  %5 = icmp eq i64 %_3.i.i.i1.i.i.i.i.i.i, 0
       218:  br i1 %5, label %"_ZN4core3ptr42drop_in_place$LT$alloc..string..String$GT$17ha0ebea32be7a5449E.exit.i.i.i.i", label %"_ZN63_$LT$alloc..alloc..Global$u20$as$u20$core..alloc..Allocator$GT$10deallocate17h0f2d39528d187dc6E.exit.i.i2.i.i.i.i.i.i"
       219:
       220: "_ZN63_$LT$alloc..alloc..Global$u20$as$u20$core..alloc..Allocator$GT$10deallocate17h0f2d39528d187dc6E.exit.i.i2.i.i.i.i.i.i": ; preds = %bb5.i.i.i.i
       221:  %6 = getelementptr inbounds i8, ptr %_6.i.i.i.i, i64 8
       222:  %self1.i.i.i3.i.i.i.i.i.i = load ptr, ptr %6, align 8, !alias.scope !149, !noalias !152, !nonnull !8, !noundef !8
       223:  tail call void @__rust_dealloc(ptr noundef nonnull %self1.i.i.i3.i.i.i.i.i.i, i64 noundef %_3.i.i.i1.i.i.i.i.i.i, i64 noundef 1) #6, !noalias !158
       224:  br label %"_ZN4core3ptr42drop_in_place$LT$alloc..string..String$GT$17ha0ebea32be7a5449E.exit.i.i.i.i"
       225:
       226: "_ZN4core3ptr42drop_in_place$LT$alloc..string..String$GT$17ha0ebea32be7a5449E.exit.i.i.i.i": ; preds = %"_ZN63_$LT$alloc..alloc..Global$u20$as$u20$core..alloc..Allocator$GT$10deallocate17h0f2d39528d187dc6E.exit.i.i2.i.i.i.i.i.i", %bb5.i.i.i.i
       227:  %_7.i.i.i.i = icmp eq i64 %4, %3
       228:  br i1 %_7.i.i.i.i, label %"_ZN5alloc3vec16in_place_collect108_$LT$impl$u20$alloc..vec..spec_from_iter..SpecFromIter$LT$T$C$I$GT$$u20$for$u20$alloc..vec..Vec$LT$T$GT$$GT$9from_iter17h2f243e1fd049e2c3E.exit", label %bb5.i.i.i.i
       229:
       230: "_ZN5alloc3vec16in_place_collect108_$LT$impl$u20$alloc..vec..spec_from_iter..SpecFromIter$LT$T$C$I$GT$$u20$for$u20$alloc..vec..Vec$LT$T$GT$$GT$9from_iter17h2f243e1fd049e2c3E.exit": ; preds = %"_ZN4core3ptr42drop_in_place$LT$alloc..string..String$GT$17ha0ebea32be7a5449E.exit.i.i.i.i", %bb6.i.i
       231:  %7 = ptrtoint ptr %accum.sroa.4.0.lcssa.i.i.i.i.i to i64
       232:  %8 = ptrtoint ptr %me.sroa.4.0.copyload.i to i64
       233:  %9 = sub nuw i64 %7, %8
       234:  %10 = udiv exact i64 %9, 24
       235:  store i64 %me.sroa.0.0.copyload.i, ptr %_0, align 8, !alias.scope !159, !noalias !160
       236:  %11 = getelementptr inbounds i8, ptr %_0, i64 8
       237:  store ptr %me.sroa.4.0.copyload.i, ptr %11, align 8, !alias.scope !159, !noalias !160
       238:  %12 = getelementptr inbounds i8, ptr %_0, i64 16
       239:  store i64 %10, ptr %12, align 8, !alias.scope !159, !noalias !160
       240:  ret void
       241: }
       242:
       243: ; Function Attrs: nonlazybind uwtable
       244: declare noundef i32 @rust_eh_personality(i32 noundef, i32 noundef, i64 noundef, ptr noundef, ptr noundef) unnamed_addr #3
       245:
       246: ; Function Attrs: nounwind nonlazybind allockind("free") uwtable
       247: declare void @__rust_dealloc(ptr allocptr noundef, i64 noundef, i64 noundef) unnamed_addr #4
       248:
       249: ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: readwrite)
       250: declare void @llvm.experimental.noalias.scope.decl(metadata) #5
       251:
       252: attributes #0 = { mustprogress nofree norecurse nosync nounwind nonlazybind willreturn memory(argmem: readwrite) uwtable "probe-stack"="inline-asm" "target-cpu"="x86-64" }
       253: attributes #1 = { nofree norecurse nosync nounwind nonlazybind memory(argmem: readwrite) uwtable "probe-stack"="inline-asm" "target-cpu"="x86-64" }
       254: attributes #2 = { nounwind nonlazybind uwtable "probe-stack"="inline-asm" "target-cpu"="x86-64" }
       255: attributes #3 = { nonlazybind uwtable "probe-stack"="inline-asm" "target-cpu"="x86-64" }
       256: attributes #4 = { nounwind nonlazybind allockind("free") uwtable "alloc-family"="__rust_alloc" "probe-stack"="inline-asm" "target-cpu"="x86-64" }
       257: attributes #5 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: readwrite) }
       258: attributes #6 = { nounwind }
       259:
       260: !llvm.module.flags = !{!0, !1}
       261: !llvm.ident = !{!2}
       262:
       263: !0 = !{i32 8, !"PIC Level", i32 2}
       264: !1 = !{i32 2, !"RtLibUseGOT", i32 1}
       265: !2 = !{!"rustc version 1.80.0-dev"}
       266: !3 = !{!4}
       267: !4 = distinct !{!4, !5, !"_ZN90_$LT$alloc..vec..Vec$LT$T$C$A$GT$$u20$as$u20$core..iter..traits..collect..IntoIterator$GT$9into_iter17h4e944e9c75742b34E: %self"}
       268: !5 = distinct !{!5, !"_ZN90_$LT$alloc..vec..Vec$LT$T$C$A$GT$$u20$as$u20$core..iter..traits..collect..IntoIterator$GT$9into_iter17h4e944e9c75742b34E"}
       269: !6 = !{!7}
       270: !7 = distinct !{!7, !5, !"_ZN90_$LT$alloc..vec..Vec$LT$T$C$A$GT$$u20$as$u20$core..iter..traits..collect..IntoIterator$GT$9into_iter17h4e944e9c75742b34E: %_0"}
       271: !8 = !{}
       272: !9 = !{!10, !12}
       273: !10 = distinct !{!10, !11, !"_ZN5alloc3vec16in_place_collect18from_iter_in_place17h95c3e8ed0aa22dd5E: %vec"}
       274: !11 = distinct !{!11, !"_ZN5alloc3vec16in_place_collect18from_iter_in_place17h95c3e8ed0aa22dd5E"}
       275: !12 = distinct !{!12, !13, !"_ZN5alloc3vec16in_place_collect108_$LT$impl$u20$alloc..vec..spec_from_iter..SpecFromIter$LT$T$C$I$GT$$u20$for$u20$alloc..vec..Vec$LT$T$GT$$GT$9from_iter17h42a09ea266c3b9e0E: %_0"}
       276: !13 = distinct !{!13, !"_ZN5alloc3vec16in_place_collect108_$LT$impl$u20$alloc..vec..spec_from_iter..SpecFromIter$LT$T$C$I$GT$$u20$for$u20$alloc..vec..Vec$LT$T$GT$$GT$9from_iter17h42a09ea266c3b9e0E"}
       277: !14 = !{!15, !16}
       278: !15 = distinct !{!15, !11, !"_ZN5alloc3vec16in_place_collect18from_iter_in_place17h95c3e8ed0aa22dd5E: %iterator"}
       279: !16 = distinct !{!16, !13, !"_ZN5alloc3vec16in_place_collect108_$LT$impl$u20$alloc..vec..spec_from_iter..SpecFromIter$LT$T$C$I$GT$$u20$for$u20$alloc..vec..Vec$LT$T$GT$$GT$9from_iter17h42a09ea266c3b9e0E: %iterator"}
       280: !17 = !{!18}
       281: !18 = distinct !{!18, !19, !"_ZN90_$LT$alloc..vec..Vec$LT$T$C$A$GT$$u20$as$u20$core..iter..traits..collect..IntoIterator$GT$9into_iter17h816975ba8271cf4fE: %self"}
       282: !19 = distinct !{!19, !"_ZN90_$LT$alloc..vec..Vec$LT$T$C$A$GT$$u20$as$u20$core..iter..traits..collect..IntoIterator$GT$9into_iter17h816975ba8271cf4fE"}
       283: !20 = !{!21}
       284: !21 = distinct !{!21, !19, !"_ZN90_$LT$alloc..vec..Vec$LT$T$C$A$GT$$u20$as$u20$core..iter..traits..collect..IntoIterator$GT$9into_iter17h816975ba8271cf4fE: %_0"}
       285: !22 = !{!23, !25}
       286: !23 = distinct !{!23, !24, !"_ZN5alloc3vec16in_place_collect18from_iter_in_place17hf702aa1637d1c1e2E: %vec"}
       287: !24 = distinct !{!24, !"_ZN5alloc3vec16in_place_collect18from_iter_in_place17hf702aa1637d1c1e2E"}
       288: !25 = distinct !{!25, !26, !"_ZN5alloc3vec16in_place_collect108_$LT$impl$u20$alloc..vec..spec_from_iter..SpecFromIter$LT$T$C$I$GT$$u20$for$u20$alloc..vec..Vec$LT$T$GT$$GT$9from_iter17h8ca7b4c96408a2b9E: %_0"}
       289: !26 = distinct !{!26, !"_ZN5alloc3vec16in_place_collect108_$LT$impl$u20$alloc..vec..spec_from_iter..SpecFromIter$LT$T$C$I$GT$$u20$for$u20$alloc..vec..Vec$LT$T$GT$$GT$9from_iter17h8ca7b4c96408a2b9E"}
       290: !27 = !{!28, !29}
       291: !28 = distinct !{!28, !24, !"_ZN5alloc3vec16in_place_collect18from_iter_in_place17hf702aa1637d1c1e2E: %iterator"}
       292: !29 = distinct !{!29, !26, !"_ZN5alloc3vec16in_place_collect108_$LT$impl$u20$alloc..vec..spec_from_iter..SpecFromIter$LT$T$C$I$GT$$u20$for$u20$alloc..vec..Vec$LT$T$GT$$GT$9from_iter17h8ca7b4c96408a2b9E: %iterator"}
       293: !30 = !{!31}
       294: !31 = distinct !{!31, !32, !"_ZN90_$LT$alloc..vec..Vec$LT$T$C$A$GT$$u20$as$u20$core..iter..traits..collect..IntoIterator$GT$9into_iter17h42a94bf679cb6a17E: %self"}
       295: !32 = distinct !{!32, !"_ZN90_$LT$alloc..vec..Vec$LT$T$C$A$GT$$u20$as$u20$core..iter..traits..collect..IntoIterator$GT$9into_iter17h42a94bf679cb6a17E"}
       296: !33 = !{!34}
       297: !34 = distinct !{!34, !32, !"_ZN90_$LT$alloc..vec..Vec$LT$T$C$A$GT$$u20$as$u20$core..iter..traits..collect..IntoIterator$GT$9into_iter17h42a94bf679cb6a17E: %_0"}
       298: !35 = !{!36, !38}
       299: !36 = distinct !{!36, !37, !"_ZN5alloc3vec16in_place_collect18from_iter_in_place17h090eecf57f869f89E: %vec"}
       300: !37 = distinct !{!37, !"_ZN5alloc3vec16in_place_collect18from_iter_in_place17h090eecf57f869f89E"}
       301: !38 = distinct !{!38, !39, !"_ZN5alloc3vec16in_place_collect108_$LT$impl$u20$alloc..vec..spec_from_iter..SpecFromIter$LT$T$C$I$GT$$u20$for$u20$alloc..vec..Vec$LT$T$GT$$GT$9from_iter17h0d58b7de551627c3E: %_0"}
       302: !39 = distinct !{!39, !"_ZN5alloc3vec16in_place_collect108_$LT$impl$u20$alloc..vec..spec_from_iter..SpecFromIter$LT$T$C$I$GT$$u20$for$u20$alloc..vec..Vec$LT$T$GT$$GT$9from_iter17h0d58b7de551627c3E"}
       303: !40 = !{!41, !42}
         .
         .
         .
>>>>>>
------------------------------------------



failures:
    [codegen] tests/codegen/vec-in-place.rs

Filing this so we don't lose track of it.

@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label May 21, 2024
@durin42 durin42 added A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. and removed needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels May 21, 2024
@durin42
Copy link
Contributor Author

durin42 commented May 21, 2024

FYI @jwong101

@jwong101
Copy link
Contributor

@rustbot claim

@jieyouxu jieyouxu added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label May 21, 2024
@jwong101
Copy link
Contributor

jwong101 commented May 29, 2024

After taking a look at this, the problem seems to be that GVN isn't propagating the pointer equalities in the following IR after this PR:

define void @src(ptr noundef %buf, ptr noundef %start, ptr noundef %end) {
bb2:
  %iter.exhausted = icmp eq ptr %end, %start
  br i1 %iter.exhausted, label %bb5, label %bb3

bb3:                                       ; preds = %bb2
  %iter.empty.loop = icmp eq ptr %end, %buf
  br i1 %iter.empty.loop, label %bb5, label %exit

bb5:                                              ; preds = %bb2, %bb3
  %self.end = phi ptr [ %buf, %bb3 ], [ %start, %bb2 ]
  ;%self.end = phi ptr [ %end %bb3 ], [ %end %bb2 ] <- gvn used to propogate this
  %_710.i.i = icmp eq ptr %end, %self.end
  br i1 %_710.i.i, label %exit, label %bb6

bb6:                                          ; preds = %bb5
  %inner.cap = load i64, ptr %self.end, align 8, !noundef !0
  call void @effect(i64 %inner.cap)
  br label %exit

exit: ; preds = %bb3, %bb5, %bb6
  ret void
}


define void @tgt(ptr noundef %buf, ptr noundef %start, ptr noundef %end) {
  ret void
}

Alive Proof

Before, GVN would blindly propagate %end to each operand of %self.end. Just doing that is incorrect, since there's a load of %self.end, which might not have the same provenance as the replaced pointer.

However, it should be sound to propagate pointer equality to just comparisons, which the PR does when the only uses are icmp or ptrtoint instructions or phi and select instructions that feed into them.

Unfortunately, this doesn't help in our case, since the phi node is also used by a load. My naive idea would be to either create duplicate phi nodes that are only used by ptrtoint or icmp, so we can propagate equality there or store pointer equality information about the phi node in some side table and replace only icmp and ptrtoint uses if all of the phi node operands turn out to be equivalent.

There's probably a better way, as I'm not that familiar with LLVM's GVNpass. Is there another approach I could take for solving the above problem; should I be looking at another pass?

@nikic
Copy link
Contributor

nikic commented Jul 15, 2024

@jwong101 That test case is a bit over-reduced. In the original test, we actually do know that the underlying objects are the same, but we have to look through phi nodes to detect this. Something like this fixes the failure:

diff --git a/llvm/lib/Analysis/Loads.cpp b/llvm/lib/Analysis/Loads.cpp
index 1d54a66705a2..13bd07312d8e 100644
--- a/llvm/lib/Analysis/Loads.cpp
+++ b/llvm/lib/Analysis/Loads.cpp
@@ -743,7 +743,11 @@ static bool isPointerAlwaysReplaceable(const Value *From, const Value *To,
   if (isa<Constant>(To) &&
       isDereferenceablePointer(To, Type::getInt8Ty(To->getContext()), DL))
     return true;
-  if (getUnderlyingObject(From) == getUnderlyingObject(To))
+  SmallVector<const Value *> FromObjs, ToObjs;
+  getUnderlyingObjects(From, FromObjs);
+  getUnderlyingObjects(To, ToObjs);
+  if (FromObjs.size() == 1 && ToObjs.size() == 1 &&
+      FromObjs.back() == ToObjs.back())
     return true;
   return false;
 }

We wouldn't want to do literally that, but something along those lines. I'll try to put up a patch soon.

@nikic
Copy link
Contributor

nikic commented Jul 18, 2024

Finally got around to this, here is the patch: llvm/llvm-project#99509

@DianQK
Copy link
Member

DianQK commented Jul 23, 2024

@rustbot label +llvm-fixed-upstream

@rustbot rustbot added the llvm-fixed-upstream Issue expected to be fixed by the next major LLVM upgrade, or backported fixes label Jul 23, 2024
@nikic
Copy link
Contributor

nikic commented Aug 1, 2024

Closing this, as it is fixed and we already have a codegen test.

@nikic nikic closed this as completed Aug 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. llvm-fixed-upstream Issue expected to be fixed by the next major LLVM upgrade, or backported fixes T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

6 participants