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

Implement a real InstCombine MIR pass #105808

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
440 changes: 440 additions & 0 deletions compiler/rustc_mir_transform/src/instcombine.rs

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions compiler/rustc_mir_transform/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ mod ffi_unwind_calls;
mod function_item_references;
mod gvn;
pub mod inline;
mod instcombine;
mod instsimplify;
mod jump_threading;
mod large_enums;
Expand Down Expand Up @@ -598,6 +599,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
&simplify_comparison_integral::SimplifyComparisonIntegral,
&dead_store_elimination::DeadStoreElimination,
&dest_prop::DestinationPropagation,
&instcombine::InstCombine,
&o1(simplify_branches::SimplifyConstCondition::Final),
&o1(remove_noop_landing_pads::RemoveNoopLandingPads),
&o1(simplify::SimplifyCfg::Final),
Expand Down
11 changes: 11 additions & 0 deletions tests/mir-opt/casts.roundtrip.PreCodegen.after.mir
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// MIR for `roundtrip` after PreCodegen

fn roundtrip(_1: *const u8) -> *const u8 {
debug x => _1;
let mut _0: *const u8;

bb0: {
_0 = _1 as *const u8 (PtrToPtr);
return;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
- // MIR for `place_projection` before InstCombine
+ // MIR for `place_projection` after InstCombine

fn place_projection(_1: Outer) -> u8 {
debug o => _1;
let mut _0: u8;
let _2: Inner;
scope 1 {
debug temp => _2;
}

bb0: {
StorageLive(_2);
- _2 = move (_1.0: Inner);
- _0 = (_2.0: u8);
+ _0 = ((_1.0: Inner).0: u8);
+ nop;
StorageDead(_2);
return;
}
}

17 changes: 17 additions & 0 deletions tests/mir-opt/instcombine/place_projection.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// skip-filecheck
// unit-test: InstCombine
#![crate_type = "lib"]

pub struct Outer {
inner: Inner,
}

struct Inner {
field: u8,
}

// EMIT_MIR place_projection.place_projection.InstCombine.diff
pub fn place_projection(o: Outer) -> u8 {
let temp = o.inner;
temp.field
}
23 changes: 23 additions & 0 deletions tests/mir-opt/instcombine/ptr_cast.ptr_cast.InstCombine.diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
- // MIR for `ptr_cast` before InstCombine
+ // MIR for `ptr_cast` after InstCombine

fn ptr_cast(_1: *const u8) -> *mut () {
debug p => _1;
let mut _0: *mut ();
let mut _2: *mut u8;
let mut _3: *const u8;

bb0: {
StorageLive(_2);
StorageLive(_3);
_3 = _1;
- _2 = move _3 as *mut u8 (PtrToPtr);
+ _0 = move _3 as *mut () (PtrToPtr);
+ nop;
StorageDead(_3);
- _0 = move _2 as *mut () (PtrToPtr);
StorageDead(_2);
return;
}
}

8 changes: 8 additions & 0 deletions tests/mir-opt/instcombine/ptr_cast.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// skip-filecheck
// unit-test: InstCombine
#![crate_type = "lib"]

// EMIT_MIR ptr_cast.ptr_cast.InstCombine.diff
pub fn ptr_cast(p: *const u8) -> *mut () {
p as *mut u8 as *mut ()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
- // MIR for `ref_addressof` before InstCombine
+ // MIR for `ref_addressof` after InstCombine

fn ref_addressof(_1: T) -> () {
debug t => _1;
let mut _0: ();
let _2: &T;
let _4: ();
let mut _5: *const T;
scope 1 {
debug r => _2;
let _3: *const T;
scope 2 {
debug ptr => _3;
}
}

bb0: {
StorageLive(_2);
- _2 = &_1;
StorageLive(_3);
- _3 = &raw const (*_2);
+ _3 = &raw const _1;
+ nop;
StorageLive(_4);
StorageLive(_5);
_5 = _3;
_4 = std::mem::drop::<*const T>(move _5) -> [return: bb1, unwind unreachable];
}

bb1: {
StorageDead(_5);
StorageDead(_4);
_0 = const ();
StorageDead(_3);
StorageDead(_2);
drop(_1) -> [return: bb2, unwind unreachable];
}

bb2: {
return;
}
}

10 changes: 10 additions & 0 deletions tests/mir-opt/instcombine/ref_addressof.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// skip-filecheck
// unit-test: InstCombine
#![crate_type = "lib"]

// EMIT_MIR ref_addressof.ref_addressof.InstCombine.diff
pub fn ref_addressof<T>(t: T) {
let r = &t;
let ptr = std::ptr::addr_of!(*r);
drop(ptr);
}
22 changes: 22 additions & 0 deletions tests/mir-opt/instcombine/ref_deref.ref_deref.InstCombine.diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
- // MIR for `ref_deref` before InstCombine
+ // MIR for `ref_deref` after InstCombine

fn ref_deref(_1: T) -> T {
debug t => _1;
let mut _0: T;
let _2: &T;
scope 1 {
debug r => _2;
}

bb0: {
StorageLive(_2);
- _2 = &_1;
- _0 = (*_2);
+ _0 = _1;
+ nop;
StorageDead(_2);
return;
}
}

9 changes: 9 additions & 0 deletions tests/mir-opt/instcombine/ref_deref.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// skip-filecheck
// unit-test: InstCombine
#![crate_type = "lib"]

// EMIT_MIR ref_deref.ref_deref.InstCombine.diff
pub fn ref_deref<T: Copy>(t: T) -> T {
let r = &t;
*r
}
18 changes: 18 additions & 0 deletions tests/mir-opt/nested_getter.outer_get.InstCombine.diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
- // MIR for `outer_get` before InstCombine
+ // MIR for `outer_get` after InstCombine

fn outer_get(_1: &Outer) -> u8 {
debug this => _1;
let mut _0: u8;
let mut _2: &Inner;
let _3: &Inner;
scope 1 (inlined inner_get) {
debug this => &((*_1).0: Inner);
}

bb0: {
_0 = (((*_1).0: Inner).0: u8);
return;
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// MIR for `outer_get` after PreCodegen

fn outer_get(_1: &Outer) -> u8 {
debug this => _1;
let mut _0: u8;
let _2: &Inner;
scope 1 (inlined inner_get) {
debug this => _2;
}

bb0: {
_0 = (((*_1).0: Inner).0: u8);
return;
}
}
23 changes: 23 additions & 0 deletions tests/mir-opt/pre-codegen/nested_getter.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// compile-flags: -O -Cdebuginfo=0 -Zmir-opt-level=2
// only-64bit
// ignore-debug

#![crate_type = "lib"]

pub struct Outer {
inner: Inner,
}

struct Inner {
inner: u8
}

#[inline]
fn inner_get(this: &Inner) -> u8 {
this.inner
}

// EMIT_MIR nested_getter.outer_get.PreCodegen.after.mir
pub fn outer_get(this: &Outer) -> u8 {
inner_get(&this.inner)
}
15 changes: 15 additions & 0 deletions tests/mir-opt/pre-codegen/simple_swap.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2
// only-64bit
// ignore-debug

#![crate_type = "lib"]

// EMIT_MIR simple_swap.simple_swap.PreCodegen.after.mir
pub fn simple_swap<T>(x: &mut T, y: &mut T) {
use std::ptr::{read, write};
unsafe {
let temp = read(x);
write(x, read(y));
write(y, temp);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// MIR for `simple_swap` after PreCodegen

fn simple_swap(_1: &mut T, _2: &mut T) -> () {
debug x => _1;
debug y => _2;
let mut _0: ();
let mut _3: *const T;
let mut _5: *mut T;
let mut _6: *const T;
let mut _7: *mut T;
let mut _8: T;
scope 1 {
let _4: T;
scope 2 {
debug temp => _4;
scope 6 (inlined std::ptr::read::<T>) {
debug src => _6;
scope 7 {
scope 8 (inlined std::ptr::read::runtime::<T>) {
debug src => _6;
}
}
}
scope 9 (inlined std::ptr::write::<T>) {
debug dst => _5;
debug src => _8;
scope 10 {
scope 11 (inlined std::ptr::write::runtime::<T>) {
debug dst => _5;
}
}
}
scope 12 (inlined std::ptr::write::<T>) {
debug dst => _7;
debug src => _4;
scope 13 {
scope 14 (inlined std::ptr::write::runtime::<T>) {
debug dst => _7;
}
}
}
}
scope 3 (inlined std::ptr::read::<T>) {
debug src => _3;
scope 4 {
scope 5 (inlined std::ptr::read::runtime::<T>) {
debug src => _3;
}
}
}
}

bb0: {
StorageLive(_3);
_3 = &raw const (*_1);
_4 = (*_3);
StorageDead(_3);
StorageLive(_5);
_5 = &raw mut (*_1);
StorageLive(_8);
StorageLive(_6);
_6 = &raw const (*_2);
(*_5) = (*_6);
StorageDead(_6);
StorageDead(_8);
StorageDead(_5);
StorageLive(_7);
_7 = &raw mut (*_2);
(*_7) = move _4;
StorageDead(_7);
return;
}
}
42 changes: 42 additions & 0 deletions tests/mir-opt/vec_as_ptr.as_ptr.InstCombine.diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
- // MIR for `as_ptr` before InstCombine
+ // MIR for `as_ptr` after InstCombine

fn as_ptr(_1: &Vec<i32>) -> *const i32 {
debug v => _1;
let mut _0: *const i32;
scope 1 (inlined Vec::<i32>::as_ptr) {
debug self => _1;
let mut _2: *mut i32;
let mut _3: &alloc::raw_vec::RawVec<i32>;
scope 2 (inlined alloc::raw_vec::RawVec::<i32>::ptr) {
debug self => _3;
let mut _5: std::ptr::NonNull<i32>;
scope 3 (inlined Unique::<i32>::as_ptr) {
debug ((self: Unique<i32>).0: std::ptr::NonNull<i32>) => _5;
debug ((self: Unique<i32>).1: std::marker::PhantomData<i32>) => const PhantomData::<i32>;
scope 4 (inlined NonNull::<i32>::as_ptr) {
debug self => _5;
let mut _4: *const i32;
}
}
}
}

bb0: {
StorageLive(_2);
StorageLive(_3);
_3 = &((*_1).0: alloc::raw_vec::RawVec<i32>);
StorageLive(_5);
_5 = ((((*_1).0: alloc::raw_vec::RawVec<i32>).0: std::ptr::Unique<i32>).0: std::ptr::NonNull<i32>);
StorageLive(_4);
_4 = (_5.0: *const i32);
_2 = move _4 as *mut i32 (PtrToPtr);
StorageDead(_4);
StorageDead(_5);
_0 = move _2 as *const i32 (PointerCoercion(MutToConstPointer));
StorageDead(_3);
StorageDead(_2);
return;
}
}

Loading
Loading