| Index: src/compiler/wasm-compiler.cc
|
| diff --git a/src/compiler/wasm-compiler.cc b/src/compiler/wasm-compiler.cc
|
| index 7caaebc4b54dedd00bcda2932bec6b515f7934ef..716e17b34f304bb53bbe5cdeac55350b14e8005e 100644
|
| --- a/src/compiler/wasm-compiler.cc
|
| +++ b/src/compiler/wasm-compiler.cc
|
| @@ -1920,36 +1920,101 @@ Node* WasmGraphBuilder::BuildI32AsmjsDivS(Node* left, Node* right) {
|
| }
|
|
|
| Node* WasmGraphBuilder::BuildI32AsmjsRemS(Node* left, Node* right) {
|
| + CommonOperatorBuilder* c = jsgraph()->common();
|
| MachineOperatorBuilder* m = jsgraph()->machine();
|
| + Node* const zero = jsgraph()->Int32Constant(0);
|
|
|
| Int32Matcher mr(right);
|
| if (mr.HasValue()) {
|
| - if (mr.Value() == 0) {
|
| - return jsgraph()->Int32Constant(0);
|
| - } else if (mr.Value() == -1) {
|
| - return jsgraph()->Int32Constant(0);
|
| + if (mr.Value() == 0 || mr.Value() == -1) {
|
| + return zero;
|
| }
|
| return graph()->NewNode(m->Int32Mod(), left, right, *control_);
|
| }
|
|
|
| - // asm.js semantics return 0 on divide or mod by zero.
|
| - // Explicit check for x % 0.
|
| - Diamond z(
|
| - graph(), jsgraph()->common(),
|
| - graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)),
|
| - BranchHint::kFalse);
|
| + // General case for signed integer modulus, with optimization for (unknown)
|
| + // power of 2 right hand side.
|
| + //
|
| + // if 0 < right then
|
| + // msk = right - 1
|
| + // if right & msk != 0 then
|
| + // left % right
|
| + // else
|
| + // if left < 0 then
|
| + // -(-left & msk)
|
| + // else
|
| + // left & msk
|
| + // else
|
| + // if right < -1 then
|
| + // left % right
|
| + // else
|
| + // zero
|
| + //
|
| + // Note: We do not use the Diamond helper class here, because it really hurts
|
| + // readability with nested diamonds.
|
| + Node* const minus_one = jsgraph()->Int32Constant(-1);
|
|
|
| - // Explicit check for x % -1.
|
| - Diamond d(
|
| - graph(), jsgraph()->common(),
|
| - graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)),
|
| - BranchHint::kFalse);
|
| - d.Chain(z.if_false);
|
| + const Operator* const merge_op = c->Merge(2);
|
| + const Operator* const phi_op = c->Phi(MachineRepresentation::kWord32, 2);
|
| +
|
| + Node* check0 = graph()->NewNode(m->Int32LessThan(), zero, right);
|
| + Node* branch0 =
|
| + graph()->NewNode(c->Branch(BranchHint::kTrue), check0, graph()->start());
|
| +
|
| + Node* if_true0 = graph()->NewNode(c->IfTrue(), branch0);
|
| + Node* true0;
|
| + {
|
| + Node* msk = graph()->NewNode(m->Int32Add(), right, minus_one);
|
| +
|
| + Node* check1 = graph()->NewNode(m->Word32And(), right, msk);
|
| + Node* branch1 = graph()->NewNode(c->Branch(), check1, if_true0);
|
| +
|
| + Node* if_true1 = graph()->NewNode(c->IfTrue(), branch1);
|
| + Node* true1 = graph()->NewNode(m->Int32Mod(), left, right, if_true1);
|
| +
|
| + Node* if_false1 = graph()->NewNode(c->IfFalse(), branch1);
|
| + Node* false1;
|
| + {
|
| + Node* check2 = graph()->NewNode(m->Int32LessThan(), left, zero);
|
| + Node* branch2 =
|
| + graph()->NewNode(c->Branch(BranchHint::kFalse), check2, if_false1);
|
| +
|
| + Node* if_true2 = graph()->NewNode(c->IfTrue(), branch2);
|
| + Node* true2 = graph()->NewNode(
|
| + m->Int32Sub(), zero,
|
| + graph()->NewNode(m->Word32And(),
|
| + graph()->NewNode(m->Int32Sub(), zero, left), msk));
|
| +
|
| + Node* if_false2 = graph()->NewNode(c->IfFalse(), branch2);
|
| + Node* false2 = graph()->NewNode(m->Word32And(), left, msk);
|
| +
|
| + if_false1 = graph()->NewNode(merge_op, if_true2, if_false2);
|
| + false1 = graph()->NewNode(phi_op, true2, false2, if_false1);
|
| + }
|
| +
|
| + if_true0 = graph()->NewNode(merge_op, if_true1, if_false1);
|
| + true0 = graph()->NewNode(phi_op, true1, false1, if_true0);
|
| + }
|
| +
|
| + Node* if_false0 = graph()->NewNode(c->IfFalse(), branch0);
|
| + Node* false0;
|
| + {
|
| + Node* check1 = graph()->NewNode(m->Int32LessThan(), right, minus_one);
|
| + Node* branch1 =
|
| + graph()->NewNode(c->Branch(BranchHint::kTrue), check1, if_false0);
|
| +
|
| + Node* if_true1 = graph()->NewNode(c->IfTrue(), branch1);
|
| + Node* true1 = graph()->NewNode(m->Int32Mod(), left, right, if_true1);
|
| +
|
| + Node* if_false1 = graph()->NewNode(c->IfFalse(), branch1);
|
| + Node* false1 = zero;
|
| +
|
| + if_false0 = graph()->NewNode(merge_op, if_true1, if_false1);
|
| + false0 = graph()->NewNode(phi_op, true1, false1, if_false0);
|
| + }
|
|
|
| - return z.Phi(
|
| - MachineRepresentation::kWord32, jsgraph()->Int32Constant(0),
|
| - d.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0),
|
| - graph()->NewNode(m->Int32Mod(), left, right, d.if_false)));
|
| + Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0);
|
| + return graph()->NewNode(phi_op, true0, false0, merge0);
|
| }
|
|
|
| Node* WasmGraphBuilder::BuildI32AsmjsDivU(Node* left, Node* right) {
|
|
|