| Index: src/compiler/effect-control-linearizer.cc
|
| diff --git a/src/compiler/effect-control-linearizer.cc b/src/compiler/effect-control-linearizer.cc
|
| index 766a2e5818f779ee8d6d7db21f7f35c1f35539d1..0c3585be980adc7f359a52fffc795d8c31ad9742 100644
|
| --- a/src/compiler/effect-control-linearizer.cc
|
| +++ b/src/compiler/effect-control-linearizer.cc
|
| @@ -732,6 +732,15 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
|
| case IrOpcode::kStoreTypedElement:
|
| state = LowerStoreTypedElement(node, *effect, *control);
|
| break;
|
| + case IrOpcode::kFloat64RoundUp:
|
| + state = LowerFloat64RoundUp(node, *effect, *control);
|
| + break;
|
| + case IrOpcode::kFloat64RoundDown:
|
| + state = LowerFloat64RoundDown(node, *effect, *control);
|
| + break;
|
| + case IrOpcode::kFloat64RoundTruncate:
|
| + state = LowerFloat64RoundTruncate(node, *effect, *control);
|
| + break;
|
| default:
|
| return false;
|
| }
|
| @@ -2702,6 +2711,390 @@ EffectControlLinearizer::LowerStoreTypedElement(Node* node, Node* effect,
|
| return ValueEffectControl(nullptr, effect, control);
|
| }
|
|
|
| +EffectControlLinearizer::ValueEffectControl
|
| +EffectControlLinearizer::LowerFloat64RoundUp(Node* node, Node* effect,
|
| + Node* control) {
|
| + // Nothing to be done if a fast hardware instruction is available.
|
| + if (machine()->Float64RoundUp().IsSupported()) {
|
| + return ValueEffectControl(node, effect, control);
|
| + }
|
| +
|
| + Node* const one = jsgraph()->Float64Constant(1.0);
|
| + Node* const zero = jsgraph()->Float64Constant(0.0);
|
| + Node* const minus_zero = jsgraph()->Float64Constant(-0.0);
|
| + Node* const two_52 = jsgraph()->Float64Constant(4503599627370496.0E0);
|
| + Node* const minus_two_52 = jsgraph()->Float64Constant(-4503599627370496.0E0);
|
| + Node* const input = node->InputAt(0);
|
| +
|
| + // General case for ceil.
|
| + //
|
| + // if 0.0 < input then
|
| + // if 2^52 <= input then
|
| + // input
|
| + // else
|
| + // let temp1 = (2^52 + input) - 2^52 in
|
| + // if temp1 < input then
|
| + // temp1 + 1
|
| + // else
|
| + // temp1
|
| + // else
|
| + // if input == 0 then
|
| + // input
|
| + // else
|
| + // if input <= -2^52 then
|
| + // input
|
| + // else
|
| + // let temp1 = -0 - input in
|
| + // let temp2 = (2^52 + temp1) - 2^52 in
|
| + // let temp3 = (if temp1 < temp2 then temp2 - 1 else temp2) in
|
| + // -0 - temp3
|
| + //
|
| + // Note: We do not use the Diamond helper class here, because it really hurts
|
| + // readability with nested diamonds.
|
| +
|
| + Node* check0 = graph()->NewNode(machine()->Float64LessThan(), zero, input);
|
| + Node* branch0 =
|
| + graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
|
| +
|
| + Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
|
| + Node* vtrue0;
|
| + {
|
| + Node* check1 =
|
| + graph()->NewNode(machine()->Float64LessThanOrEqual(), two_52, input);
|
| + Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
|
| +
|
| + Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
|
| + Node* vtrue1 = input;
|
| +
|
| + Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
|
| + Node* vfalse1;
|
| + {
|
| + Node* temp1 = graph()->NewNode(
|
| + machine()->Float64Sub(),
|
| + graph()->NewNode(machine()->Float64Add(), two_52, input), two_52);
|
| + vfalse1 = graph()->NewNode(
|
| + common()->Select(MachineRepresentation::kFloat64),
|
| + graph()->NewNode(machine()->Float64LessThan(), temp1, input),
|
| + graph()->NewNode(machine()->Float64Add(), temp1, one), temp1);
|
| + }
|
| +
|
| + if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
|
| + vtrue0 = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
|
| + vtrue1, vfalse1, if_true0);
|
| + }
|
| +
|
| + Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
|
| + Node* vfalse0;
|
| + {
|
| + Node* check1 = graph()->NewNode(machine()->Float64Equal(), input, zero);
|
| + Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
|
| + check1, if_false0);
|
| +
|
| + Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
|
| + Node* vtrue1 = input;
|
| +
|
| + Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
|
| + Node* vfalse1;
|
| + {
|
| + Node* check2 = graph()->NewNode(machine()->Float64LessThanOrEqual(),
|
| + input, minus_two_52);
|
| + Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
|
| + check2, if_false1);
|
| +
|
| + Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
|
| + Node* vtrue2 = input;
|
| +
|
| + Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
|
| + Node* vfalse2;
|
| + {
|
| + Node* temp1 =
|
| + graph()->NewNode(machine()->Float64Sub(), minus_zero, input);
|
| + Node* temp2 = graph()->NewNode(
|
| + machine()->Float64Sub(),
|
| + graph()->NewNode(machine()->Float64Add(), two_52, temp1), two_52);
|
| + Node* temp3 = graph()->NewNode(
|
| + common()->Select(MachineRepresentation::kFloat64),
|
| + graph()->NewNode(machine()->Float64LessThan(), temp1, temp2),
|
| + graph()->NewNode(machine()->Float64Sub(), temp2, one), temp2);
|
| + vfalse2 = graph()->NewNode(machine()->Float64Sub(), minus_zero, temp3);
|
| + }
|
| +
|
| + if_false1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2);
|
| + vfalse1 =
|
| + graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
|
| + vtrue2, vfalse2, if_false1);
|
| + }
|
| +
|
| + if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
|
| + vfalse0 =
|
| + graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
|
| + vtrue1, vfalse1, if_false0);
|
| + }
|
| +
|
| + Node* merge0 = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
|
| + Node* value =
|
| + graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
|
| + vtrue0, vfalse0, merge0);
|
| + return ValueEffectControl(value, effect, merge0);
|
| +}
|
| +
|
| +EffectControlLinearizer::ValueEffectControl
|
| +EffectControlLinearizer::LowerFloat64RoundDown(Node* node, Node* effect,
|
| + Node* control) {
|
| + // Nothing to be done if a fast hardware instruction is available.
|
| + if (machine()->Float64RoundDown().IsSupported()) {
|
| + return ValueEffectControl(node, effect, control);
|
| + }
|
| +
|
| + Node* const one = jsgraph()->Float64Constant(1.0);
|
| + Node* const zero = jsgraph()->Float64Constant(0.0);
|
| + Node* const minus_one = jsgraph()->Float64Constant(-1.0);
|
| + Node* const minus_zero = jsgraph()->Float64Constant(-0.0);
|
| + Node* const two_52 = jsgraph()->Float64Constant(4503599627370496.0E0);
|
| + Node* const minus_two_52 = jsgraph()->Float64Constant(-4503599627370496.0E0);
|
| + Node* const input = node->InputAt(0);
|
| +
|
| + // General case for floor.
|
| + //
|
| + // if 0.0 < input then
|
| + // if 2^52 <= input then
|
| + // input
|
| + // else
|
| + // let temp1 = (2^52 + input) - 2^52 in
|
| + // if input < temp1 then
|
| + // temp1 - 1
|
| + // else
|
| + // temp1
|
| + // else
|
| + // if input == 0 then
|
| + // input
|
| + // else
|
| + // if input <= -2^52 then
|
| + // input
|
| + // else
|
| + // let temp1 = -0 - input in
|
| + // let temp2 = (2^52 + temp1) - 2^52 in
|
| + // if temp2 < temp1 then
|
| + // -1 - temp2
|
| + // else
|
| + // -0 - temp2
|
| + //
|
| + // Note: We do not use the Diamond helper class here, because it really hurts
|
| + // readability with nested diamonds.
|
| +
|
| + Node* check0 = graph()->NewNode(machine()->Float64LessThan(), zero, input);
|
| + Node* branch0 =
|
| + graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
|
| +
|
| + Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
|
| + Node* vtrue0;
|
| + {
|
| + Node* check1 =
|
| + graph()->NewNode(machine()->Float64LessThanOrEqual(), two_52, input);
|
| + Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
|
| +
|
| + Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
|
| + Node* vtrue1 = input;
|
| +
|
| + Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
|
| + Node* vfalse1;
|
| + {
|
| + Node* temp1 = graph()->NewNode(
|
| + machine()->Float64Sub(),
|
| + graph()->NewNode(machine()->Float64Add(), two_52, input), two_52);
|
| + vfalse1 = graph()->NewNode(
|
| + common()->Select(MachineRepresentation::kFloat64),
|
| + graph()->NewNode(machine()->Float64LessThan(), input, temp1),
|
| + graph()->NewNode(machine()->Float64Sub(), temp1, one), temp1);
|
| + }
|
| +
|
| + if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
|
| + vtrue0 = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
|
| + vtrue1, vfalse1, if_true0);
|
| + }
|
| +
|
| + Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
|
| + Node* vfalse0;
|
| + {
|
| + Node* check1 = graph()->NewNode(machine()->Float64Equal(), input, zero);
|
| + Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
|
| + check1, if_false0);
|
| +
|
| + Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
|
| + Node* vtrue1 = input;
|
| +
|
| + Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
|
| + Node* vfalse1;
|
| + {
|
| + Node* check2 = graph()->NewNode(machine()->Float64LessThanOrEqual(),
|
| + input, minus_two_52);
|
| + Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
|
| + check2, if_false1);
|
| +
|
| + Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
|
| + Node* vtrue2 = input;
|
| +
|
| + Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
|
| + Node* vfalse2;
|
| + {
|
| + Node* temp1 =
|
| + graph()->NewNode(machine()->Float64Sub(), minus_zero, input);
|
| + Node* temp2 = graph()->NewNode(
|
| + machine()->Float64Sub(),
|
| + graph()->NewNode(machine()->Float64Add(), two_52, temp1), two_52);
|
| + vfalse2 = graph()->NewNode(
|
| + common()->Select(MachineRepresentation::kFloat64),
|
| + graph()->NewNode(machine()->Float64LessThan(), temp2, temp1),
|
| + graph()->NewNode(machine()->Float64Sub(), minus_one, temp2),
|
| + graph()->NewNode(machine()->Float64Sub(), minus_zero, temp2));
|
| + }
|
| +
|
| + if_false1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2);
|
| + vfalse1 =
|
| + graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
|
| + vtrue2, vfalse2, if_false1);
|
| + }
|
| +
|
| + if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
|
| + vfalse0 =
|
| + graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
|
| + vtrue1, vfalse1, if_false0);
|
| + }
|
| +
|
| + Node* merge0 = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
|
| + Node* value =
|
| + graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
|
| + vtrue0, vfalse0, merge0);
|
| + return ValueEffectControl(value, effect, merge0);
|
| +}
|
| +
|
| +EffectControlLinearizer::ValueEffectControl
|
| +EffectControlLinearizer::LowerFloat64RoundTruncate(Node* node, Node* effect,
|
| + Node* control) {
|
| + // Nothing to be done if a fast hardware instruction is available.
|
| + if (machine()->Float64RoundTruncate().IsSupported()) {
|
| + return ValueEffectControl(node, effect, control);
|
| + }
|
| +
|
| + Node* const one = jsgraph()->Float64Constant(1.0);
|
| + Node* const zero = jsgraph()->Float64Constant(0.0);
|
| + Node* const minus_zero = jsgraph()->Float64Constant(-0.0);
|
| + Node* const two_52 = jsgraph()->Float64Constant(4503599627370496.0E0);
|
| + Node* const minus_two_52 = jsgraph()->Float64Constant(-4503599627370496.0E0);
|
| + Node* const input = node->InputAt(0);
|
| +
|
| + // General case for trunc.
|
| + //
|
| + // if 0.0 < input then
|
| + // if 2^52 <= input then
|
| + // input
|
| + // else
|
| + // let temp1 = (2^52 + input) - 2^52 in
|
| + // if input < temp1 then
|
| + // temp1 - 1
|
| + // else
|
| + // temp1
|
| + // else
|
| + // if input == 0 then
|
| + // input
|
| + // else
|
| + // if input <= -2^52 then
|
| + // input
|
| + // else
|
| + // let temp1 = -0 - input in
|
| + // let temp2 = (2^52 + temp1) - 2^52 in
|
| + // let temp3 = (if temp1 < temp2 then temp2 - 1 else temp2) in
|
| + // -0 - temp3
|
| + //
|
| + // Note: We do not use the Diamond helper class here, because it really hurts
|
| + // readability with nested diamonds.
|
| +
|
| + Node* check0 = graph()->NewNode(machine()->Float64LessThan(), zero, input);
|
| + Node* branch0 =
|
| + graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
|
| +
|
| + Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
|
| + Node* vtrue0;
|
| + {
|
| + Node* check1 =
|
| + graph()->NewNode(machine()->Float64LessThanOrEqual(), two_52, input);
|
| + Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
|
| +
|
| + Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
|
| + Node* vtrue1 = input;
|
| +
|
| + Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
|
| + Node* vfalse1;
|
| + {
|
| + Node* temp1 = graph()->NewNode(
|
| + machine()->Float64Sub(),
|
| + graph()->NewNode(machine()->Float64Add(), two_52, input), two_52);
|
| + vfalse1 = graph()->NewNode(
|
| + common()->Select(MachineRepresentation::kFloat64),
|
| + graph()->NewNode(machine()->Float64LessThan(), input, temp1),
|
| + graph()->NewNode(machine()->Float64Sub(), temp1, one), temp1);
|
| + }
|
| +
|
| + if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
|
| + vtrue0 = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
|
| + vtrue1, vfalse1, if_true0);
|
| + }
|
| +
|
| + Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
|
| + Node* vfalse0;
|
| + {
|
| + Node* check1 = graph()->NewNode(machine()->Float64Equal(), input, zero);
|
| + Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
|
| + check1, if_false0);
|
| +
|
| + Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
|
| + Node* vtrue1 = input;
|
| +
|
| + Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
|
| + Node* vfalse1;
|
| + {
|
| + Node* check2 = graph()->NewNode(machine()->Float64LessThanOrEqual(),
|
| + input, minus_two_52);
|
| + Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
|
| + check2, if_false1);
|
| +
|
| + Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
|
| + Node* vtrue2 = input;
|
| +
|
| + Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
|
| + Node* vfalse2;
|
| + {
|
| + Node* temp1 =
|
| + graph()->NewNode(machine()->Float64Sub(), minus_zero, input);
|
| + Node* temp2 = graph()->NewNode(
|
| + machine()->Float64Sub(),
|
| + graph()->NewNode(machine()->Float64Add(), two_52, temp1), two_52);
|
| + Node* temp3 = graph()->NewNode(
|
| + common()->Select(MachineRepresentation::kFloat64),
|
| + graph()->NewNode(machine()->Float64LessThan(), temp1, temp2),
|
| + graph()->NewNode(machine()->Float64Sub(), temp2, one), temp2);
|
| + vfalse2 = graph()->NewNode(machine()->Float64Sub(), minus_zero, temp3);
|
| + }
|
| +
|
| + if_false1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2);
|
| + vfalse1 =
|
| + graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
|
| + vtrue2, vfalse2, if_false1);
|
| + }
|
| +
|
| + if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
|
| + vfalse0 =
|
| + graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
|
| + vtrue1, vfalse1, if_false0);
|
| + }
|
| +
|
| + Node* merge0 = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
|
| + Node* value =
|
| + graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
|
| + vtrue0, vfalse0, merge0);
|
| + return ValueEffectControl(value, effect, merge0);
|
| +}
|
| +
|
| Factory* EffectControlLinearizer::factory() const {
|
| return isolate()->factory();
|
| }
|
|
|