-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Implement simple CopyPropagation based on SSA analysis #106908
Conversation
r? @TaKO8Ki (rustbot has picked a reviewer for you, use r? to override) |
Some changes occurred to MIR optimizations cc @rust-lang/wg-mir-opt |
68fe207
to
955b639
Compare
r? @oli-obk |
@bors r+ |
📌 Commit c1a924547eaecff4bc7af3c0de848429a7ac78f1 has been approved by It is now in the queue for this repository. |
if matches!(body.local_kind(local), LocalKind::Arg) { | ||
this.assignments[local] = Set1::One(LocationExtended::Arg); | ||
} | ||
if borrowed.contains(local) && !decl.ty.is_freeze(tcx, param_env) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The freeze check is not enough here, we should be bailing out on all references. The pass currently changes the bahavior of this code:
#![feature(custom_mir, core_intrinsics)]
#![allow(unused_assignments)]
extern crate core;
use core::intrinsics::mir::*;
#[custom_mir(dialect = "analysis", phase = "post-cleanup")]
fn f(c: bool) -> bool { mir!({
let a = c;
let p = core::ptr::addr_of!(a);
let p2 = core::ptr::addr_of_mut!(*p);
*p2 = false;
RET = c;
Return()
})}
fn main() {
assert_eq!(true, f(true));
}
This is Miri UB today, but we should not depend on that on stable, especially because there is a real possibility that this may be allowed in the future.
@bors r- |
c1a9245
to
d21e04d
Compare
This comment has been minimized.
This comment has been minimized.
Sorry, should have thought of this before too. Banning raw pointers isn't enough, references cause problems too. Your pass changes the behavior of this code: #![feature(custom_mir, core_intrinsics)]
#![allow(unused_assignments)]
extern crate core;
use core::intrinsics::mir::*;
fn cmp_ref(a: &u8, b: &u8) -> bool {
std::ptr::eq(a as *const u8, b as *const u8)
}
#[custom_mir(dialect = "analysis", phase = "post-cleanup")]
fn f() -> bool { mir!(
{
let a = 5_u8;
let r1 = &a;
let b = a;
let r2 = &b;
Call(RET, next, cmp_ref(r1, r2))
}
next = {
Return()
}
)}
fn main() {
assert!(!f());
} Ideally this would actually be allowed, but we don't currently know how to do that, so need to be conservative in the meantime. See rust-lang/unsafe-code-guidelines#206 for discussion |
75ae3d0
to
a28d065
Compare
Ah, not the change I was expecting, but very nice. Technically this requires a T-opsem FCP these days (since it makes slightly more assumptions about reference immutability than we do already), but that team doesn't really exist yet, so should be fine to land |
@bors r+ |
📌 Commit cbfb98fb8bf1772e059df697c8d15a71b79256d3 has been approved by It is now in the queue for this repository. |
The assignment is complete only after the statement. This marks self-assignments `x = x + 1` as non-sSA.
cbfb98f
to
263da25
Compare
@bors r=oli-obk |
☀️ Test successful - checks-actions |
1 similar comment
☀️ Test successful - checks-actions |
Finished benchmarking commit (2a4b00b): comparison URL. Overall result: no relevant changes - no action needed@rustbot label: -perf-regression Instruction countThis benchmark run did not return any relevant results for this metric. Max RSS (memory usage)ResultsThis is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
CyclesThis benchmark run did not return any relevant results for this metric. |
Reimplement NormalizeArrayLen based on SsaLocals Based on rust-lang#106908 Fixes rust-lang#105929 Only the last commit "Reimplement NormalizeArrayLen" is relevant.
Remove both StorageLive and StorageDead in CopyProp. Fixes rust-lang#107511 rust-lang#106908 removed StorageDead without the accompanying StorageLive. In loops, execution would see repeated StorageLive, without any StorageDead, which is UB. So when removing storage statements, we have to remove both StorageLive and StorageDead. ~I also added a MIR validation pass for StorageLive. It may be a bit overzealous.~
Remove both StorageLive and StorageDead in CopyProp. Fixes rust-lang#107511 rust-lang#106908 removed StorageDead without the accompanying StorageLive. In loops, execution would see repeated StorageLive, without any StorageDead, which is UB. So when removing storage statements, we have to remove both StorageLive and StorageDead. ~I also added a MIR validation pass for StorageLive. It may be a bit overzealous.~
This PR extracts the "copy propagation" logic from #106285.
MIR may produce chains of assignment between locals, like
_x = move? _y
.This PR attempts to remove such chains by unifying locals.
The current implementation is a bit overzealous in turning moves into copies, and in removing storage statements.