diff options
author | Max Graey <maxgraey@gmail.com> | 2021-09-01 18:56:12 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-01 08:56:12 -0700 |
commit | b50064bde4f584813398b7696ce7a4a3bf1cbbaa (patch) | |
tree | ff307f7239dedc752c73ab2d61a6e6729bff1ab3 /src/emscripten-optimizer | |
parent | d66d2d9bb0ea1e067c6b3e2d322a1d2357336893 (diff) | |
download | binaryen-b50064bde4f584813398b7696ce7a4a3bf1cbbaa.tar.gz binaryen-b50064bde4f584813398b7696ce7a4a3bf1cbbaa.tar.bz2 binaryen-b50064bde4f584813398b7696ce7a4a3bf1cbbaa.zip |
[Refactoring] Cleanup asm2wasm. Use JS instead ASM prefix where possible. NFC (#4090)
Diffstat (limited to 'src/emscripten-optimizer')
-rw-r--r-- | src/emscripten-optimizer/optimizer-shared.cpp | 271 | ||||
-rw-r--r-- | src/emscripten-optimizer/optimizer.h | 146 |
2 files changed, 54 insertions, 363 deletions
diff --git a/src/emscripten-optimizer/optimizer-shared.cpp b/src/emscripten-optimizer/optimizer-shared.cpp index 720ac858e..8208f6f47 100644 --- a/src/emscripten-optimizer/optimizer-shared.cpp +++ b/src/emscripten-optimizer/optimizer-shared.cpp @@ -21,252 +21,31 @@ using namespace cashew; -IString ASM_FLOAT_ZERO; +IString JS_FLOAT_ZERO; 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 ret = *str - '0'; - while (*(++str)) { - ret *= 10; - ret += *str - '0'; - } - return ret; -} - -HeapInfo parseHeap(const char* name) { - HeapInfo ret; - if (name[0] != 'H' || name[1] != 'E' || name[2] != 'A' || name[3] != 'P') { - ret.valid = false; - return ret; - } - ret.valid = true; - ret.unsign = name[4] == 'U'; - ret.floaty = name[4] == 'F'; - ret.bits = parseInt(name + (ret.unsign || ret.floaty ? 5 : 4)); - ret.type = !ret.floaty ? ASM_INT : (ret.bits == 64 ? ASM_DOUBLE : ASM_FLOAT); - return ret; -} - -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 (!inVarDef) { - 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); - } - return ASM_FLOAT; - } - if (node->isNumber()) { - 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; - } - break; - } - break; - } - case 'c': { - 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; - } - } - return ASM_NONE; - } else if (node[0] == CONDITIONAL) { - return detectType(node[2], asmData, inVarDef, minifiedFround, allowI64); - } - break; - } - 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 ==, != - return ASM_INT; - } - } - } - break; - } - case 's': { - if (node[0] == SEQ) { - return detectType(node[2], asmData, inVarDef, minifiedFround, allowI64); - } else if (node[0] == SUB) { - assert(node[1]->isString()); - HeapInfo info = parseHeap(node[1][1]->getCString()); - if (info.valid) { - return ASM_NONE; - } - return info.floaty ? ASM_DOUBLE : ASM_INT; // XXX ASM_FLOAT? - } - break; - } - } - // dump("horrible", node); - // assert(0); - return ASM_NONE; -} - -static void abort_on(Ref node) { - node->stringify(std::cerr); - std::cerr << '\n'; - abort(); -} - -AsmSign detectSign(Ref node, IString minifiedFround) { - if (node->isString()) { - return ASM_FLEXIBLE; - } - if (node->isNumber()) { - double value = node->getNumber(); - if (value < 0) { - return ASM_SIGNED; - } - if (value > uint32_t(-1) || !wasm::isInteger(value)) { - return ASM_NONSIGNED; - } - if (wasm::isSInteger32(value)) { - return ASM_FLEXIBLE; - } - return ASM_UNSIGNED; - } - IString type = node[0]->getIString(); - if (type == BINARY) { - IString op = node[1]->getIString(); - switch (op.str[0]) { - case '>': { - 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); - } - } 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); - } - } 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; - } - } else if (type == SEQ) { - return detectSign(node[2], minifiedFround); - } - abort_on(node); - abort(); // avoid warning -} - -Ref makeAsmCoercedZero(AsmType type) { +Ref makeJsCoercedZero(JsType type) { switch (type) { - case ASM_INT: + case JS_INT: return ValueBuilder::makeNum(0); break; - case ASM_DOUBLE: + case JS_DOUBLE: return ValueBuilder::makeUnary(PLUS, ValueBuilder::makeNum(0)); break; - case ASM_FLOAT: { - if (!ASM_FLOAT_ZERO.isNull()) { - return ValueBuilder::makeName(ASM_FLOAT_ZERO); + case JS_FLOAT: { + if (!JS_FLOAT_ZERO.isNull()) { + return ValueBuilder::makeName(JS_FLOAT_ZERO); } else { return ValueBuilder::makeCall(MATH_FROUND, ValueBuilder::makeNum(0)); } break; } - case ASM_FLOAT32X4: { + case JS_FLOAT32X4: { return ValueBuilder::makeCall(SIMD_FLOAT32X4, ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), @@ -274,12 +53,12 @@ Ref makeAsmCoercedZero(AsmType type) { ValueBuilder::makeNum(0)); break; } - case ASM_FLOAT64X2: { + case JS_FLOAT64X2: { return ValueBuilder::makeCall( SIMD_FLOAT64X2, ValueBuilder::makeNum(0), ValueBuilder::makeNum(0)); break; } - case ASM_INT8X16: { + case JS_INT8X16: { return ValueBuilder::makeCall(SIMD_INT8X16, ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), @@ -299,7 +78,7 @@ Ref makeAsmCoercedZero(AsmType type) { ValueBuilder::makeNum(0)); break; } - case ASM_INT16X8: { + case JS_INT16X8: { return ValueBuilder::makeCall(SIMD_INT16X8, ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), @@ -311,7 +90,7 @@ Ref makeAsmCoercedZero(AsmType type) { ValueBuilder::makeNum(0)); break; } - case ASM_INT32X4: { + case JS_INT32X4: { return ValueBuilder::makeCall(SIMD_INT32X4, ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), @@ -325,25 +104,25 @@ Ref makeAsmCoercedZero(AsmType type) { abort(); } -Ref makeAsmCoercion(Ref node, AsmType type) { +Ref makeJsCoercion(Ref node, JsType type) { switch (type) { - case ASM_INT: + case JS_INT: return ValueBuilder::makeBinary(node, OR, ValueBuilder::makeNum(0)); - case ASM_DOUBLE: + case JS_DOUBLE: return ValueBuilder::makeUnary(PLUS, node); - case ASM_FLOAT: + case JS_FLOAT: return ValueBuilder::makeCall(MATH_FROUND, node); - case ASM_FLOAT32X4: + case JS_FLOAT32X4: return ValueBuilder::makeCall(SIMD_FLOAT32X4_CHECK, node); - case ASM_FLOAT64X2: + case JS_FLOAT64X2: return ValueBuilder::makeCall(SIMD_FLOAT64X2_CHECK, node); - case ASM_INT8X16: + case JS_INT8X16: return ValueBuilder::makeCall(SIMD_INT8X16_CHECK, node); - case ASM_INT16X8: + case JS_INT16X8: return ValueBuilder::makeCall(SIMD_INT16X8_CHECK, node); - case ASM_INT32X4: + case JS_INT32X4: return ValueBuilder::makeCall(SIMD_INT32X4_CHECK, node); - case ASM_NONE: + case JS_NONE: default: // non-validating code, emit nothing XXX this is dangerous, we should only // allow this when we know we are not validating @@ -351,8 +130,8 @@ Ref makeAsmCoercion(Ref node, AsmType type) { } } -Ref makeSigning(Ref node, AsmSign sign) { - assert(sign == ASM_SIGNED || sign == ASM_UNSIGNED); +Ref makeSigning(Ref node, JsSign sign) { + assert(sign == JS_SIGNED || sign == JS_UNSIGNED); return ValueBuilder::makeBinary( - node, sign == ASM_SIGNED ? OR : TRSHIFT, ValueBuilder::makeNum(0)); + node, sign == JS_SIGNED ? OR : TRSHIFT, ValueBuilder::makeNum(0)); } diff --git a/src/emscripten-optimizer/optimizer.h b/src/emscripten-optimizer/optimizer.h index e30347025..132ff6fb8 100644 --- a/src/emscripten-optimizer/optimizer.h +++ b/src/emscripten-optimizer/optimizer.h @@ -19,127 +19,39 @@ #include "simple_ast.h" -extern bool preciseF32, receiveJSON, emitJSON, minifyWhitespace, last; - -extern cashew::Ref extraInfo; - -// - -enum AsmType { - ASM_INT = 0, - ASM_DOUBLE, - ASM_FLOAT, - ASM_FLOAT32X4, - ASM_FLOAT64X2, - ASM_INT8X16, - ASM_INT16X8, - ASM_INT32X4, - ASM_INT64, // non-asm.js - ASM_NONE // number of types +using namespace cashew; + +extern IString JS_FLOAT_ZERO; + +extern IString SIMD_INT8X16_CHECK; +extern IString SIMD_INT16X8_CHECK; +extern IString SIMD_INT32X4_CHECK; +extern IString SIMD_FLOAT32X4_CHECK; +extern IString SIMD_FLOAT64X2_CHECK; + +enum JsType { + JS_INT = 0, + JS_DOUBLE, + JS_FLOAT, + JS_FLOAT32X4, + JS_FLOAT64X2, + JS_INT8X16, + JS_INT16X8, + JS_INT32X4, + JS_INT64, + JS_NONE // number of types }; -struct AsmData; - -AsmType detectType(cashew::Ref node, - AsmData* asmData = nullptr, - bool inVarDef = false, - cashew::IString minifiedFround = cashew::IString(), - bool allowI64 = false); - -struct AsmData { - struct Local { - Local() = default; - Local(AsmType type, bool param) : type(type), param(param) {} - AsmType type; - bool param; // false if a var - }; - typedef std::unordered_map<cashew::IString, Local> Locals; - - Locals locals; - std::vector<cashew::IString> params; // in order - std::vector<cashew::IString> vars; // in order - AsmType ret; - - cashew::Ref func; - - AsmType getType(const cashew::IString& name) { - auto ret = locals.find(name); - if (ret != locals.end()) { - return ret->second.type; - } - return ASM_NONE; - } - void setType(const cashew::IString& name, AsmType type) { - locals[name].type = type; - } - - bool isLocal(const cashew::IString& name) { return locals.count(name) > 0; } - bool isParam(const cashew::IString& name) { - return isLocal(name) && locals[name].param; - } - bool isVar(const cashew::IString& name) { - return isLocal(name) && !locals[name].param; - } - - // if you want to fill in the data yourself - AsmData() = default; - // if you want to read data from f, and modify it as you go (parallel to - // denormalize) - AsmData(cashew::Ref f); - - void denormalize(); - - void addParam(cashew::IString name, AsmType type) { - locals[name] = Local(type, true); - params.push_back(name); - } - void addVar(cashew::IString name, AsmType type) { - locals[name] = Local(type, false); - vars.push_back(name); - } - - void deleteVar(cashew::IString name) { - locals.erase(name); - for (size_t i = 0; i < vars.size(); i++) { - if (vars[i] == name) { - vars.erase(vars.begin() + i); - break; - } - } - } -}; - -extern cashew::IString ASM_FLOAT_ZERO; - -extern cashew::IString SIMD_INT8X16_CHECK; -extern cashew::IString SIMD_INT16X8_CHECK; -extern cashew::IString SIMD_INT32X4_CHECK; -extern cashew::IString SIMD_FLOAT32X4_CHECK; -extern cashew::IString SIMD_FLOAT64X2_CHECK; - -int parseInt(const char* str); - -struct HeapInfo { - bool valid, unsign, floaty; - int bits; - AsmType type; -}; - -HeapInfo parseHeap(const char* name); - -enum AsmSign { +enum JsSign { // small constants can be signed or unsigned, variables are also flexible - ASM_FLEXIBLE = 0, - ASM_SIGNED = 1, - ASM_UNSIGNED = 2, - ASM_NONSIGNED = 3, + JS_FLEXIBLE = 0, + JS_SIGNED, + JS_UNSIGNED, + JS_NONSIGNED, }; -extern AsmSign detectSign(cashew::Ref node, cashew::IString minifiedFround); - -cashew::Ref makeAsmCoercedZero(AsmType type); -cashew::Ref makeAsmCoercion(cashew::Ref node, AsmType type); - -cashew::Ref makeSigning(cashew::Ref node, AsmSign sign); +Ref makeJsCoercedZero(JsType type); +Ref makeJsCoercion(Ref node, JsType type); +Ref makeSigning(Ref node, JsSign sign); #endif // wasm_optimizer_h |