Commit 88efe28d authored by bmeurer@chromium.org's avatar bmeurer@chromium.org

[turbofan] Combine JSToNumber and ChangeTaggedToFloat64 for fast SMI case.

This does the following optimization during ChangeLowering:

 ChangeTaggedToFloat64(JSToNumber(x)) =>
   if IsSmi(x) then ChangeSmiToFloat64(x)
   else let y = JSToNumber(x) in
     if IsSmi(y) then ChangeSmiToFloat64(y)
     else LoadHeapNumberValue(y)

Also cleanup/rearrange some code duplication in ChangeLowering.

R=dcarney@chromium.org

Review URL: https://codereview.chromium.org/703103003

Cr-Commit-Position: refs/heads/master@{#25195}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@25195 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 9734f236
......@@ -9,6 +9,7 @@
#include "src/compiler/js-graph.h"
#include "src/compiler/linkage.h"
#include "src/compiler/machine-operator.h"
#include "src/compiler/node-properties-inl.h"
namespace v8 {
namespace internal {
......@@ -85,6 +86,16 @@ Node* ChangeLowering::AllocateHeapNumberWithValue(Node* value, Node* control) {
}
Node* ChangeLowering::ChangeInt32ToFloat64(Node* value) {
return graph()->NewNode(machine()->ChangeInt32ToFloat64(), value);
}
Node* ChangeLowering::ChangeSmiToFloat64(Node* value) {
return ChangeInt32ToFloat64(ChangeSmiToInt32(value));
}
Node* ChangeLowering::ChangeSmiToInt32(Node* value) {
value = graph()->NewNode(machine()->WordSar(), value, SmiShiftBitsConstant());
if (machine()->Is64()) {
......@@ -94,6 +105,19 @@ Node* ChangeLowering::ChangeSmiToInt32(Node* value) {
}
Node* ChangeLowering::ChangeUint32ToFloat64(Node* value) {
return graph()->NewNode(machine()->ChangeUint32ToFloat64(), value);
}
Node* ChangeLowering::ChangeUint32ToSmi(Node* value) {
if (machine()->Is64()) {
value = graph()->NewNode(machine()->ChangeUint32ToUint64(), value);
}
return graph()->NewNode(machine()->WordShl(), value, SmiShiftBitsConstant());
}
Node* ChangeLowering::LoadHeapNumberValue(Node* value, Node* control) {
return graph()->NewNode(machine()->Load(kMachFloat64), value,
HeapNumberValueIndexConstant(), graph()->start(),
......@@ -101,6 +125,19 @@ Node* ChangeLowering::LoadHeapNumberValue(Node* value, Node* control) {
}
Node* ChangeLowering::TestNotSmi(Node* value) {
STATIC_ASSERT(kSmiTag == 0);
STATIC_ASSERT(kSmiTagMask == 1);
return graph()->NewNode(machine()->WordAnd(), value,
jsgraph()->IntPtrConstant(kSmiTagMask));
}
Node* ChangeLowering::Uint32LessThanOrEqual(Node* lhs, Node* rhs) {
return graph()->NewNode(machine()->Uint32LessThanOrEqual(), lhs, rhs);
}
Reduction ChangeLowering::ChangeBitToBool(Node* val, Node* control) {
MachineType const type = static_cast<MachineType>(kTypeBool | kRepTagged);
return Replace(graph()->NewNode(common()->Select(type), val,
......@@ -120,82 +157,108 @@ Reduction ChangeLowering::ChangeFloat64ToTagged(Node* val, Node* control) {
}
Reduction ChangeLowering::ChangeInt32ToTagged(Node* val, Node* control) {
Reduction ChangeLowering::ChangeInt32ToTagged(Node* value, Node* control) {
if (machine()->Is64()) {
return Replace(
graph()->NewNode(machine()->Word64Shl(),
graph()->NewNode(machine()->ChangeInt32ToInt64(), val),
SmiShiftBitsConstant()));
return Replace(graph()->NewNode(
machine()->Word64Shl(),
graph()->NewNode(machine()->ChangeInt32ToInt64(), value),
SmiShiftBitsConstant()));
}
Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), val, val);
Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), value, value);
Node* ovf = graph()->NewNode(common()->Projection(1), add);
Diamond d(graph(), common(), ovf, BranchHint::kFalse);
d.Chain(control);
Node* heap_number = AllocateHeapNumberWithValue(
graph()->NewNode(machine()->ChangeInt32ToFloat64(), val), d.if_true);
Node* smi = graph()->NewNode(common()->Projection(0), add);
return Replace(d.Phi(kMachAnyTagged, heap_number, smi));
return Replace(
d.Phi(kMachAnyTagged,
AllocateHeapNumberWithValue(ChangeInt32ToFloat64(value), d.if_true),
graph()->NewNode(common()->Projection(0), add)));
}
Reduction ChangeLowering::ChangeTaggedToUI32(Node* val, Node* control,
Reduction ChangeLowering::ChangeTaggedToUI32(Node* value, Node* control,
Signedness signedness) {
STATIC_ASSERT(kSmiTag == 0);
STATIC_ASSERT(kSmiTagMask == 1);
Node* tag = graph()->NewNode(machine()->WordAnd(), val,
jsgraph()->IntPtrConstant(kSmiTagMask));
Diamond d(graph(), common(), tag, BranchHint::kFalse);
d.Chain(control);
const MachineType type = (signedness == kSigned) ? kMachInt32 : kMachUint32;
const Operator* op = (signedness == kSigned)
? machine()->ChangeFloat64ToInt32()
: machine()->ChangeFloat64ToUint32();
Node* load = graph()->NewNode(op, LoadHeapNumberValue(val, d.if_true));
Node* number = ChangeSmiToInt32(val);
Diamond d(graph(), common(), TestNotSmi(value), BranchHint::kFalse);
d.Chain(control);
return Replace(
d.Phi((signedness == kSigned) ? kMachInt32 : kMachUint32, load, number));
d.Phi(type, graph()->NewNode(op, LoadHeapNumberValue(value, d.if_true)),
ChangeSmiToInt32(value)));
}
Reduction ChangeLowering::ChangeTaggedToFloat64(Node* val, Node* control) {
STATIC_ASSERT(kSmiTag == 0);
STATIC_ASSERT(kSmiTagMask == 1);
namespace {
Node* tag = graph()->NewNode(machine()->WordAnd(), val,
jsgraph()->IntPtrConstant(kSmiTagMask));
Diamond d(graph(), common(), tag, BranchHint::kFalse);
d.Chain(control);
Node* load = LoadHeapNumberValue(val, d.if_true);
Node* number = graph()->NewNode(machine()->ChangeInt32ToFloat64(),
ChangeSmiToInt32(val));
return Replace(d.Phi(kMachFloat64, load, number));
bool CanCover(Node* value, IrOpcode::Value opcode) {
if (value->opcode() != opcode) return false;
bool first = true;
for (auto i = value->uses().begin(); i != value->uses().end(); ++i) {
if (NodeProperties::IsEffectEdge(i.edge())) continue;
DCHECK(NodeProperties::IsValueEdge(i.edge()));
if (!first) return false;
first = false;
}
return true;
}
} // namespace
Reduction ChangeLowering::ChangeTaggedToFloat64(Node* value, Node* control) {
if (CanCover(value, IrOpcode::kJSToNumber)) {
// ChangeTaggedToFloat64(JSToNumber(x)) =>
// if IsSmi(x) then ChangeSmiToFloat64(x)
// else let y = JSToNumber(x) in
// if IsSmi(y) then ChangeSmiToFloat64(y)
// else LoadHeapNumberValue(y)
Node* const object = NodeProperties::GetValueInput(value, 0);
Node* const context = NodeProperties::GetContextInput(value);
Node* const effect = NodeProperties::GetEffectInput(value);
Node* const control = NodeProperties::GetControlInput(value);
Diamond d1(graph(), common(), TestNotSmi(object), BranchHint::kFalse);
d1.Chain(control);
Node* number =
graph()->NewNode(value->op(), object, context, effect, d1.if_true);
Diamond d2(graph(), common(), TestNotSmi(number));
d2.Nest(d1, true);
Node* phi2 = d2.Phi(kMachFloat64, LoadHeapNumberValue(number, d2.if_true),
ChangeSmiToFloat64(number));
Node* phi1 = d1.Phi(kMachFloat64, phi2, ChangeSmiToFloat64(object));
Node* ephi1 = d1.EffectPhi(number, effect);
for (auto i = value->uses().begin(); i != value->uses().end();) {
if (NodeProperties::IsEffectEdge(i.edge())) {
i.UpdateToAndIncrement(ephi1);
} else {
++i;
}
}
return Replace(phi1);
}
Reduction ChangeLowering::ChangeUint32ToTagged(Node* val, Node* control) {
STATIC_ASSERT(kSmiTag == 0);
STATIC_ASSERT(kSmiTagMask == 1);
Node* cmp = graph()->NewNode(machine()->Uint32LessThanOrEqual(), val,
SmiMaxValueConstant());
Diamond d(graph(), common(), cmp, BranchHint::kTrue);
Diamond d(graph(), common(), TestNotSmi(value), BranchHint::kFalse);
d.Chain(control);
Node* smi = graph()->NewNode(
machine()->WordShl(),
machine()->Is64()
? graph()->NewNode(machine()->ChangeUint32ToUint64(), val)
: val,
SmiShiftBitsConstant());
Node* load = LoadHeapNumberValue(value, d.if_true);
Node* number = ChangeSmiToFloat64(value);
return Replace(d.Phi(kMachFloat64, load, number));
}
Node* heap_number = AllocateHeapNumberWithValue(
graph()->NewNode(machine()->ChangeUint32ToFloat64(), val), d.if_false);
return Replace(d.Phi(kMachAnyTagged, smi, heap_number));
Reduction ChangeLowering::ChangeUint32ToTagged(Node* value, Node* control) {
Diamond d(graph(), common(),
Uint32LessThanOrEqual(value, SmiMaxValueConstant()),
BranchHint::kTrue);
d.Chain(control);
return Replace(d.Phi(
kMachAnyTagged, ChangeUint32ToSmi(value),
AllocateHeapNumberWithValue(ChangeUint32ToFloat64(value), d.if_false)));
}
......
......@@ -31,16 +31,23 @@ class ChangeLowering FINAL : public Reducer {
Node* SmiShiftBitsConstant();
Node* AllocateHeapNumberWithValue(Node* value, Node* control);
Node* ChangeInt32ToFloat64(Node* value);
Node* ChangeSmiToFloat64(Node* value);
Node* ChangeSmiToInt32(Node* value);
Node* ChangeUint32ToFloat64(Node* value);
Node* ChangeUint32ToSmi(Node* value);
Node* LoadHeapNumberValue(Node* value, Node* control);
Node* TestNotSmi(Node* value);
Node* Uint32LessThanOrEqual(Node* lhs, Node* rhs);
Reduction ChangeBitToBool(Node* val, Node* control);
Reduction ChangeBoolToBit(Node* val);
Reduction ChangeFloat64ToTagged(Node* val, Node* control);
Reduction ChangeInt32ToTagged(Node* val, Node* control);
Reduction ChangeTaggedToFloat64(Node* val, Node* control);
Reduction ChangeTaggedToUI32(Node* val, Node* control, Signedness signedness);
Reduction ChangeUint32ToTagged(Node* val, Node* control);
Reduction ChangeBitToBool(Node* value, Node* control);
Reduction ChangeBoolToBit(Node* value);
Reduction ChangeFloat64ToTagged(Node* value, Node* control);
Reduction ChangeInt32ToTagged(Node* value, Node* control);
Reduction ChangeTaggedToFloat64(Node* value, Node* control);
Reduction ChangeTaggedToUI32(Node* value, Node* control,
Signedness signedness);
Reduction ChangeUint32ToTagged(Node* value, Node* control);
Graph* graph() const;
Isolate* isolate() const;
......
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