Index: src/compiler/effect-control-linearizer.cc |
diff --git a/src/compiler/effect-control-linearizer.cc b/src/compiler/effect-control-linearizer.cc |
index 351382ebf4320c2896dbf0665612787ab18b9242..d17195c984a0a9ac41ad2bff8d670bb40b27c20f 100644 |
--- a/src/compiler/effect-control-linearizer.cc |
+++ b/src/compiler/effect-control-linearizer.cc |
@@ -780,6 +780,9 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node, |
case IrOpcode::kFloat64RoundTruncate: |
state = LowerFloat64RoundTruncate(node, *effect, *control); |
break; |
+ case IrOpcode::kFloat64RoundTiesEven: |
+ state = LowerFloat64RoundTiesEven(node, *effect, *control); |
+ break; |
default: |
return false; |
} |
@@ -3375,6 +3378,137 @@ EffectControlLinearizer::LowerFloat64RoundUp(Node* node, Node* effect, |
} |
EffectControlLinearizer::ValueEffectControl |
+EffectControlLinearizer::BuildFloat64RoundDown(Node* value, Node* effect, |
+ Node* control) { |
+ if (machine()->Float64RoundDown().IsSupported()) { |
+ value = graph()->NewNode(machine()->Float64RoundDown().op(), value); |
+ } else { |
+ 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 = value; |
+ |
+ // 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); |
+ } |
+ |
+ control = graph()->NewNode(common()->Merge(2), if_true0, if_false0); |
+ value = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), |
+ vtrue0, vfalse0, control); |
+ } |
+ return ValueEffectControl(value, effect, control); |
+} |
+ |
+EffectControlLinearizer::ValueEffectControl |
EffectControlLinearizer::LowerFloat64RoundDown(Node* node, Node* effect, |
Node* control) { |
// Nothing to be done if a fast hardware instruction is available. |
@@ -3382,108 +3516,78 @@ EffectControlLinearizer::LowerFloat64RoundDown(Node* node, Node* effect, |
return ValueEffectControl(node, effect, control); |
} |
+ Node* const input = node->InputAt(0); |
+ return BuildFloat64RoundDown(input, effect, control); |
+} |
+ |
+EffectControlLinearizer::ValueEffectControl |
+EffectControlLinearizer::LowerFloat64RoundTiesEven(Node* node, Node* effect, |
+ Node* control) { |
+ // Nothing to be done if a fast hardware instruction is available. |
+ if (machine()->Float64RoundTiesEven().IsSupported()) { |
+ return ValueEffectControl(node, effect, control); |
+ } |
+ |
Node* const one = jsgraph()->Float64Constant(1.0); |
+ Node* const two = jsgraph()->Float64Constant(2.0); |
+ Node* const half = jsgraph()->Float64Constant(0.5); |
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. |
+ // Generate case for round ties to even: |
// |
- // 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 |
+ // let value = floor(input) in |
+ // let temp1 = input - value in |
+ // if temp1 < 0.5 then |
+ // value |
+ // else if 0.5 < temp1 then |
+ // value + 1.0 |
// else |
- // if input == 0 then |
- // input |
+ // let temp2 = value % 2.0 in |
+ // if temp2 == 0.0 then |
+ // value |
// 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 |
+ // value + 1.0 |
// |
// 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); |
+ ValueEffectControl continuation = |
+ BuildFloat64RoundDown(input, effect, control); |
+ Node* value = continuation.value; |
+ effect = continuation.effect; |
+ control = continuation.control; |
- Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); |
- Node* vtrue1 = input; |
+ Node* temp1 = graph()->NewNode(machine()->Float64Sub(), input, value); |
- 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); |
- } |
+ Node* check0 = graph()->NewNode(machine()->Float64LessThan(), temp1, half); |
+ Node* branch0 = graph()->NewNode(common()->Branch(), check0, control); |
- 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_true0 = graph()->NewNode(common()->IfTrue(), branch0); |
+ Node* vtrue0 = value; |
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* check1 = graph()->NewNode(machine()->Float64LessThan(), half, temp1); |
+ Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0); |
Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); |
- Node* vtrue1 = input; |
+ Node* vtrue1 = graph()->NewNode(machine()->Float64Add(), value, one); |
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* temp2 = graph()->NewNode(machine()->Float64Mod(), value, two); |
+ |
+ Node* check2 = graph()->NewNode(machine()->Float64Equal(), temp2, zero); |
+ Node* branch2 = graph()->NewNode(common()->Branch(), check2, if_false1); |
Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2); |
- Node* vtrue2 = input; |
+ Node* vtrue2 = value; |
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)); |
- } |
+ Node* vfalse2 = graph()->NewNode(machine()->Float64Add(), value, one); |
if_false1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2); |
vfalse1 = |
@@ -3497,11 +3601,11 @@ EffectControlLinearizer::LowerFloat64RoundDown(Node* node, Node* effect, |
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); |
+ control = graph()->NewNode(common()->Merge(2), if_true0, if_false0); |
+ value = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), |
+ vtrue0, vfalse0, control); |
+ |
+ return ValueEffectControl(value, effect, control); |
} |
EffectControlLinearizer::ValueEffectControl |