Skip to content

Exhaustively test OptimizeInstructions on ref.cast #7542

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

Merged
merged 2 commits into from
Apr 23, 2025
Merged
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
2 changes: 1 addition & 1 deletion scripts/test/fuzzing.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@
'exact-references-lowering.wast',
'exact-casts.wast',
'exact-casts-trivial.wast',
'optimize-instructions-exact.wast',
'optimize-instructions-all-casts.wast',
'local-subtyping-exact.wast',
'remove-unused-types-exact.wast',
'coalesce-locals-exact.wast',
Expand Down
96 changes: 96 additions & 0 deletions scripts/test/gen-cast-test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#! /usr/bin/python3

'''
This script is used to generate
test/lit/passes/optimize-instructions-all-casts.wast
'''

import itertools

interesting_pairs = [('$super', '$super', 'cast-to-self-nonfinal'),
('$sub-final', '$sub-final', 'cast-to-self-final'),
('$sub', '$super', 'cast-to-super'),
('$super', '$sub', 'cast-to-sub'),
('$sub-final', '$sub', 'cast-to-sibling'),
('$super', 'none', 'cast-to-bottom'),
('none', '$super', 'cast-from-bottom')]


def gen_test_configs():
for src_heap, cast_heap, heap_name in interesting_pairs:
for src_nullable, src_exact, cast_nullable, cast_exact in \
itertools.product([True, False], repeat=4):
if src_exact and src_heap == 'none':
continue
if cast_exact and cast_heap == 'none':
continue
yield heap_name, src_heap, cast_heap, src_nullable, cast_nullable, \
src_exact, cast_exact


def print_test(config):
heap_name, src_heap, cast_heap, src_nullable, cast_nullable, src_exact, \
cast_exact = config

src_nullable_name = 'null' if src_nullable else 'non-null'
cast_nullable_name = 'null' if cast_nullable else 'non-null'

src_exact_name = 'exact' if src_exact else 'inexact'
cast_exact_name = 'exact' if cast_exact else 'inexact'

test_name = f'{heap_name}-{src_nullable_name}-{src_exact_name}-to-' + \
f'{cast_nullable_name}-{cast_exact_name}'

src_nullable_type = ' null' if src_nullable else ''
cast_nullable_type = ' null' if cast_nullable else ''

src_heap_type = f'(exact {src_heap})' if src_exact else src_heap
cast_heap_type = f'(exact {cast_heap})' if cast_exact else cast_heap

src_type = f'(ref{src_nullable_type} {src_heap_type})'
cast_type = f'(ref{cast_nullable_type} {cast_heap_type})'

test = f'''
(func ${test_name} (param {src_type}) (result {cast_type})
(local anyref)
(ref.cast {cast_type}
(local.tee 1
(local.get 0)
)
)
)'''
print(test)


def print_tests():
for config in gen_test_configs():
print_test(config)


def print_header():
header = ''';; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
;; NOTE: Test has been generated by scripts/test/gen-cast-test.py. Do not edit manually.

;; Exhaustively test optimization of all interesting casts.

;; RUN: wasm-opt %s -all --optimize-instructions -S -o - | filecheck %s

(module
(type $super (sub (struct)))
(type $sub (sub $super (struct)))
(type $sub-final (sub final $super (struct)))'''
print(header)


def print_footer():
print(')')


def main():
print_header()
print_tests()
print_footer()


if __name__ == '__main__':
main()
9 changes: 9 additions & 0 deletions src/passes/OptimizeInstructions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2333,6 +2333,15 @@ struct OptimizeInstructions
builder.makeRefNull(nullType)));
return;
}

// At this point we know the cast will succeed as long as nullability
// works out, but we still need the cast to recover the exactness that
// is not present in the value's static type, so there's nothing we
// can do.
if (needsExactCast) {
return;
}

// We need to use a tee to return the value since we can't materialize
// it directly.
auto scratch = builder.addVar(getFunction(), ref->type);
Expand Down
Loading
Loading