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

Slice index becomes wrong (beta regression) #73223

Closed
djc opened this issue Jun 10, 2020 · 16 comments · Fixed by #73949
Closed

Slice index becomes wrong (beta regression) #73223

djc opened this issue Jun 10, 2020 · 16 comments · Fixed by #73949
Assignees
Labels
A-mir-opt Area: MIR optimizations C-bug Category: This is a bug. P-medium Medium priority requires-nightly This issue requires a nightly compiler in some way. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@djc
Copy link
Contributor

djc commented Jun 10, 2020

One of my tests (test_nested_rest) is failing on beta (in CI and locally) but not stable (locally).

https://github.com/djc/mendes/pull/18/checks?check_run_id=759480560

Minimal reproduction:

https://play.rust-lang.org/?version=beta&mode=debug&edition=2018&gist=e31da4955ca52b19e2131b51473bcb4e

When executed with miri, it doesn't panic. When the call to nothing() is moved before the assignment to self.prev, it also doesn't panic. Works on stable, panics on both beta and nightly-2020-06-10.

searched nightlies: from nightly-2020-04-12 to nightly-2020-06-10
regressed nightly: nightly-2020-05-15
searched commits: from 75e1463 to a74d186
regressed commit: 7c34d8d

bisected with cargo-bisect-rustc v0.5.2

Host triple: x86_64-apple-darwin
Reproduce with:

cargo bisect-rustc --start 2020-04-12 --end 2020-06-10 -- run 
@djc djc added the C-bug Category: This is a bug. label Jun 10, 2020
@jonas-schievink jonas-schievink added the regression-from-stable-to-beta Performance or correctness regression from stable to beta. label Jun 10, 2020
@rustbot rustbot added the I-prioritize Issue: Indicates that prioritization has been requested for this issue. label Jun 10, 2020
@Dylan-DPC-zz
Copy link

This is the test in question

@djc
Copy link
Contributor Author

djc commented Jun 11, 2020

Here's a reduced test case that doesn't quite reproduce what I'm seeing but has what I think should be a smoking gun:

https://play.rust-lang.org/?version=beta&mode=debug&edition=2018&gist=d1fa510430df349361ab658c7d51ad08

If you comment out the dbg!() statement on line 19, the slicing at line 21 panics even though start should be well within bounds. However, if you allow the dbg!() to execute, this code doesn't panic and prints the expected result.

@djc
Copy link
Contributor Author

djc commented Jun 11, 2020

So here's a link to a further reduced panicking version:

https://play.rust-lang.org/?version=beta&mode=debug&edition=2018&gist=e31da4955ca52b19e2131b51473bcb4e

When executed with miri, it doesn't panic. When the call to nothing() is moved before the assignment to self.prev, it also doesn't panic.

Here's a reduced diff between the LLVM IR for a working and a panicking version:

--- okay.ir     2020-06-11 10:05:02.000000000 +0200
+++ panic.ir    2020-06-11 10:05:07.000000000 +0200
@@ -2,16 +2,15 @@
 ; Function Attrs: nonlazybind uwtable
 define internal void @_ZN10playground4main17he15b3beb12586d44E() unnamed_addr #1 {
 start:
-  %split.dbg.spill = alloca i64, align 8
-  %v.dbg.spill = alloca i64, align 8
-  %prev = alloca { i64, i64 }, align 8
-  %_14 = alloca i64, align 8
+  %prev.dbg.spill = alloca { i64, i64 }, align 8
+  %_15 = alloca i64, align 8
   %_5 = alloca { i64, i64 }, align 8
   %_3 = alloca { i64, i64 }, align 8
+  %split = alloca i64, align 8
   %ls = alloca [2 x i32], align 4
   %0 = alloca {}, align 1
   call void @llvm.dbg.declare(metadata [2 x i32]* %ls, metadata !679, metadata !DIExpression()),
-  call void @llvm.dbg.declare(metadata { i64, i64 }* %prev, metadata !688, metadata !DIExpression()),
+  call void @llvm.dbg.declare(metadata i64* %split, metadata !684, metadata !DIExpression()),
   %1 = bitcast [2 x i32]* %ls to i32*,
   store i32 0, i32* %1, align 4,
   %2 = getelementptr inbounds [2 x i32], [2 x i32]* %ls, i32 0, i32 1,
@@ -41,33 +40,31 @@
   unreachable,
 
 bb4:                                              ; preds = %bb1
-  %8 = bitcast { i64, i64 }* %_3 to %"core::option::Option<usize>::Some"*,
-  %9 = getelementptr inbounds %"core::option::Option<usize>::Some", %"core::option::Option<usize>::Some"* %8, i32 0, i32 1,
-  %v = load i64, i64* %9, align 8,
-  store i64 %v, i64* %v.dbg.spill, align 8,
-  call void @llvm.dbg.declare(metadata i64* %v.dbg.spill, metadata !686, metadata !DIExpression()),
-  store i64 %v, i64* %split.dbg.spill, align 8,
-  call void @llvm.dbg.declare(metadata i64* %split.dbg.spill, metadata !684, metadata !DIExpression()),
-  %_12.0 = bitcast [2 x i32]* %ls to [0 x i32]*,
-  store i64 %v, i64* %_14, align 8,
-  %10 = load i64, i64* %_14, align 8,
+  %8 = getelementptr inbounds { i64, i64 }, { i64, i64 }* %_3, i32 0, i32 0,
+  %prev.0 = load i64, i64* %8, align 8,, !range !192
+  %9 = getelementptr inbounds { i64, i64 }, { i64, i64 }* %_3, i32 0, i32 1,
+  %prev.1 = load i64, i64* %9, align 8,
+  %10 = getelementptr inbounds { i64, i64 }, { i64, i64 }* %prev.dbg.spill, i32 0, i32 0,
+  store i64 %prev.0, i64* %10, align 8,
+  %11 = getelementptr inbounds { i64, i64 }, { i64, i64 }* %prev.dbg.spill, i32 0, i32 1,
+  store i64 %prev.1, i64* %11, align 8,
+  call void @llvm.dbg.declare(metadata { i64, i64 }* %prev.dbg.spill, metadata !688, metadata !DIExpression()),
+  %_13.0 = bitcast [2 x i32]* %ls to [0 x i32]*,
+  %_16 = load i64, i64* %split, align 8,
+  store i64 %_16, i64* %_15, align 8,
+  %12 = load i64, i64* %_15, align 8,
 ; call core::slice::<impl core::ops::index::Index<I> for [T]>::index
-  %11 = call { [0 x i32]*, i64 } @"_ZN4core5slice74_$LT$impl$u20$core..ops..index..Index$LT$I$GT$$u20$for$u20$$u5b$T$u5d$$GT$5index17h58cba0627d7192e9E"([0 x i32]* noalias nonnull readonly align 4 %_12.0, i64 2, i64 %10, %"core::panic::Location"* noalias readonly align 8 dereferenceable(24) bitcast (<{ i8*, [16 x i8] }>* @alloc23 to %"core::panic::Location"*)),
-  %_11.0 = extractvalue { [0 x i32]*, i64 } %11, 0,
-  %_11.1 = extractvalue { [0 x i32]*, i64 } %11, 1,
+  %13 = call { [0 x i32]*, i64 } @"_ZN4core5slice74_$LT$impl$u20$core..ops..index..Index$LT$I$GT$$u20$for$u20$$u5b$T$u5d$$GT$5index17h58cba0627d7192e9E"([0 x i32]* noalias nonnull readonly align 4 %_13.0, i64 2, i64 %12, %"core::panic::Location"* noalias readonly align 8 dereferenceable(24) bitcast (<{ i8*, [16 x i8] }>* @alloc23 to %"core::panic::Location"*)),
+  %_12.0 = extractvalue { [0 x i32]*, i64 } %13, 0,
+  %_12.1 = extractvalue { [0 x i32]*, i64 } %13, 1,
   br label %bb5,
 
 bb5:                                              ; preds = %bb4
 ; call playground::nothing
-  call void @_ZN10playground7nothing17h8446c2fa6397d61fE([0 x i32]* noalias nonnull readonly align 4 %_11.0, i64 %_11.1),
+  call void @_ZN10playground7nothing17h8446c2fa6397d61fE([0 x i32]* noalias nonnull readonly align 4 %_12.0, i64 %_12.1),
   br label %bb6,
 
 bb6:                                              ; preds = %bb5
-  %12 = bitcast { i64, i64 }* %prev to %"core::option::Option<usize>::Some"*,
-  %13 = getelementptr inbounds %"core::option::Option<usize>::Some", %"core::option::Option<usize>::Some"* %12, i32 0, i32 1,
-  store i64 %v, i64* %13, align 8,
-  %14 = bitcast { i64, i64 }* %prev to i64*,
-  store i64 1, i64* %14, align 8,
   br label %bb7,
 
 bb7:                                              ; preds = %bb2, %bb6

@djc djc changed the title Test regression from stable to beta Slice index becomes wrong (beta regression) Jun 11, 2020
@djc
Copy link
Contributor Author

djc commented Jun 11, 2020

In my original test, adding a dbg!() statement before the self.prev = Some(start); statement also appears to fix the test. It's somewhat interesting that in the test, the slice index always becomes 0 in the wrong version, rather than the random values seen with the playground test.

@djc
Copy link
Contributor Author

djc commented Jun 11, 2020

Bisection blames #69756. @wesleywiser / @oli-obk care to take a look?

@lcnr
Copy link
Contributor

lcnr commented Jun 11, 2020

Another small repro:

fn main() {
    let split = match Some(1) {
        Some(v) => v,
        None => return,
    };

    let _prev = Some(split);
    assert_eq!(split, 1);
    //~^ fails with `left: 0, right: 1`
}

@wesleywiser wesleywiser self-assigned this Jun 11, 2020
@spastorino spastorino added P-critical Critical priority and removed I-prioritize Issue: Indicates that prioritization has been requested for this issue. labels Jun 11, 2020
@spastorino
Copy link
Member

Assigning P-critical as discussed as part of the Prioritization Working Group process and removing I-prioritize.

@spastorino spastorino added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Jun 11, 2020
@Aaron1011
Copy link
Member

Relevant MIR from before and after SimplifyArmIdentity:

before:

    bb3: {
        StorageLive(_4);                 // scope 0 at bad_arm.rs:3:14: 3:15
        _4 = ((_2 as Some).0: i32);      // scope 0 at bad_arm.rs:3:14: 3:15
        _1 = _4;                         // scope 2 at bad_arm.rs:3:20: 3:21
        StorageDead(_4);                 // scope 0 at bad_arm.rs:3:21: 3:22
        StorageDead(_2);                 // scope 0 at bad_arm.rs:5:6: 5:7
        StorageLive(_6);                 // scope 1 at bad_arm.rs:7:9: 7:14
        StorageLive(_7);                 // scope 1 at bad_arm.rs:7:22: 7:27
        _7 = _1;                         // scope 1 at bad_arm.rs:7:22: 7:27
        ((_6 as Some).0: i32) = move _7; // scope 1 at bad_arm.rs:7:17: 7:28
        discriminant(_6) = 1;            // scope 1 at bad_arm.rs:7:17: 7:28
        StorageDead(_7);                 // scope 1 at bad_arm.rs:7:27: 7:28

after:

    bb3: {
        _6 = move _2;                    // scope 1 at bad_arm.rs:7:17: 7:28
        StorageDead(_2);                 // scope 0 at bad_arm.rs:5:6: 5:7
        StorageLive(_6);                 // scope 1 at bad_arm.rs:7:9: 7:14

Note how we are assigning to _6 before the StorageLive(_6) statement.

wesleywiser added a commit to wesleywiser/rust that referenced this issue Jun 12, 2020
This pass is buggy so I'm disabling it to fix a stable-to-beta
regression.

Related to rust-lang#73223
bors added a commit to rust-lang-ci/rust that referenced this issue Jun 12, 2020
…regression, r=oli-obk

Disable the `SimplifyArmIdentity` pass

This pass is buggy so I'm disabling it to fix a stable-to-beta
regression.

Related to rust-lang#73223
@jonas-schievink
Copy link
Contributor

cc #72800

@RalfJung
Copy link
Member

#73262 landed, what is needed to close this regression ticket?

@oli-obk
Copy link
Contributor

oli-obk commented Jun 25, 2020

the PR needs to get backported

Mark-Simulacrum pushed a commit to Mark-Simulacrum/rust that referenced this issue Jun 26, 2020
This pass is buggy so I'm disabling it to fix a stable-to-beta
regression.

Related to rust-lang#73223
@LeSeulArtichaut
Copy link
Contributor

PR has been backported. Unless we need to add some regression tests I think we can close this.

@JohnTitor
Copy link
Member

I think #73210 will add regression tests (cc @wesleywiser). I'd +1 for closing issue or at least downgrading the prio.

@LeSeulArtichaut LeSeulArtichaut removed the P-critical Critical priority label Jul 1, 2020
@LeSeulArtichaut LeSeulArtichaut added the I-prioritize Issue: Indicates that prioritization has been requested for this issue. label Jul 1, 2020
@wesleywiser wesleywiser added P-medium Medium priority requires-nightly This issue requires a nightly compiler in some way. and removed I-prioritize Issue: Indicates that prioritization has been requested for this issue. regression-from-stable-to-beta Performance or correctness regression from stable to beta. labels Jul 1, 2020
@wesleywiser
Copy link
Member

@JohnTitor Did you mean to link a different PR? I don't think that one is related to this issue.

@JohnTitor
Copy link
Member

JohnTitor commented Jul 2, 2020

Did you mean to link a different PR? I don't think that one is related to this issue.

@wesleywiser Ahhh, sorry! I saw your comment that you would add regression tests in next PR so I commented without checking carefully. So, don't we have any PRs that add tests? Marking as E-needs-test so that we don't forget.

@JohnTitor JohnTitor added the E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added. label Jul 2, 2020
@wesleywiser
Copy link
Member

@JohnTitor All good! The PR you're looking for is #73949 🙂

@wesleywiser wesleywiser removed the E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added. label Jul 2, 2020
@bors bors closed this as completed in 60cad20 Jul 4, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-mir-opt Area: MIR optimizations C-bug Category: This is a bug. P-medium Medium priority requires-nightly This issue requires a nightly compiler in some way. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.