Update binaryen.js and enable tee optimizations

This commit is contained in:
dcodeIO
2017-12-29 04:38:39 +01:00
parent 4207f6460d
commit c67f87a988
15 changed files with 246 additions and 329 deletions

View File

@ -1028,7 +1028,7 @@ export class StringLiteralExpression extends LiteralExpression {
value: string;
serialize(sb: string[]): void {
sb.push(escapeString(this.value));
sb.push(stringToLiteral(this.value));
}
}
@ -2181,19 +2181,93 @@ function builderEndsWith(sb: string[], code: CharCode): bool {
return false;
}
/** Escapes a string to a string literal. */
export function escapeString(str: string): string {
var k = str.length;
var ret = new Array<string>(k);
for (var i = 0, c: string; i < k; ++i) {
switch (c = str.charAt(i)) {
case "\\": ret[i] = "\\\\"; break;
case "\"": ret[i] = "\\\""; break;
case "\r": ret[i] = "\\r"; break;
case "\n": ret[i] = "\\n"; break;
case "\0": ret[i] = "\\0"; break;
default: ret[i] = c;
/** Converts a string to its literal representation including quotes. */
export function stringToLiteral(str: string): string {
var ret = new Array<string>();
var off = 0;
for (var i = 0, k = str.length; i < k;) {
switch (str.charCodeAt(i)) {
case CharCode.NULL:
if (i > off)
ret.push(str.substring(off, off = i + 1));
ret.push("\\0");
off = ++i;
break;
case CharCode.BACKSPACE:
if (i > off)
ret.push(str.substring(off, i));
off = ++i;
ret.push("\\b");
break;
case CharCode.TAB:
if (i > off)
ret.push(str.substring(off, i));
off = ++i;
ret.push("\\t");
break;
case CharCode.LINEFEED:
if (i > off)
ret.push(str.substring(off, i));
off = ++i;
ret.push("\\n");
break;
case CharCode.VERTICALTAB:
if (i > off)
ret.push(str.substring(off, i));
off = ++i;
ret.push("\\v");
break;
case CharCode.FORMFEED:
if (i > off)
ret.push(str.substring(off, i));
off = ++i;
ret.push("\\f");
break;
case CharCode.CARRIAGERETURN:
if (i > off)
ret.push(str.substring(off, i));
ret.push("\\r");
off = ++i;
break;
case CharCode.DOUBLEQUOTE:
if (i > off)
ret.push(str.substring(off, i));
ret.push("\\\"");
off = ++i;
break;
case CharCode.SINGLEQUOTE:
if (i > off)
ret.push(str.substring(off, i));
ret.push("\\'");
off = ++i;
break;
case CharCode.BACKSLASH:
if (i > off)
ret.push(str.substring(off, i));
ret.push("\\\\");
off = ++i;
break;
default:
++i;
break;
}
}
if (off == 0) {
assert(ret.length == 0);
return "\"" + str + "\"";
}
if (i > off)
ret.push(str.substring(off, i));
return "\"" + ret.join("") + "\"";
}

View File

@ -1573,19 +1573,19 @@ export class Compiler extends DiagnosticEmitter {
left = this.compileExpression(expression.left, contextualType, ConversionKind.NONE);
right = this.compileExpression(expression.right, this.currentType);
// simplify if left is free of side effects while tolerating two levels of nesting, e.g., i32.load(i32.load(i32.const))
// if (condition = this.module.cloneExpression(left, true, 2))
// return this.module.createIf(
// this.currentType.isLongInteger
// ? this.module.createBinary(BinaryOp.NeI64, condition, this.module.createI64(0, 0))
// : this.currentType == Type.f64
// ? this.module.createBinary(BinaryOp.NeF64, condition, this.module.createF64(0))
// : this.currentType == Type.f32
// ? this.module.createBinary(BinaryOp.NeF32, condition, this.module.createF32(0))
// : condition, // usual case: saves one EQZ when not using EQZ above
// right,
// left
// );
// simplify if left is free of side effects while tolerating one level of nesting, e.g., i32.load(i32.const)
if (condition = this.module.cloneExpression(left, true, 1))
return this.module.createIf(
this.currentType.isLongInteger
? this.module.createBinary(BinaryOp.NeI64, condition, this.module.createI64(0, 0))
: this.currentType == Type.f64
? this.module.createBinary(BinaryOp.NeF64, condition, this.module.createF64(0))
: this.currentType == Type.f32
? this.module.createBinary(BinaryOp.NeF32, condition, this.module.createF32(0))
: condition, // usual case: saves one EQZ when not using EQZ above
right,
left
);
// otherwise use a temporary local for the intermediate value
tempLocal = this.currentFunction.getAndFreeTempLocal(this.currentType);
@ -1606,19 +1606,19 @@ export class Compiler extends DiagnosticEmitter {
left = this.compileExpression(expression.left, contextualType, ConversionKind.NONE);
right = this.compileExpression(expression.right, this.currentType);
// simplify if left is free of side effects while tolerating two levels of nesting
// if (condition = this.module.cloneExpression(left, true, 2))
// return this.module.createIf(
// this.currentType.isLongInteger
// ? this.module.createBinary(BinaryOp.NeI64, condition, this.module.createI64(0, 0))
// : this.currentType == Type.f64
// ? this.module.createBinary(BinaryOp.NeF64, condition, this.module.createF64(0))
// : this.currentType == Type.f32
// ? this.module.createBinary(BinaryOp.NeF32, condition, this.module.createF32(0))
// : condition, // usual case: saves one EQZ when not using EQZ above
// left,
// right
// );
// simplify if left is free of side effects while tolerating one level of nesting
if (condition = this.module.cloneExpression(left, true, 1))
return this.module.createIf(
this.currentType.isLongInteger
? this.module.createBinary(BinaryOp.NeI64, condition, this.module.createI64(0, 0))
: this.currentType == Type.f64
? this.module.createBinary(BinaryOp.NeF64, condition, this.module.createF64(0))
: this.currentType == Type.f32
? this.module.createBinary(BinaryOp.NeF32, condition, this.module.createF32(0))
: condition, // usual case: saves one EQZ when not using EQZ above
left,
right
);
// otherwise use a temporary local for the intermediate value
tempLocal = this.currentFunction.getAndFreeTempLocal(this.currentType);

View File

@ -15,33 +15,15 @@ export type ImportRef = usize;
export type ExportRef = usize;
export type Index = u32;
// snip...
declare function _BinaryenNone(): NativeType;
declare function _BinaryenInt32(): NativeType;
declare function _BinaryenInt64(): NativeType;
declare function _BinaryenFloat32(): NativeType;
declare function _BinaryenFloat64(): NativeType;
declare function _BinaryenUndefined(): NativeType;
export enum NativeType {
None = _BinaryenNone(),
I32 = _BinaryenInt32(),
I64 = _BinaryenInt64(),
F32 = _BinaryenFloat32(),
F64 = _BinaryenFloat64(),
Unreachable = 5,
Auto = _BinaryenUndefined()
export enum NativeType {
None = _BinaryenTypeNone(),
I32 = _BinaryenTypeInt32(),
I64 = _BinaryenTypeInt64(),
F32 = _BinaryenTypeFloat32(),
F64 = _BinaryenTypeFloat64(),
Unreachable = _BinaryenTypeUnreachable(),
Auto = _BinaryenTypeAuto()
}
// ...snap, once binaryen is updated
// export enum NativeType {
// None = _BinaryenTypeNone(),
// I32 = _BinaryenTypeInt32(),
// I64 = _BinaryenTypeInt64(),
// F32 = _BinaryenTypeFloat32(),
// F64 = _BinaryenTypeFloat64(),
// Unreachable = _BinaryenTypeUnreachable(),
// Auto = _BinaryenTypeAuto()
// }
export enum ExpressionId {
Invalid = _BinaryenInvalidId(),
@ -828,28 +810,35 @@ export class Module {
case NativeType.I64: return this.createI64(_BinaryenConstGetValueI64Low(expr), _BinaryenConstGetValueI64High(expr));
case NativeType.F32: return this.createF32(_BinaryenConstGetValueF32(expr));
case NativeType.F64: return this.createF64(_BinaryenConstGetValueF64(expr));
default: throw new Error("unexpected constant type");
default: throw new Error("concrete type expected");
}
case ExpressionId.GetLocal:
return _BinaryenGetLocal(this.ref, _BinaryenGetLocalGetIndex(expr), _BinaryenExpressionGetType(expr));
// case ExpressionId.GetGlobal: explodes if it doesn't have a name
// return _BinaryenGetGlobal(this.ref, _BinaryenGetGlobalGetName(expr), _BinaryenExpressionGetType(expr));
case ExpressionId.GetGlobal:
var globalName = _BinaryenGetGlobalGetName(expr);
if (!globalName)
break;
return _BinaryenGetGlobal(this.ref, globalName, _BinaryenExpressionGetType(expr));
case ExpressionId.Load:
if (!(nested1 = this.cloneExpression(_BinaryenLoadGetPtr(expr), noSideEffects, maxDepth - 1))) break;
if (!(nested1 = this.cloneExpression(_BinaryenLoadGetPtr(expr), noSideEffects, maxDepth - 1)))
break;
return _BinaryenLoadIsAtomic(expr)
? _BinaryenAtomicLoad(this.ref, _BinaryenLoadGetBytes(expr), _BinaryenLoadGetOffset(expr), _BinaryenExpressionGetType(expr), nested1)
: _BinaryenLoad(this.ref, _BinaryenLoadGetBytes(expr), _BinaryenLoadIsSigned(expr) ? 1 : 0, _BinaryenLoadGetOffset(expr), _BinaryenLoadGetAlign(expr), _BinaryenExpressionGetType(expr), nested1);
case ExpressionId.Unary:
if (!(nested1 = this.cloneExpression(_BinaryenUnaryGetValue(expr), noSideEffects, maxDepth - 1))) break;
if (!(nested1 = this.cloneExpression(_BinaryenUnaryGetValue(expr), noSideEffects, maxDepth - 1)))
break;
return _BinaryenUnary(this.ref, _BinaryenUnaryGetOp(expr), nested1);
case ExpressionId.Binary:
if (!(nested1 = this.cloneExpression(_BinaryenBinaryGetLeft(expr), noSideEffects, maxDepth - 1))) break;
if (!(nested2 = this.cloneExpression(_BinaryenBinaryGetRight(expr), noSideEffects, maxDepth - 1))) break;
if (!(nested1 = this.cloneExpression(_BinaryenBinaryGetLeft(expr), noSideEffects, maxDepth - 1)))
break;
if (!(nested2 = this.cloneExpression(_BinaryenBinaryGetRight(expr), noSideEffects, maxDepth - 1)))
break;
return _BinaryenBinary(this.ref, _BinaryenBinaryGetOp(expr), nested1, nested2);
}
return 0;