summaryrefslogtreecommitdiff
path: root/src/emscripten-optimizer
diff options
context:
space:
mode:
authorMax Graey <maxgraey@gmail.com>2021-09-01 18:56:12 +0300
committerGitHub <noreply@github.com>2021-09-01 08:56:12 -0700
commitb50064bde4f584813398b7696ce7a4a3bf1cbbaa (patch)
treeff307f7239dedc752c73ab2d61a6e6729bff1ab3 /src/emscripten-optimizer
parentd66d2d9bb0ea1e067c6b3e2d322a1d2357336893 (diff)
downloadbinaryen-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.cpp271
-rw-r--r--src/emscripten-optimizer/optimizer.h146
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