| Index: src/compiler/wasm-compiler.cc
|
| diff --git a/src/compiler/wasm-compiler.cc b/src/compiler/wasm-compiler.cc
|
| index bd98934b7a3f0c5e22fe4b83ea6471e394cb8a7d..2afefd719bcb0983306d068fda8626b0e727cb8d 100644
|
| --- a/src/compiler/wasm-compiler.cc
|
| +++ b/src/compiler/wasm-compiler.cc
|
| @@ -393,43 +393,14 @@ Node* WasmGraphBuilder::Binop(wasm::WasmOpcode opcode, Node* left,
|
| case wasm::kExprI32Mul:
|
| op = m->Int32Mul();
|
| break;
|
| - case wasm::kExprI32DivS: {
|
| - trap_->ZeroCheck32(kTrapDivByZero, right);
|
| - Node* before = *control_;
|
| - Node* denom_is_m1;
|
| - Node* denom_is_not_m1;
|
| - Branch(graph()->NewNode(jsgraph()->machine()->Word32Equal(), right,
|
| - jsgraph()->Int32Constant(-1)),
|
| - &denom_is_m1, &denom_is_not_m1);
|
| - *control_ = denom_is_m1;
|
| - trap_->TrapIfEq32(kTrapDivUnrepresentable, left, kMinInt);
|
| - if (*control_ != denom_is_m1) {
|
| - *control_ = graph()->NewNode(jsgraph()->common()->Merge(2),
|
| - denom_is_not_m1, *control_);
|
| - } else {
|
| - *control_ = before;
|
| - }
|
| - return graph()->NewNode(m->Int32Div(), left, right, *control_);
|
| - }
|
| + case wasm::kExprI32DivS:
|
| + return BuildI32DivS(left, right);
|
| case wasm::kExprI32DivU:
|
| - op = m->Uint32Div();
|
| - return graph()->NewNode(op, left, right,
|
| - trap_->ZeroCheck32(kTrapDivByZero, right));
|
| - case wasm::kExprI32RemS: {
|
| - trap_->ZeroCheck32(kTrapRemByZero, right);
|
| - Diamond d(graph(), jsgraph()->common(),
|
| - graph()->NewNode(jsgraph()->machine()->Word32Equal(), right,
|
| - jsgraph()->Int32Constant(-1)));
|
| -
|
| - Node* rem = graph()->NewNode(m->Int32Mod(), left, right, d.if_false);
|
| -
|
| - return d.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0),
|
| - rem);
|
| - }
|
| + return BuildI32DivU(left, right);
|
| + case wasm::kExprI32RemS:
|
| + return BuildI32RemS(left, right);
|
| case wasm::kExprI32RemU:
|
| - op = m->Uint32Mod();
|
| - return graph()->NewNode(op, left, right,
|
| - trap_->ZeroCheck32(kTrapRemByZero, right));
|
| + return BuildI32RemU(left, right);
|
| case wasm::kExprI32And:
|
| op = m->Word32And();
|
| break;
|
| @@ -1743,6 +1714,132 @@ Node* WasmGraphBuilder::BuildFloatToIntConversionInstruction(
|
| return load;
|
| }
|
|
|
| +Node* WasmGraphBuilder::BuildI32DivS(Node* left, Node* right) {
|
| + MachineOperatorBuilder* m = jsgraph()->machine();
|
| + if (module_ && module_->asm_js()) {
|
| + // asm.js semantics return 0 on divide or mod by zero.
|
| + if (m->Int32DivIsSafe()) {
|
| + // The hardware instruction does the right thing (e.g. arm).
|
| + return graph()->NewNode(m->Int32Div(), left, right, graph()->start());
|
| + }
|
| +
|
| + // Check denominator for zero.
|
| + Diamond z(
|
| + graph(), jsgraph()->common(),
|
| + graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)),
|
| + BranchHint::kFalse);
|
| +
|
| + // Check numerator for -1. (avoid minint / -1 case).
|
| + Diamond n(
|
| + graph(), jsgraph()->common(),
|
| + graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)),
|
| + BranchHint::kFalse);
|
| +
|
| + Node* div = graph()->NewNode(m->Int32Div(), left, right, z.if_false);
|
| + Node* neg =
|
| + graph()->NewNode(m->Int32Sub(), jsgraph()->Int32Constant(0), left);
|
| +
|
| + return n.Phi(MachineRepresentation::kWord32, neg,
|
| + z.Phi(MachineRepresentation::kWord32,
|
| + jsgraph()->Int32Constant(0), div));
|
| + }
|
| +
|
| + trap_->ZeroCheck32(kTrapDivByZero, right);
|
| + Node* before = *control_;
|
| + Node* denom_is_m1;
|
| + Node* denom_is_not_m1;
|
| + Branch(
|
| + graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)),
|
| + &denom_is_m1, &denom_is_not_m1);
|
| + *control_ = denom_is_m1;
|
| + trap_->TrapIfEq32(kTrapDivUnrepresentable, left, kMinInt);
|
| + if (*control_ != denom_is_m1) {
|
| + *control_ = graph()->NewNode(jsgraph()->common()->Merge(2), denom_is_not_m1,
|
| + *control_);
|
| + } else {
|
| + *control_ = before;
|
| + }
|
| + return graph()->NewNode(m->Int32Div(), left, right, *control_);
|
| +}
|
| +
|
| +Node* WasmGraphBuilder::BuildI32RemS(Node* left, Node* right) {
|
| + MachineOperatorBuilder* m = jsgraph()->machine();
|
| + if (module_ && module_->asm_js()) {
|
| + // 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);
|
| +
|
| + // 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);
|
| +
|
| + return z.Phi(
|
| + MachineRepresentation::kWord32, jsgraph()->Int32Constant(0),
|
| + d.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0),
|
| + graph()->NewNode(m->Int32Mod(), left, right, d.if_false)));
|
| + }
|
| +
|
| + trap_->ZeroCheck32(kTrapRemByZero, right);
|
| +
|
| + Diamond d(
|
| + graph(), jsgraph()->common(),
|
| + graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)),
|
| + BranchHint::kFalse);
|
| + d.Chain(*control_);
|
| +
|
| + return d.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0),
|
| + graph()->NewNode(m->Int32Mod(), left, right, d.if_false));
|
| +}
|
| +
|
| +Node* WasmGraphBuilder::BuildI32DivU(Node* left, Node* right) {
|
| + MachineOperatorBuilder* m = jsgraph()->machine();
|
| + if (module_ && module_->asm_js()) {
|
| + // asm.js semantics return 0 on divide or mod by zero.
|
| + if (m->Uint32DivIsSafe()) {
|
| + // The hardware instruction does the right thing (e.g. arm).
|
| + return graph()->NewNode(m->Uint32Div(), left, right, graph()->start());
|
| + }
|
| +
|
| + // Explicit check for x % 0.
|
| + Diamond z(
|
| + graph(), jsgraph()->common(),
|
| + graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)),
|
| + BranchHint::kFalse);
|
| +
|
| + return z.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0),
|
| + graph()->NewNode(jsgraph()->machine()->Uint32Div(), left,
|
| + right, z.if_false));
|
| + }
|
| + return graph()->NewNode(m->Uint32Div(), left, right,
|
| + trap_->ZeroCheck32(kTrapDivByZero, right));
|
| +}
|
| +
|
| +Node* WasmGraphBuilder::BuildI32RemU(Node* left, Node* right) {
|
| + MachineOperatorBuilder* m = jsgraph()->machine();
|
| + if (module_ && module_->asm_js()) {
|
| + // 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);
|
| +
|
| + Node* rem = graph()->NewNode(jsgraph()->machine()->Uint32Mod(), left, right,
|
| + z.if_false);
|
| + return z.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0),
|
| + rem);
|
| + }
|
| +
|
| + return graph()->NewNode(m->Uint32Mod(), left, right,
|
| + trap_->ZeroCheck32(kTrapRemByZero, right));
|
| +}
|
| +
|
| Node* WasmGraphBuilder::BuildI64DivS(Node* left, Node* right) {
|
| if (jsgraph()->machine()->Is32()) {
|
| return BuildDiv64Call(
|
|
|