diff options
-rw-r--r-- | tools/bisect_pair_lines.py | 63 | ||||
-rw-r--r-- | tools/eliminator/asm-eliminator-test-output.js | 14 | ||||
-rw-r--r-- | tools/eliminator/asm-eliminator-test.js | 17 | ||||
-rw-r--r-- | tools/js-optimizer.js | 10 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-pre-output.js | 4 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-pre.js | 4 |
6 files changed, 109 insertions, 3 deletions
diff --git a/tools/bisect_pair_lines.py b/tools/bisect_pair_lines.py new file mode 100644 index 00000000..f698ef2a --- /dev/null +++ b/tools/bisect_pair_lines.py @@ -0,0 +1,63 @@ +''' +Given two similar files, for example one with an additional optimization pass, +and with different results, will bisect between them to find the smallest +diff that makes the outputs different. +Unlike bisect_pairs, this uses lines instead of diffs. We replace line by line. This assumes +the programs differ on each line but lines have not been added or removed +''' + +import os, sys, shutil +from subprocess import Popen, PIPE, STDOUT + +__rootpath__ = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) +def path_from_root(*pathelems): + return os.path.join(__rootpath__, *pathelems) +exec(open(path_from_root('tools', 'shared.py'), 'r').read()) + +file1 = open(sys.argv[1]).read() +file2 = open(sys.argv[2]).read() + +leftf = open('left', 'w') +leftf.write(file1) +leftf.close() + +rightf = open('right', 'w') +rightf.write(file2) +rightf.close() + +def run_code(name): + ret = run_js(name, stderr=PIPE, full_output=True) + # fix stack traces + ret = filter(lambda line: not line.startswith(' at ') and not name in line, ret.split('\n')) + return '\n'.join(ret) + +print 'running files' +left_result = run_code('left') +right_result = run_code('right') # right as in left-right, not as in correct +assert left_result != right_result + +low = 0 +high = file1.count('\n') + +print 'beginning bisection, %d lines' % high + +left_lines = file1.split('\n') +right_lines = file2.split('\n') + +while True: + mid = int((low + high)/2) + print low, high, ' current: %d' % mid, + open('middle', 'w').write('\n'.join(left_lines[:mid] + right_lines[mid:])) + shutil.copyfile('middle', 'middle' + str(mid)) + result = run_code('middle') + print result == left_result, result == right_result#, 'XXX', left_result, 'YYY', result, 'ZZZ', right_result + if mid == low or mid == high: break + if result == right_result: + low = mid + elif result == left_result: + high = mid + else: + raise Exception('new result!?!?') + +print 'middle%d is like left, middle%d is like right' % (mid+1, mid) + diff --git a/tools/eliminator/asm-eliminator-test-output.js b/tools/eliminator/asm-eliminator-test-output.js index d530a90c..ab4c13cc 100644 --- a/tools/eliminator/asm-eliminator-test-output.js +++ b/tools/eliminator/asm-eliminator-test-output.js @@ -954,4 +954,18 @@ function loopVarWithContinue() { } } } +function helperExtraUse() { + var i = 0, i$looptemp = 0; + i = 0; + while (1) { + i$looptemp = i; + i = i + 1; + work(i$looptemp); + work(i); + if (check()) { + break; + } + } + return i; +} diff --git a/tools/eliminator/asm-eliminator-test.js b/tools/eliminator/asm-eliminator-test.js index 8c469964..7b949c44 100644 --- a/tools/eliminator/asm-eliminator-test.js +++ b/tools/eliminator/asm-eliminator-test.js @@ -1208,5 +1208,20 @@ function loopVarWithContinue() { } } } -// EMSCRIPTEN_GENERATED_FUNCTIONS: ["asm", "__Z11printResultPiS_j", "_segment_holding", "__ZN5identC2EiPKcPci", "_vec2Length", "exc", "label", "confuusion", "tempDouble", "_org_apache_harmony_luni_util_NumberConverter_freeFormat__", "__ZN23b2EdgeAndPolygonContact8EvaluateEP10b2ManifoldRK11b2TransformS4_", "_java_nio_charset_Charset_forNameInternal___java_lang_String", "looop2", "looop3", "looop4", "looop5", "looop6", "looop7", "looop8", "multiloop", "multiloop2", "tempDouble2", "watIf", "select2", "binary", "cute", "selfAssign", "elimOneLoopVar", "elimOneLoopVar2", "elimOneLoopVar3", "elimOneLoopVar4", "elimOneLoopVarStillUsed", "elimOneLoopVarStillUsedSE", "elimOneLoopVar5"] +function helperExtraUse() { + var i = 0, inc = 0; + i = 0; + while (1) { + inc = i + 1; + work(i); + work(inc); + if (check()) { + break; + } else { + i = inc; + } + } + return inc; +} +// EMSCRIPTEN_GENERATED_FUNCTIONS: ["asm", "__Z11printResultPiS_j", "_segment_holding", "__ZN5identC2EiPKcPci", "_vec2Length", "exc", "label", "confuusion", "tempDouble", "_org_apache_harmony_luni_util_NumberConverter_freeFormat__", "__ZN23b2EdgeAndPolygonContact8EvaluateEP10b2ManifoldRK11b2TransformS4_", "_java_nio_charset_Charset_forNameInternal___java_lang_String", "looop2", "looop3", "looop4", "looop5", "looop6", "looop7", "looop8", "multiloop", "multiloop2", "tempDouble2", "watIf", "select2", "binary", "cute", "selfAssign", "elimOneLoopVar", "elimOneLoopVar2", "elimOneLoopVar3", "elimOneLoopVar4", "elimOneLoopVarStillUsed", "elimOneLoopVarStillUsedSE", "elimOneLoopVar5", "helperExtraUse"] diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index c0096df4..088c4f0f 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -750,9 +750,12 @@ function simplifyExpressions(ast) { } function emitsBoolean(node) { + if (node[0] === 'num') { + return node[1] === 0 || node[1] === 1; + } if (node[0] === 'binary') return node[1] in COMPARE_OPS; if (node[0] === 'unary-prefix') return node[1] === '!'; - if (node[0] === 'conditional') return true; + if (node[0] === 'conditional') return emitsBoolean(node[2]) && emitsBoolean(node[3]); return false; } @@ -1030,6 +1033,7 @@ function hasSideEffects(node) { // this is 99% incomplete! } return false; } + case 'conditional': return hasSideEffects(node[1]) || hasSideEffects(node[2]) || hasSideEffects(node[3]); default: return true; } } @@ -3704,9 +3708,11 @@ function eliminate(ast, memSafe) { } if (firstLooperUsage >= 0) { // the looper is used, we cannot simply merge the two variables - if ((firstHelperUsage < 0 || firstHelperUsage > lastLooperUsage) && lastLooperUsage+1 < stats.length && triviallySafeToMove(stats[found], asmData)) { + if ((firstHelperUsage < 0 || firstHelperUsage > lastLooperUsage) && lastLooperUsage+1 < stats.length && triviallySafeToMove(stats[found], asmData) && + seenUses[helper] === namings[helper]) { // the helper is not used, or it is used after the last use of the looper, so they do not overlap, // and the last looper usage is not on the last line (where we could not append after it), and the + // helper is not used outside of the loop. // just move the looper definition to after the looper's last use stats.splice(lastLooperUsage+1, 0, stats[found]); stats.splice(found, 1); diff --git a/tools/test-js-optimizer-asm-pre-output.js b/tools/test-js-optimizer-asm-pre-output.js index 31b9cfd7..5281b87c 100644 --- a/tools/test-js-optimizer-asm-pre-output.js +++ b/tools/test-js-optimizer-asm-pre-output.js @@ -596,6 +596,10 @@ function conditionalizeMe() { if (x > 10 | HEAP[20] + 2 > 5) { b(); } + print(((HEAP8[a] + HEAP8[b] + HEAP8[c] + HEAP8[d] + HEAP8[e] + HEAP8[f] | 0) > a % b % c % d ? 1 : $el) | $cheap > 0); + print(((HEAP8[a] + HEAP8[b] + HEAP8[c] + HEAP8[d] + HEAP8[e] + HEAP8[f] | 0) > a % b % c % d ? 1 : -1) | $cheap > 0); + print($cheap > 0 ? 1 : (HEAP8[a] + HEAP8[b] + HEAP8[c] + HEAP8[d] + HEAP8[e] + HEAP8[f] | 0) > a % b % c % d ? 1 : 0); + print(((HEAP8[a] + HEAP8[b] + HEAP8[c] + HEAP8[d] + HEAP8[e] + HEAP8[f] | 0) > a % b % c % d ? -1 : 1) | $cheap > 0); return (((((Math_imul(i6 + 1, i7) | 0) + 17 | 0) % 5 | 0) == 0 ? 1 : ((((Math_imul(i7 + 1, i7) | 0) + 11 | 0) >>> 0) % 3 | 0) == 0) | 0) == 0; } diff --git a/tools/test-js-optimizer-asm-pre.js b/tools/test-js-optimizer-asm-pre.js index 2a6ea4a9..d48d736e 100644 --- a/tools/test-js-optimizer-asm-pre.js +++ b/tools/test-js-optimizer-asm-pre.js @@ -608,6 +608,10 @@ function conditionalizeMe() { if (x > 10 | (HEAP[20] + 2) > 5) { b(); } + print( (((HEAP8[a] + HEAP8[b] + HEAP8[c] + HEAP8[d] + HEAP8[e] + HEAP8[f] | 0) > (a % b % c % d)) ? 1 : $el) | ($cheap > 0) ); // conditional does not always emit boolean + print( (((HEAP8[a] + HEAP8[b] + HEAP8[c] + HEAP8[d] + HEAP8[e] + HEAP8[f] | 0) > (a % b % c % d)) ? 1 : -1) | ($cheap > 0) ); + print( (((HEAP8[a] + HEAP8[b] + HEAP8[c] + HEAP8[d] + HEAP8[e] + HEAP8[f] | 0) > (a % b % c % d)) ? 1 : 0) | ($cheap > 0) ); // this one is safe! + print( (((HEAP8[a] + HEAP8[b] + HEAP8[c] + HEAP8[d] + HEAP8[e] + HEAP8[f] | 0) > (a % b % c % d)) ? -1 : 1) | ($cheap > 0) ); return ((((Math_imul(i6+1, i7) | 0) + 17 | 0) % 5 | 0 | 0) == 0 | ((((Math_imul(i7+1, i7) | 0) + 11 | 0) >>> 0) % 3 | 0 | 0) == 0 | 0) == 0; } // EMSCRIPTEN_GENERATED_FUNCTIONS: ["a", "b", "rett", "ret2t", "retf", "i32_8", "tempDoublePtr", "boxx", "_main", "badf", "badf2", "fcomp", "conditionalizeMe"] |