Skip to content

Commit 541272d

Browse files
committed
[move compiler] [CSE Step 3] add test cases for CSE
1 parent a0bad1c commit 541272d

File tree

4 files changed

+371
-0
lines changed

4 files changed

+371
-0
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
module 0x99::FiledAccess {
2+
struct Inner has copy, drop {
3+
value: u64,
4+
}
5+
6+
struct Outer has copy, drop {
7+
inner: Inner,
8+
}
9+
10+
fun get_value(outer: &Outer): u64 {
11+
outer.inner.value
12+
}
13+
14+
fun set_value(outer: &mut Outer, new_value: u64) {
15+
outer.inner.value = new_value;
16+
}
17+
18+
// `arg1.inner.value` can be reused
19+
// perf_gain: 2 field accesses + 1 readref eliminated
20+
// new_cost: `u64` flushed and copied twice
21+
fun test_field_access(arg1: Outer, arg2: u64): u64 {
22+
arg1.inner.value + arg2 + arg1.inner.value
23+
}
24+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
2+
============ disassembled file-format ==================
3+
// Bytecode version v9
4+
module 0x99::FiledAccess
5+
struct Inner has copy + drop
6+
value: u64
7+
8+
struct Outer has copy + drop
9+
inner: Inner
10+
11+
// Function definition at index 0
12+
fun get_value(l0: &Outer): u64
13+
move_loc l0
14+
borrow_field Outer, inner
15+
borrow_field Inner, value
16+
read_ref
17+
ret
18+
19+
// Function definition at index 1
20+
fun set_value(l0: &mut Outer, l1: u64)
21+
local l2: &mut u64
22+
move_loc l0
23+
mut_borrow_field Outer, inner
24+
mut_borrow_field Inner, value
25+
st_loc l2
26+
move_loc l1
27+
// @5
28+
move_loc l2
29+
write_ref
30+
ret
31+
32+
// Function definition at index 2
33+
fun test_field_access(l0: Outer, l1: u64): u64
34+
borrow_loc l0
35+
borrow_field Outer, inner
36+
borrow_field Inner, value
37+
read_ref
38+
move_loc l1
39+
// @5
40+
add
41+
borrow_loc l0
42+
borrow_field Outer, inner
43+
borrow_field Inner, value
44+
read_ref
45+
// @10
46+
add
47+
ret
48+
49+
50+
============ bytecode verification succeeded ========
Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
============ after ReachingDefProcessor: ================
2+
3+
[variant baseline]
4+
fun FiledAccess::get_value($t0: &0x99::FiledAccess::Outer): u64 {
5+
var $t1: u64
6+
var $t2: &0x99::FiledAccess::Inner
7+
var $t3: &u64
8+
# live vars: $t0
9+
# reaching instruction #0:
10+
# refs: [$t0 => #0]
11+
# #0
12+
# <no edges>
13+
# #root
14+
# <no edges>
15+
#
16+
0: $t2 := borrow_field<0x99::FiledAccess::Outer>.inner($t0)
17+
# live vars: $t2
18+
# reaching instruction #1: `t2` @ {0}
19+
# refs: [$t2 => #2]
20+
# #2
21+
# <no edges>
22+
# #root
23+
# <no edges>
24+
#
25+
1: $t3 := borrow_field<0x99::FiledAccess::Inner>.value($t2)
26+
# live vars: $t3
27+
# reaching instruction #2: `t2` @ {0}, `t3` @ {1}
28+
# refs: [$t3 => #3]
29+
# #3
30+
# <no edges>
31+
# #root
32+
# <no edges>
33+
#
34+
2: $t1 := read_ref($t3)
35+
# live vars: $t1
36+
# reaching instruction #3: `t1` @ {2}, `t2` @ {0}, `t3` @ {1}
37+
# refs: []
38+
#
39+
3: return $t1
40+
}
41+
42+
43+
[variant baseline]
44+
fun FiledAccess::set_value($t0: &mut 0x99::FiledAccess::Outer, $t1: u64) {
45+
var $t2: &mut u64
46+
var $t3: &mut 0x99::FiledAccess::Inner
47+
# live vars: $t0, $t1
48+
# reaching instruction #0:
49+
# refs: [$t0 => #0]
50+
# #0
51+
# <no edges>
52+
# #root
53+
# <no edges>
54+
#
55+
0: $t3 := borrow_field<0x99::FiledAccess::Outer>.inner($t0)
56+
# flush: $t1
57+
# live vars: $t1, $t3
58+
# reaching instruction #1: `t3` @ {0}
59+
# refs: [$t3 => #3]
60+
# #3
61+
# <no edges>
62+
# #root
63+
# <no edges>
64+
#
65+
1: $t2 := borrow_field<0x99::FiledAccess::Inner>.value($t3)
66+
# live vars: $t1, $t2
67+
# reaching instruction #2: `t2` @ {1}, `t3` @ {0}
68+
# refs: [$t2 => #2]
69+
# #2
70+
# <no edges>
71+
# #root
72+
# <no edges>
73+
#
74+
2: write_ref($t2, $t1)
75+
# live vars:
76+
# reaching instruction #3: `t2` @ {1}, `t3` @ {0}
77+
# refs: []
78+
#
79+
3: return ()
80+
}
81+
82+
83+
[variant baseline]
84+
fun FiledAccess::test_field_access($t0: 0x99::FiledAccess::Outer, $t1: u64): u64 {
85+
var $t2: u64
86+
var $t3: u64
87+
var $t4: u64
88+
var $t5: &0x99::FiledAccess::Inner
89+
var $t6: &0x99::FiledAccess::Outer
90+
var $t7: &u64
91+
var $t8: u64
92+
var $t9: &0x99::FiledAccess::Inner
93+
var $t10: &0x99::FiledAccess::Outer
94+
var $t11: &u64
95+
# live vars: $t0, $t1
96+
# reaching instruction #0:
97+
# refs: []
98+
#
99+
0: $t6 := borrow_local($t0)
100+
# live vars: $t0, $t1, $t6
101+
# reaching instruction #1: `t6` @ {0}
102+
# refs: [$t6 => #6]
103+
# #6
104+
# <no edges>
105+
# #root
106+
# => #6 via [local `arg1`] at line 19
107+
#
108+
1: $t5 := borrow_field<0x99::FiledAccess::Outer>.inner($t6)
109+
# live vars: $t0, $t1, $t5
110+
# reaching instruction #2: `t5` @ {1}, `t6` @ {0}
111+
# refs: [$t5 => #5]
112+
# #5
113+
# <no edges>
114+
# #root
115+
# => #5 via [local `arg1`, field `inner`] at line 19
116+
#
117+
2: $t7 := borrow_field<0x99::FiledAccess::Inner>.value($t5)
118+
# live vars: $t0, $t1, $t7
119+
# reaching instruction #3: `t5` @ {1}, `t6` @ {0}, `t7` @ {2}
120+
# refs: [$t7 => #7]
121+
# #7
122+
# <no edges>
123+
# #root
124+
# => #7 via [local `arg1`, field `inner`, field `value`] at line 19
125+
#
126+
3: $t4 := read_ref($t7)
127+
# live vars: $t0, $t1, $t4
128+
# reaching instruction #4: `t4` @ {3}, `t5` @ {1}, `t6` @ {0}, `t7` @ {2}
129+
# refs: []
130+
#
131+
4: $t3 := +($t4, $t1)
132+
# live vars: $t0, $t3
133+
# reaching instruction #5: `t3` @ {4}, `t4` @ {3}, `t5` @ {1}, `t6` @ {0}, `t7` @ {2}
134+
# refs: []
135+
#
136+
5: $t10 := borrow_local($t0)
137+
# live vars: $t3, $t10
138+
# reaching instruction #6: `t3` @ {4}, `t4` @ {3}, `t5` @ {1}, `t6` @ {0}, `t7` @ {2}, `t10` @ {5}
139+
# refs: [$t10 => #10]
140+
# #10
141+
# <no edges>
142+
# #root
143+
# => #10 via [local `arg1`] at line 19
144+
#
145+
6: $t9 := borrow_field<0x99::FiledAccess::Outer>.inner($t10)
146+
# live vars: $t3, $t9
147+
# reaching instruction #7: `t3` @ {4}, `t4` @ {3}, `t5` @ {1}, `t6` @ {0}, `t7` @ {2}, `t9` @ {6}, `t10` @ {5}
148+
# refs: [$t9 => #9]
149+
# #9
150+
# <no edges>
151+
# #root
152+
# => #9 via [local `arg1`, field `inner`] at line 19
153+
#
154+
7: $t11 := borrow_field<0x99::FiledAccess::Inner>.value($t9)
155+
# live vars: $t3, $t11
156+
# reaching instruction #8: `t3` @ {4}, `t4` @ {3}, `t5` @ {1}, `t6` @ {0}, `t7` @ {2}, `t9` @ {6}, `t10` @ {5}, `t11` @ {7}
157+
# refs: [$t11 => #11]
158+
# #11
159+
# <no edges>
160+
# #root
161+
# => #11 via [local `arg1`, field `inner`, field `value`] at line 19
162+
#
163+
8: $t8 := read_ref($t11)
164+
# live vars: $t3, $t8
165+
# reaching instruction #9: `t3` @ {4}, `t4` @ {3}, `t5` @ {1}, `t6` @ {0}, `t7` @ {2}, `t8` @ {8}, `t9` @ {6}, `t10` @ {5}, `t11` @ {7}
166+
# refs: []
167+
#
168+
9: $t2 := +($t3, $t8)
169+
# live vars: $t2
170+
# reaching instruction #10: `t2` @ {9}, `t3` @ {4}, `t4` @ {3}, `t5` @ {1}, `t6` @ {0}, `t7` @ {2}, `t8` @ {8}, `t9` @ {6}, `t10` @ {5}, `t11` @ {7}
171+
# refs: []
172+
#
173+
10: return $t2
174+
}
175+
176+
============ after CommonSubexpElimination: ================
177+
178+
[variant baseline]
179+
fun FiledAccess::get_value($t0: &0x99::FiledAccess::Outer): u64 {
180+
var $t1: u64
181+
var $t2: &0x99::FiledAccess::Inner
182+
var $t3: &u64
183+
0: $t2 := borrow_field<0x99::FiledAccess::Outer>.inner($t0)
184+
1: $t3 := borrow_field<0x99::FiledAccess::Inner>.value($t2)
185+
2: $t1 := read_ref($t3)
186+
3: return $t1
187+
}
188+
189+
190+
[variant baseline]
191+
fun FiledAccess::set_value($t0: &mut 0x99::FiledAccess::Outer, $t1: u64) {
192+
var $t2: &mut u64
193+
var $t3: &mut 0x99::FiledAccess::Inner
194+
0: $t3 := borrow_field<0x99::FiledAccess::Outer>.inner($t0)
195+
1: $t2 := borrow_field<0x99::FiledAccess::Inner>.value($t3)
196+
2: write_ref($t2, $t1)
197+
3: return ()
198+
}
199+
200+
201+
[variant baseline]
202+
fun FiledAccess::test_field_access($t0: 0x99::FiledAccess::Outer, $t1: u64): u64 {
203+
var $t2: u64
204+
var $t3: u64
205+
var $t4: u64
206+
var $t5: &0x99::FiledAccess::Inner
207+
var $t6: &0x99::FiledAccess::Outer
208+
var $t7: &u64
209+
var $t8: u64
210+
var $t9: &0x99::FiledAccess::Inner [unused]
211+
var $t10: &0x99::FiledAccess::Outer [unused]
212+
var $t11: &u64
213+
0: $t6 := borrow_local($t0)
214+
1: $t5 := borrow_field<0x99::FiledAccess::Outer>.inner($t6)
215+
2: $t7 := borrow_field<0x99::FiledAccess::Inner>.value($t5)
216+
3: $t4 := read_ref($t7)
217+
4: $t3 := +($t4, $t1)
218+
5: $t11 := infer($t7)
219+
6: $t8 := infer($t4)
220+
7: $t2 := +($t3, $t8)
221+
8: return $t2
222+
}
223+
224+
225+
============ disassembled file-format ==================
226+
// Bytecode version v9
227+
module 0x99::FiledAccess
228+
struct Inner has copy + drop
229+
value: u64
230+
231+
struct Outer has copy + drop
232+
inner: Inner
233+
234+
// Function definition at index 0
235+
fun get_value(l0: &Outer): u64
236+
move_loc l0
237+
borrow_field Outer, inner
238+
borrow_field Inner, value
239+
read_ref
240+
ret
241+
242+
// Function definition at index 1
243+
fun set_value(l0: &mut Outer, l1: u64)
244+
local l2: &mut u64
245+
move_loc l0
246+
mut_borrow_field Outer, inner
247+
mut_borrow_field Inner, value
248+
st_loc l2
249+
move_loc l1
250+
// @5
251+
move_loc l2
252+
write_ref
253+
ret
254+
255+
// Function definition at index 2
256+
fun test_field_access(l0: Outer, l1: u64): u64
257+
local l2: &u64
258+
local l3: u64
259+
borrow_loc l0
260+
borrow_field Outer, inner
261+
borrow_field Inner, value
262+
st_loc l2
263+
copy_loc l2
264+
// @5
265+
read_ref
266+
st_loc l3
267+
copy_loc l3
268+
move_loc l1
269+
add
270+
// @10
271+
move_loc l2
272+
pop
273+
move_loc l3
274+
add
275+
ret
276+
277+
278+
============ bytecode verification succeeded ========

third_party/move/move-compiler-v2/tests/testsuite.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,25 @@ const TEST_CONFIGS: Lazy<BTreeMap<&str, TestConfig>> = Lazy::new(|| {
459459
// For testing
460460
.exp(Experiment::VARIABLE_COALESCING_ANNOTATE)
461461
},
462+
// Common exbpression elimination tests
463+
TestConfig {
464+
name: "common-subexp-elim-on",
465+
runner: |p| run_test(p, get_config_by_name("common-subexp-elim-on")),
466+
include: vec!["/common-subexp-elimination/"],
467+
exp_suffix: Some("on.exp"),
468+
dump_bytecode: DumpLevel::AllStages,
469+
dump_bytecode_filter: Some(vec!["ReachingDefProcessor", "CommonSubexpElimination", FILE_FORMAT_STAGE]),
470+
..config().exp(Experiment::COMMON_SUBEXP_ELIMINATION)
471+
},
472+
TestConfig {
473+
name: "common-subexp-elim-off",
474+
runner: |p| run_test(p, get_config_by_name("common-subexp-elim-off")),
475+
include: vec!["/common-subexp-elimination/"],
476+
exp_suffix: Some("off.exp"),
477+
dump_bytecode: DumpLevel::AllStages,
478+
dump_bytecode_filter: Some(vec!["ReachingDefProcessor", "CommonSubexpElimination", FILE_FORMAT_STAGE]),
479+
..config().exp_off(Experiment::COMMON_SUBEXP_ELIMINATION)
480+
},
462481
// Flush writes processor tests
463482
TestConfig {
464483
name: "flush-writes-on",

0 commit comments

Comments
 (0)