aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tools/bisect_pair_lines.py63
-rw-r--r--tools/eliminator/asm-eliminator-test-output.js14
-rw-r--r--tools/eliminator/asm-eliminator-test.js17
-rw-r--r--tools/js-optimizer.js10
-rw-r--r--tools/test-js-optimizer-asm-pre-output.js4
-rw-r--r--tools/test-js-optimizer-asm-pre.js4
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"]