Skip to content

Commit d208320

Browse files
committed
Auto merge of #109597 - cjgillot:gvn, r=oli-obk
Implement a global value numbering MIR optimization The aim of this pass is to avoid repeated computations by reusing past assignments. It is based on an analysis of SSA locals, in order to perform a restricted form of common subexpression elimination. By opportunity, this pass allows for some simplifications by combining assignments. For instance, this pass could be able to see through projections of aggregates to directly reuse the aggregate field (not in this PR). We handle references by assigning a different "provenance" index to each `Ref`/`AddressOf` rvalue. This ensure that we do not spuriously merge borrows that should not be merged. Meanwhile, we consider all the derefs of an immutable reference to a freeze type to give the same value: ```rust _a = *_b // _b is &Freeze _c = *_b // replaced by _c = _a ```
2 parents 9a0aafa + 0268dac commit d208320

File tree

1 file changed

+16
-4
lines changed

1 file changed

+16
-4
lines changed

tests/pass/function_pointers.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ fn h(i: i32, j: i32) -> i32 {
2323
j * i * 7
2424
}
2525

26+
fn i() -> i32 {
27+
73
28+
}
29+
2630
fn return_fn_ptr(f: fn() -> i32) -> fn() -> i32 {
2731
f
2832
}
@@ -72,10 +76,18 @@ fn main() {
7276
assert_eq!(indirect3(h), 210);
7377
assert_eq!(indirect_mut3(h), 210);
7478
assert_eq!(indirect_once3(h), 210);
75-
let g = f as fn() -> i32;
76-
assert!(return_fn_ptr(g) == g);
77-
assert!(return_fn_ptr(g) as unsafe fn() -> i32 == g as fn() -> i32 as unsafe fn() -> i32);
78-
assert!(return_fn_ptr(f) != f);
79+
// Check that `i` always has the same address. This is not guaranteed
80+
// but Miri currently uses a fixed address for monomorphic functions.
81+
assert!(return_fn_ptr(i) == i);
82+
assert!(return_fn_ptr(i) as unsafe fn() -> i32 == i as fn() -> i32 as unsafe fn() -> i32);
83+
// We don't check anything for `f`. Miri gives it many different addresses
84+
// but mir-opts can turn them into the same address.
85+
let _val = return_fn_ptr(f) != f;
86+
// However, if we only turn `f` into a function pointer and use that pointer,
87+
// it is equal to itself.
88+
let f2 = f as fn() -> i32;
89+
assert!(return_fn_ptr(f2) == f2);
90+
assert!(return_fn_ptr(f2) as unsafe fn() -> i32 == f2 as fn() -> i32 as unsafe fn() -> i32);
7991

8092
// Any non-null value is okay for function pointers.
8193
unsafe {

0 commit comments

Comments
 (0)