Commit cdf9a406 authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan][x64] Improve code generation for Float64LessThan with Float64Abs.

During instruction selection, match the pattern

  Float64LessThan(#0.0, Float64Abs(x))

which TurboFan generates for NumberToBoolean in the general case,
and which evaluates to false if x is 0, -0 or NaN, and compile this
to a simple (v)ucomisd using not_equal flags condition, which avoids
the costly Float64Abs.

Also consistently generate this pattern in TurboFan and the code
stubs/interpreter for ToBoolean.

R=mstarzinger@chromium.org
BUG=v8:5267

Review-Url: https://codereview.chromium.org/2473923003
Cr-Commit-Position: refs/heads/master@{#40740}
parent 2525b057
......@@ -879,9 +879,8 @@ void CodeStubAssembler::BranchIfToBooleanIsTrue(Node* value, Label* if_true,
MachineType::Float64());
// Check if the floating point {value} is neither 0.0, -0.0 nor NaN.
Node* zero = Float64Constant(0.0);
GotoIf(Float64LessThan(zero, value_value), if_true);
Branch(Float64LessThan(value_value, zero), if_true, if_false);
Branch(Float64LessThan(Float64Constant(0.0), Float64Abs(value_value)),
if_true, if_false);
}
Bind(&if_valueisother);
......
......@@ -913,15 +913,14 @@ EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerTruncateTaggedToBit(Node* node, Node* effect,
Node* control) {
Node* value = node->InputAt(0);
Node* one = jsgraph()->Int32Constant(1);
Node* zero = jsgraph()->Int32Constant(0);
Node* fzero = jsgraph()->Float64Constant(0.0);
// Collect effect/control/value triples.
int count = 0;
Node* values[7];
Node* effects[7];
Node* controls[6];
Node* values[6];
Node* effects[6];
Node* controls[5];
// Check if {value} is a Smi.
Node* check_smi = ObjectIsSmi(value);
......@@ -1012,20 +1011,12 @@ EffectControlLinearizer::LowerTruncateTaggedToBit(Node* node, Node* effect,
simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), value,
eheapnumber, if_heapnumber);
// Check if {value} is either less than 0.0 or greater than 0.0.
Node* check =
graph()->NewNode(machine()->Float64LessThan(), fzero, value_value);
Node* branch = graph()->NewNode(common()->Branch(), check, if_heapnumber);
controls[count] = graph()->NewNode(common()->IfTrue(), branch);
// Check if {value} is not one of 0, -0, or NaN.
controls[count] = if_heapnumber;
effects[count] = eheapnumber;
values[count] = one;
count++;
controls[count] = graph()->NewNode(common()->IfFalse(), branch);
effects[count] = eheapnumber;
values[count] =
graph()->NewNode(machine()->Float64LessThan(), value_value, fzero);
values[count] = graph()->NewNode(
machine()->Float64LessThan(), fzero,
graph()->NewNode(machine()->Float64Abs(), value_value));
count++;
}
control = graph()->NewNode(common()->IfFalse(), branch_heapnumber);
......
......@@ -1942,9 +1942,26 @@ void VisitWordCompareZero(InstructionSelector* selector, Node* user,
case IrOpcode::kFloat64Equal:
cont->OverwriteAndNegateIfEqual(kUnorderedEqual);
return VisitFloat64Compare(selector, value, cont);
case IrOpcode::kFloat64LessThan:
case IrOpcode::kFloat64LessThan: {
Float64BinopMatcher m(value);
if (m.left().Is(0.0) && m.right().IsFloat64Abs()) {
// This matches the pattern
//
// Float64LessThan(#0.0, Float64Abs(x))
//
// which TurboFan generates for NumberToBoolean in the general case,
// and which evaluates to false if x is 0, -0 or NaN. We can compile
// this to a simple (v)ucomisd using not_equal flags condition, which
// avoids the costly Float64Abs.
cont->OverwriteAndNegateIfEqual(kNotEqual);
InstructionCode const opcode =
selector->IsSupported(AVX) ? kAVXFloat64Cmp : kSSEFloat64Cmp;
return VisitCompare(selector, opcode, m.left().node(),
m.right().InputAt(0), cont, false);
}
cont->OverwriteAndNegateIfEqual(kUnsignedGreaterThan);
return VisitFloat64Compare(selector, value, cont);
}
case IrOpcode::kFloat64LessThanOrEqual:
cont->OverwriteAndNegateIfEqual(kUnsignedGreaterThanOrEqual);
return VisitFloat64Compare(selector, value, cont);
......@@ -2205,14 +2222,28 @@ void InstructionSelector::VisitFloat64Equal(Node* node) {
VisitFloat64Compare(this, node, &cont);
}
void InstructionSelector::VisitFloat64LessThan(Node* node) {
Float64BinopMatcher m(node);
if (m.left().Is(0.0) && m.right().IsFloat64Abs()) {
// This matches the pattern
//
// Float64LessThan(#0.0, Float64Abs(x))
//
// which TurboFan generates for NumberToBoolean in the general case,
// and which evaluates to false if x is 0, -0 or NaN. We can compile
// this to a simple (v)ucomisd using not_equal flags condition, which
// avoids the costly Float64Abs.
FlagsContinuation cont = FlagsContinuation::ForSet(kNotEqual, node);
InstructionCode const opcode =
IsSupported(AVX) ? kAVXFloat64Cmp : kSSEFloat64Cmp;
return VisitCompare(this, opcode, m.left().node(), m.right().InputAt(0),
&cont, false);
}
FlagsContinuation cont =
FlagsContinuation::ForSet(kUnsignedGreaterThan, node);
VisitFloat64Compare(this, node, &cont);
}
void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) {
FlagsContinuation cont =
FlagsContinuation::ForSet(kUnsignedGreaterThanOrEqual, node);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment