Skip to content

Commit 2d97856

Browse files
authored
Exhaustively test OptimizeInstructions on ref.cast (#7542)
Write a script to systematically generate test cases for all possible interesting cast patterns. Update the code to correctly handle the case where the cast is known to succeed but still requires a cast to recover exactness.
1 parent e43be97 commit 2d97856

File tree

5 files changed

+1936
-23
lines changed

5 files changed

+1936
-23
lines changed

scripts/test/fuzzing.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@
114114
'exact-references-lowering.wast',
115115
'exact-casts.wast',
116116
'exact-casts-trivial.wast',
117-
'optimize-instructions-exact.wast',
117+
'optimize-instructions-all-casts.wast',
118118
'local-subtyping-exact.wast',
119119
'remove-unused-types-exact.wast',
120120
'coalesce-locals-exact.wast',

scripts/test/gen-cast-test.py

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
#! /usr/bin/python3
2+
3+
'''
4+
This script is used to generate
5+
test/lit/passes/optimize-instructions-all-casts.wast
6+
'''
7+
8+
import itertools
9+
10+
interesting_pairs = [('$super', '$super', 'cast-to-self-nonfinal'),
11+
('$sub-final', '$sub-final', 'cast-to-self-final'),
12+
('$sub', '$super', 'cast-to-super'),
13+
('$super', '$sub', 'cast-to-sub'),
14+
('$sub-final', '$sub', 'cast-to-sibling'),
15+
('$super', 'none', 'cast-to-bottom'),
16+
('none', '$super', 'cast-from-bottom')]
17+
18+
19+
def gen_test_configs():
20+
for src_heap, cast_heap, heap_name in interesting_pairs:
21+
for src_nullable, src_exact, cast_nullable, cast_exact in \
22+
itertools.product([True, False], repeat=4):
23+
if src_exact and src_heap == 'none':
24+
continue
25+
if cast_exact and cast_heap == 'none':
26+
continue
27+
yield heap_name, src_heap, cast_heap, src_nullable, cast_nullable, \
28+
src_exact, cast_exact
29+
30+
31+
def print_test(config):
32+
heap_name, src_heap, cast_heap, src_nullable, cast_nullable, src_exact, \
33+
cast_exact = config
34+
35+
src_nullable_name = 'null' if src_nullable else 'non-null'
36+
cast_nullable_name = 'null' if cast_nullable else 'non-null'
37+
38+
src_exact_name = 'exact' if src_exact else 'inexact'
39+
cast_exact_name = 'exact' if cast_exact else 'inexact'
40+
41+
test_name = f'{heap_name}-{src_nullable_name}-{src_exact_name}-to-' + \
42+
f'{cast_nullable_name}-{cast_exact_name}'
43+
44+
src_nullable_type = ' null' if src_nullable else ''
45+
cast_nullable_type = ' null' if cast_nullable else ''
46+
47+
src_heap_type = f'(exact {src_heap})' if src_exact else src_heap
48+
cast_heap_type = f'(exact {cast_heap})' if cast_exact else cast_heap
49+
50+
src_type = f'(ref{src_nullable_type} {src_heap_type})'
51+
cast_type = f'(ref{cast_nullable_type} {cast_heap_type})'
52+
53+
test = f'''
54+
(func ${test_name} (param {src_type}) (result {cast_type})
55+
(local anyref)
56+
(ref.cast {cast_type}
57+
(local.tee 1
58+
(local.get 0)
59+
)
60+
)
61+
)'''
62+
print(test)
63+
64+
65+
def print_tests():
66+
for config in gen_test_configs():
67+
print_test(config)
68+
69+
70+
def print_header():
71+
header = ''';; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
72+
;; NOTE: Test has been generated by scripts/test/gen-cast-test.py. Do not edit manually.
73+
74+
;; Exhaustively test optimization of all interesting casts.
75+
76+
;; RUN: wasm-opt %s -all --optimize-instructions -S -o - | filecheck %s
77+
78+
(module
79+
(type $super (sub (struct)))
80+
(type $sub (sub $super (struct)))
81+
(type $sub-final (sub final $super (struct)))'''
82+
print(header)
83+
84+
85+
def print_footer():
86+
print(')')
87+
88+
89+
def main():
90+
print_header()
91+
print_tests()
92+
print_footer()
93+
94+
95+
if __name__ == '__main__':
96+
main()

src/passes/OptimizeInstructions.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2333,6 +2333,15 @@ struct OptimizeInstructions
23332333
builder.makeRefNull(nullType)));
23342334
return;
23352335
}
2336+
2337+
// At this point we know the cast will succeed as long as nullability
2338+
// works out, but we still need the cast to recover the exactness that
2339+
// is not present in the value's static type, so there's nothing we
2340+
// can do.
2341+
if (needsExactCast) {
2342+
return;
2343+
}
2344+
23362345
// We need to use a tee to return the value since we can't materialize
23372346
// it directly.
23382347
auto scratch = builder.addVar(getFunction(), ref->type);

0 commit comments

Comments
 (0)