Skip to content

Commit 89f9fe5

Browse files
authored
Run multiple iterations of JSDCE, as more may be removable (#5855)
* Run JSDCE with or without closure. It helps even if closure runs later. As we improve it further it may help more. * Add AJSDCE (aggressive JSDCE) which runs multiple iterations. This is enabled on -Os, -Oz builds. * Clean up how we add closure testing to tests in test_core.py, and add it to some -Os tests too, not just -O2, for more coverage.
1 parent b12c9de commit 89f9fe5

File tree

8 files changed

+243
-119
lines changed

8 files changed

+243
-119
lines changed

emcc.py

+11-10
Original file line numberDiff line numberDiff line change
@@ -2355,20 +2355,21 @@ def do_binaryen(target, asm_target, options, memfile, wasm_binary_target,
23552355
if options.opt_level >= 2:
23562356
# minify the JS
23572357
optimizer.do_minify() # calculate how to minify
2358-
if optimizer.cleanup_shell or optimizer.minify_whitespace or options.use_closure_compiler:
2359-
misc_temp_files.note(final)
2358+
if optimizer.cleanup_shell or options.use_closure_compiler:
23602359
if DEBUG: save_intermediate('preclean', 'js')
2360+
# in -Os and -Oz, run AJSDCE (aggressive JS DCE, performs multiple iterations)
2361+
passes = ['noPrintMetadata', 'JSDCE' if options.shrink_level == 0 else 'AJSDCE', 'last']
2362+
if optimizer.minify_whitespace:
2363+
passes.append('minifyWhitespace')
2364+
misc_temp_files.note(final)
2365+
logging.debug('running cleanup on shell code: ' + ' '.join(passes))
2366+
final = shared.Building.js_optimizer_no_asmjs(final, passes)
2367+
if DEBUG: save_intermediate('postclean', 'js')
23612368
if options.use_closure_compiler:
23622369
logging.debug('running closure on shell code')
2370+
misc_temp_files.note(final)
23632371
final = shared.Building.closure_compiler(final, pretty=not optimizer.minify_whitespace)
2364-
else:
2365-
assert optimizer.cleanup_shell
2366-
logging.debug('running cleanup on shell code')
2367-
passes = ['noPrintMetadata', 'JSDCE', 'last']
2368-
if optimizer.minify_whitespace:
2369-
passes.append('minifyWhitespace')
2370-
final = shared.Building.js_optimizer_no_asmjs(final, passes)
2371-
if DEBUG: save_intermediate('postclean', 'js')
2372+
if DEBUG: save_intermediate('postclosure', 'js')
23722373
# replace placeholder strings with correct subresource locations
23732374
if shared.Settings.SINGLE_FILE:
23742375
f = open(final, 'r')

tests/optimizer/AJSDCE-output.js

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
2+
var z = fleefl();
3+
var zz = fleefl();
4+
function g(a) {
5+
return a + 1;
6+
}
7+
Module["g"] = g;
8+
function h(a) {
9+
return a + 1;
10+
}
11+
print(h(123));
12+
((function() {
13+
var z = fleefl();
14+
var zz = fleefl();
15+
function g(a) {
16+
return a + 1;
17+
}
18+
Module["g"] = g;
19+
function hh(a) {
20+
return a + 1;
21+
}
22+
print(hh(123));
23+
}))();
24+
function glue() {
25+
}
26+
glue();
27+

tests/optimizer/AJSDCE.js

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
2+
// all unused
3+
var x;
4+
var y = 1;
5+
var z = fleefl();
6+
var xx, yy = 1, zz = fleefl(); // but zz must remain due to the side effects in the value
7+
function f(x, y, z) {
8+
// shadow the x,y,z
9+
x = y;
10+
y = z;
11+
}
12+
13+
// exported
14+
function g(a) {
15+
return a+1;
16+
}
17+
Module['g'] = g;
18+
19+
// used
20+
function h(a) {
21+
var t; // unused
22+
return a+1;
23+
}
24+
print(h(123));
25+
26+
// inner workings
27+
(function() {
28+
var x;
29+
var y = 1;
30+
var z = fleefl();
31+
var xx, yy = 1, zz = fleefl();
32+
function f(x, y, z) {
33+
// shadow the x,y,z
34+
x = y;
35+
y = z;
36+
}
37+
38+
// exported
39+
function g(a) {
40+
return a+1;
41+
}
42+
Module['g'] = g;
43+
44+
// used
45+
function hh(a) {
46+
var t; // unused
47+
return a+1;
48+
}
49+
print(hh(123));
50+
})();
51+
52+
function glue() {
53+
function lookup() { // 2 passes needed for this one
54+
throw 1;
55+
}
56+
function removable() { // first remove this
57+
lookup();
58+
}
59+
}
60+
glue();
61+

tests/optimizer/JSDCE-output.js

+6
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,10 @@ print(h(123));
2121
}
2222
print(hh(123));
2323
}))();
24+
function glue() {
25+
function lookup() {
26+
throw 1;
27+
}
28+
}
29+
glue();
2430

tests/optimizer/JSDCE.js

+10
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,13 @@ print(h(123));
4949
print(hh(123));
5050
})();
5151

52+
function glue() {
53+
function lookup() { // 2 passes needed for this one
54+
throw 1;
55+
}
56+
function removable() { // first remove this
57+
lookup();
58+
}
59+
}
60+
glue();
61+

tests/test_core.py

+13-12
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,13 @@ def is_split_memory(self):
5555
def is_wasm(self):
5656
return 'BINARYEN' in str(self.emcc_args) or self.is_wasm_backend()
5757

58+
# Use closure in some tests for some additional coverage
59+
def maybe_closure(self):
60+
if '-O2' in self.emcc_args or '-Os' in self.emcc_args:
61+
self.emcc_args += ['--closure', '1']
62+
return True
63+
return False
64+
5865
def do_run_in_out_file_test(self, *path, **kwargs):
5966
test_path = path_from_root(*path)
6067

@@ -882,8 +889,7 @@ def test_exceptions(self):
882889
Settings.EXCEPTION_DEBUG = 1
883890

884891
Settings.DISABLE_EXCEPTION_CATCHING = 0
885-
if '-O2' in self.emcc_args:
886-
self.emcc_args += ['--closure', '1'] # Use closure here for some additional coverage
892+
self.maybe_closure()
887893

888894
src = '''
889895
#include <stdio.h>
@@ -4089,8 +4095,7 @@ def test_langinfo(self):
40894095

40904096
def test_files(self):
40914097
self.banned_js_engines = [SPIDERMONKEY_ENGINE] # closure can generate variables called 'gc', which pick up js shell stuff
4092-
if '-O2' in self.emcc_args:
4093-
self.emcc_args += ['--closure', '1'] # Use closure here, to test we don't break FS stuff
4098+
if self.maybe_closure(): # Use closure here, to test we don't break FS stuff
40944099
self.emcc_args = [x for x in self.emcc_args if x != '-g'] # ensure we test --closure 1 --memory-init-file 1 (-g would disable closure)
40954100
elif '-O3' in self.emcc_args and not self.is_wasm():
40964101
print('closure 2')
@@ -5107,8 +5112,7 @@ def test_sse1(self):
51075112
orig_args = self.emcc_args
51085113
for mode in [[], ['-s', 'SIMD=1']]:
51095114
self.emcc_args = orig_args + mode + ['-msse']
5110-
if '-O2' in self.emcc_args:
5111-
self.emcc_args += ['--closure', '1'] # Use closure here for some additional coverage
5115+
self.maybe_closure()
51125116

51135117
self.do_run(open(path_from_root('tests', 'test_sse1.cpp'), 'r').read(), 'Success!')
51145118

@@ -5130,8 +5134,7 @@ def test_sse1_full(self):
51305134
orig_args = self.emcc_args
51315135
for mode in [[], ['-s', 'SIMD=1']]:
51325136
self.emcc_args = orig_args + mode + ['-I' + path_from_root('tests'), '-msse']
5133-
if '-O2' in self.emcc_args:
5134-
self.emcc_args += ['--closure', '1'] # Use closure here for some additional coverage
5137+
self.maybe_closure()
51355138

51365139
self.do_run(open(path_from_root('tests', 'test_sse1_full.cpp'), 'r').read(), self.ignore_nans(native_result), output_nicerizer=self.ignore_nans)
51375140

@@ -5153,8 +5156,7 @@ def test_sse2_full(self):
51535156
orig_args = self.emcc_args
51545157
for mode in [[], ['-s', 'SIMD=1']]:
51555158
self.emcc_args = orig_args + mode + ['-I' + path_from_root('tests'), '-msse2'] + args
5156-
if '-O2' in self.emcc_args:
5157-
self.emcc_args += ['--closure', '1'] # Use closure here for some additional coverage
5159+
self.maybe_closure()
51585160

51595161
self.do_run(open(path_from_root('tests', 'test_sse2_full.cpp'), 'r').read(), self.ignore_nans(native_result), output_nicerizer=self.ignore_nans)
51605162

@@ -5463,8 +5465,7 @@ def test_sqlite(self):
54635465
force_c=True)
54645466

54655467
def test_zlib(self):
5466-
if '-O2' in self.emcc_args and 'ASM_JS=0' not in self.emcc_args: # without asm, closure minifies Math.imul badly
5467-
self.emcc_args += ['--closure', '1'] # Use closure here for some additional coverage
5468+
self.maybe_closure()
54685469

54695470
assert 'asm2g' in test_modes
54705471
if self.run_name == 'asm2g':

tests/test_other.py

+2
Original file line numberDiff line numberDiff line change
@@ -1973,6 +1973,8 @@ def test_js_optimizer(self):
19731973
['JSDCE']),
19741974
(path_from_root('tests', 'optimizer', 'JSDCE-hasOwnProperty.js'), open(path_from_root('tests', 'optimizer', 'JSDCE-hasOwnProperty-output.js')).read(),
19751975
['JSDCE']),
1976+
(path_from_root('tests', 'optimizer', 'AJSDCE.js'), open(path_from_root('tests', 'optimizer', 'AJSDCE-output.js')).read(),
1977+
['AJSDCE']),
19761978
]:
19771979
print(input, passes)
19781980

0 commit comments

Comments
 (0)