diff options
-rw-r--r-- | src/asm2wasm.h | 137 | ||||
-rw-r--r-- | src/emscripten-optimizer/parser.cpp | 3 | ||||
-rw-r--r-- | src/emscripten-optimizer/parser.h | 3 | ||||
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 22 | ||||
-rw-r--r-- | src/passes/Print.cpp | 56 | ||||
-rw-r--r-- | src/wasm-builder.h | 116 | ||||
-rw-r--r-- | src/wasm.h | 10 | ||||
-rw-r--r-- | test/emcc_O2_hello_world.fromasm | 42 | ||||
-rw-r--r-- | test/emcc_O2_hello_world.fromasm.imprecise | 42 | ||||
-rw-r--r-- | test/emcc_hello_world.asm.js | 14 | ||||
-rw-r--r-- | test/emcc_hello_world.fromasm | 1354 | ||||
-rw-r--r-- | test/emcc_hello_world.fromasm.imprecise | 1354 | ||||
-rw-r--r-- | test/memorygrowth.fromasm | 42 | ||||
-rw-r--r-- | test/memorygrowth.fromasm.imprecise | 42 | ||||
-rw-r--r-- | test/min.asm.js | 4 | ||||
-rw-r--r-- | test/min.fromasm | 7 | ||||
-rw-r--r-- | test/min.fromasm.imprecise | 7 | ||||
-rw-r--r-- | test/passes/optimize-instructions.txt | 32 | ||||
-rw-r--r-- | test/passes/optimize-instructions.wast | 8 | ||||
-rw-r--r-- | test/unit.fromasm | 6 | ||||
-rw-r--r-- | test/unit.fromasm.imprecise | 6 |
21 files changed, 544 insertions, 2763 deletions
diff --git a/src/asm2wasm.h b/src/asm2wasm.h index 910134024..72a8b9048 100644 --- a/src/asm2wasm.h +++ b/src/asm2wasm.h @@ -29,6 +29,7 @@ #include "asm_v_wasm.h" #include "pass.h" #include "ast_utils.h" +#include "wasm-builder.h" namespace wasm { @@ -132,6 +133,8 @@ class Asm2WasmBuilder { MixedArena &allocator; + Builder builder; + // globals unsigned nextGlobal; // next place to put a global @@ -202,8 +205,14 @@ private: IString Math_ceil; IString Math_sqrt; + IString llvm_cttz_i32; + IString tempDoublePtr; // imported name of tempDoublePtr + // possibly-minified names, detected via their exports + IString udivmoddi4; + IString getTempRet0; + // function types. we fill in this information as we see // uses, in the first pass @@ -260,6 +269,7 @@ public: Asm2WasmBuilder(AllocatingModule& wasm, bool memoryGrowth, bool debug, bool imprecise) : wasm(wasm), allocator(wasm.allocator), + builder(wasm), nextGlobal(8), maxGlobal(1000), memoryGrowth(memoryGrowth), @@ -486,10 +496,15 @@ void Asm2WasmBuilder::processAsm(Ref ast) { assert(module[0] == NAME); moduleName = module[1]->getIString(); if (moduleName == ENV) { - if (imported[2] == TEMP_DOUBLE_PTR) { + auto base = imported[2]->getIString(); + if (base == TEMP_DOUBLE_PTR) { assert(tempDoublePtr.isNull()); tempDoublePtr = name; // we don't return here, as we can only optimize out some uses of tDP. So it remains imported + } else if (base == LLVM_CTTZ_I32) { + assert(llvm_cttz_i32.isNull()); + llvm_cttz_i32 = name; + return; } } } @@ -657,6 +672,10 @@ void Asm2WasmBuilder::processAsm(Ref ast) { // asm.js memory growth provides this special non-asm function, which we don't need (we use grow_memory) assert(!wasm.checkFunction(value)); continue; + } else if (key == UDIVMODDI4) { + udivmoddi4 = value; + } else if (key == GET_TEMP_RET0) { + getTempRet0 = value; } assert(wasm.checkFunction(value)); auto export_ = allocator.alloc<Export>(); @@ -739,10 +758,107 @@ void Asm2WasmBuilder::processAsm(Ref ast) { } wasm.memory.exportName = MEMORY; + + if (udivmoddi4.is() && getTempRet0.is()) { + // generate a wasm-optimized __udivmoddi4 method, which we can do much more efficiently in wasm + // we can only do this if we know getTempRet0 as well since we use it to figure out which minified global is tempRet0 + // (getTempRet0 might be an import, if this is a shared module, so we can't optimize that case) + int tempRet0; + { + Expression* curr = wasm.getFunction(getTempRet0)->body; + if (curr->is<Block>()) curr = curr->cast<Block>()->list[0]; + curr = curr->cast<Return>()->value; + auto* load = curr->cast<Load>(); + auto* ptr = load->ptr->cast<Const>(); + tempRet0 = ptr->value.geti32() + load->offset; + } + // udivmoddi4 receives xl, xh, yl, yl, r, and + // if r then *r = x % y + // returns x / y + auto* func = wasm.getFunction(udivmoddi4); + assert(!func->type.is()); + Name xl = func->params[0].name, + xh = func->params[1].name, + yl = func->params[2].name, + yh = func->params[3].name, + r = func->params[4].name; + func->locals.clear(); + Name x64("x64"), y64("y64"); + func->locals.emplace_back(x64, i64); + func->locals.emplace_back(y64, i64); + auto* body = allocator.alloc<Block>(); + auto recreateI64 = [&](Name target, Name low, Name high) { + return builder.makeSetLocal( + target, + builder.makeBinary( + Or, + builder.makeUnary( + ExtendUInt32, + builder.makeGetLocal(low, i32) + ), + builder.makeBinary( + Shl, + builder.makeUnary( + ExtendUInt32, + builder.makeGetLocal(high, i32) + ), + builder.makeConst(Literal(int64_t(32))) + ) + ) + ); + }; + body->list.push_back(recreateI64(x64, xl, xh)); + body->list.push_back(recreateI64(y64, yl, yh)); + body->list.push_back( + builder.makeIf( + builder.makeGetLocal(r, i32), + builder.makeStore( + 8, 0, 8, + builder.makeGetLocal(r, i32), + builder.makeBinary( + RemU, + builder.makeGetLocal(x64, i64), + builder.makeGetLocal(y64, i64) + ) + ) + ) + ); + body->list.push_back( + builder.makeSetLocal( + x64, + builder.makeBinary( + DivU, + builder.makeGetLocal(x64, i64), + builder.makeGetLocal(y64, i64) + ) + ) + ); + body->list.push_back( + builder.makeStore( + 4, 0, 4, + builder.makeConst(Literal(int32_t(tempRet0))), + builder.makeUnary( + WrapInt64, + builder.makeBinary( + ShrU, + builder.makeGetLocal(x64, i64), + builder.makeConst(Literal(int64_t(32))) + ) + ) + ) + ); + body->list.push_back( + builder.makeUnary( + WrapInt64, + builder.makeGetLocal(x64, i64) + ) + ); + func->body = body; + } } Function* Asm2WasmBuilder::processFunction(Ref ast) { - //if (ast[1] != IString("qta")) return nullptr; + auto name = ast[1]->getIString(); if (debug) { std::cout << "\nfunc: " << ast[1]->getIString().str << '\n'; @@ -751,7 +867,7 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { } auto function = allocator.alloc<Function>(); - function->name = ast[1]->getIString(); + function->name = name; Ref params = ast[2]; Ref body = ast[3]; @@ -1092,10 +1208,10 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { ret->type = WasmType::i32; return ret; } - if (name == Math_clz32) { + if (name == Math_clz32 || name == llvm_cttz_i32) { assert(ast[2]->size() == 1); auto ret = allocator.alloc<Unary>(); - ret->op = Clz; + ret->op = name == Math_clz32 ? Clz : Ctz; ret->value = process(ast[2][0]); ret->type = WasmType::i32; return ret; @@ -1279,9 +1395,8 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { Break *breakOut = allocator.alloc<Break>(); breakOut->name = out; If *condition = allocator.alloc<If>(); - condition->condition = process(ast[1]); - condition->ifTrue = allocator.alloc<Nop>(); - condition->ifFalse = breakOut; + condition->condition = builder.makeUnary(EqZ, process(ast[1])); + condition->ifTrue = breakOut; auto body = allocator.alloc<Block>(); body->list.push_back(condition); body->list.push_back(process(ast[2])); @@ -1377,9 +1492,8 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { Break *breakOut = allocator.alloc<Break>(); breakOut->name = out; If *condition = allocator.alloc<If>(); - condition->condition = process(fcond); - condition->ifTrue = allocator.alloc<Nop>(); - condition->ifFalse = breakOut; + condition->condition = builder.makeUnary(EqZ, process(fcond)); + condition->ifTrue = breakOut; auto body = allocator.alloc<Block>(); body->list.push_back(condition); body->list.push_back(process(fbody)); @@ -1594,7 +1708,6 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { // cleanups/checks assert(breakStack.size() == 0 && continueStack.size() == 0); assert(parentLabel.isNull()); - return function; } diff --git a/src/emscripten-optimizer/parser.cpp b/src/emscripten-optimizer/parser.cpp index 7005dc4b4..b8297fc29 100644 --- a/src/emscripten-optimizer/parser.cpp +++ b/src/emscripten-optimizer/parser.cpp @@ -48,6 +48,9 @@ IString TOPLEVEL("toplevel"), INF("inf"), NaN("nan"), TEMP_RET0("tempRet0"), + GET_TEMP_RET0("getTempRet0"), + LLVM_CTTZ_I32("_llvm_cttz_i32"), + UDIVMODDI4("___udivmoddi4"), UNARY_PREFIX("unary-prefix"), UNARY_POSTFIX("unary-postfix"), MATH_FROUND("Math_fround"), diff --git a/src/emscripten-optimizer/parser.h b/src/emscripten-optimizer/parser.h index da3e6f5c7..367c831e2 100644 --- a/src/emscripten-optimizer/parser.h +++ b/src/emscripten-optimizer/parser.h @@ -63,6 +63,9 @@ extern IString TOPLEVEL, INF, NaN, TEMP_RET0, + GET_TEMP_RET0, + LLVM_CTTZ_I32, + UDIVMODDI4, UNARY_PREFIX, UNARY_POSTFIX, MATH_FROUND, diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 638977353..de342b43f 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -36,6 +36,28 @@ struct OptimizeInstructions : public WalkerPass<WasmWalker<OptimizeInstructions> } } } + void visitUnary(Unary* curr) { + if (curr->op == EqZ) { + // fold comparisons that flow into an EqZ + auto* child = curr->value->dyn_cast<Binary>(); + if (child && (child->type == i32 || child->type == i64)) { + switch (child->op) { + case Eq: child->op = Ne; break; + case Ne: child->op = Eq; break; + case LtS: child->op = GeS; break; + case LtU: child->op = GeU; break; + case LeS: child->op = GtS; break; + case LeU: child->op = GtU; break; + case GtS: child->op = LeS; break; + case GtU: child->op = LeU; break; + case GeS: child->op = LtS; break; + case GeU: child->op = LtU; break; + default: return; + } + replaceCurrent(child); + } + } + } }; static RegisterPass<OptimizeInstructions> registerPass("optimize-instructions", "optimizes instruction combinations"); diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index 056b61939..8e3d503b8 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -26,17 +26,27 @@ namespace wasm { struct PrintSExpression : public WasmVisitor<PrintSExpression, void> { std::ostream& o; - unsigned indent; + unsigned indent = 0; + bool minify; const char *maybeSpace; const char *maybeNewLine; - PrintSExpression(std::ostream& o, bool minify = false) - : o(o), indent(0), minify(minify) { + bool fullAST = false; // whether to not elide nodes in output when possible + // (like implicit blocks) + + PrintSExpression(std::ostream& o) : o(o) { + setMinify(false); + } + + void setMinify(bool minify_) { + minify = minify_; maybeSpace = minify ? "" : " "; maybeNewLine = minify ? "" : "\n"; } + void setFullAST(bool fullAST_) { fullAST = fullAST_; } + void incIndent() { if (minify) return; o << '\n'; @@ -95,13 +105,13 @@ struct PrintSExpression : public WasmVisitor<PrintSExpression, void> { incIndent(); printFullLine(curr->condition); // ifTrue and False have implict blocks, avoid printing them if possible - if (curr->ifTrue->is<Block>() && curr->ifTrue->dyn_cast<Block>()->name.isNull() && curr->ifTrue->dyn_cast<Block>()->list.size() == 1) { + if (!fullAST && curr->ifTrue->is<Block>() && curr->ifTrue->dyn_cast<Block>()->name.isNull() && curr->ifTrue->dyn_cast<Block>()->list.size() == 1) { printFullLine(curr->ifTrue->dyn_cast<Block>()->list.back()); } else { printFullLine(curr->ifTrue); } if (curr->ifFalse) { - if (curr->ifFalse->is<Block>() && curr->ifFalse->dyn_cast<Block>()->name.isNull() && curr->ifFalse->dyn_cast<Block>()->list.size() == 1) { + if (!fullAST && curr->ifFalse->is<Block>() && curr->ifFalse->dyn_cast<Block>()->name.isNull() && curr->ifFalse->dyn_cast<Block>()->list.size() == 1) { printFullLine(curr->ifFalse->dyn_cast<Block>()->list.back()); } else { printFullLine(curr->ifFalse); @@ -120,7 +130,7 @@ struct PrintSExpression : public WasmVisitor<PrintSExpression, void> { } incIndent(); auto block = curr->body->dyn_cast<Block>(); - if (block && block->name.isNull()) { + if (!fullAST && block && block->name.isNull()) { // wasm spec has loops containing children directly, while our ast // has a single child for simplicity. print out the optimal form. for (auto expression : block->list) { @@ -435,7 +445,7 @@ struct PrintSExpression : public WasmVisitor<PrintSExpression, void> { } // It is ok to emit a block here, as a function can directly contain a list, even if our // ast avoids that for simplicity. We can just do that optimization here.. - if (curr->body->is<Block>() && curr->body->cast<Block>()->name.isNull()) { + if (!fullAST && curr->body->is<Block>() && curr->body->cast<Block>()->name.isNull()) { Block* block = curr->body->cast<Block>(); for (auto item : block->list) { printFullLine(item); @@ -526,8 +536,6 @@ struct PrintSExpression : public WasmVisitor<PrintSExpression, void> { } }; -// Pass entry point. Eventually this will direct printing to one of various options. - void Printer::run(PassRunner* runner, Module* module) { PrintSExpression print(o); print.visitModule(module); @@ -536,26 +544,42 @@ void Printer::run(PassRunner* runner, Module* module) { static RegisterPass<Printer> registerPass("print", "print in s-expression format"); // Prints out a minified module + class MinifiedPrinter : public Printer { public: MinifiedPrinter() : Printer() {} MinifiedPrinter(std::ostream& o) : Printer(o) {} - void run(PassRunner* runner, Module* module) override; + void run(PassRunner* runner, Module* module) override { + PrintSExpression print(o); + print.setMinify(true); + print.visitModule(module); + } }; -void MinifiedPrinter::run(PassRunner* runner, Module* module) { - PrintSExpression print(o, true); - print.visitModule(module); -} +static RegisterPass<MinifiedPrinter> registerMinifyPass("print-minified", "print in minified s-expression format"); +// Prints out a module withough elision, i.e., the full ast -static RegisterPass<MinifiedPrinter> registerMinifyPass("print-minified", "print in minified s-expression format"); +class FullPrinter : public Printer { + public: + FullPrinter() : Printer() {} + FullPrinter(std::ostream& o) : Printer(o) {} + + void run(PassRunner* runner, Module* module) override { + PrintSExpression print(o); + print.setFullAST(true); + print.visitModule(module); + } +}; + +static RegisterPass<FullPrinter> registerFullASTPass("print-full", "print in full s-expression format"); // Print individual expressions std::ostream& WasmPrinter::printExpression(Expression* expression, std::ostream& o, bool minify) { - PrintSExpression print(o, minify); + PrintSExpression print(o); + print.setMinify(minify); print.visit(expression); return o; } diff --git a/src/wasm-builder.h b/src/wasm-builder.h new file mode 100644 index 000000000..de3371274 --- /dev/null +++ b/src/wasm-builder.h @@ -0,0 +1,116 @@ +/* + * Copyright 2016 WebAssembly Community Group participants + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef wasm_builder_h +#define wasm_builder_h + +#include <wasm.h> + +namespace wasm { + +class Builder { + MixedArena &allocator; + +public: + Builder(AllocatingModule& wasm) : allocator(wasm.allocator) {} + + // Nop TODO: add all the rest + // Block + If* makeIf(Expression* condition, Expression* ifTrue, Expression* ifFalse=nullptr) { + auto* ret = allocator.alloc<If>(); + ret->condition = condition; ret->ifTrue = ifTrue; ret->ifFalse = ifFalse; + ret->finalize(); + return ret; + } + // Loop + // Break + // Switch + // CallBase + // Call + // CallImport + // FunctionType + GetLocal* makeGetLocal(Name name, WasmType type) { + auto* ret = allocator.alloc<GetLocal>(); + ret->name = name; + ret->type = type; + return ret; + } + SetLocal* makeSetLocal(Name name, Expression* value) { + auto* ret = allocator.alloc<SetLocal>(); + ret->name = name; + ret->value = value; + ret->type = value->type; + return ret; + } + // Load + Store* makeStore(unsigned bytes, uint32_t offset, unsigned align, Expression *ptr, Expression *value) { + auto* ret = allocator.alloc<Store>(); + ret->bytes = bytes; ret->offset = offset; ret->align = align; ret->ptr = ptr; ret->value = value; + ret->type = value->type; + return ret; + } + Const* makeConst(Literal value) { + auto* ret = allocator.alloc<Const>(); + ret->value = value; + ret->type = value.type; + return ret; + } + Unary* makeUnary(UnaryOp op, Expression *value, WasmType type=none) { + auto* ret = allocator.alloc<Unary>(); + ret->op = op; ret->value = value; + if (type != none) { + ret->type = type; // some opcodes have more than one type, user must provide it + } else { + switch (op) { + case Clz: + case Ctz: + case Popcnt: + case Neg: + case Abs: + case Ceil: + case Floor: + case Trunc: + case Nearest: + case Sqrt: ret->type = value->type; break; + case EqZ: ret->type = i32; break; + case ExtendSInt32: case ExtendUInt32: ret->type = i64; break; + case WrapInt64: ret->type = i32; break; + case PromoteFloat32: ret->type = f64; break; + case DemoteFloat64: ret->type = f32; break; + case TruncSFloat32: case TruncUFloat32: case TruncSFloat64: case TruncUFloat64: case ReinterpretFloat: + case ConvertSInt32: case ConvertUInt32: case ConvertSInt64: case ConvertUInt64: case ReinterpretInt: abort(); // user needs to say the type + default: abort(); + } + } + return ret; + } + Binary* makeBinary(BinaryOp op, Expression *left, Expression *right) { + auto* ret = allocator.alloc<Binary>(); + ret->op = op; ret->left = left; ret->right = right; + ret->finalize(); + return ret; + } + // Select + // Return + // Host + // Unreachable + +}; + +} // namespace wasm + +#endif // wasm_builder_h + diff --git a/src/wasm.h b/src/wasm.h index f985e9b59..c9494d4d6 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -742,7 +742,8 @@ public: ReturnId, HostId, NopId, - UnreachableId + UnreachableId, + NumExpressionIds }; Id _id; @@ -827,7 +828,7 @@ public: Expression *condition, *ifTrue, *ifFalse; void finalize() { - if (condition) { + if (ifFalse) { type = getReachableWasmType(ifTrue->type, ifFalse->type); } } @@ -975,10 +976,9 @@ public: UnaryOp op; Expression *value; - // the type is always the type of the operands, - // except for relationals - bool isRelational() { return op == EqZ; } + + // no finalize since some opcodes have more than one type, so user must set it anyhow }; class Binary : public Expression { diff --git a/test/emcc_O2_hello_world.fromasm b/test/emcc_O2_hello_world.fromasm index 62eb5d4a9..8ca7f7436 100644 --- a/test/emcc_O2_hello_world.fromasm +++ b/test/emcc_O2_hello_world.fromasm @@ -9543,13 +9543,13 @@ ) (block (loop $while-out$0 $while-in$1 - (if - (i32.and - (get_local $i1) - (i32.const 3) + (br_if $while-out$0 + (i32.eqz + (i32.and + (get_local $i1) + (i32.const 3) + ) ) - (nop) - (br $while-out$0) ) (if (i32.eqz @@ -9586,13 +9586,11 @@ (br $while-in$1) ) (loop $while-out$2 $while-in$3 - (if - (i32.ge_s + (br_if $while-out$2 + (i32.lt_s (get_local $i3) (i32.const 4) ) - (nop) - (br $while-out$2) ) (i32.store (get_local $i1) @@ -9623,13 +9621,11 @@ ) ) (loop $while-out$4 $while-in$5 - (if - (i32.gt_s + (br_if $while-out$4 + (i32.le_s (get_local $i3) (i32.const 0) ) - (nop) - (br $while-out$4) ) (i32.store8 (get_local $i1) @@ -9736,13 +9732,11 @@ ) ) (loop $while-out$0 $while-in$1 - (if - (i32.lt_s + (br_if $while-out$0 + (i32.ge_s (get_local $i1) (get_local $i5) ) - (nop) - (br $while-out$0) ) (i32.store8 (get_local $i1) @@ -9759,13 +9753,11 @@ ) ) (loop $while-out$2 $while-in$3 - (if - (i32.lt_s + (br_if $while-out$2 + (i32.ge_s (get_local $i1) (get_local $i7) ) - (nop) - (br $while-out$2) ) (i32.store (get_local $i1) @@ -9782,13 +9774,11 @@ ) ) (loop $while-out$4 $while-in$5 - (if - (i32.lt_s + (br_if $while-out$4 + (i32.ge_s (get_local $i1) (get_local $i4) ) - (nop) - (br $while-out$4) ) (i32.store8 (get_local $i1) diff --git a/test/emcc_O2_hello_world.fromasm.imprecise b/test/emcc_O2_hello_world.fromasm.imprecise index 62eb5d4a9..8ca7f7436 100644 --- a/test/emcc_O2_hello_world.fromasm.imprecise +++ b/test/emcc_O2_hello_world.fromasm.imprecise @@ -9543,13 +9543,13 @@ ) (block (loop $while-out$0 $while-in$1 - (if - (i32.and - (get_local $i1) - (i32.const 3) + (br_if $while-out$0 + (i32.eqz + (i32.and + (get_local $i1) + (i32.const 3) + ) ) - (nop) - (br $while-out$0) ) (if (i32.eqz @@ -9586,13 +9586,11 @@ (br $while-in$1) ) (loop $while-out$2 $while-in$3 - (if - (i32.ge_s + (br_if $while-out$2 + (i32.lt_s (get_local $i3) (i32.const 4) ) - (nop) - (br $while-out$2) ) (i32.store (get_local $i1) @@ -9623,13 +9621,11 @@ ) ) (loop $while-out$4 $while-in$5 - (if - (i32.gt_s + (br_if $while-out$4 + (i32.le_s (get_local $i3) (i32.const 0) ) - (nop) - (br $while-out$4) ) (i32.store8 (get_local $i1) @@ -9736,13 +9732,11 @@ ) ) (loop $while-out$0 $while-in$1 - (if - (i32.lt_s + (br_if $while-out$0 + (i32.ge_s (get_local $i1) (get_local $i5) ) - (nop) - (br $while-out$0) ) (i32.store8 (get_local $i1) @@ -9759,13 +9753,11 @@ ) ) (loop $while-out$2 $while-in$3 - (if - (i32.lt_s + (br_if $while-out$2 + (i32.ge_s (get_local $i1) (get_local $i7) ) - (nop) - (br $while-out$2) ) (i32.store (get_local $i1) @@ -9782,13 +9774,11 @@ ) ) (loop $while-out$4 $while-in$5 - (if - (i32.lt_s + (br_if $while-out$4 + (i32.ge_s (get_local $i1) (get_local $i4) ) - (nop) - (br $while-out$4) ) (i32.store8 (get_local $i1) diff --git a/test/emcc_hello_world.asm.js b/test/emcc_hello_world.asm.js index 6b904c741..cd188303e 100644 --- a/test/emcc_hello_world.asm.js +++ b/test/emcc_hello_world.asm.js @@ -77,6 +77,7 @@ Module["asm"] = (function(global, env, buffer) { var _pthread_cleanup_push=env._pthread_cleanup_push; var _sysconf=env._sysconf; var ___syscall146=env.___syscall146; + var _llvm_cttz_i32=env._llvm_cttz_i32; var tempFloat = 0.0; // EMSCRIPTEN_START_FUNCS @@ -6757,17 +6758,6 @@ function _bitshift64Ashr(low, high, bits) { tempRet0 = (high|0) < 0 ? -1 : 0; return (high >> (bits - 32))|0; } -function _llvm_cttz_i32(x) { - x = x|0; - var ret = 0; - ret = ((HEAP8[(((cttz_i8)+(x & 0xff))>>0)])|0); - if ((ret|0) < 8) return ret|0; - ret = ((HEAP8[(((cttz_i8)+((x >> 8)&0xff))>>0)])|0); - if ((ret|0) < 8) return (ret + 8)|0; - ret = ((HEAP8[(((cttz_i8)+((x >> 16)&0xff))>>0)])|0); - if ((ret|0) < 8) return (ret + 16)|0; - return (((HEAP8[(((cttz_i8)+(x >>> 24))>>0)])|0) + 24)|0; - } // ======== compiled code from system/lib/compiler-rt , see readme therein function ___muldsi3($a, $b) { @@ -7106,6 +7096,6 @@ var FUNCTION_TABLE_ii = [b0,___stdio_close]; var FUNCTION_TABLE_iiii = [b1,b1,___stdout_write,___stdio_seek,___stdio_write,b1,b1,b1]; var FUNCTION_TABLE_vi = [b2,b2,b2,b2,b2,_cleanup,b2,b2]; - return { _i64Subtract: _i64Subtract, _free: _free, _main: _main, _i64Add: _i64Add, _memset: _memset, _malloc: _malloc, _memcpy: _memcpy, _bitshift64Lshr: _bitshift64Lshr, _fflush: _fflush, ___errno_location: ___errno_location, _bitshift64Shl: _bitshift64Shl, runPostSets: runPostSets, stackAlloc: stackAlloc, stackSave: stackSave, stackRestore: stackRestore, establishStackSpace: establishStackSpace, setThrew: setThrew, setTempRet0: setTempRet0, getTempRet0: getTempRet0, dynCall_ii: dynCall_ii, dynCall_iiii: dynCall_iiii, dynCall_vi: dynCall_vi }; + return { _i64Subtract: _i64Subtract, _free: _free, _main: _main, _i64Add: _i64Add, _memset: _memset, _malloc: _malloc, _memcpy: _memcpy, _bitshift64Lshr: _bitshift64Lshr, _fflush: _fflush, ___errno_location: ___errno_location, _bitshift64Shl: _bitshift64Shl, runPostSets: runPostSets, stackAlloc: stackAlloc, stackSave: stackSave, stackRestore: stackRestore, establishStackSpace: establishStackSpace, setThrew: setThrew, setTempRet0: setTempRet0, getTempRet0: getTempRet0, dynCall_ii: dynCall_ii, dynCall_iiii: dynCall_iiii, dynCall_vi: dynCall_vi, ___udivmoddi4: ___udivmoddi4 }; }) ; diff --git a/test/emcc_hello_world.fromasm b/test/emcc_hello_world.fromasm index be7a45cec..60394be4f 100644 --- a/test/emcc_hello_world.fromasm +++ b/test/emcc_hello_world.fromasm @@ -50,6 +50,7 @@ (export "dynCall_ii" $dynCall_ii) (export "dynCall_iiii" $dynCall_iiii) (export "dynCall_vi" $dynCall_vi) + (export "___udivmoddi4" $___udivmoddi4) (table $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $___stdio_write $b1 $b1 $b1 $b2 $b2 $b2 $b2 $b2 $_cleanup $b2 $b2) (func $stackAlloc (param $size i32) (result i32) (local $ret i32) @@ -28142,13 +28143,11 @@ ) ) (loop $while-out$0 $while-in$1 - (if - (i32.lt_s + (br_if $while-out$0 + (i32.ge_s (get_local $ptr) (get_local $unaligned) ) - (nop) - (br $while-out$0) ) (i32.store8 (get_local $ptr) @@ -28165,13 +28164,11 @@ ) ) (loop $while-out$2 $while-in$3 - (if - (i32.lt_s + (br_if $while-out$2 + (i32.ge_s (get_local $ptr) (get_local $stop4) ) - (nop) - (br $while-out$2) ) (i32.store (get_local $ptr) @@ -28188,13 +28185,11 @@ ) ) (loop $while-out$4 $while-in$5 - (if - (i32.lt_s + (br_if $while-out$4 + (i32.ge_s (get_local $ptr) (get_local $stop) ) - (nop) - (br $while-out$4) ) (i32.store8 (get_local $ptr) @@ -28368,13 +28363,13 @@ ) (block (loop $while-out$0 $while-in$1 - (if - (i32.and - (get_local $dest) - (i32.const 3) + (br_if $while-out$0 + (i32.eqz + (i32.and + (get_local $dest) + (i32.const 3) + ) ) - (nop) - (br $while-out$0) ) (if (i32.eq @@ -28412,13 +28407,11 @@ (br $while-in$1) ) (loop $while-out$2 $while-in$3 - (if - (i32.ge_s + (br_if $while-out$2 + (i32.lt_s (get_local $num) (i32.const 4) ) - (nop) - (br $while-out$2) ) (i32.store (get_local $dest) @@ -28449,13 +28442,11 @@ ) ) (loop $while-out$4 $while-in$5 - (if - (i32.gt_s + (br_if $while-out$4 + (i32.le_s (get_local $num) (i32.const 0) ) - (nop) - (br $while-out$4) ) (i32.store8 (get_local $dest) @@ -28552,100 +28543,6 @@ ) ) ) - (func $_llvm_cttz_i32 (param $x i32) (result i32) - (local $ret i32) - (if - (i32.lt_s - (set_local $ret - (i32.load8_s - (i32.add - (i32.load - (i32.const 40) - ) - (i32.and - (get_local $x) - (i32.const 255) - ) - ) - ) - ) - (i32.const 8) - ) - (return - (get_local $ret) - ) - ) - (if - (i32.lt_s - (set_local $ret - (i32.load8_s - (i32.add - (i32.load - (i32.const 40) - ) - (i32.and - (i32.shr_s - (get_local $x) - (i32.const 8) - ) - (i32.const 255) - ) - ) - ) - ) - (i32.const 8) - ) - (return - (i32.add - (get_local $ret) - (i32.const 8) - ) - ) - ) - (if - (i32.lt_s - (set_local $ret - (i32.load8_s - (i32.add - (i32.load - (i32.const 40) - ) - (i32.and - (i32.shr_s - (get_local $x) - (i32.const 16) - ) - (i32.const 255) - ) - ) - ) - ) - (i32.const 8) - ) - (return - (i32.add - (get_local $ret) - (i32.const 16) - ) - ) - ) - (return - (i32.add - (i32.load8_s - (i32.add - (i32.load - (i32.const 40) - ) - (i32.shr_u - (get_local $x) - (i32.const 24) - ) - ) - ) - (i32.const 24) - ) - ) - ) (func $___muldsi3 (param $$a i32) (param $$b i32) (result i32) (local $$8 i32) (local $$6 i32) @@ -29240,1209 +29137,60 @@ ) ) (func $___udivmoddi4 (param $$a$0 i32) (param $$a$1 i32) (param $$b$0 i32) (param $$b$1 i32) (param $$rem i32) (result i32) - (local $$_0$1 i32) - (local $$_0$0 i32) - (local $$n_sroa_1_4_extract_trunc i32) - (local $$n_sroa_0_0_extract_trunc i32) - (local $$d_sroa_0_0_extract_trunc i32) - (local $$d_sroa_1_4_extract_trunc i32) - (local $$88 i32) - (local $$sr_1_ph i32) - (local $$r_sroa_1_1_ph i32) - (local $$r_sroa_0_1_ph i32) - (local $$q_sroa_1_1_ph i32) - (local $$q_sroa_0_1_ph i32) - (local $$r_sroa_0_1201 i32) - (local $$q_sroa_1_1198 i32) - (local $$q_sroa_0_1199 i32) - (local $$q_sroa_0_0_insert_ext75$0 i32) - (local $$n_sroa_1_4_extract_shift$0 i32) - (local $$91 i32) - (local $$78 i32) - (local $$57 i32) - (local $$150$1 i32) - (local $$125 i32) - (local $$119 i32) - (local $$sr_1202 i32) - (local $$r_sroa_1_4_extract_trunc i32) - (local $$r_sroa_1_1_lcssa i32) - (local $$r_sroa_1_1200 i32) - (local $$r_sroa_0_1_lcssa i32) - (local $$r_sroa_0_0_insert_insert42$1 i32) - (local $$r_sroa_0_0_insert_insert42$0 i32) - (local $$r_sroa_0_0_extract_trunc i32) - (local $$q_sroa_1_1_lcssa i32) - (local $$q_sroa_0_1_lcssa i32) - (local $$q_sroa_0_0_insert_ext75$1 i32) - (local $$d_sroa_0_0_insert_insert99$1 i32) - (local $$d_sroa_0_0_insert_insert99$0 i32) - (local $$carry_0_lcssa$1 i32) - (local $$carry_0_lcssa$0 i32) - (local $$carry_0203 i32) - (local $$95 i32) - (local $$92 i32) - (local $$89 i32) - (local $$58 i32) - (local $$51 i32) - (local $$4 i32) - (local $$17 i32) - (local $$152 i32) - (local $$149 i32) - (local $$147 i32) - (local $$130 i32) - (local $$126 i32) - (local $$105 i32) - (local $$q_sroa_0_0_insert_insert77$1 i32) - (local $$d_sroa_1_4_extract_shift$0 i32) - (local $$66 i32) - (local $$37 i32) - (local $$155 i32) - (local $$151$0 i32) - (local $$137$1 i32) - (local $$137$0 i32) - (local $$86 i32) - (local $$49 i32) - (local $$154$0 i32) - (local $$117 i32) - (set_local $$n_sroa_0_0_extract_trunc - (get_local $$a$0) - ) - (set_local $$n_sroa_1_4_extract_trunc - (set_local $$n_sroa_1_4_extract_shift$0 - (get_local $$a$1) - ) - ) - (set_local $$d_sroa_0_0_extract_trunc - (get_local $$b$0) - ) - (set_local $$d_sroa_1_4_extract_trunc - (set_local $$d_sroa_1_4_extract_shift$0 - (get_local $$b$1) - ) - ) - (if - (i32.eq - (get_local $$n_sroa_1_4_extract_trunc) - (i32.const 0) - ) - (block - (set_local $$4 - (i32.ne - (get_local $$rem) - (i32.const 0) - ) - ) - (if - (i32.eq - (get_local $$d_sroa_1_4_extract_trunc) - (i32.const 0) - ) - (block - (if - (get_local $$4) - (block - (i32.store - (get_local $$rem) - (i32.rem_u - (get_local $$n_sroa_0_0_extract_trunc) - (get_local $$d_sroa_0_0_extract_trunc) - ) - ) - (i32.store offset=4 - (get_local $$rem) - (i32.const 0) - ) - ) - ) - (set_local $$_0$1 - (i32.const 0) - ) - (set_local $$_0$0 - (i32.div_u - (get_local $$n_sroa_0_0_extract_trunc) - (get_local $$d_sroa_0_0_extract_trunc) - ) - ) - (return - (block - (i32.store - (i32.const 168) - (get_local $$_0$1) - ) - (get_local $$_0$0) - ) - ) - ) - (block - (if - (i32.eqz - (get_local $$4) - ) - (block - (set_local $$_0$1 - (i32.const 0) - ) - (set_local $$_0$0 - (i32.const 0) - ) - (return - (block - (i32.store - (i32.const 168) - (get_local $$_0$1) - ) - (get_local $$_0$0) - ) - ) - ) - ) - (i32.store - (get_local $$rem) - (i32.and - (get_local $$a$0) - (i32.const -1) - ) - ) - (i32.store offset=4 - (get_local $$rem) - (i32.and - (get_local $$a$1) - (i32.const 0) - ) - ) - (set_local $$_0$1 - (i32.const 0) - ) - (set_local $$_0$0 - (i32.const 0) - ) - (return - (block - (i32.store - (i32.const 168) - (get_local $$_0$1) - ) - (get_local $$_0$0) - ) - ) - ) - ) - ) - ) - (set_local $$17 - (i32.eq - (get_local $$d_sroa_1_4_extract_trunc) - (i32.const 0) - ) - ) - (block $do-once$0 - (if - (i32.eq - (get_local $$d_sroa_0_0_extract_trunc) - (i32.const 0) - ) - (block - (if - (get_local $$17) - (block - (if - (i32.ne - (get_local $$rem) - (i32.const 0) - ) - (block - (i32.store - (get_local $$rem) - (i32.rem_u - (get_local $$n_sroa_1_4_extract_trunc) - (get_local $$d_sroa_0_0_extract_trunc) - ) - ) - (i32.store offset=4 - (get_local $$rem) - (i32.const 0) - ) - ) - ) - (set_local $$_0$1 - (i32.const 0) - ) - (set_local $$_0$0 - (i32.div_u - (get_local $$n_sroa_1_4_extract_trunc) - (get_local $$d_sroa_0_0_extract_trunc) - ) - ) - (return - (block - (i32.store - (i32.const 168) - (get_local $$_0$1) - ) - (get_local $$_0$0) - ) - ) - ) - ) - (if - (i32.eq - (get_local $$n_sroa_0_0_extract_trunc) - (i32.const 0) - ) - (block - (if - (i32.ne - (get_local $$rem) - (i32.const 0) - ) - (block - (i32.store - (get_local $$rem) - (i32.const 0) - ) - (i32.store offset=4 - (get_local $$rem) - (i32.rem_u - (get_local $$n_sroa_1_4_extract_trunc) - (get_local $$d_sroa_1_4_extract_trunc) - ) - ) - ) - ) - (set_local $$_0$1 - (i32.const 0) - ) - (set_local $$_0$0 - (i32.div_u - (get_local $$n_sroa_1_4_extract_trunc) - (get_local $$d_sroa_1_4_extract_trunc) - ) - ) - (return - (block - (i32.store - (i32.const 168) - (get_local $$_0$1) - ) - (get_local $$_0$0) - ) - ) - ) - ) - (if - (i32.eq - (i32.and - (set_local $$37 - (i32.sub - (get_local $$d_sroa_1_4_extract_trunc) - (i32.const 1) - ) - ) - (get_local $$d_sroa_1_4_extract_trunc) - ) - (i32.const 0) - ) - (block - (if - (i32.ne - (get_local $$rem) - (i32.const 0) - ) - (block - (i32.store - (get_local $$rem) - (i32.or - (i32.const 0) - (i32.and - (get_local $$a$0) - (i32.const -1) - ) - ) - ) - (i32.store offset=4 - (get_local $$rem) - (i32.or - (i32.and - (get_local $$37) - (get_local $$n_sroa_1_4_extract_trunc) - ) - (i32.and - (get_local $$a$1) - (i32.const 0) - ) - ) - ) - ) - ) - (set_local $$_0$1 - (i32.const 0) - ) - (set_local $$_0$0 - (i32.shr_u - (get_local $$n_sroa_1_4_extract_trunc) - (call $_llvm_cttz_i32 - (get_local $$d_sroa_1_4_extract_trunc) - ) - ) - ) - (return - (block - (i32.store - (i32.const 168) - (get_local $$_0$1) - ) - (get_local $$_0$0) - ) - ) - ) - ) - (if - (i32.le_u - (set_local $$51 - (i32.sub - (set_local $$49 - (i32.clz - (get_local $$d_sroa_1_4_extract_trunc) - ) - ) - (i32.clz - (get_local $$n_sroa_1_4_extract_trunc) - ) - ) - ) - (i32.const 30) - ) - (block - (set_local $$57 - (i32.add - (get_local $$51) - (i32.const 1) - ) - ) - (set_local $$58 - (i32.sub - (i32.const 31) - (get_local $$51) - ) - ) - (set_local $$sr_1_ph - (get_local $$57) - ) - (set_local $$r_sroa_0_1_ph - (i32.or - (i32.shl - (get_local $$n_sroa_1_4_extract_trunc) - (get_local $$58) - ) - (i32.shr_u - (get_local $$n_sroa_0_0_extract_trunc) - (get_local $$57) - ) - ) - ) - (set_local $$r_sroa_1_1_ph - (i32.shr_u - (get_local $$n_sroa_1_4_extract_trunc) - (get_local $$57) - ) - ) - (set_local $$q_sroa_0_1_ph - (i32.const 0) - ) - (set_local $$q_sroa_1_1_ph - (i32.shl - (get_local $$n_sroa_0_0_extract_trunc) - (get_local $$58) - ) - ) - (br $do-once$0) - ) - ) - (if - (i32.eq - (get_local $$rem) - (i32.const 0) - ) - (block - (set_local $$_0$1 - (i32.const 0) - ) - (set_local $$_0$0 - (i32.const 0) - ) - (return - (block - (i32.store - (i32.const 168) - (get_local $$_0$1) - ) - (get_local $$_0$0) - ) - ) - ) - ) - (i32.store - (get_local $$rem) - (i32.or - (i32.const 0) - (i32.and - (get_local $$a$0) - (i32.const -1) - ) - ) - ) - (i32.store offset=4 - (get_local $$rem) - (i32.or - (get_local $$n_sroa_1_4_extract_shift$0) - (i32.and - (get_local $$a$1) - (i32.const 0) - ) - ) - ) - (set_local $$_0$1 - (i32.const 0) - ) - (set_local $$_0$0 - (i32.const 0) - ) - (return - (block - (i32.store - (i32.const 168) - (get_local $$_0$1) - ) - (get_local $$_0$0) - ) - ) + (local $x64 i64) + (local $y64 i64) + (set_local $x64 + (i64.or + (i64.extend_u/i32 + (get_local $$a$0) ) - (block - (if - (i32.eqz - (get_local $$17) - ) - (block - (if - (i32.le_u - (set_local $$119 - (i32.sub - (set_local $$117 - (i32.clz - (get_local $$d_sroa_1_4_extract_trunc) - ) - ) - (i32.clz - (get_local $$n_sroa_1_4_extract_trunc) - ) - ) - ) - (i32.const 31) - ) - (block - (set_local $$125 - (i32.add - (get_local $$119) - (i32.const 1) - ) - ) - (set_local $$126 - (i32.sub - (i32.const 31) - (get_local $$119) - ) - ) - (set_local $$130 - (i32.shr_s - (i32.sub - (get_local $$119) - (i32.const 31) - ) - (i32.const 31) - ) - ) - (set_local $$sr_1_ph - (get_local $$125) - ) - (set_local $$r_sroa_0_1_ph - (i32.or - (i32.and - (i32.shr_u - (get_local $$n_sroa_0_0_extract_trunc) - (get_local $$125) - ) - (get_local $$130) - ) - (i32.shl - (get_local $$n_sroa_1_4_extract_trunc) - (get_local $$126) - ) - ) - ) - (set_local $$r_sroa_1_1_ph - (i32.and - (i32.shr_u - (get_local $$n_sroa_1_4_extract_trunc) - (get_local $$125) - ) - (get_local $$130) - ) - ) - (set_local $$q_sroa_0_1_ph - (i32.const 0) - ) - (set_local $$q_sroa_1_1_ph - (i32.shl - (get_local $$n_sroa_0_0_extract_trunc) - (get_local $$126) - ) - ) - (br $do-once$0) - ) - ) - (if - (i32.eq - (get_local $$rem) - (i32.const 0) - ) - (block - (set_local $$_0$1 - (i32.const 0) - ) - (set_local $$_0$0 - (i32.const 0) - ) - (return - (block - (i32.store - (i32.const 168) - (get_local $$_0$1) - ) - (get_local $$_0$0) - ) - ) - ) - ) - (i32.store - (get_local $$rem) - (i32.or - (i32.const 0) - (i32.and - (get_local $$a$0) - (i32.const -1) - ) - ) - ) - (i32.store offset=4 - (get_local $$rem) - (i32.or - (get_local $$n_sroa_1_4_extract_shift$0) - (i32.and - (get_local $$a$1) - (i32.const 0) - ) - ) - ) - (set_local $$_0$1 - (i32.const 0) - ) - (set_local $$_0$0 - (i32.const 0) - ) - (return - (block - (i32.store - (i32.const 168) - (get_local $$_0$1) - ) - (get_local $$_0$0) - ) - ) - ) - ) - (if - (i32.ne - (i32.and - (set_local $$66 - (i32.sub - (get_local $$d_sroa_0_0_extract_trunc) - (i32.const 1) - ) - ) - (get_local $$d_sroa_0_0_extract_trunc) - ) - (i32.const 0) - ) - (block - (set_local $$89 - (i32.sub - (i32.const 64) - (set_local $$88 - (i32.sub - (set_local $$86 - (i32.add - (i32.clz - (get_local $$d_sroa_0_0_extract_trunc) - ) - (i32.const 33) - ) - ) - (i32.clz - (get_local $$n_sroa_1_4_extract_trunc) - ) - ) - ) - ) - ) - (set_local $$92 - (i32.shr_s - (set_local $$91 - (i32.sub - (i32.const 32) - (get_local $$88) - ) - ) - (i32.const 31) - ) - ) - (set_local $$105 - (i32.shr_s - (set_local $$95 - (i32.sub - (get_local $$88) - (i32.const 32) - ) - ) - (i32.const 31) - ) - ) - (set_local $$sr_1_ph - (get_local $$88) - ) - (set_local $$r_sroa_0_1_ph - (i32.or - (i32.and - (i32.shr_s - (i32.sub - (get_local $$91) - (i32.const 1) - ) - (i32.const 31) - ) - (i32.shr_u - (get_local $$n_sroa_1_4_extract_trunc) - (get_local $$95) - ) - ) - (i32.and - (i32.or - (i32.shl - (get_local $$n_sroa_1_4_extract_trunc) - (get_local $$91) - ) - (i32.shr_u - (get_local $$n_sroa_0_0_extract_trunc) - (get_local $$88) - ) - ) - (get_local $$105) - ) - ) - ) - (set_local $$r_sroa_1_1_ph - (i32.and - (get_local $$105) - (i32.shr_u - (get_local $$n_sroa_1_4_extract_trunc) - (get_local $$88) - ) - ) - ) - (set_local $$q_sroa_0_1_ph - (i32.and - (i32.shl - (get_local $$n_sroa_0_0_extract_trunc) - (get_local $$89) - ) - (get_local $$92) - ) - ) - (set_local $$q_sroa_1_1_ph - (i32.or - (i32.and - (i32.or - (i32.shl - (get_local $$n_sroa_1_4_extract_trunc) - (get_local $$89) - ) - (i32.shr_u - (get_local $$n_sroa_0_0_extract_trunc) - (get_local $$95) - ) - ) - (get_local $$92) - ) - (i32.and - (i32.shl - (get_local $$n_sroa_0_0_extract_trunc) - (get_local $$91) - ) - (i32.shr_s - (i32.sub - (get_local $$88) - (i32.const 33) - ) - (i32.const 31) - ) - ) - ) - ) - (br $do-once$0) - ) - ) - (if - (i32.ne - (get_local $$rem) - (i32.const 0) - ) - (block - (i32.store - (get_local $$rem) - (i32.and - (get_local $$66) - (get_local $$n_sroa_0_0_extract_trunc) - ) - ) - (i32.store offset=4 - (get_local $$rem) - (i32.const 0) - ) - ) - ) - (if - (i32.eq - (get_local $$d_sroa_0_0_extract_trunc) - (i32.const 1) - ) - (block - (set_local $$_0$1 - (i32.or - (get_local $$n_sroa_1_4_extract_shift$0) - (i32.and - (get_local $$a$1) - (i32.const 0) - ) - ) - ) - (set_local $$_0$0 - (i32.or - (i32.const 0) - (i32.and - (get_local $$a$0) - (i32.const -1) - ) - ) - ) - (return - (block - (i32.store - (i32.const 168) - (get_local $$_0$1) - ) - (get_local $$_0$0) - ) - ) - ) - (block - (set_local $$78 - (call $_llvm_cttz_i32 - (get_local $$d_sroa_0_0_extract_trunc) - ) - ) - (set_local $$_0$1 - (i32.or - (i32.const 0) - (i32.shr_u - (get_local $$n_sroa_1_4_extract_trunc) - (get_local $$78) - ) - ) - ) - (set_local $$_0$0 - (i32.or - (i32.shl - (get_local $$n_sroa_1_4_extract_trunc) - (i32.sub - (i32.const 32) - (get_local $$78) - ) - ) - (i32.shr_u - (get_local $$n_sroa_0_0_extract_trunc) - (get_local $$78) - ) - ) - ) - (return - (block - (i32.store - (i32.const 168) - (get_local $$_0$1) - ) - (get_local $$_0$0) - ) - ) - ) + (i64.shl + (i64.extend_u/i32 + (get_local $$a$1) ) + (i64.const 32) ) ) ) - (if - (i32.eq - (get_local $$sr_1_ph) - (i32.const 0) - ) - (block - (set_local $$q_sroa_1_1_lcssa - (get_local $$q_sroa_1_1_ph) - ) - (set_local $$q_sroa_0_1_lcssa - (get_local $$q_sroa_0_1_ph) - ) - (set_local $$r_sroa_1_1_lcssa - (get_local $$r_sroa_1_1_ph) - ) - (set_local $$r_sroa_0_1_lcssa - (get_local $$r_sroa_0_1_ph) - ) - (set_local $$carry_0_lcssa$1 - (i32.const 0) - ) - (set_local $$carry_0_lcssa$0 - (i32.const 0) - ) - ) - (block - (set_local $$d_sroa_0_0_insert_insert99$0 - (i32.or - (i32.const 0) - (i32.and - (get_local $$b$0) - (i32.const -1) - ) - ) - ) - (set_local $$d_sroa_0_0_insert_insert99$1 - (i32.or - (get_local $$d_sroa_1_4_extract_shift$0) - (i32.and - (get_local $$b$1) - (i32.const 0) - ) - ) - ) - (set_local $$137$0 - (call $_i64Add - (get_local $$d_sroa_0_0_insert_insert99$0) - (get_local $$d_sroa_0_0_insert_insert99$1) - (i32.const -1) - (i32.const -1) - ) - ) - (set_local $$137$1 - (i32.load - (i32.const 168) - ) - ) - (set_local $$q_sroa_1_1198 - (get_local $$q_sroa_1_1_ph) - ) - (set_local $$q_sroa_0_1199 - (get_local $$q_sroa_0_1_ph) - ) - (set_local $$r_sroa_1_1200 - (get_local $$r_sroa_1_1_ph) - ) - (set_local $$r_sroa_0_1201 - (get_local $$r_sroa_0_1_ph) - ) - (set_local $$sr_1202 - (get_local $$sr_1_ph) - ) - (set_local $$carry_0203 - (i32.const 0) + (set_local $y64 + (i64.or + (i64.extend_u/i32 + (get_local $$b$0) ) - (loop $while-out$2 $while-in$3 - (set_local $$147 - (i32.or - (i32.shr_u - (get_local $$q_sroa_0_1199) - (i32.const 31) - ) - (i32.shl - (get_local $$q_sroa_1_1198) - (i32.const 1) - ) - ) - ) - (set_local $$149 - (i32.or - (get_local $$carry_0203) - (i32.shl - (get_local $$q_sroa_0_1199) - (i32.const 1) - ) - ) - ) - (set_local $$r_sroa_0_0_insert_insert42$0 - (i32.or - (i32.const 0) - (i32.or - (i32.shl - (get_local $$r_sroa_0_1201) - (i32.const 1) - ) - (i32.shr_u - (get_local $$q_sroa_1_1198) - (i32.const 31) - ) - ) - ) - ) - (set_local $$r_sroa_0_0_insert_insert42$1 - (i32.or - (i32.shr_u - (get_local $$r_sroa_0_1201) - (i32.const 31) - ) - (i32.shl - (get_local $$r_sroa_1_1200) - (i32.const 1) - ) - ) - ) - (call $_i64Subtract - (get_local $$137$0) - (get_local $$137$1) - (get_local $$r_sroa_0_0_insert_insert42$0) - (get_local $$r_sroa_0_0_insert_insert42$1) - ) - (set_local $$152 - (i32.and - (set_local $$151$0 - (i32.or - (i32.shr_s - (set_local $$150$1 - (i32.load - (i32.const 168) - ) - ) - (i32.const 31) - ) - (i32.shl - (if - (i32.lt_s - (get_local $$150$1) - (i32.const 0) - ) - (i32.const -1) - (i32.const 0) - ) - (i32.const 1) - ) - ) - ) - (i32.const 1) - ) - ) - (set_local $$r_sroa_0_0_extract_trunc - (set_local $$154$0 - (call $_i64Subtract - (get_local $$r_sroa_0_0_insert_insert42$0) - (get_local $$r_sroa_0_0_insert_insert42$1) - (i32.and - (get_local $$151$0) - (get_local $$d_sroa_0_0_insert_insert99$0) - ) - (i32.and - (i32.or - (i32.shr_s - (if - (i32.lt_s - (get_local $$150$1) - (i32.const 0) - ) - (i32.const -1) - (i32.const 0) - ) - (i32.const 31) - ) - (i32.shl - (if - (i32.lt_s - (get_local $$150$1) - (i32.const 0) - ) - (i32.const -1) - (i32.const 0) - ) - (i32.const 1) - ) - ) - (get_local $$d_sroa_0_0_insert_insert99$1) - ) - ) - ) - ) - (set_local $$r_sroa_1_4_extract_trunc - (i32.load - (i32.const 168) - ) - ) - (if - (i32.eq - (set_local $$155 - (i32.sub - (get_local $$sr_1202) - (i32.const 1) - ) - ) - (i32.const 0) - ) - (br $while-out$2) - (block - (set_local $$q_sroa_1_1198 - (get_local $$147) - ) - (set_local $$q_sroa_0_1199 - (get_local $$149) - ) - (set_local $$r_sroa_1_1200 - (get_local $$r_sroa_1_4_extract_trunc) - ) - (set_local $$r_sroa_0_1201 - (get_local $$r_sroa_0_0_extract_trunc) - ) - (set_local $$sr_1202 - (get_local $$155) - ) - (set_local $$carry_0203 - (get_local $$152) - ) - ) + (i64.shl + (i64.extend_u/i32 + (get_local $$b$1) ) - (br $while-in$3) - ) - (set_local $$q_sroa_1_1_lcssa - (get_local $$147) + (i64.const 32) ) - (set_local $$q_sroa_0_1_lcssa - (get_local $$149) - ) - (set_local $$r_sroa_1_1_lcssa - (get_local $$r_sroa_1_4_extract_trunc) - ) - (set_local $$r_sroa_0_1_lcssa - (get_local $$r_sroa_0_0_extract_trunc) - ) - (set_local $$carry_0_lcssa$1 - (i32.const 0) - ) - (set_local $$carry_0_lcssa$0 - (get_local $$152) - ) - ) - ) - (set_local $$q_sroa_0_0_insert_ext75$0 - (get_local $$q_sroa_0_1_lcssa) - ) - (set_local $$q_sroa_0_0_insert_ext75$1 - (i32.const 0) - ) - (set_local $$q_sroa_0_0_insert_insert77$1 - (i32.or - (get_local $$q_sroa_1_1_lcssa) - (get_local $$q_sroa_0_0_insert_ext75$1) ) ) (if - (i32.ne + (get_local $$rem) + (i64.store (get_local $$rem) - (i32.const 0) - ) - (block - (i32.store - (get_local $$rem) - (i32.or - (i32.const 0) - (get_local $$r_sroa_0_1_lcssa) - ) - ) - (i32.store offset=4 - (get_local $$rem) - (get_local $$r_sroa_1_1_lcssa) + (i64.rem_u + (get_local $x64) + (get_local $y64) ) ) ) - (set_local $$_0$1 - (i32.or - (i32.or - (i32.or - (i32.shr_u - (i32.or - (i32.const 0) - (get_local $$q_sroa_0_0_insert_ext75$0) - ) - (i32.const 31) - ) - (i32.shl - (get_local $$q_sroa_0_0_insert_insert77$1) - (i32.const 1) - ) - ) - (i32.and - (i32.or - (i32.shl - (get_local $$q_sroa_0_0_insert_ext75$1) - (i32.const 1) - ) - (i32.shr_u - (get_local $$q_sroa_0_0_insert_ext75$0) - (i32.const 31) - ) - ) - (i32.const 0) - ) - ) - (get_local $$carry_0_lcssa$1) - ) - ) - (set_local $$_0$0 - (i32.or - (i32.and - (i32.or - (i32.shl - (get_local $$q_sroa_0_0_insert_ext75$0) - (i32.const 1) - ) - (i32.shr_u - (i32.const 0) - (i32.const 31) + (i32.store + (i32.const 168) + (i32.wrap/i64 + (i64.shr_u + (set_local $x64 + (i64.div_u + (get_local $x64) + (get_local $y64) ) ) - (i32.const -2) + (i64.const 32) ) - (get_local $$carry_0_lcssa$0) ) ) - (return - (block - (i32.store - (i32.const 168) - (get_local $$_0$1) - ) - (get_local $$_0$0) - ) + (i32.wrap/i64 + (get_local $x64) ) ) (func $dynCall_ii (param $index i32) (param $a1 i32) (result i32) diff --git a/test/emcc_hello_world.fromasm.imprecise b/test/emcc_hello_world.fromasm.imprecise index fc4418930..75ec71e5d 100644 --- a/test/emcc_hello_world.fromasm.imprecise +++ b/test/emcc_hello_world.fromasm.imprecise @@ -48,6 +48,7 @@ (export "dynCall_ii" $dynCall_ii) (export "dynCall_iiii" $dynCall_iiii) (export "dynCall_vi" $dynCall_vi) + (export "___udivmoddi4" $___udivmoddi4) (table $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $___stdio_write $b1 $b1 $b1 $b2 $b2 $b2 $b2 $b2 $_cleanup $b2 $b2) (func $stackAlloc (param $size i32) (result i32) (local $ret i32) @@ -28140,13 +28141,11 @@ ) ) (loop $while-out$0 $while-in$1 - (if - (i32.lt_s + (br_if $while-out$0 + (i32.ge_s (get_local $ptr) (get_local $unaligned) ) - (nop) - (br $while-out$0) ) (i32.store8 (get_local $ptr) @@ -28163,13 +28162,11 @@ ) ) (loop $while-out$2 $while-in$3 - (if - (i32.lt_s + (br_if $while-out$2 + (i32.ge_s (get_local $ptr) (get_local $stop4) ) - (nop) - (br $while-out$2) ) (i32.store (get_local $ptr) @@ -28186,13 +28183,11 @@ ) ) (loop $while-out$4 $while-in$5 - (if - (i32.lt_s + (br_if $while-out$4 + (i32.ge_s (get_local $ptr) (get_local $stop) ) - (nop) - (br $while-out$4) ) (i32.store8 (get_local $ptr) @@ -28366,13 +28361,13 @@ ) (block (loop $while-out$0 $while-in$1 - (if - (i32.and - (get_local $dest) - (i32.const 3) + (br_if $while-out$0 + (i32.eqz + (i32.and + (get_local $dest) + (i32.const 3) + ) ) - (nop) - (br $while-out$0) ) (if (i32.eq @@ -28410,13 +28405,11 @@ (br $while-in$1) ) (loop $while-out$2 $while-in$3 - (if - (i32.ge_s + (br_if $while-out$2 + (i32.lt_s (get_local $num) (i32.const 4) ) - (nop) - (br $while-out$2) ) (i32.store (get_local $dest) @@ -28447,13 +28440,11 @@ ) ) (loop $while-out$4 $while-in$5 - (if - (i32.gt_s + (br_if $while-out$4 + (i32.le_s (get_local $num) (i32.const 0) ) - (nop) - (br $while-out$4) ) (i32.store8 (get_local $dest) @@ -28550,100 +28541,6 @@ ) ) ) - (func $_llvm_cttz_i32 (param $x i32) (result i32) - (local $ret i32) - (if - (i32.lt_s - (set_local $ret - (i32.load8_s - (i32.add - (i32.load - (i32.const 40) - ) - (i32.and - (get_local $x) - (i32.const 255) - ) - ) - ) - ) - (i32.const 8) - ) - (return - (get_local $ret) - ) - ) - (if - (i32.lt_s - (set_local $ret - (i32.load8_s - (i32.add - (i32.load - (i32.const 40) - ) - (i32.and - (i32.shr_s - (get_local $x) - (i32.const 8) - ) - (i32.const 255) - ) - ) - ) - ) - (i32.const 8) - ) - (return - (i32.add - (get_local $ret) - (i32.const 8) - ) - ) - ) - (if - (i32.lt_s - (set_local $ret - (i32.load8_s - (i32.add - (i32.load - (i32.const 40) - ) - (i32.and - (i32.shr_s - (get_local $x) - (i32.const 16) - ) - (i32.const 255) - ) - ) - ) - ) - (i32.const 8) - ) - (return - (i32.add - (get_local $ret) - (i32.const 16) - ) - ) - ) - (return - (i32.add - (i32.load8_s - (i32.add - (i32.load - (i32.const 40) - ) - (i32.shr_u - (get_local $x) - (i32.const 24) - ) - ) - ) - (i32.const 24) - ) - ) - ) (func $___muldsi3 (param $$a i32) (param $$b i32) (result i32) (local $$8 i32) (local $$6 i32) @@ -29238,1209 +29135,60 @@ ) ) (func $___udivmoddi4 (param $$a$0 i32) (param $$a$1 i32) (param $$b$0 i32) (param $$b$1 i32) (param $$rem i32) (result i32) - (local $$_0$1 i32) - (local $$_0$0 i32) - (local $$n_sroa_1_4_extract_trunc i32) - (local $$n_sroa_0_0_extract_trunc i32) - (local $$d_sroa_0_0_extract_trunc i32) - (local $$d_sroa_1_4_extract_trunc i32) - (local $$88 i32) - (local $$sr_1_ph i32) - (local $$r_sroa_1_1_ph i32) - (local $$r_sroa_0_1_ph i32) - (local $$q_sroa_1_1_ph i32) - (local $$q_sroa_0_1_ph i32) - (local $$r_sroa_0_1201 i32) - (local $$q_sroa_1_1198 i32) - (local $$q_sroa_0_1199 i32) - (local $$q_sroa_0_0_insert_ext75$0 i32) - (local $$n_sroa_1_4_extract_shift$0 i32) - (local $$91 i32) - (local $$78 i32) - (local $$57 i32) - (local $$150$1 i32) - (local $$125 i32) - (local $$119 i32) - (local $$sr_1202 i32) - (local $$r_sroa_1_4_extract_trunc i32) - (local $$r_sroa_1_1_lcssa i32) - (local $$r_sroa_1_1200 i32) - (local $$r_sroa_0_1_lcssa i32) - (local $$r_sroa_0_0_insert_insert42$1 i32) - (local $$r_sroa_0_0_insert_insert42$0 i32) - (local $$r_sroa_0_0_extract_trunc i32) - (local $$q_sroa_1_1_lcssa i32) - (local $$q_sroa_0_1_lcssa i32) - (local $$q_sroa_0_0_insert_ext75$1 i32) - (local $$d_sroa_0_0_insert_insert99$1 i32) - (local $$d_sroa_0_0_insert_insert99$0 i32) - (local $$carry_0_lcssa$1 i32) - (local $$carry_0_lcssa$0 i32) - (local $$carry_0203 i32) - (local $$95 i32) - (local $$92 i32) - (local $$89 i32) - (local $$58 i32) - (local $$51 i32) - (local $$4 i32) - (local $$17 i32) - (local $$152 i32) - (local $$149 i32) - (local $$147 i32) - (local $$130 i32) - (local $$126 i32) - (local $$105 i32) - (local $$q_sroa_0_0_insert_insert77$1 i32) - (local $$d_sroa_1_4_extract_shift$0 i32) - (local $$66 i32) - (local $$37 i32) - (local $$155 i32) - (local $$151$0 i32) - (local $$137$1 i32) - (local $$137$0 i32) - (local $$86 i32) - (local $$49 i32) - (local $$154$0 i32) - (local $$117 i32) - (set_local $$n_sroa_0_0_extract_trunc - (get_local $$a$0) - ) - (set_local $$n_sroa_1_4_extract_trunc - (set_local $$n_sroa_1_4_extract_shift$0 - (get_local $$a$1) - ) - ) - (set_local $$d_sroa_0_0_extract_trunc - (get_local $$b$0) - ) - (set_local $$d_sroa_1_4_extract_trunc - (set_local $$d_sroa_1_4_extract_shift$0 - (get_local $$b$1) - ) - ) - (if - (i32.eq - (get_local $$n_sroa_1_4_extract_trunc) - (i32.const 0) - ) - (block - (set_local $$4 - (i32.ne - (get_local $$rem) - (i32.const 0) - ) - ) - (if - (i32.eq - (get_local $$d_sroa_1_4_extract_trunc) - (i32.const 0) - ) - (block - (if - (get_local $$4) - (block - (i32.store - (get_local $$rem) - (i32.rem_u - (get_local $$n_sroa_0_0_extract_trunc) - (get_local $$d_sroa_0_0_extract_trunc) - ) - ) - (i32.store offset=4 - (get_local $$rem) - (i32.const 0) - ) - ) - ) - (set_local $$_0$1 - (i32.const 0) - ) - (set_local $$_0$0 - (i32.div_u - (get_local $$n_sroa_0_0_extract_trunc) - (get_local $$d_sroa_0_0_extract_trunc) - ) - ) - (return - (block - (i32.store - (i32.const 168) - (get_local $$_0$1) - ) - (get_local $$_0$0) - ) - ) - ) - (block - (if - (i32.eqz - (get_local $$4) - ) - (block - (set_local $$_0$1 - (i32.const 0) - ) - (set_local $$_0$0 - (i32.const 0) - ) - (return - (block - (i32.store - (i32.const 168) - (get_local $$_0$1) - ) - (get_local $$_0$0) - ) - ) - ) - ) - (i32.store - (get_local $$rem) - (i32.and - (get_local $$a$0) - (i32.const -1) - ) - ) - (i32.store offset=4 - (get_local $$rem) - (i32.and - (get_local $$a$1) - (i32.const 0) - ) - ) - (set_local $$_0$1 - (i32.const 0) - ) - (set_local $$_0$0 - (i32.const 0) - ) - (return - (block - (i32.store - (i32.const 168) - (get_local $$_0$1) - ) - (get_local $$_0$0) - ) - ) - ) - ) - ) - ) - (set_local $$17 - (i32.eq - (get_local $$d_sroa_1_4_extract_trunc) - (i32.const 0) - ) - ) - (block $do-once$0 - (if - (i32.eq - (get_local $$d_sroa_0_0_extract_trunc) - (i32.const 0) - ) - (block - (if - (get_local $$17) - (block - (if - (i32.ne - (get_local $$rem) - (i32.const 0) - ) - (block - (i32.store - (get_local $$rem) - (i32.rem_u - (get_local $$n_sroa_1_4_extract_trunc) - (get_local $$d_sroa_0_0_extract_trunc) - ) - ) - (i32.store offset=4 - (get_local $$rem) - (i32.const 0) - ) - ) - ) - (set_local $$_0$1 - (i32.const 0) - ) - (set_local $$_0$0 - (i32.div_u - (get_local $$n_sroa_1_4_extract_trunc) - (get_local $$d_sroa_0_0_extract_trunc) - ) - ) - (return - (block - (i32.store - (i32.const 168) - (get_local $$_0$1) - ) - (get_local $$_0$0) - ) - ) - ) - ) - (if - (i32.eq - (get_local $$n_sroa_0_0_extract_trunc) - (i32.const 0) - ) - (block - (if - (i32.ne - (get_local $$rem) - (i32.const 0) - ) - (block - (i32.store - (get_local $$rem) - (i32.const 0) - ) - (i32.store offset=4 - (get_local $$rem) - (i32.rem_u - (get_local $$n_sroa_1_4_extract_trunc) - (get_local $$d_sroa_1_4_extract_trunc) - ) - ) - ) - ) - (set_local $$_0$1 - (i32.const 0) - ) - (set_local $$_0$0 - (i32.div_u - (get_local $$n_sroa_1_4_extract_trunc) - (get_local $$d_sroa_1_4_extract_trunc) - ) - ) - (return - (block - (i32.store - (i32.const 168) - (get_local $$_0$1) - ) - (get_local $$_0$0) - ) - ) - ) - ) - (if - (i32.eq - (i32.and - (set_local $$37 - (i32.sub - (get_local $$d_sroa_1_4_extract_trunc) - (i32.const 1) - ) - ) - (get_local $$d_sroa_1_4_extract_trunc) - ) - (i32.const 0) - ) - (block - (if - (i32.ne - (get_local $$rem) - (i32.const 0) - ) - (block - (i32.store - (get_local $$rem) - (i32.or - (i32.const 0) - (i32.and - (get_local $$a$0) - (i32.const -1) - ) - ) - ) - (i32.store offset=4 - (get_local $$rem) - (i32.or - (i32.and - (get_local $$37) - (get_local $$n_sroa_1_4_extract_trunc) - ) - (i32.and - (get_local $$a$1) - (i32.const 0) - ) - ) - ) - ) - ) - (set_local $$_0$1 - (i32.const 0) - ) - (set_local $$_0$0 - (i32.shr_u - (get_local $$n_sroa_1_4_extract_trunc) - (call $_llvm_cttz_i32 - (get_local $$d_sroa_1_4_extract_trunc) - ) - ) - ) - (return - (block - (i32.store - (i32.const 168) - (get_local $$_0$1) - ) - (get_local $$_0$0) - ) - ) - ) - ) - (if - (i32.le_u - (set_local $$51 - (i32.sub - (set_local $$49 - (i32.clz - (get_local $$d_sroa_1_4_extract_trunc) - ) - ) - (i32.clz - (get_local $$n_sroa_1_4_extract_trunc) - ) - ) - ) - (i32.const 30) - ) - (block - (set_local $$57 - (i32.add - (get_local $$51) - (i32.const 1) - ) - ) - (set_local $$58 - (i32.sub - (i32.const 31) - (get_local $$51) - ) - ) - (set_local $$sr_1_ph - (get_local $$57) - ) - (set_local $$r_sroa_0_1_ph - (i32.or - (i32.shl - (get_local $$n_sroa_1_4_extract_trunc) - (get_local $$58) - ) - (i32.shr_u - (get_local $$n_sroa_0_0_extract_trunc) - (get_local $$57) - ) - ) - ) - (set_local $$r_sroa_1_1_ph - (i32.shr_u - (get_local $$n_sroa_1_4_extract_trunc) - (get_local $$57) - ) - ) - (set_local $$q_sroa_0_1_ph - (i32.const 0) - ) - (set_local $$q_sroa_1_1_ph - (i32.shl - (get_local $$n_sroa_0_0_extract_trunc) - (get_local $$58) - ) - ) - (br $do-once$0) - ) - ) - (if - (i32.eq - (get_local $$rem) - (i32.const 0) - ) - (block - (set_local $$_0$1 - (i32.const 0) - ) - (set_local $$_0$0 - (i32.const 0) - ) - (return - (block - (i32.store - (i32.const 168) - (get_local $$_0$1) - ) - (get_local $$_0$0) - ) - ) - ) - ) - (i32.store - (get_local $$rem) - (i32.or - (i32.const 0) - (i32.and - (get_local $$a$0) - (i32.const -1) - ) - ) - ) - (i32.store offset=4 - (get_local $$rem) - (i32.or - (get_local $$n_sroa_1_4_extract_shift$0) - (i32.and - (get_local $$a$1) - (i32.const 0) - ) - ) - ) - (set_local $$_0$1 - (i32.const 0) - ) - (set_local $$_0$0 - (i32.const 0) - ) - (return - (block - (i32.store - (i32.const 168) - (get_local $$_0$1) - ) - (get_local $$_0$0) - ) - ) + (local $x64 i64) + (local $y64 i64) + (set_local $x64 + (i64.or + (i64.extend_u/i32 + (get_local $$a$0) ) - (block - (if - (i32.eqz - (get_local $$17) - ) - (block - (if - (i32.le_u - (set_local $$119 - (i32.sub - (set_local $$117 - (i32.clz - (get_local $$d_sroa_1_4_extract_trunc) - ) - ) - (i32.clz - (get_local $$n_sroa_1_4_extract_trunc) - ) - ) - ) - (i32.const 31) - ) - (block - (set_local $$125 - (i32.add - (get_local $$119) - (i32.const 1) - ) - ) - (set_local $$126 - (i32.sub - (i32.const 31) - (get_local $$119) - ) - ) - (set_local $$130 - (i32.shr_s - (i32.sub - (get_local $$119) - (i32.const 31) - ) - (i32.const 31) - ) - ) - (set_local $$sr_1_ph - (get_local $$125) - ) - (set_local $$r_sroa_0_1_ph - (i32.or - (i32.and - (i32.shr_u - (get_local $$n_sroa_0_0_extract_trunc) - (get_local $$125) - ) - (get_local $$130) - ) - (i32.shl - (get_local $$n_sroa_1_4_extract_trunc) - (get_local $$126) - ) - ) - ) - (set_local $$r_sroa_1_1_ph - (i32.and - (i32.shr_u - (get_local $$n_sroa_1_4_extract_trunc) - (get_local $$125) - ) - (get_local $$130) - ) - ) - (set_local $$q_sroa_0_1_ph - (i32.const 0) - ) - (set_local $$q_sroa_1_1_ph - (i32.shl - (get_local $$n_sroa_0_0_extract_trunc) - (get_local $$126) - ) - ) - (br $do-once$0) - ) - ) - (if - (i32.eq - (get_local $$rem) - (i32.const 0) - ) - (block - (set_local $$_0$1 - (i32.const 0) - ) - (set_local $$_0$0 - (i32.const 0) - ) - (return - (block - (i32.store - (i32.const 168) - (get_local $$_0$1) - ) - (get_local $$_0$0) - ) - ) - ) - ) - (i32.store - (get_local $$rem) - (i32.or - (i32.const 0) - (i32.and - (get_local $$a$0) - (i32.const -1) - ) - ) - ) - (i32.store offset=4 - (get_local $$rem) - (i32.or - (get_local $$n_sroa_1_4_extract_shift$0) - (i32.and - (get_local $$a$1) - (i32.const 0) - ) - ) - ) - (set_local $$_0$1 - (i32.const 0) - ) - (set_local $$_0$0 - (i32.const 0) - ) - (return - (block - (i32.store - (i32.const 168) - (get_local $$_0$1) - ) - (get_local $$_0$0) - ) - ) - ) - ) - (if - (i32.ne - (i32.and - (set_local $$66 - (i32.sub - (get_local $$d_sroa_0_0_extract_trunc) - (i32.const 1) - ) - ) - (get_local $$d_sroa_0_0_extract_trunc) - ) - (i32.const 0) - ) - (block - (set_local $$89 - (i32.sub - (i32.const 64) - (set_local $$88 - (i32.sub - (set_local $$86 - (i32.add - (i32.clz - (get_local $$d_sroa_0_0_extract_trunc) - ) - (i32.const 33) - ) - ) - (i32.clz - (get_local $$n_sroa_1_4_extract_trunc) - ) - ) - ) - ) - ) - (set_local $$92 - (i32.shr_s - (set_local $$91 - (i32.sub - (i32.const 32) - (get_local $$88) - ) - ) - (i32.const 31) - ) - ) - (set_local $$105 - (i32.shr_s - (set_local $$95 - (i32.sub - (get_local $$88) - (i32.const 32) - ) - ) - (i32.const 31) - ) - ) - (set_local $$sr_1_ph - (get_local $$88) - ) - (set_local $$r_sroa_0_1_ph - (i32.or - (i32.and - (i32.shr_s - (i32.sub - (get_local $$91) - (i32.const 1) - ) - (i32.const 31) - ) - (i32.shr_u - (get_local $$n_sroa_1_4_extract_trunc) - (get_local $$95) - ) - ) - (i32.and - (i32.or - (i32.shl - (get_local $$n_sroa_1_4_extract_trunc) - (get_local $$91) - ) - (i32.shr_u - (get_local $$n_sroa_0_0_extract_trunc) - (get_local $$88) - ) - ) - (get_local $$105) - ) - ) - ) - (set_local $$r_sroa_1_1_ph - (i32.and - (get_local $$105) - (i32.shr_u - (get_local $$n_sroa_1_4_extract_trunc) - (get_local $$88) - ) - ) - ) - (set_local $$q_sroa_0_1_ph - (i32.and - (i32.shl - (get_local $$n_sroa_0_0_extract_trunc) - (get_local $$89) - ) - (get_local $$92) - ) - ) - (set_local $$q_sroa_1_1_ph - (i32.or - (i32.and - (i32.or - (i32.shl - (get_local $$n_sroa_1_4_extract_trunc) - (get_local $$89) - ) - (i32.shr_u - (get_local $$n_sroa_0_0_extract_trunc) - (get_local $$95) - ) - ) - (get_local $$92) - ) - (i32.and - (i32.shl - (get_local $$n_sroa_0_0_extract_trunc) - (get_local $$91) - ) - (i32.shr_s - (i32.sub - (get_local $$88) - (i32.const 33) - ) - (i32.const 31) - ) - ) - ) - ) - (br $do-once$0) - ) - ) - (if - (i32.ne - (get_local $$rem) - (i32.const 0) - ) - (block - (i32.store - (get_local $$rem) - (i32.and - (get_local $$66) - (get_local $$n_sroa_0_0_extract_trunc) - ) - ) - (i32.store offset=4 - (get_local $$rem) - (i32.const 0) - ) - ) - ) - (if - (i32.eq - (get_local $$d_sroa_0_0_extract_trunc) - (i32.const 1) - ) - (block - (set_local $$_0$1 - (i32.or - (get_local $$n_sroa_1_4_extract_shift$0) - (i32.and - (get_local $$a$1) - (i32.const 0) - ) - ) - ) - (set_local $$_0$0 - (i32.or - (i32.const 0) - (i32.and - (get_local $$a$0) - (i32.const -1) - ) - ) - ) - (return - (block - (i32.store - (i32.const 168) - (get_local $$_0$1) - ) - (get_local $$_0$0) - ) - ) - ) - (block - (set_local $$78 - (call $_llvm_cttz_i32 - (get_local $$d_sroa_0_0_extract_trunc) - ) - ) - (set_local $$_0$1 - (i32.or - (i32.const 0) - (i32.shr_u - (get_local $$n_sroa_1_4_extract_trunc) - (get_local $$78) - ) - ) - ) - (set_local $$_0$0 - (i32.or - (i32.shl - (get_local $$n_sroa_1_4_extract_trunc) - (i32.sub - (i32.const 32) - (get_local $$78) - ) - ) - (i32.shr_u - (get_local $$n_sroa_0_0_extract_trunc) - (get_local $$78) - ) - ) - ) - (return - (block - (i32.store - (i32.const 168) - (get_local $$_0$1) - ) - (get_local $$_0$0) - ) - ) - ) + (i64.shl + (i64.extend_u/i32 + (get_local $$a$1) ) + (i64.const 32) ) ) ) - (if - (i32.eq - (get_local $$sr_1_ph) - (i32.const 0) - ) - (block - (set_local $$q_sroa_1_1_lcssa - (get_local $$q_sroa_1_1_ph) - ) - (set_local $$q_sroa_0_1_lcssa - (get_local $$q_sroa_0_1_ph) - ) - (set_local $$r_sroa_1_1_lcssa - (get_local $$r_sroa_1_1_ph) - ) - (set_local $$r_sroa_0_1_lcssa - (get_local $$r_sroa_0_1_ph) - ) - (set_local $$carry_0_lcssa$1 - (i32.const 0) - ) - (set_local $$carry_0_lcssa$0 - (i32.const 0) - ) - ) - (block - (set_local $$d_sroa_0_0_insert_insert99$0 - (i32.or - (i32.const 0) - (i32.and - (get_local $$b$0) - (i32.const -1) - ) - ) - ) - (set_local $$d_sroa_0_0_insert_insert99$1 - (i32.or - (get_local $$d_sroa_1_4_extract_shift$0) - (i32.and - (get_local $$b$1) - (i32.const 0) - ) - ) - ) - (set_local $$137$0 - (call $_i64Add - (get_local $$d_sroa_0_0_insert_insert99$0) - (get_local $$d_sroa_0_0_insert_insert99$1) - (i32.const -1) - (i32.const -1) - ) - ) - (set_local $$137$1 - (i32.load - (i32.const 168) - ) - ) - (set_local $$q_sroa_1_1198 - (get_local $$q_sroa_1_1_ph) - ) - (set_local $$q_sroa_0_1199 - (get_local $$q_sroa_0_1_ph) - ) - (set_local $$r_sroa_1_1200 - (get_local $$r_sroa_1_1_ph) - ) - (set_local $$r_sroa_0_1201 - (get_local $$r_sroa_0_1_ph) - ) - (set_local $$sr_1202 - (get_local $$sr_1_ph) - ) - (set_local $$carry_0203 - (i32.const 0) + (set_local $y64 + (i64.or + (i64.extend_u/i32 + (get_local $$b$0) ) - (loop $while-out$2 $while-in$3 - (set_local $$147 - (i32.or - (i32.shr_u - (get_local $$q_sroa_0_1199) - (i32.const 31) - ) - (i32.shl - (get_local $$q_sroa_1_1198) - (i32.const 1) - ) - ) - ) - (set_local $$149 - (i32.or - (get_local $$carry_0203) - (i32.shl - (get_local $$q_sroa_0_1199) - (i32.const 1) - ) - ) - ) - (set_local $$r_sroa_0_0_insert_insert42$0 - (i32.or - (i32.const 0) - (i32.or - (i32.shl - (get_local $$r_sroa_0_1201) - (i32.const 1) - ) - (i32.shr_u - (get_local $$q_sroa_1_1198) - (i32.const 31) - ) - ) - ) - ) - (set_local $$r_sroa_0_0_insert_insert42$1 - (i32.or - (i32.shr_u - (get_local $$r_sroa_0_1201) - (i32.const 31) - ) - (i32.shl - (get_local $$r_sroa_1_1200) - (i32.const 1) - ) - ) - ) - (call $_i64Subtract - (get_local $$137$0) - (get_local $$137$1) - (get_local $$r_sroa_0_0_insert_insert42$0) - (get_local $$r_sroa_0_0_insert_insert42$1) - ) - (set_local $$152 - (i32.and - (set_local $$151$0 - (i32.or - (i32.shr_s - (set_local $$150$1 - (i32.load - (i32.const 168) - ) - ) - (i32.const 31) - ) - (i32.shl - (if - (i32.lt_s - (get_local $$150$1) - (i32.const 0) - ) - (i32.const -1) - (i32.const 0) - ) - (i32.const 1) - ) - ) - ) - (i32.const 1) - ) - ) - (set_local $$r_sroa_0_0_extract_trunc - (set_local $$154$0 - (call $_i64Subtract - (get_local $$r_sroa_0_0_insert_insert42$0) - (get_local $$r_sroa_0_0_insert_insert42$1) - (i32.and - (get_local $$151$0) - (get_local $$d_sroa_0_0_insert_insert99$0) - ) - (i32.and - (i32.or - (i32.shr_s - (if - (i32.lt_s - (get_local $$150$1) - (i32.const 0) - ) - (i32.const -1) - (i32.const 0) - ) - (i32.const 31) - ) - (i32.shl - (if - (i32.lt_s - (get_local $$150$1) - (i32.const 0) - ) - (i32.const -1) - (i32.const 0) - ) - (i32.const 1) - ) - ) - (get_local $$d_sroa_0_0_insert_insert99$1) - ) - ) - ) - ) - (set_local $$r_sroa_1_4_extract_trunc - (i32.load - (i32.const 168) - ) - ) - (if - (i32.eq - (set_local $$155 - (i32.sub - (get_local $$sr_1202) - (i32.const 1) - ) - ) - (i32.const 0) - ) - (br $while-out$2) - (block - (set_local $$q_sroa_1_1198 - (get_local $$147) - ) - (set_local $$q_sroa_0_1199 - (get_local $$149) - ) - (set_local $$r_sroa_1_1200 - (get_local $$r_sroa_1_4_extract_trunc) - ) - (set_local $$r_sroa_0_1201 - (get_local $$r_sroa_0_0_extract_trunc) - ) - (set_local $$sr_1202 - (get_local $$155) - ) - (set_local $$carry_0203 - (get_local $$152) - ) - ) + (i64.shl + (i64.extend_u/i32 + (get_local $$b$1) ) - (br $while-in$3) - ) - (set_local $$q_sroa_1_1_lcssa - (get_local $$147) + (i64.const 32) ) - (set_local $$q_sroa_0_1_lcssa - (get_local $$149) - ) - (set_local $$r_sroa_1_1_lcssa - (get_local $$r_sroa_1_4_extract_trunc) - ) - (set_local $$r_sroa_0_1_lcssa - (get_local $$r_sroa_0_0_extract_trunc) - ) - (set_local $$carry_0_lcssa$1 - (i32.const 0) - ) - (set_local $$carry_0_lcssa$0 - (get_local $$152) - ) - ) - ) - (set_local $$q_sroa_0_0_insert_ext75$0 - (get_local $$q_sroa_0_1_lcssa) - ) - (set_local $$q_sroa_0_0_insert_ext75$1 - (i32.const 0) - ) - (set_local $$q_sroa_0_0_insert_insert77$1 - (i32.or - (get_local $$q_sroa_1_1_lcssa) - (get_local $$q_sroa_0_0_insert_ext75$1) ) ) (if - (i32.ne + (get_local $$rem) + (i64.store (get_local $$rem) - (i32.const 0) - ) - (block - (i32.store - (get_local $$rem) - (i32.or - (i32.const 0) - (get_local $$r_sroa_0_1_lcssa) - ) - ) - (i32.store offset=4 - (get_local $$rem) - (get_local $$r_sroa_1_1_lcssa) + (i64.rem_u + (get_local $x64) + (get_local $y64) ) ) ) - (set_local $$_0$1 - (i32.or - (i32.or - (i32.or - (i32.shr_u - (i32.or - (i32.const 0) - (get_local $$q_sroa_0_0_insert_ext75$0) - ) - (i32.const 31) - ) - (i32.shl - (get_local $$q_sroa_0_0_insert_insert77$1) - (i32.const 1) - ) - ) - (i32.and - (i32.or - (i32.shl - (get_local $$q_sroa_0_0_insert_ext75$1) - (i32.const 1) - ) - (i32.shr_u - (get_local $$q_sroa_0_0_insert_ext75$0) - (i32.const 31) - ) - ) - (i32.const 0) - ) - ) - (get_local $$carry_0_lcssa$1) - ) - ) - (set_local $$_0$0 - (i32.or - (i32.and - (i32.or - (i32.shl - (get_local $$q_sroa_0_0_insert_ext75$0) - (i32.const 1) - ) - (i32.shr_u - (i32.const 0) - (i32.const 31) + (i32.store + (i32.const 168) + (i32.wrap/i64 + (i64.shr_u + (set_local $x64 + (i64.div_u + (get_local $x64) + (get_local $y64) ) ) - (i32.const -2) + (i64.const 32) ) - (get_local $$carry_0_lcssa$0) ) ) - (return - (block - (i32.store - (i32.const 168) - (get_local $$_0$1) - ) - (get_local $$_0$0) - ) + (i32.wrap/i64 + (get_local $x64) ) ) (func $dynCall_ii (param $index i32) (param $a1 i32) (result i32) diff --git a/test/memorygrowth.fromasm b/test/memorygrowth.fromasm index 99ae1f394..872ac6db1 100644 --- a/test/memorygrowth.fromasm +++ b/test/memorygrowth.fromasm @@ -9609,13 +9609,13 @@ ) (block (loop $while-out$0 $while-in$1 - (if - (i32.and - (get_local $a) - (i32.const 3) + (br_if $while-out$0 + (i32.eqz + (i32.and + (get_local $a) + (i32.const 3) + ) ) - (nop) - (br $while-out$0) ) (if (i32.eqz @@ -9652,13 +9652,11 @@ (br $while-in$1) ) (loop $while-out$2 $while-in$3 - (if - (i32.ge_s + (br_if $while-out$2 + (i32.lt_s (get_local $c) (i32.const 4) ) - (nop) - (br $while-out$2) ) (i32.store (get_local $a) @@ -9689,13 +9687,11 @@ ) ) (loop $while-out$4 $while-in$5 - (if - (i32.gt_s + (br_if $while-out$4 + (i32.le_s (get_local $c) (i32.const 0) ) - (nop) - (br $while-out$4) ) (i32.store8 (get_local $a) @@ -9802,13 +9798,11 @@ ) ) (loop $while-out$0 $while-in$1 - (if - (i32.lt_s + (br_if $while-out$0 + (i32.ge_s (get_local $a) (get_local $e) ) - (nop) - (br $while-out$0) ) (i32.store8 (get_local $a) @@ -9825,13 +9819,11 @@ ) ) (loop $while-out$2 $while-in$3 - (if - (i32.lt_s + (br_if $while-out$2 + (i32.ge_s (get_local $a) (get_local $g) ) - (nop) - (br $while-out$2) ) (i32.store (get_local $a) @@ -9848,13 +9840,11 @@ ) ) (loop $while-out$4 $while-in$5 - (if - (i32.lt_s + (br_if $while-out$4 + (i32.ge_s (get_local $a) (get_local $d) ) - (nop) - (br $while-out$4) ) (i32.store8 (get_local $a) diff --git a/test/memorygrowth.fromasm.imprecise b/test/memorygrowth.fromasm.imprecise index 99ae1f394..872ac6db1 100644 --- a/test/memorygrowth.fromasm.imprecise +++ b/test/memorygrowth.fromasm.imprecise @@ -9609,13 +9609,13 @@ ) (block (loop $while-out$0 $while-in$1 - (if - (i32.and - (get_local $a) - (i32.const 3) + (br_if $while-out$0 + (i32.eqz + (i32.and + (get_local $a) + (i32.const 3) + ) ) - (nop) - (br $while-out$0) ) (if (i32.eqz @@ -9652,13 +9652,11 @@ (br $while-in$1) ) (loop $while-out$2 $while-in$3 - (if - (i32.ge_s + (br_if $while-out$2 + (i32.lt_s (get_local $c) (i32.const 4) ) - (nop) - (br $while-out$2) ) (i32.store (get_local $a) @@ -9689,13 +9687,11 @@ ) ) (loop $while-out$4 $while-in$5 - (if - (i32.gt_s + (br_if $while-out$4 + (i32.le_s (get_local $c) (i32.const 0) ) - (nop) - (br $while-out$4) ) (i32.store8 (get_local $a) @@ -9802,13 +9798,11 @@ ) ) (loop $while-out$0 $while-in$1 - (if - (i32.lt_s + (br_if $while-out$0 + (i32.ge_s (get_local $a) (get_local $e) ) - (nop) - (br $while-out$0) ) (i32.store8 (get_local $a) @@ -9825,13 +9819,11 @@ ) ) (loop $while-out$2 $while-in$3 - (if - (i32.lt_s + (br_if $while-out$2 + (i32.ge_s (get_local $a) (get_local $g) ) - (nop) - (br $while-out$2) ) (i32.store (get_local $a) @@ -9848,13 +9840,11 @@ ) ) (loop $while-out$4 $while-in$5 - (if - (i32.lt_s + (br_if $while-out$4 + (i32.ge_s (get_local $a) (get_local $d) ) - (nop) - (br $while-out$4) ) (i32.store8 (get_local $a) diff --git a/test/min.asm.js b/test/min.asm.js index ed5d186f5..b72002f97 100644 --- a/test/min.asm.js +++ b/test/min.asm.js @@ -7,6 +7,7 @@ function (global, env, buffer) { var fr = global.Math.fround; var tDP = env.tempDoublePtr | 0; + var ctz32 = env._llvm_cttz_i32; var h8 = new global.Int8Array(buffer); var h16 = new global.Int16Array(buffer); @@ -36,6 +37,9 @@ function (global, env, buffer) { (h32[tDP >> 2] = i, +hF32[tDP >> 2]); // i32->f32, no fround (hF32[tDP >> 2] = f, h32[tDP >> 2] | 0); // f32->i32 } + function ctzzzz() { + return ctz32(0x1234) | 0; + } return { floats: floats }; } diff --git a/test/min.fromasm b/test/min.fromasm index 199056e42..f4c170b62 100644 --- a/test/min.fromasm +++ b/test/min.fromasm @@ -42,4 +42,11 @@ (get_local $f) ) ) + (func $ctzzzz (result i32) + (return + (i32.ctz + (i32.const 4660) + ) + ) + ) ) diff --git a/test/min.fromasm.imprecise b/test/min.fromasm.imprecise index 199056e42..f4c170b62 100644 --- a/test/min.fromasm.imprecise +++ b/test/min.fromasm.imprecise @@ -42,4 +42,11 @@ (get_local $f) ) ) + (func $ctzzzz (result i32) + (return + (i32.ctz + (i32.const 4660) + ) + ) + ) ) diff --git a/test/passes/optimize-instructions.txt b/test/passes/optimize-instructions.txt index ea6e78908..c64115f49 100644 --- a/test/passes/optimize-instructions.txt +++ b/test/passes/optimize-instructions.txt @@ -19,5 +19,37 @@ (i32.const 11) (i32.const 12) ) + (i32.le_s + (i32.const 1) + (i32.const 2) + ) + (i32.lt_s + (i32.const 1) + (i32.const 2) + ) + (i32.ge_s + (i32.const 1) + (i32.const 2) + ) + (i32.gt_s + (i32.const 1) + (i32.const 2) + ) + (i32.le_u + (i32.const 1) + (i32.const 2) + ) + (i32.lt_u + (i32.const 1) + (i32.const 2) + ) + (i32.ge_u + (i32.const 1) + (i32.const 2) + ) + (i32.gt_u + (i32.const 1) + (i32.const 2) + ) ) ) diff --git a/test/passes/optimize-instructions.wast b/test/passes/optimize-instructions.wast index 058aee042..b579a2054 100644 --- a/test/passes/optimize-instructions.wast +++ b/test/passes/optimize-instructions.wast @@ -21,6 +21,14 @@ (i32.const 11) (i32.const 12) ) + (i32.eqz (i32.gt_s (i32.const 1) (i32.const 2))) + (i32.eqz (i32.ge_s (i32.const 1) (i32.const 2))) + (i32.eqz (i32.lt_s (i32.const 1) (i32.const 2))) + (i32.eqz (i32.le_s (i32.const 1) (i32.const 2))) + (i32.eqz (i32.gt_u (i32.const 1) (i32.const 2))) + (i32.eqz (i32.ge_u (i32.const 1) (i32.const 2))) + (i32.eqz (i32.lt_u (i32.const 1) (i32.const 2))) + (i32.eqz (i32.le_u (i32.const 1) (i32.const 2))) ) ) diff --git a/test/unit.fromasm b/test/unit.fromasm index 8a8b2ebd9..3d66f1c28 100644 --- a/test/unit.fromasm +++ b/test/unit.fromasm @@ -442,13 +442,11 @@ (i32.const 1) ) (loop $for-out$0 $for-in$1 - (if - (i32.lt_s + (br_if $for-out$0 + (i32.ge_s (get_local $i) (i32.const 200) ) - (nop) - (br $for-out$0) ) (call_import $h (get_local $i) diff --git a/test/unit.fromasm.imprecise b/test/unit.fromasm.imprecise index 677336c09..0c8da43e9 100644 --- a/test/unit.fromasm.imprecise +++ b/test/unit.fromasm.imprecise @@ -438,13 +438,11 @@ (i32.const 1) ) (loop $for-out$0 $for-in$1 - (if - (i32.lt_s + (br_if $for-out$0 + (i32.ge_s (get_local $i) (i32.const 200) ) - (nop) - (br $for-out$0) ) (call_import $h (get_local $i) |