summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xemscripten.py20
-rw-r--r--src/fastLong.js18
-rw-r--r--src/jsifier.js7
-rw-r--r--src/library.js2
-rw-r--r--src/parseTools.js10
-rw-r--r--src/runtime.js6
-rw-r--r--tests/lua/binarytrees.lua17
-rw-r--r--tests/lua/scimark.lua50
-rwxr-xr-xtests/runner.py37
-rw-r--r--tools/js-optimizer.js118
-rw-r--r--tools/test-js-optimizer-asm-pre-output.js4
-rw-r--r--tools/test-js-optimizer-asm-pre.js4
12 files changed, 173 insertions, 120 deletions
diff --git a/emscripten.py b/emscripten.py
index c9a5eb59..56f59273 100755
--- a/emscripten.py
+++ b/emscripten.py
@@ -407,7 +407,7 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
math_envs = ['Math.min'] # TODO: move min to maths
asm_setup += '\n'.join(['var %s = %s;' % (f.replace('.', '_'), f) for f in math_envs])
- basic_funcs = ['abort', 'assert', 'asmPrintInt', 'asmPrintFloat', 'copyTempDouble', 'copyTempFloat'] + [m.replace('.', '_') for m in math_envs]
+ basic_funcs = ['abort', 'assert', 'asmPrintInt', 'asmPrintFloat'] + [m.replace('.', '_') for m in math_envs]
if settings['RESERVED_FUNCTION_POINTERS'] > 0: basic_funcs.append('jsCall')
if settings['SAFE_HEAP']: basic_funcs += ['SAFE_HEAP_LOAD', 'SAFE_HEAP_STORE', 'SAFE_HEAP_CLEAR']
if settings['CHECK_HEAP_ALIGN']: basic_funcs += ['CHECK_ALIGN_2', 'CHECK_ALIGN_4', 'CHECK_ALIGN_8']
@@ -555,6 +555,24 @@ var asm = (function(global, env, buffer) {
threwValue = value;
}
}
+ function copyTempFloat(ptr) {
+ ptr = ptr|0;
+ HEAP8[tempDoublePtr] = HEAP8[ptr];
+ HEAP8[tempDoublePtr+1|0] = HEAP8[ptr+1|0];
+ HEAP8[tempDoublePtr+2|0] = HEAP8[ptr+2|0];
+ HEAP8[tempDoublePtr+3|0] = HEAP8[ptr+3|0];
+ }
+ function copyTempDouble(ptr) {
+ ptr = ptr|0;
+ HEAP8[tempDoublePtr] = HEAP8[ptr];
+ HEAP8[tempDoublePtr+1|0] = HEAP8[ptr+1|0];
+ HEAP8[tempDoublePtr+2|0] = HEAP8[ptr+2|0];
+ HEAP8[tempDoublePtr+3|0] = HEAP8[ptr+3|0];
+ HEAP8[tempDoublePtr+4|0] = HEAP8[ptr+4|0];
+ HEAP8[tempDoublePtr+5|0] = HEAP8[ptr+5|0];
+ HEAP8[tempDoublePtr+6|0] = HEAP8[ptr+6|0];
+ HEAP8[tempDoublePtr+7|0] = HEAP8[ptr+7|0];
+ }
''' + ''.join(['''
function setTempRet%d(value) {
value = value|0;
diff --git a/src/fastLong.js b/src/fastLong.js
index d1ce5d39..4f6efd9f 100644
--- a/src/fastLong.js
+++ b/src/fastLong.js
@@ -5,12 +5,12 @@ function ___muldsi3($a, $b) {
var $1 = 0, $2 = 0, $3 = 0, $6 = 0, $8 = 0, $11 = 0, $12 = 0;
$1 = $a & 65535;
$2 = $b & 65535;
- $3 = Math.imul($2, $1);
+ $3 = Math.imul($2, $1) | 0;
$6 = $a >>> 16;
- $8 = ($3 >>> 16) + Math.imul($2, $6) | 0;
+ $8 = ($3 >>> 16) + (Math.imul($2, $6) | 0) | 0;
$11 = $b >>> 16;
- $12 = Math.imul($11, $1);
- return (tempRet0 = (($8 >>> 16) + Math.imul($11, $6) | 0) + ((($8 & 65535) + $12 | 0) >>> 16) | 0, 0 | ($8 + $12 << 16 | $3 & 65535)) | 0;
+ $12 = Math.imul($11, $1) | 0;
+ return (tempRet0 = (($8 >>> 16) + (Math.imul($11, $6) | 0) | 0) + ((($8 & 65535) + $12 | 0) >>> 16) | 0, 0 | ($8 + $12 << 16 | $3 & 65535)) | 0;
}
function ___divdi3($a$0, $a$1, $b$0, $b$1) {
$a$0 = $a$0 | 0;
@@ -47,7 +47,7 @@ function ___remdi3($a$0, $a$1, $b$0, $b$1) {
$4$0 = _i64Subtract($1$0 ^ $a$0, $1$1 ^ $a$1, $1$0, $1$1) | 0;
$4$1 = tempRet0;
$6$0 = _i64Subtract($2$0 ^ $b$0, $2$1 ^ $b$1, $2$0, $2$1) | 0;
- ___udivmoddi4($4$0, $4$1, $6$0, tempRet0, $rem);
+ ___udivmoddi4($4$0, $4$1, $6$0, tempRet0, $rem) | 0;
$10$0 = _i64Subtract(HEAP32[$rem >> 2] ^ $1$0, HEAP32[$rem + 4 >> 2] ^ $1$1, $1$0, $1$1) | 0;
$10$1 = tempRet0;
STACKTOP = __stackBase__;
@@ -63,8 +63,8 @@ function ___muldi3($a$0, $a$1, $b$0, $b$1) {
$y_sroa_0_0_extract_trunc = $b$0;
$1$0 = ___muldsi3($x_sroa_0_0_extract_trunc, $y_sroa_0_0_extract_trunc) | 0;
$1$1 = tempRet0;
- $2 = Math.imul($a$1, $y_sroa_0_0_extract_trunc);
- return (tempRet0 = (Math.imul($b$1, $x_sroa_0_0_extract_trunc) + $2 | 0) + $1$1 | $1$1 & 0, 0 | $1$0 & -1) | 0;
+ $2 = Math.imul($a$1, $y_sroa_0_0_extract_trunc) | 0;
+ return (tempRet0 = ((Math.imul($b$1, $x_sroa_0_0_extract_trunc) | 0) + $2 | 0) + $1$1 | $1$1 & 0, 0 | $1$0 & -1) | 0;
}
function ___udivdi3($a$0, $a$1, $b$0, $b$1) {
$a$0 = $a$0 | 0;
@@ -84,7 +84,7 @@ function ___uremdi3($a$0, $a$1, $b$0, $b$1) {
__stackBase__ = STACKTOP;
STACKTOP = STACKTOP + 8 | 0;
$rem = __stackBase__ | 0;
- ___udivmoddi4($a$0, $a$1, $b$0, $b$1, $rem);
+ ___udivmoddi4($a$0, $a$1, $b$0, $b$1, $rem) | 0;
STACKTOP = __stackBase__;
return (tempRet0 = HEAP32[$rem + 4 >> 2] | 0, HEAP32[$rem >> 2] | 0) | 0;
}
@@ -258,7 +258,7 @@ function ___udivmoddi4($a$0, $a$1, $b$0, $b$1, $rem) {
$149 = $carry_0203 | $q_sroa_0_1199 << 1;
$r_sroa_0_0_insert_insert42$0 = 0 | ($r_sroa_0_1201 << 1 | $q_sroa_1_1198 >>> 31);
$r_sroa_0_0_insert_insert42$1 = $r_sroa_0_1201 >>> 31 | $r_sroa_1_1200 << 1 | 0;
- _i64Subtract($137$0, $137$1, $r_sroa_0_0_insert_insert42$0, $r_sroa_0_0_insert_insert42$1);
+ _i64Subtract($137$0, $137$1, $r_sroa_0_0_insert_insert42$0, $r_sroa_0_0_insert_insert42$1) | 0;
$150$1 = tempRet0;
$151$0 = $150$1 >> 31 | (($150$1 | 0) < 0 ? -1 : 0) << 1;
$152 = $151$0 & 1;
diff --git a/src/jsifier.js b/src/jsifier.js
index 88b9d9f6..e9bc9a79 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -1185,8 +1185,13 @@ function JSify(data, functionsOnly, givenFunctions) {
if (disabled) {
ret = call_ + ';';
} else if (ASM_JS) {
+ if (item.type != 'void') call_ = asmCoercion(call_, item.type); // ensure coercion to ffi in comma operator
call_ = call_.replace('; return', ''); // we auto-add returns when aborting, but do not need them here
- ret = '(__THREW__ = 0,' + call_ + ');';
+ if (item.type == 'void') {
+ ret = '__THREW__ = 0;' + call_ + ';';
+ } else {
+ ret = '(__THREW__ = 0,' + call_ + ');';
+ }
} else {
ret = '(function() { try { __THREW__ = 0; return '
+ call_ + ' '
diff --git a/src/library.js b/src/library.js
index 33dcbd5f..01a67804 100644
--- a/src/library.js
+++ b/src/library.js
@@ -4399,7 +4399,7 @@ LibraryManager.library = {
{{{ makeSetValueAsm('dest', 0, makeGetValueAsm('src', 0, 'i8'), 'i8') }}};
}
} else {
- _memcpy(dest, src, num);
+ _memcpy(dest, src, num) | 0;
}
},
llvm_memmove_i32: 'memmove',
diff --git a/src/parseTools.js b/src/parseTools.js
index 687faaa8..0b83a12b 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -710,9 +710,9 @@ function splitI64(value, floatConversion) {
var lowInput = legalizedI64s ? value : 'VALUE';
if (floatConversion && ASM_JS) lowInput = asmFloatToInt(lowInput);
if (legalizedI64s) {
- return [lowInput + '>>>0', 'Math.min(Math.floor((' + value + ')/' + asmEnsureFloat(4294967296, 'float') + '), ' + asmEnsureFloat(4294967295, 'float') + ')>>>0'];
+ return [lowInput + '>>>0', asmCoercion('Math.min(' + asmCoercion('Math.floor((' + value + ')/' + asmEnsureFloat(4294967296, 'float') + ')', 'double') + ', ' + asmEnsureFloat(4294967295, 'float') + ')', 'i32') + '>>>0'];
} else {
- return makeInlineCalculation(makeI64(lowInput + '>>>0', 'Math.min(Math.floor(VALUE/' + asmEnsureFloat(4294967296, 'float') + '), ' + asmEnsureFloat(4294967295, 'float') + ')>>>0'), value, 'tempBigIntP');
+ return makeInlineCalculation(makeI64(lowInput + '>>>0', asmCoercion('Math.min(' + asmCoercion('Math.floor(VALUE/' + asmEnsureFloat(4294967296, 'float') + ')', 'double') + ', ' + asmEnsureFloat(4294967295, 'float') + ')', 'i32') + '>>>0'), value, 'tempBigIntP');
}
}
function mergeI64(value, unsigned) {
@@ -1049,7 +1049,7 @@ function getHeapOffset(offset, type, forceAsm) {
offset = '(' + offset + ')';
if (shifts != 0) {
if (CHECK_HEAP_ALIGN) {
- return '(CHECK_ALIGN_' + sz + '(' + offset + '|0)>>' + shifts + ')';
+ return '((CHECK_ALIGN_' + sz + '(' + offset + '|0)|0)>>' + shifts + ')';
} else {
return '(' + offset + '>>' + shifts + ')';
}
@@ -1383,7 +1383,7 @@ function makeCopyValues(dest, src, num, type, modifier, align, sep) {
if (!isNumber(num)) num = stripCorrections(num);
if (!isNumber(align)) align = stripCorrections(align);
if (!isNumber(num) || (parseInt(num)/align >= UNROLL_LOOP_MAX)) {
- return '_memcpy(' + dest + ', ' + src + ', ' + num + ')';
+ return '(_memcpy(' + dest + ', ' + src + ', ' + num + ')|0)';
}
num = parseInt(num);
if (ASM_JS) {
@@ -1465,7 +1465,7 @@ function getFastValue(a, op, b, type) {
if ((isNumber(a) && Math.abs(a) < TWO_TWENTY) || (isNumber(b) && Math.abs(b) < TWO_TWENTY) || (bits < 32 && !ASM_JS)) {
return '(((' + a + ')*(' + b + '))&' + ((Math.pow(2, bits)-1)|0) + ')'; // keep a non-eliminatable coercion directly on this
}
- return 'Math.imul(' + a + ',' + b + ')';
+ return '(Math.imul(' + a + ',' + b + ')|0)';
}
} else {
if (a == '0') {
diff --git a/src/runtime.js b/src/runtime.js
index 9bedfe68..e6d5f962 100644
--- a/src/runtime.js
+++ b/src/runtime.js
@@ -25,7 +25,7 @@ var RuntimeGenerator = {
sep = sep || ';';
var ret = RuntimeGenerator.alloc(size, 'STACK', false, sep, USE_TYPED_ARRAYS != 2 || (isNumber(size) && parseInt(size) % {{{ STACK_ALIGN }}} == 0));
if (ASSERTIONS) {
- ret += sep + 'assert(' + asmCoercion('(STACKTOP|0) < (STACK_MAX|0)', 'i32') + ')';
+ ret += sep + '(assert(' + asmCoercion('(STACKTOP|0) < (STACK_MAX|0)', 'i32') + ')|0)';
}
return ret;
},
@@ -37,11 +37,11 @@ var RuntimeGenerator = {
if (USE_TYPED_ARRAYS == 2) {
assert(initial % Runtime.STACK_ALIGN == 0);
if (ASSERTIONS && Runtime.STACK_ALIGN == 4) {
- ret += '; assert(' + asmCoercion('!(STACKTOP&3)', 'i32') + ')';
+ ret += '; (assert(' + asmCoercion('!(STACKTOP&3)', 'i32') + ')|0)';
}
}
if (ASSERTIONS) {
- ret += '; assert(' + asmCoercion('(STACKTOP|0) < (STACK_MAX|0)', 'i32') + ')';
+ ret += '; (assert(' + asmCoercion('(STACKTOP|0) < (STACK_MAX|0)', 'i32') + ')|0)';
}
if (false) {
ret += '; _memset(' + asmCoercion('__stackBase__', 'i32') + ', 0, ' + initial + ')';
diff --git a/tests/lua/binarytrees.lua b/tests/lua/binarytrees.lua
index 2ae3dd69..58c0ce87 100644
--- a/tests/lua/binarytrees.lua
+++ b/tests/lua/binarytrees.lua
@@ -21,7 +21,22 @@ local function ItemCheck(tree)
end
end
-local N = tonumber(arg and arg[1]) or 0
+local N = tonumber(arg and arg[1]) or 4
+
+if N == 0 then
+ N = 0
+elseif N == 1 then
+ N = 9.5
+elseif N == 2 then
+ N = 11.99
+elseif N == 3 then
+ N = 12.85
+elseif N == 4 then
+ N = 14.72
+elseif N == 5 then
+ N = 15.82
+end
+
local mindepth = 4
local maxdepth = mindepth + 2
if maxdepth < N then maxdepth = N end
diff --git a/tests/lua/scimark.lua b/tests/lua/scimark.lua
index 7e37c219..34fbc4ff 100644
--- a/tests/lua/scimark.lua
+++ b/tests/lua/scimark.lua
@@ -387,31 +387,31 @@ end
--printf("Lua SciMark %s based on SciMark 2.0a. %s.\n\n",
-- SCIMARK_VERSION, SCIMARK_COPYRIGHT)
-while arg and arg[1] do
- local a = table.remove(arg, 1)
- if a == "-noffi" then
- package.preload.ffi = nil
- elseif a == "-small" then
- SIZE_SELECT = "small"
- elseif a == "-large" then
- SIZE_SELECT = "large"
- elseif benchmarks[a] then
- local p = benchmarks[SIZE_SELECT][a]
- measure(MIN_TIME, a, tonumber(arg[1]) or p[1], tonumber(arg[2]) or p[2])
- return
- else
- printf("Usage: scimark [-noffi] [-small|-large] [BENCH params...]\n\n")
- printf("BENCH -small -large\n")
- printf("---------------------------------------\n")
- for _,name in ipairs(benchmarks) do
- printf("%-7s %-13s %s\n", name,
- fmtparams(unpack(benchmarks.small[name])),
- fmtparams(unpack(benchmarks.large[name])))
- end
- printf("\n")
- os.exit(1)
- end
-end
+--while arg and arg[1] do
+-- local a = table.remove(arg, 1)
+-- if a == "-noffi" then
+-- package.preload.ffi = nil
+-- elseif a == "-small" then
+-- SIZE_SELECT = "small"
+-- elseif a == "-large" then
+-- SIZE_SELECT = "large"
+-- elseif benchmarks[a] then
+-- local p = benchmarks[SIZE_SELECT][a]
+-- measure(MIN_TIME, a, tonumber(arg[1]) or p[1], tonumber(arg[2]) or p[2])
+-- return
+-- else
+-- printf("Usage: scimark [-noffi] [-small|-large] [BENCH params...]\n\n")
+-- printf("BENCH -small -large\n")
+-- printf("---------------------------------------\n")
+-- for _,name in ipairs(benchmarks) do
+-- printf("%-7s %-13s %s\n", name,
+-- fmtparams(unpack(benchmarks.small[name])),
+-- fmtparams(unpack(benchmarks.large[name])))
+-- end
+-- printf("\n")
+-- os.exit(1)
+-- end
+--end
local params = benchmarks[SIZE_SELECT]
local sum = 0
diff --git a/tests/runner.py b/tests/runner.py
index 610a39f6..bcd8e84c 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -133,7 +133,7 @@ class RunnerCore(unittest.TestCase):
# Hardcode in the arguments, so js is portable without manual commandlinearguments
if not args: return
js = open(filename).read()
- open(filename, 'w').write(js.replace('run();', 'run(%s);' % str(args)))
+ open(filename, 'w').write(js.replace('run();', 'run(%s + Module["arguments"]);' % str(args)))
def prep_ll_run(self, filename, ll_file, force_recompile=False, build_ll_hook=None):
if ll_file.endswith(('.bc', '.o')):
@@ -12698,7 +12698,7 @@ elif 'browser' in str(sys.argv):
src = filename
filename = 'main.cpp'
else:
- with open(filepath) as f: f.read()
+ with open(filepath) as f: src = f.read()
with open(temp_filepath, 'w') as f: f.write(self.with_report_result(src))
else:
expected = [str(i) for i in range(0, reference_slack+1)]
@@ -13314,17 +13314,26 @@ elif 'benchmark' in str(sys.argv):
f.close()
final_filename = os.path.join(dirname, name + '.js')
+ open('hardcode.py', 'w').write('''
+def process(filename):
+ js = open(filename).read()
+ replaced = js.replace("run();", "run(%s.concat(Module[\\"arguments\\"]));")
+ assert js != replaced
+ open(filename, 'w').write(replaced)
+import sys
+process(sys.argv[1])
+''' % str(args[:-1]) # do not hardcode in the last argument, the default arg
+)
+
try_delete(final_filename)
output = Popen([PYTHON, EMCC, filename, #'-O3',
'-O2', '-s', 'DOUBLE_MODE=0', '-s', 'PRECISE_I64_MATH=0',
- '--llvm-lto', '1', '--memory-init-file', '0',
+ '--llvm-lto', '1', '--memory-init-file', '0', '--js-transform', 'python hardcode.py',
'-s', 'TOTAL_MEMORY=128*1024*1024',
'--closure', '1',
'-o', final_filename] + shared_args + emcc_args, stdout=PIPE, stderr=self.stderr_redirect).communicate()
assert os.path.exists(final_filename), 'Failed to compile file: ' + output[0]
- self.hardcode_arguments(final_filename, args)
-
# Run JS
global total_times, tests_done
times = []
@@ -13650,7 +13659,7 @@ elif 'benchmark' in str(sys.argv):
native_args = self.get_library('lua_native', [os.path.join('src', 'lua'), os.path.join('src', 'liblua.a')], make=['make', 'generic'], configure=None, native=True)
self.do_benchmark('lua_' + benchmark, '', expected,
- force_c=True, args=[benchmark + '.lua'], emcc_args=emcc_args, native_args=native_args, native_exec=os.path.join('building', 'lua_native', 'src', 'lua'),
+ force_c=True, args=[benchmark + '.lua', DEFAULT_ARG], emcc_args=emcc_args, native_args=native_args, native_exec=os.path.join('building', 'lua_native', 'src', 'lua'),
output_parser=output_parser, args_processor=args_processor)
def test_zzz_lua_scimark(self):
@@ -13661,21 +13670,7 @@ elif 'benchmark' in str(sys.argv):
def test_zzz_lua_binarytrees(self):
# js version: ['binarytrees.lua', {0: 0, 1: 9.5, 2: 11.99, 3: 12.85, 4: 14.72, 5: 15.82}[arguments[0]]]
- def args_processor(args):
- arg = int(DEFAULT_ARG)
- if arg == 0:
- return args + ['0']
- elif arg == 1:
- return args + ['9.5']
- elif arg == 2:
- return args + ['11.99']
- elif arg == 3:
- return args + ['12.85']
- elif arg == 4:
- return args + ['14.72']
- elif arg == 5:
- return args + ['15.82']
- self.lua('binarytrees', 'long lived tree of depth', args_processor=args_processor)
+ self.lua('binarytrees', 'long lived tree of depth')
def test_zzz_zlib(self):
src = open(path_from_root('tests', 'zlib', 'benchmark.c'), 'r').read()
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js
index 7f186252..432c6208 100644
--- a/tools/js-optimizer.js
+++ b/tools/js-optimizer.js
@@ -435,63 +435,69 @@ function simplifyExpressionsPre(ast) {
} else {
SAFE_BINARY_OPS = set('+', '-', '*');
}
- var COERCION_REQUIRING_OPS = set('call', 'sub', 'unary-prefix'); // ops that in asm must be coerced
+ var COERCION_REQUIRING_OPS = set('sub', 'unary-prefix'); // ops that in asm must be coerced right away
var COERCION_REQUIRING_BINARIES = set('*', '/', '%'); // binary ops that in asm must be coerced
var ZERO = ['num', 0];
- var rerun = true;
- while (rerun) {
- rerun = false;
- traverse(ast, function process(node, type, stack) {
- if (type == 'binary' && node[1] == '|') {
- if (node[2][0] == 'num' && node[3][0] == 'num') {
- return ['num', node[2][1] | node[3][1]];
- }
- var go = false;
- if (jsonCompare(node[2], ZERO)) {
- // canonicalize order
- var temp = node[3];
- node[3] = node[2];
- node[2] = temp;
- go = true;
- } else if (jsonCompare(node[3], ZERO)) {
- go = true;
- }
- if (!go) {
- stack.push(1);
- return;
- }
- // We might be able to remove this correction
- for (var i = stack.length-1; i >= 0; i--) {
- if (stack[i] == 1) {
- if (asm && stack[stack.length-1] != 1) {
- if (node[2][0] in COERCION_REQUIRING_OPS ||
- (node[2][0] == 'binary' && node[2][1] in COERCION_REQUIRING_BINARIES)) break;
- }
- // we will replace ourselves with the non-zero side. Recursively process that node.
- var result = jsonCompare(node[2], ZERO) ? node[3] : node[2], other;
- // replace node in-place
- node.length = result.length;
- for (var j = 0; j < result.length; j++) {
- node[j] = result[j];
+
+ function removeMultipleOrZero() {
+ var rerun = true;
+ while (rerun) {
+ rerun = false;
+ traverse(ast, function process(node, type, stack) {
+ if (type == 'binary' && node[1] == '|') {
+ if (node[2][0] == 'num' && node[3][0] == 'num') {
+ return ['num', node[2][1] | node[3][1]];
+ }
+ var go = false;
+ if (jsonCompare(node[2], ZERO)) {
+ // canonicalize order
+ var temp = node[3];
+ node[3] = node[2];
+ node[2] = temp;
+ go = true;
+ } else if (jsonCompare(node[3], ZERO)) {
+ go = true;
+ }
+ if (!go) {
+ stack.push(1);
+ return;
+ }
+ // We might be able to remove this correction
+ for (var i = stack.length-1; i >= 0; i--) {
+ if (stack[i] >= 1) {
+ if (asm) {
+ if (stack[stack.length-1] < 2 && node[2][0] == 'call') break; // we can only remove multiple |0s on these
+ if (stack[stack.length-1] < 1 && (node[2][0] in COERCION_REQUIRING_OPS ||
+ (node[2][0] == 'binary' && node[2][1] in COERCION_REQUIRING_BINARIES))) break; // we can remove |0 or >>2
+ }
+ // we will replace ourselves with the non-zero side. Recursively process that node.
+ var result = jsonCompare(node[2], ZERO) ? node[3] : node[2], other;
+ // replace node in-place
+ node.length = result.length;
+ for (var j = 0; j < result.length; j++) {
+ node[j] = result[j];
+ }
+ rerun = true;
+ return process(result, result[0], stack);
+ } else if (stack[i] == -1) {
+ break; // Too bad, we can't
}
- rerun = true;
- return process(result, result[0], stack);
- } else if (stack[i] == -1) {
- break; // Too bad, we can't
}
+ stack.push(2); // From here on up, no need for this kind of correction, it's done at the top
+ // (Add this at the end, so it is only added if we did not remove it)
+ } else if (type == 'binary' && node[1] in USEFUL_BINARY_OPS) {
+ stack.push(1);
+ } else if ((type == 'binary' && node[1] in SAFE_BINARY_OPS) || type == 'num' || type == 'name') {
+ stack.push(0); // This node is safe in that it does not interfere with this optimization
+ } else {
+ stack.push(-1); // This node is dangerous! Give up if you see this before you see '1'
}
- stack.push(1); // From here on up, no need for this kind of correction, it's done at the top
- // (Add this at the end, so it is only added if we did not remove it)
- } else if (type == 'binary' && node[1] in USEFUL_BINARY_OPS) {
- stack.push(1);
- } else if ((type == 'binary' && node[1] in SAFE_BINARY_OPS) || type == 'num' || type == 'name') {
- stack.push(0); // This node is safe in that it does not interfere with this optimization
- } else {
- stack.push(-1); // This node is dangerous! Give up if you see this before you see '1'
- }
- }, null, []);
+ }, null, []);
+ }
}
+ removeMultipleOrZero();
+
// & and heap-related optimizations
var heapBits, heapUnsigned;
@@ -502,7 +508,7 @@ function simplifyExpressionsPre(ast) {
return true;
}
- var hasTempDoublePtr = false;
+ var hasTempDoublePtr = false, rerunOrZeroPass = false;
traverse(ast, function(node, type) {
if (type == 'name') {
@@ -537,7 +543,6 @@ function simplifyExpressionsPre(ast) {
node[2][0] == 'binary' && node[2][1] == '<<' && node[2][3][0] == 'num' &&
node[2][2][0] == 'sub' && node[2][2][1][0] == 'name') {
// collapse HEAPU?8[..] << 24 >> 24 etc. into HEAP8[..] | 0
- // TODO: run this before | 0 | 0 removal, because we generate | 0
var amount = node[3][1];
var name = node[2][2][1][1];
if (amount == node[2][3][1] && parseHeap(name)) {
@@ -546,6 +551,7 @@ function simplifyExpressionsPre(ast) {
node[1] = '|';
node[2] = node[2][2];
node[3][1] = 0;
+ rerunOrZeroPass = true;
return node;
}
}
@@ -578,6 +584,8 @@ function simplifyExpressionsPre(ast) {
}
});
+ if (rerunOrZeroPass) removeMultipleOrZero();
+
if (asm) {
if (hasTempDoublePtr) {
traverse(ast, function(node, type) {
@@ -1108,11 +1116,15 @@ function simplifyNotCompsDirect(node) {
return node[2][2];
}
}
- return node;
+ if (!simplifyNotCompsPass) return node;
}
+var simplifyNotCompsPass = false;
+
function simplifyNotComps(ast) {
+ simplifyNotCompsPass = true;
traverse(ast, simplifyNotCompsDirect);
+ simplifyNotCompsPass = false;
}
function simplifyExpressionsPost(ast) {
diff --git a/tools/test-js-optimizer-asm-pre-output.js b/tools/test-js-optimizer-asm-pre-output.js
index 903de1f9..0e95580f 100644
--- a/tools/test-js-optimizer-asm-pre-output.js
+++ b/tools/test-js-optimizer-asm-pre-output.js
@@ -15,6 +15,10 @@ function a() {
+f();
f(+(+h() + 5));
$140 = $p_3_i + (-$mantSize_0_i | 0) | 0;
+ f(g() | 0);
+ f(g() | 0 & -1);
+ f((g() | 0) >> 2);
+ $56 = _fcntl() | 0 | 1;
}
function b($this, $__n) {
$this = $this | 0;
diff --git a/tools/test-js-optimizer-asm-pre.js b/tools/test-js-optimizer-asm-pre.js
index aac70b60..4f3ba780 100644
--- a/tools/test-js-optimizer-asm-pre.js
+++ b/tools/test-js-optimizer-asm-pre.js
@@ -16,6 +16,10 @@ function a() {
+f();
f(+(+h() + 5));
$140 = $p_3_i + (-$mantSize_0_i | 0) | 0;
+ f(g() | 0 | 0);
+ f(g() | 0 & -1);
+ f((g() | 0) >> 2);
+ $56 = (_fcntl() | 0) | 1;
}
function b($this, $__n) {
$this = $this | 0;