rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
97.53k stars 12.61k forks source link

[MIR-opt] Broken MIR for vec indexing with MIR inlining #67590

Closed bjorn3 closed 4 years ago

bjorn3 commented 4 years ago
pub fn inxbuild(this: Vec<()>) {
    for j in 0..1 {
        this[j];
    }
}
$ rustc -V
rustc 1.42.0-nightly (9ae6cedb8 2019-12-23)
$ rustc src/lib.rs -Zmir-opt-level=3 --crate-type lib --emit mir,llvm-ir --sysroot rustc_codegen_cranelift/build_sysroot/sysroot
error: internal compiler error: src/librustc_codegen_ssa/mir/operand.rs:122: not immediate: OperandRef(Pair((i64:  %33 = load i64, i64* %32, align 8), (i64:  %35 = load i64, i64* %34, align 8)) @ TyLayout { ty: std::ops::Range<usize>, details: LayoutDetails { variants: Single { index: 0 }, fields: Arbitrary { offsets: [Size { raw: 0 }, Size { raw: 8 }], memory_index: [0, 1] }, abi: ScalarPair(Scalar { value: Int(I64, false), valid_range: 0..=18446744073709551615 }, Scalar { value: Int(I64, false), valid_range: 0..=18446744073709551615 }), largest_niche: None, align: AbiAndPrefAlign { abi: Align { pow2: 3 }, pref: Align { pow2: 3 } }, size: Size { raw: 16 } } })

The mir inliner doesn't seem to inline <Vec<()> as Index<usize>>::index when not using the patched sysroot of rustc_codegen_cranelift, so this problem doesn't trigger with the normal sysroot.

Optimized MIR ```rust // WARNING: This output format is intended for human consumers only // and is subject to change without notice. Knock yourself out. fn inxbuild(_1: std::vec::Vec<()>) -> () { debug this => _1; // in scope 0 at src/lib.rs:1:17: 1:21 let mut _0: (); // return place in scope 0 at src/lib.rs:1:32: 1:32 let mut _2: std::ops::Range; // in scope 0 at src/lib.rs:2:14: 2:18 let mut _3: std::ops::Range; // in scope 0 at src/lib.rs:2:14: 2:18 let mut _4: std::ops::Range; // in scope 0 at src/lib.rs:2:14: 2:18 let mut _5: std::option::Option; // in scope 0 at src/lib.rs:2:14: 2:18 let mut _6: &mut std::ops::Range; // in scope 0 at src/lib.rs:2:14: 2:18 let mut _7: isize; // in scope 0 at src/lib.rs:2:9: 2:10 let _9: (); // in scope 0 at src/lib.rs:3:9: 3:16 let mut _10: &std::vec::Vec<()>; // in scope 0 at src/lib.rs:3:9: 3:13 scope 1 { debug iter => _4; // in scope 1 at src/lib.rs:2:14: 2:18 scope 2 { debug __next => _8; // in scope 2 at src/lib.rs:2:14: 2:18 let _8: usize; // in scope 2 at src/lib.rs:2:9: 2:10 scope 3 { debug val => _8; // in scope 3 at src/lib.rs:2:9: 2:10 } scope 4 { debug j => _8; // in scope 4 at src/lib.rs:2:9: 2:10 scope 6 { debug self => _10; // in scope 6 at /home/bjorn/Documenten/cg_clif/build_sysroot/sysroot_src/src/liballoc/vec.rs:1877:14: 1877:19 debug index => _8; // in scope 6 at /home/bjorn/Documenten/cg_clif/build_sysroot/sysroot_src/src/liballoc/vec.rs:1877:21: 1877:26 let _11: &[()]; // in scope 6 at src/lib.rs:3:9: 3:16 scope 7 { debug self => _11; // in scope 7 at /home/bjorn/Documenten/cg_clif/build_sysroot/sysroot_src/src/libcore/slice/mod.rs:2655:14: 2655:19 debug index => _8; // in scope 7 at /home/bjorn/Documenten/cg_clif/build_sysroot/sysroot_src/src/libcore/slice/mod.rs:2655:21: 2655:26 scope 8 { debug self => _8; // in scope 8 at /home/bjorn/Documenten/cg_clif/build_sysroot/sysroot_src/src/libcore/slice/mod.rs:2789:14: 2789:18 debug slice => _11; // in scope 8 at /home/bjorn/Documenten/cg_clif/build_sysroot/sysroot_src/src/libcore/slice/mod.rs:2789:20: 2789:25 let _12: &(); // in scope 8 at /home/bjorn/Documenten/cg_clif/build_sysroot/sysroot_src/src/libcore/slice/mod.rs:2656:9: 2656:26 let mut _13: usize; // in scope 8 at /home/bjorn/Documenten/cg_clif/build_sysroot/sysroot_src/src/libcore/slice/mod.rs:2656:9: 2656:26 let mut _14: bool; // in scope 8 at /home/bjorn/Documenten/cg_clif/build_sysroot/sysroot_src/src/libcore/slice/mod.rs:2656:9: 2656:26 } } } } } } scope 5 { debug self => _3; // in scope 5 at /home/bjorn/Documenten/cg_clif/build_sysroot/sysroot_src/src/libcore/iter/traits/collect.rs:247:18: 247:22 } bb0: { StorageLive(_2); // bb0[0]: scope 0 at src/lib.rs:2:14: 2:18 StorageLive(_3); // bb0[1]: scope 0 at src/lib.rs:2:14: 2:18 (_3.0: usize) = const 0usize; // bb0[2]: scope 0 at src/lib.rs:2:14: 2:18 // ty::Const // + ty: usize // + val: Value(Scalar(0x0000000000000000)) // mir::Constant // + span: src/lib.rs:2:14: 2:15 // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000000)) } (_3.1: usize) = const 1usize; // bb0[3]: scope 0 at src/lib.rs:2:14: 2:18 // ty::Const // + ty: usize // + val: Value(Scalar(0x0000000000000001)) // mir::Constant // + span: src/lib.rs:2:17: 2:18 // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000001)) } _2 = move _3; // bb0[4]: scope 5 at /home/bjorn/Documenten/cg_clif/build_sysroot/sysroot_src/src/libcore/iter/traits/collect.rs:248:9: 248:13 StorageDead(_3); // bb0[5]: scope 0 at src/lib.rs:2:17: 2:18 StorageLive(_4); // bb0[6]: scope 0 at src/lib.rs:2:14: 2:18 _4 = move _2; // bb0[7]: scope 0 at src/lib.rs:2:14: 2:18 goto -> bb1; // bb0[8]: scope 1 at src/lib.rs:2:5: 4:6 } bb1: { StorageLive(_5); // bb1[0]: scope 2 at src/lib.rs:2:14: 2:18 _6 = &mut _4; // bb1[1]: scope 2 at src/lib.rs:2:14: 2:18 _5 = const as std::iter::Iterator>::next(move _6) -> bb2; // bb1[2]: scope 2 at src/lib.rs:2:14: 2:18 // ty::Const // + ty: for<'r> fn(&'r mut std::ops::Range) -> std::option::Option< as std::iter::Iterator>::Item> { as std::iter::Iterator>::next} // + val: Value(Scalar()) // mir::Constant // + span: src/lib.rs:2:14: 2:18 // + literal: Const { ty: for<'r> fn(&'r mut std::ops::Range) -> std::option::Option< as std::iter::Iterator>::Item> { as std::iter::Iterator>::next}, val: Value(Scalar()) } } bb2: { _7 = discriminant(_5); // bb2[0]: scope 2 at src/lib.rs:2:9: 2:10 switchInt(move _7) -> [0isize: bb3, 1isize: bb5, otherwise: bb4]; // bb2[1]: scope 2 at src/lib.rs:2:9: 2:10 } bb3: { StorageDead(_5); // bb3[0]: scope 2 at src/lib.rs:2:17: 2:18 StorageDead(_4); // bb3[1]: scope 0 at src/lib.rs:4:5: 4:6 StorageDead(_2); // bb3[2]: scope 0 at src/lib.rs:2:17: 2:18 drop(_1) -> bb6; // bb3[3]: scope 0 at src/lib.rs:5:1: 5:2 } bb4: { unreachable; // bb4[0]: scope 2 at src/lib.rs:2:14: 2:18 } bb5: { _8 = ((_5 as Some).0: usize); // bb5[0]: scope 2 at src/lib.rs:2:9: 2:10 StorageDead(_5); // bb5[1]: scope 2 at src/lib.rs:2:17: 2:18 StorageLive(_9); // bb5[2]: scope 4 at src/lib.rs:3:9: 3:16 _10 = &_1; // bb5[3]: scope 4 at src/lib.rs:3:9: 3:13 _11 = const as std::ops::Deref>::deref(move _10) -> bb7; // bb5[4]: scope 6 at /home/bjorn/Documenten/cg_clif/build_sysroot/sysroot_src/src/liballoc/vec.rs:1878:23: 1878:29 // ty::Const // + ty: for<'r> fn(&'r std::vec::Vec<()>) -> &'r as std::ops::Deref>::Target { as std::ops::Deref>::deref} // + val: Value(Scalar()) // mir::Constant // + span: /home/bjorn/Documenten/cg_clif/build_sysroot/sysroot_src/src/liballoc/vec.rs:1878:23: 1878:29 // + literal: Const { ty: for<'r> fn(&'r std::vec::Vec<()>) -> &'r as std::ops::Deref>::Target { as std::ops::Deref>::deref}, val: Value(Scalar()) } } bb6: { return; // bb6[0]: scope 0 at src/lib.rs:5:2: 5:2 } bb7: { _13 = Len((*_11)); // bb7[0]: scope 8 at /home/bjorn/Documenten/cg_clif/build_sysroot/sysroot_src/src/libcore/slice/mod.rs:2791:10: 2791:24 _14 = Lt(_8, _13); // bb7[1]: scope 8 at /home/bjorn/Documenten/cg_clif/build_sysroot/sysroot_src/src/libcore/slice/mod.rs:2791:10: 2791:24 assert(move _14, "index out of bounds: the len is move _13 but the index is _8") -> bb8; // bb7[2]: scope 8 at /home/bjorn/Documenten/cg_clif/build_sysroot/sysroot_src/src/libcore/slice/mod.rs:2791:10: 2791:24 } bb8: { _12 = &(*_11)[_4]; // bb8[0]: scope 8 at /home/bjorn/Documenten/cg_clif/build_sysroot/sysroot_src/src/libcore/slice/mod.rs:2791:9: 2791:24 _9 = (*_12); // bb8[1]: scope 4 at src/lib.rs:3:9: 3:16 StorageDead(_9); // bb8[2]: scope 4 at src/lib.rs:3:16: 3:17 goto -> bb1; // bb8[3]: scope 1 at src/lib.rs:2:5: 4:6 } } ```

The _12 = &(*_11)[_4]; is invalid because _4 is of type Range<usize>.

@rustbot modify label: +A-mir +C-bug +requires-nightly

Aaron1011 commented 4 years ago

I think this will be fixed by https://github.com/rust-lang/rust/pull/67796

bjorn3 commented 4 years ago

Yes. The crate from which this was reduced compiles fine now.