[turbofan] Avoid unnecessary (u)int32<->float64 changes in simplified lowering.

BUG=
R=bmeurer@chromium.org, titzer@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#25045}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@25045 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
jarin@chromium.org 2014-10-31 19:53:28 +00:00
parent 6935e0131c
commit 4a9579feeb
2 changed files with 92 additions and 101 deletions

View File

@ -296,61 +296,46 @@ class RepresentationSelector {
void VisitInt64Cmp(Node* node) { VisitBinop(node, kMachInt64, kRepBit); }
void VisitUint64Cmp(Node* node) { VisitBinop(node, kMachUint64, kRepBit); }
// Infer representation for phi-like nodes.
MachineType GetRepresentationForPhi(Node* node, MachineTypeUnion use) {
// Phis adapt to the output representation their uses demand.
Type* upper = NodeProperties::GetBounds(node).upper;
if ((use & kRepMask) == kRepTagged) {
// only tagged uses.
return kRepTagged;
} else if (IsSafeIntAdditiveOperand(node)) {
// Integer within [-2^52, 2^52] range.
if ((use & kRepMask) == kRepFloat64) {
// only float64 uses.
return kRepFloat64;
} else if (upper->Is(Type::Signed32()) || upper->Is(Type::Unsigned32())) {
// multiple uses, but we are within 32 bits range => pick kRepWord32.
return kRepWord32;
} else if ((use & kRepMask) == kRepWord32 ||
(use & kTypeMask) == kTypeInt32 ||
(use & kTypeMask) == kTypeUint32) {
// The type is a safe integer, but we only use 32 bits.
return kRepWord32;
} else {
return kRepFloat64;
}
} else if (upper->Is(Type::Boolean())) {
// multiple uses => pick kRepBit.
return kRepBit;
} else if (upper->Is(Type::Number())) {
// multiple uses => pick kRepFloat64.
return kRepFloat64;
}
return kRepTagged;
}
// Helper for handling selects.
// TODO(turbofan): Share some code with VisitPhi() below?
void VisitSelect(Node* node, MachineTypeUnion use,
SimplifiedLowering* lowering) {
ProcessInput(node, 0, kRepBit);
MachineType output = GetRepresentationForPhi(node, use);
// Selects adapt to the output representation their uses demand, pushing
// representation changes to their inputs.
Type* upper = NodeProperties::GetBounds(node).upper;
MachineType output = kMachNone;
MachineType propagate = kMachNone;
if (upper->Is(Type::Signed32()) || upper->Is(Type::Unsigned32())) {
// legal = kRepTagged | kRepFloat64 | kRepWord32;
if ((use & kRepMask) == kRepTagged) {
// only tagged uses.
output = kRepTagged;
propagate = kRepTagged;
} else if ((use & kRepMask) == kRepFloat64) {
// only float64 uses.
output = kRepFloat64;
propagate = kRepFloat64;
} else {
// multiple uses.
output = kRepWord32;
propagate = kRepWord32;
}
} else if (upper->Is(Type::Boolean())) {
// legal = kRepTagged | kRepBit;
if ((use & kRepMask) == kRepTagged) {
// only tagged uses.
output = kRepTagged;
propagate = kRepTagged;
} else {
// multiple uses.
output = kRepBit;
propagate = kRepBit;
}
} else if (upper->Is(Type::Number())) {
// legal = kRepTagged | kRepFloat64;
if ((use & kRepMask) == kRepTagged) {
// only tagged uses.
output = kRepTagged;
propagate = kRepTagged;
} else {
// multiple uses.
output = kRepFloat64;
propagate = kRepFloat64;
}
} else {
// legal = kRepTagged;
output = kRepTagged;
propagate = kRepTagged;
}
MachineType output_type =
static_cast<MachineType>(changer_->TypeFromUpperBound(upper) | output);
SetOutput(node, output_type);
@ -369,7 +354,7 @@ class RepresentationSelector {
} else {
// Propagate {use} of the select to value inputs.
MachineType use_type =
static_cast<MachineType>((use & kTypeMask) | propagate);
static_cast<MachineType>((use & kTypeMask) | output);
ProcessInput(node, 1, use_type);
ProcessInput(node, 2, use_type);
}
@ -378,55 +363,9 @@ class RepresentationSelector {
// Helper for handling phis.
void VisitPhi(Node* node, MachineTypeUnion use,
SimplifiedLowering* lowering) {
// Phis adapt to the output representation their uses demand, pushing
// representation changes to their inputs.
MachineType output = GetRepresentationForPhi(node, use);
Type* upper = NodeProperties::GetBounds(node).upper;
MachineType output = kMachNone;
MachineType propagate = kMachNone;
if (upper->Is(Type::Signed32()) || upper->Is(Type::Unsigned32())) {
// legal = kRepTagged | kRepFloat64 | kRepWord32;
if ((use & kRepMask) == kRepTagged) {
// only tagged uses.
output = kRepTagged;
propagate = kRepTagged;
} else if ((use & kRepMask) == kRepFloat64) {
// only float64 uses.
output = kRepFloat64;
propagate = kRepFloat64;
} else {
// multiple uses.
output = kRepWord32;
propagate = kRepWord32;
}
} else if (upper->Is(Type::Boolean())) {
// legal = kRepTagged | kRepBit;
if ((use & kRepMask) == kRepTagged) {
// only tagged uses.
output = kRepTagged;
propagate = kRepTagged;
} else {
// multiple uses.
output = kRepBit;
propagate = kRepBit;
}
} else if (upper->Is(Type::Number())) {
// legal = kRepTagged | kRepFloat64;
if ((use & kRepMask) == kRepTagged) {
// only tagged uses.
output = kRepTagged;
propagate = kRepTagged;
} else {
// multiple uses.
output = kRepFloat64;
propagate = kRepFloat64;
}
} else {
// legal = kRepTagged;
output = kRepTagged;
propagate = kRepTagged;
}
MachineType output_type =
static_cast<MachineType>(changer_->TypeFromUpperBound(upper) | output);
SetOutput(node, output_type);
@ -451,7 +390,7 @@ class RepresentationSelector {
// Propagate {use} of the phi to value inputs, and 0 to control.
Node::Inputs inputs = node->inputs();
MachineType use_type =
static_cast<MachineType>((use & kTypeMask) | propagate);
static_cast<MachineType>((use & kTypeMask) | output);
for (Node::Inputs::iterator iter(inputs.begin()); iter != inputs.end();
++iter, --values) {
// TODO(titzer): it'd be nice to have distinguished edge kinds here.
@ -725,13 +664,15 @@ class RepresentationSelector {
case IrOpcode::kNumberToInt32: {
MachineTypeUnion use_rep = use & kRepMask;
Node* input = node->InputAt(0);
Type* in_upper = NodeProperties::GetBounds(input).upper;
MachineTypeUnion in = GetInfo(input)->output;
if (NodeProperties::GetBounds(input).upper->Is(Type::Signed32())) {
if (in_upper->Is(Type::Signed32())) {
// If the input has type int32, pass through representation.
VisitUnop(node, kTypeInt32 | use_rep, kTypeInt32 | use_rep);
if (lower()) DeferReplacement(node, node->InputAt(0));
} else if ((in & kTypeMask) == kTypeUint32 ||
(in & kTypeMask) == kTypeInt32 ||
in_upper->Is(Type::Unsigned32()) ||
(in & kRepMask) == kRepWord32) {
// Just change representation if necessary.
VisitUnop(node, kTypeInt32 | kRepWord32, kTypeInt32 | kRepWord32);
@ -748,13 +689,15 @@ class RepresentationSelector {
case IrOpcode::kNumberToUint32: {
MachineTypeUnion use_rep = use & kRepMask;
Node* input = node->InputAt(0);
Type* in_upper = NodeProperties::GetBounds(input).upper;
MachineTypeUnion in = GetInfo(input)->output;
if (NodeProperties::GetBounds(input).upper->Is(Type::Unsigned32())) {
if (in_upper->Is(Type::Unsigned32())) {
// If the input has type uint32, pass through representation.
VisitUnop(node, kTypeUint32 | use_rep, kTypeUint32 | use_rep);
if (lower()) DeferReplacement(node, node->InputAt(0));
} else if ((in & kTypeMask) == kTypeUint32 ||
(in & kTypeMask) == kTypeInt32 ||
in_upper->Is(Type::Signed32()) ||
(in & kRepMask) == kRepWord32) {
// Just change representation if necessary.
VisitUnop(node, kTypeUint32 | kRepWord32, kTypeUint32 | kRepWord32);

View File

@ -1957,3 +1957,51 @@ TEST(NumberModulus_Uint32) {
}
}
}
TEST(PhiRepresentation) {
HandleAndZoneScope scope;
Zone* z = scope.main_zone();
Factory* f = z->isolate()->factory();
Handle<Object> range_min = f->NewNumber(-1e13);
Handle<Object> range_max = f->NewNumber(1e+15);
Type* range = Type::Range(range_min, range_max, z);
struct TestData {
Type* arg1;
Type* arg2;
MachineType use;
MachineTypeUnion expected;
};
TestData test_data[] = {
{Type::Signed32(), Type::Unsigned32(), kMachInt32,
kRepWord32 | kTypeNumber},
{range, range, kMachUint32, kRepWord32 | kTypeNumber},
{Type::Signed32(), Type::Signed32(), kMachInt32, kMachInt32},
{Type::Unsigned32(), Type::Unsigned32(), kMachInt32, kMachUint32},
{Type::Number(), Type::Signed32(), kMachInt32, kMachFloat64},
{Type::Signed32(), Type::String(), kMachInt32, kMachAnyTagged}};
for (auto const d : test_data) {
TestingGraph t(d.arg1, d.arg2, Type::Boolean());
Node* br = t.graph()->NewNode(t.common()->Branch(), t.p2, t.start);
Node* tb = t.graph()->NewNode(t.common()->IfTrue(), br);
Node* fb = t.graph()->NewNode(t.common()->IfFalse(), br);
Node* m = t.graph()->NewNode(t.common()->Merge(2), tb, fb);
Node* phi =
t.graph()->NewNode(t.common()->Phi(kMachAnyTagged, 2), t.p0, t.p1, m);
Bounds phi_bounds = Bounds::Either(Bounds(d.arg1), Bounds(d.arg2), z);
NodeProperties::SetBounds(phi, phi_bounds);
Node* use = t.Use(phi, d.use);
t.Return(use);
t.Lower();
CHECK_EQ(d.expected, OpParameter<MachineType>(phi));
}
}