Skip to content

Commit d308f02

Browse files
committed
Implement a few basic InstCombine optimizations
1 parent bbcc169 commit d308f02

19 files changed

+849
-0
lines changed

compiler/rustc_mir_transform/src/instcombine.rs

+440
Large diffs are not rendered by default.

compiler/rustc_mir_transform/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ mod ffi_unwind_calls;
8282
mod function_item_references;
8383
mod gvn;
8484
pub mod inline;
85+
mod instcombine;
8586
mod instsimplify;
8687
mod jump_threading;
8788
mod large_enums;
@@ -598,6 +599,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
598599
&simplify_comparison_integral::SimplifyComparisonIntegral,
599600
&dead_store_elimination::DeadStoreElimination,
600601
&dest_prop::DestinationPropagation,
602+
&instcombine::InstCombine,
601603
&o1(simplify_branches::SimplifyConstCondition::Final),
602604
&o1(remove_noop_landing_pads::RemoveNoopLandingPads),
603605
&o1(simplify::SimplifyCfg::Final),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// MIR for `roundtrip` after PreCodegen
2+
3+
fn roundtrip(_1: *const u8) -> *const u8 {
4+
debug x => _1;
5+
let mut _0: *const u8;
6+
7+
bb0: {
8+
_0 = _1 as *const u8 (PtrToPtr);
9+
return;
10+
}
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
- // MIR for `place_projection` before InstCombine
2+
+ // MIR for `place_projection` after InstCombine
3+
4+
fn place_projection(_1: Outer) -> u8 {
5+
debug o => _1;
6+
let mut _0: u8;
7+
let _2: Inner;
8+
scope 1 {
9+
debug temp => _2;
10+
}
11+
12+
bb0: {
13+
StorageLive(_2);
14+
- _2 = move (_1.0: Inner);
15+
- _0 = (_2.0: u8);
16+
+ _0 = ((_1.0: Inner).0: u8);
17+
+ nop;
18+
StorageDead(_2);
19+
return;
20+
}
21+
}
22+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// skip-filecheck
2+
// unit-test: InstCombine
3+
#![crate_type = "lib"]
4+
5+
pub struct Outer {
6+
inner: Inner,
7+
}
8+
9+
struct Inner {
10+
field: u8,
11+
}
12+
13+
// EMIT_MIR place_projection.place_projection.InstCombine.diff
14+
pub fn place_projection(o: Outer) -> u8 {
15+
let temp = o.inner;
16+
temp.field
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
- // MIR for `ptr_cast` before InstCombine
2+
+ // MIR for `ptr_cast` after InstCombine
3+
4+
fn ptr_cast(_1: *const u8) -> *mut () {
5+
debug p => _1;
6+
let mut _0: *mut ();
7+
let mut _2: *mut u8;
8+
let mut _3: *const u8;
9+
10+
bb0: {
11+
StorageLive(_2);
12+
StorageLive(_3);
13+
_3 = _1;
14+
- _2 = move _3 as *mut u8 (PtrToPtr);
15+
+ _0 = move _3 as *mut () (PtrToPtr);
16+
+ nop;
17+
StorageDead(_3);
18+
- _0 = move _2 as *mut () (PtrToPtr);
19+
StorageDead(_2);
20+
return;
21+
}
22+
}
23+

tests/mir-opt/instcombine/ptr_cast.rs

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// skip-filecheck
2+
// unit-test: InstCombine
3+
#![crate_type = "lib"]
4+
5+
// EMIT_MIR ptr_cast.ptr_cast.InstCombine.diff
6+
pub fn ptr_cast(p: *const u8) -> *mut () {
7+
p as *mut u8 as *mut ()
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
- // MIR for `ref_addressof` before InstCombine
2+
+ // MIR for `ref_addressof` after InstCombine
3+
4+
fn ref_addressof(_1: T) -> () {
5+
debug t => _1;
6+
let mut _0: ();
7+
let _2: &T;
8+
let _4: ();
9+
let mut _5: *const T;
10+
scope 1 {
11+
debug r => _2;
12+
let _3: *const T;
13+
scope 2 {
14+
debug ptr => _3;
15+
}
16+
}
17+
18+
bb0: {
19+
StorageLive(_2);
20+
- _2 = &_1;
21+
StorageLive(_3);
22+
- _3 = &raw const (*_2);
23+
+ _3 = &raw const _1;
24+
+ nop;
25+
StorageLive(_4);
26+
StorageLive(_5);
27+
_5 = _3;
28+
_4 = std::mem::drop::<*const T>(move _5) -> [return: bb1, unwind unreachable];
29+
}
30+
31+
bb1: {
32+
StorageDead(_5);
33+
StorageDead(_4);
34+
_0 = const ();
35+
StorageDead(_3);
36+
StorageDead(_2);
37+
drop(_1) -> [return: bb2, unwind unreachable];
38+
}
39+
40+
bb2: {
41+
return;
42+
}
43+
}
44+
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// skip-filecheck
2+
// unit-test: InstCombine
3+
#![crate_type = "lib"]
4+
5+
// EMIT_MIR ref_addressof.ref_addressof.InstCombine.diff
6+
pub fn ref_addressof<T>(t: T) {
7+
let r = &t;
8+
let ptr = std::ptr::addr_of!(*r);
9+
drop(ptr);
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
- // MIR for `ref_deref` before InstCombine
2+
+ // MIR for `ref_deref` after InstCombine
3+
4+
fn ref_deref(_1: T) -> T {
5+
debug t => _1;
6+
let mut _0: T;
7+
let _2: &T;
8+
scope 1 {
9+
debug r => _2;
10+
}
11+
12+
bb0: {
13+
StorageLive(_2);
14+
- _2 = &_1;
15+
- _0 = (*_2);
16+
+ _0 = _1;
17+
+ nop;
18+
StorageDead(_2);
19+
return;
20+
}
21+
}
22+
+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// skip-filecheck
2+
// unit-test: InstCombine
3+
#![crate_type = "lib"]
4+
5+
// EMIT_MIR ref_deref.ref_deref.InstCombine.diff
6+
pub fn ref_deref<T: Copy>(t: T) -> T {
7+
let r = &t;
8+
*r
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
- // MIR for `outer_get` before InstCombine
2+
+ // MIR for `outer_get` after InstCombine
3+
4+
fn outer_get(_1: &Outer) -> u8 {
5+
debug this => _1;
6+
let mut _0: u8;
7+
let mut _2: &Inner;
8+
let _3: &Inner;
9+
scope 1 (inlined inner_get) {
10+
debug this => &((*_1).0: Inner);
11+
}
12+
13+
bb0: {
14+
_0 = (((*_1).0: Inner).0: u8);
15+
return;
16+
}
17+
}
18+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// MIR for `outer_get` after PreCodegen
2+
3+
fn outer_get(_1: &Outer) -> u8 {
4+
debug this => _1;
5+
let mut _0: u8;
6+
let _2: &Inner;
7+
scope 1 (inlined inner_get) {
8+
debug this => _2;
9+
}
10+
11+
bb0: {
12+
_0 = (((*_1).0: Inner).0: u8);
13+
return;
14+
}
15+
}
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// compile-flags: -O -Cdebuginfo=0 -Zmir-opt-level=2
2+
// only-64bit
3+
// ignore-debug
4+
5+
#![crate_type = "lib"]
6+
7+
pub struct Outer {
8+
inner: Inner,
9+
}
10+
11+
struct Inner {
12+
inner: u8
13+
}
14+
15+
#[inline]
16+
fn inner_get(this: &Inner) -> u8 {
17+
this.inner
18+
}
19+
20+
// EMIT_MIR nested_getter.outer_get.PreCodegen.after.mir
21+
pub fn outer_get(this: &Outer) -> u8 {
22+
inner_get(&this.inner)
23+
}
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2
2+
// only-64bit
3+
// ignore-debug
4+
5+
#![crate_type = "lib"]
6+
7+
// EMIT_MIR simple_swap.simple_swap.PreCodegen.after.mir
8+
pub fn simple_swap<T>(x: &mut T, y: &mut T) {
9+
use std::ptr::{read, write};
10+
unsafe {
11+
let temp = read(x);
12+
write(x, read(y));
13+
write(y, temp);
14+
}
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// MIR for `simple_swap` after PreCodegen
2+
3+
fn simple_swap(_1: &mut T, _2: &mut T) -> () {
4+
debug x => _1;
5+
debug y => _2;
6+
let mut _0: ();
7+
let mut _3: *const T;
8+
let mut _5: *mut T;
9+
let mut _6: *const T;
10+
let mut _7: *mut T;
11+
let mut _8: T;
12+
scope 1 {
13+
let _4: T;
14+
scope 2 {
15+
debug temp => _4;
16+
scope 6 (inlined std::ptr::read::<T>) {
17+
debug src => _6;
18+
scope 7 {
19+
scope 8 (inlined std::ptr::read::runtime::<T>) {
20+
debug src => _6;
21+
}
22+
}
23+
}
24+
scope 9 (inlined std::ptr::write::<T>) {
25+
debug dst => _5;
26+
debug src => _8;
27+
scope 10 {
28+
scope 11 (inlined std::ptr::write::runtime::<T>) {
29+
debug dst => _5;
30+
}
31+
}
32+
}
33+
scope 12 (inlined std::ptr::write::<T>) {
34+
debug dst => _7;
35+
debug src => _4;
36+
scope 13 {
37+
scope 14 (inlined std::ptr::write::runtime::<T>) {
38+
debug dst => _7;
39+
}
40+
}
41+
}
42+
}
43+
scope 3 (inlined std::ptr::read::<T>) {
44+
debug src => _3;
45+
scope 4 {
46+
scope 5 (inlined std::ptr::read::runtime::<T>) {
47+
debug src => _3;
48+
}
49+
}
50+
}
51+
}
52+
53+
bb0: {
54+
StorageLive(_3);
55+
_3 = &raw const (*_1);
56+
_4 = (*_3);
57+
StorageDead(_3);
58+
StorageLive(_5);
59+
_5 = &raw mut (*_1);
60+
StorageLive(_8);
61+
StorageLive(_6);
62+
_6 = &raw const (*_2);
63+
(*_5) = (*_6);
64+
StorageDead(_6);
65+
StorageDead(_8);
66+
StorageDead(_5);
67+
StorageLive(_7);
68+
_7 = &raw mut (*_2);
69+
(*_7) = move _4;
70+
StorageDead(_7);
71+
return;
72+
}
73+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
- // MIR for `as_ptr` before InstCombine
2+
+ // MIR for `as_ptr` after InstCombine
3+
4+
fn as_ptr(_1: &Vec<i32>) -> *const i32 {
5+
debug v => _1;
6+
let mut _0: *const i32;
7+
scope 1 (inlined Vec::<i32>::as_ptr) {
8+
debug self => _1;
9+
let mut _2: *mut i32;
10+
let mut _3: &alloc::raw_vec::RawVec<i32>;
11+
scope 2 (inlined alloc::raw_vec::RawVec::<i32>::ptr) {
12+
debug self => _3;
13+
let mut _5: std::ptr::NonNull<i32>;
14+
scope 3 (inlined Unique::<i32>::as_ptr) {
15+
debug ((self: Unique<i32>).0: std::ptr::NonNull<i32>) => _5;
16+
debug ((self: Unique<i32>).1: std::marker::PhantomData<i32>) => const PhantomData::<i32>;
17+
scope 4 (inlined NonNull::<i32>::as_ptr) {
18+
debug self => _5;
19+
let mut _4: *const i32;
20+
}
21+
}
22+
}
23+
}
24+
25+
bb0: {
26+
StorageLive(_2);
27+
StorageLive(_3);
28+
_3 = &((*_1).0: alloc::raw_vec::RawVec<i32>);
29+
StorageLive(_5);
30+
_5 = ((((*_1).0: alloc::raw_vec::RawVec<i32>).0: std::ptr::Unique<i32>).0: std::ptr::NonNull<i32>);
31+
StorageLive(_4);
32+
_4 = (_5.0: *const i32);
33+
_2 = move _4 as *mut i32 (PtrToPtr);
34+
StorageDead(_4);
35+
StorageDead(_5);
36+
_0 = move _2 as *const i32 (PointerCoercion(MutToConstPointer));
37+
StorageDead(_3);
38+
StorageDead(_2);
39+
return;
40+
}
41+
}
42+

0 commit comments

Comments
 (0)