Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(421)

Unified Diff: src/compiler/simplified-lowering.cc

Issue 1841993002: [builtins] Make Math.ceil, Math.trunc and Math.round optimizable. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/compiler/simplified-lowering.h ('k') | src/compiler/simplified-operator.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/compiler/simplified-lowering.cc
diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc
index 6f3eb902622d3ad7e410ef45733f6c575b7e8843..a813d136646ac67c78de9018662a6373ddc0b27b 100644
--- a/src/compiler/simplified-lowering.cc
+++ b/src/compiler/simplified-lowering.cc
@@ -962,11 +962,26 @@ class RepresentationSelector {
}
break;
}
+ case IrOpcode::kNumberCeil: {
+ VisitUnop(node, UseInfo::Float64(), MachineRepresentation::kFloat64);
+ if (lower()) DeferReplacement(node, lowering->Float64Ceil(node));
+ break;
+ }
case IrOpcode::kNumberFloor: {
VisitUnop(node, UseInfo::Float64(), MachineRepresentation::kFloat64);
if (lower()) DeferReplacement(node, lowering->Float64Floor(node));
break;
}
+ case IrOpcode::kNumberRound: {
+ VisitUnop(node, UseInfo::Float64(), MachineRepresentation::kFloat64);
+ if (lower()) DeferReplacement(node, lowering->Float64Round(node));
+ break;
+ }
+ case IrOpcode::kNumberTrunc: {
+ VisitUnop(node, UseInfo::Float64(), MachineRepresentation::kFloat64);
+ if (lower()) DeferReplacement(node, lowering->Float64Trunc(node));
+ break;
+ }
case IrOpcode::kNumberToInt32: {
// Just change representation if necessary.
VisitUnop(node, UseInfo::TruncatingWord32(),
@@ -1524,6 +1539,129 @@ void SimplifiedLowering::DoStoreBuffer(Node* node) {
NodeProperties::ChangeOp(node, machine()->CheckedStore(rep));
}
+Node* SimplifiedLowering::Float64Ceil(Node* const node) {
+ 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);
+
+ // Use fast hardware instruction if available.
+ if (machine()->Float64RoundUp().IsSupported()) {
+ return graph()->NewNode(machine()->Float64RoundUp().op(), input);
+ }
+
+ // 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,
+ graph()->start());
+
+ 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);
+ return graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
+ vtrue0, vfalse0, merge0);
+}
+
Node* SimplifiedLowering::Float64Floor(Node* const node) {
Node* const one = jsgraph()->Float64Constant(1.0);
Node* const zero = jsgraph()->Float64Constant(0.0);
@@ -1650,6 +1788,144 @@ Node* SimplifiedLowering::Float64Floor(Node* const node) {
vtrue0, vfalse0, merge0);
}
+Node* SimplifiedLowering::Float64Round(Node* const node) {
+ Node* const one = jsgraph()->Float64Constant(1.0);
+ Node* const one_half = jsgraph()->Float64Constant(0.5);
+ Node* const input = node->InputAt(0);
+
+ // Round up towards Infinity, and adjust if the difference exceeds 0.5.
+ Node* result = Float64Ceil(node);
+ return graph()->NewNode(
+ common()->Select(MachineRepresentation::kFloat64),
+ graph()->NewNode(
+ machine()->Float64LessThanOrEqual(),
+ graph()->NewNode(machine()->Float64Sub(), result, one_half), input),
+ result, graph()->NewNode(machine()->Float64Sub(), result, one));
+}
+
+Node* SimplifiedLowering::Float64Trunc(Node* const node) {
+ 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);
+
+ // Use fast hardware instruction if available.
+ if (machine()->Float64RoundTruncate().IsSupported()) {
+ return graph()->NewNode(machine()->Float64RoundTruncate().op(), input);
+ }
+
+ // 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,
+ graph()->start());
+
+ 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);
+ return graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
+ vtrue0, vfalse0, merge0);
+}
+
Node* SimplifiedLowering::Int32Div(Node* const node) {
Int32BinopMatcher m(node);
Node* const zero = jsgraph()->Int32Constant(0);
« no previous file with comments | « src/compiler/simplified-lowering.h ('k') | src/compiler/simplified-operator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698