Open gootorov opened 1 year ago
Interestingly, the stack no longer overflows when just a few fields are removed:
diff --git a/src/lib.rs b/src/lib.rs
index d84519e..3d43db8 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -18,9 +18,6 @@ impl Outer {
pub struct LargeStruct {
d0: Option<Box<u128>>,
d1: Option<Box<u128>>,
- d2: Option<Box<u128>>,
- d3: Option<Box<u128>>,
- d4: Option<Box<u128>>,
huge: [u8; SIZE],
}
@@ -30,9 +27,6 @@ impl LargeStruct {
Self {
d0: None,
d1: None,
- d2: None,
- d3: None,
- d4: None,
huge: [0; SIZE],
}
}
At the first glace, it looks like RVO/destination propagation isn't applied
Both these MIR optimizations are off by default, and the NRVO MIR opt is unsound.
Both these MIR optimizations are off by default, and the NRVO MIR opt is unsound.
Interesting, thank you. I was always under the impression that optimizations of the Box::new(returns_large_object())
type are RVO. Or is it (currently) just LLVM's RVO and not MIR?
Also, is there a way to turn on these MIR optimizations via a compiler flag/crate attribute?
Yes, currently LLVM performs the relevant RVO (or doesn't).
You can use -Zmir-enable-passes=+DestinationPropagation,+RenameReturnPlace
.
Alternately, I believe most unsound opts are enabled at -Zmir-opt-level=4
, but that can cause other hilarious bugs.
Unsound optimizations must be enabled by their own flag, -Zunsound-mir-opts
. Unfortunately perhaps, -Zmir-opt-level=4
is used in the ecosystem.
It's possible your request here will be fulfilled by https://github.com/rust-lang/rust/pull/116531.
Unfortunately, if I did everything correctly, #116531 doesn't help in this case :(
I've checked-out #116531 and built stage2
. Then ran the binary again:
RUSTFLAGS="-Zmir-opt-level=4 --emit=mir" cargo +stage2 run --release
Still overflows.
This is the emitted MIR:
Also, just in case, I tried perhaps less aggressive
RUSTFLAGS="-Zmir-enable-passes=+DestinationPropagation,+RenameReturnPlace --emit=mir" cargo +stage2 run --release
and there were no difference in the emitted MIR
Did you use -Zunsound-mir-opts
as well?
I thought that wasn't necessary judging by the diff in #116531, but to be sure, I've just tried these two variants:
RUSTFLAGS="-Zunsound-mir-opts -Zmir-enable-passes=+DestinationPropagation,+RenameReturnPlace --emit=mir" cargo +stage2 run --release
RUSTFLAGS="-Zunsound-mir-opts -Zmir-opt-level=4 --emit=mir" cargo +stage2 run --release
Unfortunately, same outcome, and the emitted MIR is also the same as before.
Actually, I think I'm doing something wrong. Just tried comparing this MIR to stable MIR (RUSTFLAGS="--emit=mir" cargo run --release
) and there also isn't any difference
--release
is about equivalent to -Zmir-opt-level=2
. You're doing things fine, the MIR optimization as-written simply doesn't help for this specific case.
Consider the code below. At the first glace, it looks like RVO/destination propagation isn't applied, resulting in a stack overflow.
File structure
tree .
Code
Cargo.toml
bin/rvo.rs
src/lib.rs
Running
cargo run --release
results in:Compiler version:
rustc --version --verbose