diff options
Diffstat (limited to 'src/emscripten-optimizer/optimizer-shared.cpp')
-rw-r--r-- | src/emscripten-optimizer/optimizer-shared.cpp | 234 |
1 files changed, 170 insertions, 64 deletions
diff --git a/src/emscripten-optimizer/optimizer-shared.cpp b/src/emscripten-optimizer/optimizer-shared.cpp index 81f7949ba..3ac3ca7ea 100644 --- a/src/emscripten-optimizer/optimizer-shared.cpp +++ b/src/emscripten-optimizer/optimizer-shared.cpp @@ -23,14 +23,14 @@ using namespace cashew; IString ASM_FLOAT_ZERO; -IString SIMD_INT8X16_CHECK("SIMD_Int8x16_check"), - SIMD_INT16X8_CHECK("SIMD_Int16x8_check"), - SIMD_INT32X4_CHECK("SIMD_Int32x4_check"), - SIMD_FLOAT32X4_CHECK("SIMD_Float32x4_check"), - SIMD_FLOAT64X2_CHECK("SIMD_Float64x2_check"), - TEMP_RET0("tempRet0"); +IString SIMD_INT8X16_CHECK("SIMD_Int8x16_check"); +IString SIMD_INT16X8_CHECK("SIMD_Int16x8_check"); +IString SIMD_INT32X4_CHECK("SIMD_Int32x4_check"); +IString SIMD_FLOAT32X4_CHECK("SIMD_Float32x4_check"); +IString SIMD_FLOAT64X2_CHECK("SIMD_Float64x2_check"); +IString TEMP_RET0("tempRet0"); -int parseInt(const char *str) { +int parseInt(const char* str) { int ret = *str - '0'; while (*(++str)) { ret *= 10; @@ -39,7 +39,7 @@ int parseInt(const char *str) { return ret; } -HeapInfo parseHeap(const char *name) { +HeapInfo parseHeap(const char* name) { HeapInfo ret; if (name[0] != 'H' || name[1] != 'E' || name[2] != 'A' || name[3] != 'P') { ret.valid = false; @@ -53,33 +53,49 @@ HeapInfo parseHeap(const char *name) { return ret; } -AsmType detectType(Ref node, AsmData *asmData, bool inVarDef, IString minifiedFround, bool allowI64) { +AsmType detectType(Ref node, + AsmData* asmData, + bool inVarDef, + IString minifiedFround, + bool allowI64) { if (node->isString()) { if (asmData) { AsmType ret = asmData->getType(node->getCString()); - if (ret != ASM_NONE) return ret; + if (ret != ASM_NONE) + return ret; } if (!inVarDef) { - if (node == INF || node == NaN) return ASM_DOUBLE; - if (node == TEMP_RET0) return ASM_INT; + if (node == INF || node == NaN) + return ASM_DOUBLE; + if (node == TEMP_RET0) + return ASM_INT; return ASM_NONE; } - // We are in a variable definition, where Math_fround(0) optimized into a global constant becomes f0 = Math_fround(0) - if (ASM_FLOAT_ZERO.isNull()) ASM_FLOAT_ZERO = node->getIString(); - else assert(node == ASM_FLOAT_ZERO); + // We are in a variable definition, where Math_fround(0) optimized into a + // global constant becomes f0 = Math_fround(0) + if (ASM_FLOAT_ZERO.isNull()) + ASM_FLOAT_ZERO = node->getIString(); + else + assert(node == ASM_FLOAT_ZERO); return ASM_FLOAT; } if (node->isNumber()) { - if (!wasm::isInteger(node->getNumber())) return ASM_DOUBLE; + if (!wasm::isInteger(node->getNumber())) + return ASM_DOUBLE; return ASM_INT; } switch (node[0]->getCString()[0]) { case 'u': { if (node[0] == UNARY_PREFIX) { switch (node[1]->getCString()[0]) { - case '+': return ASM_DOUBLE; - case '-': return detectType(node[2], asmData, inVarDef, minifiedFround, allowI64); - case '!': case '~': return ASM_INT; + case '+': + return ASM_DOUBLE; + case '-': + return detectType( + node[2], asmData, inVarDef, minifiedFround, allowI64); + case '!': + case '~': + return ASM_INT; } break; } @@ -89,13 +105,20 @@ AsmType detectType(Ref node, AsmData *asmData, bool inVarDef, IString minifiedFr if (node[0] == CALL) { if (node[1]->isString()) { IString name = node[1]->getIString(); - if (name == MATH_FROUND || name == minifiedFround) return ASM_FLOAT; - else if (allowI64 && (name == INT64 || name == INT64_CONST)) return ASM_INT64; - else if (name == SIMD_FLOAT32X4 || name == SIMD_FLOAT32X4_CHECK) return ASM_FLOAT32X4; - else if (name == SIMD_FLOAT64X2 || name == SIMD_FLOAT64X2_CHECK) return ASM_FLOAT64X2; - else if (name == SIMD_INT8X16 || name == SIMD_INT8X16_CHECK) return ASM_INT8X16; - else if (name == SIMD_INT16X8 || name == SIMD_INT16X8_CHECK) return ASM_INT16X8; - else if (name == SIMD_INT32X4 || name == SIMD_INT32X4_CHECK) return ASM_INT32X4; + if (name == MATH_FROUND || name == minifiedFround) + return ASM_FLOAT; + else if (allowI64 && (name == INT64 || name == INT64_CONST)) + return ASM_INT64; + else if (name == SIMD_FLOAT32X4 || name == SIMD_FLOAT32X4_CHECK) + return ASM_FLOAT32X4; + else if (name == SIMD_FLOAT64X2 || name == SIMD_FLOAT64X2_CHECK) + return ASM_FLOAT64X2; + else if (name == SIMD_INT8X16 || name == SIMD_INT8X16_CHECK) + return ASM_INT8X16; + else if (name == SIMD_INT16X8 || name == SIMD_INT16X8_CHECK) + return ASM_INT16X8; + else if (name == SIMD_INT32X4 || name == SIMD_INT32X4_CHECK) + return ASM_INT32X4; } return ASM_NONE; } else if (node[0] == CONDITIONAL) { @@ -106,10 +129,20 @@ AsmType detectType(Ref node, AsmData *asmData, bool inVarDef, IString minifiedFr case 'b': { if (node[0] == BINARY) { switch (node[1]->getCString()[0]) { - case '+': case '-': - case '*': case '/': case '%': return detectType(node[2], asmData, inVarDef, minifiedFround, allowI64); - case '|': case '&': case '^': case '<': case '>': // handles <<, >>, >>=, <=, >= - case '=': case '!': { // handles ==, != + case '+': + case '-': + case '*': + case '/': + case '%': + return detectType( + node[2], asmData, inVarDef, minifiedFround, allowI64); + case '|': + case '&': + case '^': + case '<': + case '>': // handles <<, >>, >>=, <=, >= + case '=': + case '!': { // handles ==, != return ASM_INT; } } @@ -122,14 +155,15 @@ AsmType detectType(Ref node, AsmData *asmData, bool inVarDef, IString minifiedFr } else if (node[0] == SUB) { assert(node[1]->isString()); HeapInfo info = parseHeap(node[1][1]->getCString()); - if (info.valid) return ASM_NONE; + if (info.valid) + return ASM_NONE; return info.floaty ? ASM_DOUBLE : ASM_INT; // XXX ASM_FLOAT? } break; } } - //dump("horrible", node); - //assert(0); + // dump("horrible", node); + // assert(0); return ASM_NONE; } @@ -145,9 +179,12 @@ AsmSign detectSign(Ref node, IString minifiedFround) { } if (node->isNumber()) { double value = node->getNumber(); - if (value < 0) return ASM_SIGNED; - if (value > uint32_t(-1) || fmod(value, 1) != 0) return ASM_NONSIGNED; - if (wasm::isSInteger32(value)) return ASM_FLEXIBLE; + if (value < 0) + return ASM_SIGNED; + if (value > uint32_t(-1) || fmod(value, 1) != 0) + return ASM_NONSIGNED; + if (wasm::isSInteger32(value)) + return ASM_FLEXIBLE; return ASM_UNSIGNED; } IString type = node[0]->getIString(); @@ -155,25 +192,44 @@ AsmSign detectSign(Ref node, IString minifiedFround) { IString op = node[1]->getIString(); switch (op.str[0]) { case '>': { - if (op == TRSHIFT) return ASM_UNSIGNED; + if (op == TRSHIFT) + return ASM_UNSIGNED; } // fallthrough - case '|': case '&': case '^': case '<': case '=': case '!': return ASM_SIGNED; - case '+': case '-': return ASM_FLEXIBLE; - case '*': case '/': case '%': return ASM_NONSIGNED; // without a coercion, these are double - default: abort_on(node); + case '|': + case '&': + case '^': + case '<': + case '=': + case '!': + return ASM_SIGNED; + case '+': + case '-': + return ASM_FLEXIBLE; + case '*': + case '/': + case '%': + return ASM_NONSIGNED; // without a coercion, these are double + default: + abort_on(node); } } else if (type == UNARY_PREFIX) { IString op = node[1]->getIString(); switch (op.str[0]) { - case '-': return ASM_FLEXIBLE; - case '+': return ASM_NONSIGNED; // XXX double - case '~': return ASM_SIGNED; - default: abort_on(node); + case '-': + return ASM_FLEXIBLE; + case '+': + return ASM_NONSIGNED; // XXX double + case '~': + return ASM_SIGNED; + default: + abort_on(node); } } else if (type == CONDITIONAL) { return detectSign(node[2], minifiedFround); } else if (type == CALL) { - if (node[1]->isString() && (node[1] == MATH_FROUND || node[1] == minifiedFround)) return ASM_NONSIGNED; + if (node[1]->isString() && + (node[1] == MATH_FROUND || node[1] == minifiedFround)) + return ASM_NONSIGNED; } else if (type == SEQ) { return detectSign(node[2], minifiedFround); } @@ -183,8 +239,12 @@ AsmSign detectSign(Ref node, IString minifiedFround) { Ref makeAsmCoercedZero(AsmType type) { switch (type) { - case ASM_INT: return ValueBuilder::makeNum(0); break; - case ASM_DOUBLE: return ValueBuilder::makeUnary(PLUS, ValueBuilder::makeNum(0)); break; + case ASM_INT: + return ValueBuilder::makeNum(0); + break; + case ASM_DOUBLE: + return ValueBuilder::makeUnary(PLUS, ValueBuilder::makeNum(0)); + break; case ASM_FLOAT: { if (!ASM_FLOAT_ZERO.isNull()) { return ValueBuilder::makeName(ASM_FLOAT_ZERO); @@ -194,46 +254,92 @@ Ref makeAsmCoercedZero(AsmType type) { break; } case ASM_FLOAT32X4: { - return ValueBuilder::makeCall(SIMD_FLOAT32X4, ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0)); + return ValueBuilder::makeCall(SIMD_FLOAT32X4, + ValueBuilder::makeNum(0), + ValueBuilder::makeNum(0), + ValueBuilder::makeNum(0), + ValueBuilder::makeNum(0)); break; } case ASM_FLOAT64X2: { - return ValueBuilder::makeCall(SIMD_FLOAT64X2, ValueBuilder::makeNum(0), ValueBuilder::makeNum(0)); + return ValueBuilder::makeCall( + SIMD_FLOAT64X2, ValueBuilder::makeNum(0), ValueBuilder::makeNum(0)); break; } case ASM_INT8X16: { - return ValueBuilder::makeCall(SIMD_INT8X16, ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0)); + return ValueBuilder::makeCall(SIMD_INT8X16, + ValueBuilder::makeNum(0), + ValueBuilder::makeNum(0), + ValueBuilder::makeNum(0), + ValueBuilder::makeNum(0), + ValueBuilder::makeNum(0), + ValueBuilder::makeNum(0), + ValueBuilder::makeNum(0), + ValueBuilder::makeNum(0), + ValueBuilder::makeNum(0), + ValueBuilder::makeNum(0), + ValueBuilder::makeNum(0), + ValueBuilder::makeNum(0), + ValueBuilder::makeNum(0), + ValueBuilder::makeNum(0), + ValueBuilder::makeNum(0), + ValueBuilder::makeNum(0)); break; } case ASM_INT16X8: { - return ValueBuilder::makeCall(SIMD_INT16X8, ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0)); + return ValueBuilder::makeCall(SIMD_INT16X8, + ValueBuilder::makeNum(0), + ValueBuilder::makeNum(0), + ValueBuilder::makeNum(0), + ValueBuilder::makeNum(0), + ValueBuilder::makeNum(0), + ValueBuilder::makeNum(0), + ValueBuilder::makeNum(0), + ValueBuilder::makeNum(0)); break; } case ASM_INT32X4: { - return ValueBuilder::makeCall(SIMD_INT32X4, ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0)); + return ValueBuilder::makeCall(SIMD_INT32X4, + ValueBuilder::makeNum(0), + ValueBuilder::makeNum(0), + ValueBuilder::makeNum(0), + ValueBuilder::makeNum(0)); break; } - default: assert(0); + default: + assert(0); } abort(); } Ref makeAsmCoercion(Ref node, AsmType type) { switch (type) { - case ASM_INT: return ValueBuilder::makeBinary(node, OR, ValueBuilder::makeNum(0)); - case ASM_DOUBLE: return ValueBuilder::makeUnary(PLUS, node); - case ASM_FLOAT: return ValueBuilder::makeCall(MATH_FROUND, node); - case ASM_FLOAT32X4: return ValueBuilder::makeCall(SIMD_FLOAT32X4_CHECK, node); - case ASM_FLOAT64X2: return ValueBuilder::makeCall(SIMD_FLOAT64X2_CHECK, node); - case ASM_INT8X16: return ValueBuilder::makeCall(SIMD_INT8X16_CHECK, node); - case ASM_INT16X8: return ValueBuilder::makeCall(SIMD_INT16X8_CHECK, node); - case ASM_INT32X4: return ValueBuilder::makeCall(SIMD_INT32X4_CHECK, node); + case ASM_INT: + return ValueBuilder::makeBinary(node, OR, ValueBuilder::makeNum(0)); + case ASM_DOUBLE: + return ValueBuilder::makeUnary(PLUS, node); + case ASM_FLOAT: + return ValueBuilder::makeCall(MATH_FROUND, node); + case ASM_FLOAT32X4: + return ValueBuilder::makeCall(SIMD_FLOAT32X4_CHECK, node); + case ASM_FLOAT64X2: + return ValueBuilder::makeCall(SIMD_FLOAT64X2_CHECK, node); + case ASM_INT8X16: + return ValueBuilder::makeCall(SIMD_INT8X16_CHECK, node); + case ASM_INT16X8: + return ValueBuilder::makeCall(SIMD_INT16X8_CHECK, node); + case ASM_INT32X4: + return ValueBuilder::makeCall(SIMD_INT32X4_CHECK, node); case ASM_NONE: - default: return node; // non-validating code, emit nothing XXX this is dangerous, we should only allow this when we know we are not validating + default: + // non-validating code, emit nothing XXX this is dangerous, we should only + // allow this when we know we are not validating + return node; } } Ref makeSigning(Ref node, AsmSign sign) { assert(sign == ASM_SIGNED || sign == ASM_UNSIGNED); - return ValueBuilder::makeBinary(node, sign == ASM_SIGNED ? OR : TRSHIFT, ValueBuilder::makeNum(0)); + return ValueBuilder::makeBinary( + node, sign == ASM_SIGNED ? OR : TRSHIFT, ValueBuilder::makeNum(0)); } |