Skip to content

GVN causes moved function arguments to be used again #120613

Closed
@cbeuw

Description

@cbeuw
#![feature(custom_mir, core_intrinsics)]
extern crate core;
use core::intrinsics::mir::*;

#[inline(never)]
fn dump_var(x: [u128; 6]) {
    println!("{x:?}");
}

#[custom_mir(dialect = "runtime", phase = "initial")]
pub fn fn0() {
    mir! {
    let _12: usize;
    let _14: [u128; 6];
    let _26: ([u128; 6],);
    let _29: ([u128; 6],);
    let x: ();
    {
    _12 = 1_usize;
    _14 = [42; 6];
    _14[_12] = 1;
    _29 = (_14,);
    _26 = _29;
    Call(x = fn1(_29.0, _26), ReturnTo(bb14), UnwindUnreachable())
    }
    bb14 = {
    Return()
    }
    }
}

pub fn fn1(mut _13: [u128; 6], mut _14: ([u128; 6],)) {
    _14.0 = [0; 6];
    dump_var(_13);
    dump_var(_14.0);
}
pub fn main() {
    fn0();
}

Right:

$ rustc -Zmir-opt-level=2 -Zmir-enable-passes=-GVN -Copt-level=0 1717541-debug.rs && ./1717541-debug
[42, 1, 42, 42, 42, 42]
[0, 0, 0, 0, 0, 0]

Wrong:

$ rustc -Zmir-opt-level=2 -Copt-level=0 1717541-debug.rs && ./1717541-debug
[0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0]

The first argument to fn1 is partially moved. GVN causes the second argument to use the partially moved value:

--- a/mir_dump/1717541_debug.fn0.005-015.GVN.before.mir
+++ b/mir_dump/1717541_debug.fn0.005-015.GVN.after.mir
@@ -1,4 +1,4 @@
-// MIR for `fn0` before GVN
+// MIR for `fn0` after GVN
 
 fn fn0() -> () {
     let mut _0: ();
@@ -11,10 +11,10 @@ fn fn0() -> () {
     bb0: {
         _1 = const 1_usize;
         _2 = [const 42_u128; 6];
-        _2[_1] = const 1_u128;
+        _2[1 of 2] = const 1_u128;
         _4 = (_2,);
         _3 = _4;
-        _5 = fn1(move (_4.0: [u128; 6]), move _3) -> [return: bb1, unwind unreachable];
+        _5 = fn1(move (_4.0: [u128; 6]), _4) -> [return: bb1, unwind unreachable];
     }
 
     bb1: {
rustc 1.77.0-nightly (11f32b73e 2024-01-31)
binary: rustc
commit-hash: 11f32b73e0dc9287e305b5b9980d24aecdc8c17f
commit-date: 2024-01-31
host: x86_64-unknown-linux-gnu
release: 1.77.0-nightly
LLVM version: 17.0.6

Metadata

Metadata

Assignees

Labels

A-mir-optArea: MIR optimizationsA-rustlantisA miscompilation found by RustlantisI-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessP-mediumMedium priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.regression-from-stable-to-nightlyPerformance or correctness regression from stable to nightly.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions