Index: src/compiler/simplified-lowering.cc |
diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc |
index 35707f287b95a9135cb3067190058942bb84a0ab..43a0d5257f9e4e3400e7e2edad0c42e712adbd67 100644 |
--- a/src/compiler/simplified-lowering.cc |
+++ b/src/compiler/simplified-lowering.cc |
@@ -299,6 +299,85 @@ class RepresentationSelector { |
void VisitInt64Cmp(Node* node) { VisitBinop(node, kMachInt64, kRepBit); } |
void VisitUint64Cmp(Node* node) { VisitBinop(node, kMachUint64, kRepBit); } |
+ // Helper for handling selects. |
+ // TODO(turbofan): Share some code with VisitPhi() below? |
+ void VisitSelect(Node* node, MachineTypeUnion use, |
+ SimplifiedLowering* lowering) { |
+ ProcessInput(node, 0, kRepBit); |
+ |
+ // 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); |
+ |
+ if (lower()) { |
+ // Update the select operator. |
+ SelectParameters p = SelectParametersOf(node->op()); |
+ MachineType type = static_cast<MachineType>(output_type); |
+ if (type != p.type()) { |
+ node->set_op(lowering->common()->Select(type, p.hint())); |
+ } |
+ |
+ // Convert inputs to the output representation of this select. |
+ ProcessInput(node, 1, output_type); |
+ ProcessInput(node, 2, output_type); |
+ } else { |
+ // Propagate {use} of the select to value inputs. |
+ MachineType use_type = |
+ static_cast<MachineType>((use & kTypeMask) | propagate); |
+ ProcessInput(node, 1, use_type); |
+ ProcessInput(node, 2, use_type); |
+ } |
+ } |
+ |
// Helper for handling phis. |
void VisitPhi(Node* node, MachineTypeUnion use, |
SimplifiedLowering* lowering) { |
@@ -481,6 +560,8 @@ class RepresentationSelector { |
ProcessInput(node, 0, kRepBit); |
Enqueue(NodeProperties::GetControlInput(node, 0)); |
break; |
+ case IrOpcode::kSelect: |
+ return VisitSelect(node, use, lowering); |
case IrOpcode::kPhi: |
return VisitPhi(node, use, lowering); |
@@ -1057,25 +1138,67 @@ void SimplifiedLowering::DoStoreField(Node* node) { |
Node* SimplifiedLowering::ComputeIndex(const ElementAccess& access, |
- Node* index) { |
- int element_size = ElementSizeOf(access.machine_type); |
+ Node* const key) { |
+ Node* index = key; |
+ const int element_size = ElementSizeOf(access.machine_type); |
if (element_size != 1) { |
- index = graph()->NewNode(machine()->Int32Mul(), |
- jsgraph()->Int32Constant(element_size), index); |
+ index = graph()->NewNode(machine()->Int32Mul(), index, |
+ jsgraph()->Int32Constant(element_size)); |
+ } |
+ const int fixed_offset = access.header_size - access.tag(); |
+ if (fixed_offset != 0) { |
+ index = graph()->NewNode(machine()->Int32Add(), index, |
+ jsgraph()->Int32Constant(fixed_offset)); |
+ } |
+ // TODO(bmeurer): 64-Bit |
+ // if (machine()->Is64()) { |
+ // index = graph()->NewNode(machine()->ChangeInt32ToInt64(), index); |
+ // } |
+ return index; |
+} |
+ |
+ |
+namespace { |
+ |
+intptr_t AddressForOutOfBoundsLoad(MachineType type) { |
+ switch (RepresentationOf(type)) { |
+ case kRepFloat32: { |
+ static const float dummy = std::numeric_limits<float>::quiet_NaN(); |
+ return bit_cast<intptr_t>(&dummy); |
+ } |
+ case kRepFloat64: { |
+ static const double dummy = std::numeric_limits<double>::quiet_NaN(); |
+ return bit_cast<intptr_t>(&dummy); |
+ } |
+ case kRepBit: |
+ case kRepWord8: |
+ case kRepWord16: |
+ case kRepWord32: { |
+ static const int32_t dummy = 0; |
+ return bit_cast<intptr_t>(&dummy); |
+ } |
+ default: |
+ break; |
} |
- int fixed_offset = access.header_size - access.tag(); |
- if (fixed_offset == 0) return index; |
- return graph()->NewNode(machine()->Int32Add(), index, |
- jsgraph()->Int32Constant(fixed_offset)); |
+ UNREACHABLE(); |
+ return 0; |
} |
+intptr_t AddressForOutOfBoundsStore() { |
+ static volatile double dummy = 0; |
+ return bit_cast<intptr_t>(&dummy); |
+} |
+ |
+} // namespace |
+ |
+ |
void SimplifiedLowering::DoLoadElement(Node* node, MachineType output_type) { |
const ElementAccess& access = ElementAccessOf(node->op()); |
const Operator* op = machine()->Load(access.machine_type); |
Node* key = node->InputAt(1); |
- Node* effect = node->InputAt(3); |
Node* index = ComputeIndex(access, key); |
+ Node* effect = node->InputAt(3); |
if (access.bounds_check == kNoBoundsCheck) { |
DCHECK_EQ(access.machine_type, output_type); |
node->set_op(op); |
@@ -1087,54 +1210,68 @@ void SimplifiedLowering::DoLoadElement(Node* node, MachineType output_type) { |
Node* base = node->InputAt(0); |
Node* length = node->InputAt(2); |
- |
Node* check = graph()->NewNode(machine()->Uint32LessThan(), key, length); |
- Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), check, |
- graph()->start()); |
- |
- Node* if_true = graph()->NewNode(common()->IfTrue(), branch); |
- Node* load = graph()->NewNode(op, base, index, effect, if_true); |
- Node* result = load; |
- if (output_type & kRepTagged) { |
- // TODO(turbofan): This is ugly as hell! |
- SimplifiedOperatorBuilder simplified(graph()->zone()); |
- RepresentationChanger changer(jsgraph(), &simplified, |
- graph()->zone()->isolate()); |
- result = changer.GetTaggedRepresentationFor(result, access.machine_type); |
- } |
- Node* if_false = graph()->NewNode(common()->IfFalse(), branch); |
- Node* undefined; |
- if (output_type & kRepTagged) { |
- DCHECK(!(access.machine_type & kRepTagged)); |
- undefined = jsgraph()->UndefinedConstant(); |
- } else if (output_type & kRepFloat32) { |
- undefined = |
- jsgraph()->Float32Constant(std::numeric_limits<float>::quiet_NaN()); |
- } else if (output_type & kRepFloat64) { |
- undefined = |
- jsgraph()->Float64Constant(std::numeric_limits<double>::quiet_NaN()); |
+ IntPtrMatcher mbase(base); |
+ if (mbase.HasValue() && (output_type & kRepTagged) == 0) { |
+ Node* select = graph()->NewNode( |
+ common()->Select(kMachIntPtr, BranchHint::kTrue), check, index, |
+ jsgraph()->IntPtrConstant(AddressForOutOfBoundsLoad(output_type) - |
+ mbase.Value())); |
+ |
+ node->set_op(op); |
+ node->ReplaceInput(1, select); |
+ node->ReplaceInput(2, effect); |
+ node->ReplaceInput(3, graph()->start()); |
} else { |
- undefined = jsgraph()->Int32Constant(0); |
- } |
- |
- Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); |
- Node* phi = graph()->NewNode(common()->EffectPhi(2), load, effect, merge); |
+ Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), |
+ check, graph()->start()); |
+ |
+ Node* if_true = graph()->NewNode(common()->IfTrue(), branch); |
+ Node* load = graph()->NewNode(op, base, index, effect, if_true); |
+ Node* result = load; |
+ if (output_type & kRepTagged) { |
+ // TODO(turbofan): This is ugly as hell! |
+ SimplifiedOperatorBuilder simplified(graph()->zone()); |
+ RepresentationChanger changer(jsgraph(), &simplified, |
+ graph()->zone()->isolate()); |
+ result = |
+ changer.GetTaggedRepresentationFor(result, access.machine_type); |
+ } |
- // Replace effect uses of node with the effect phi. |
- for (UseIter i = node->uses().begin(); i != node->uses().end();) { |
- if (NodeProperties::IsEffectEdge(i.edge())) { |
- i = i.UpdateToAndIncrement(phi); |
+ Node* if_false = graph()->NewNode(common()->IfFalse(), branch); |
+ Node* undefined; |
+ if (output_type & kRepTagged) { |
+ DCHECK_EQ(0, access.machine_type & kRepTagged); |
+ undefined = jsgraph()->UndefinedConstant(); |
+ } else if (output_type & kRepFloat32) { |
+ undefined = |
+ jsgraph()->Float32Constant(std::numeric_limits<float>::quiet_NaN()); |
+ } else if (output_type & kRepFloat64) { |
+ undefined = jsgraph()->Float64Constant( |
+ std::numeric_limits<double>::quiet_NaN()); |
} else { |
- ++i; |
+ undefined = jsgraph()->Int32Constant(0); |
} |
- } |
- node->set_op(common()->Phi(output_type, 2)); |
- node->ReplaceInput(0, result); |
- node->ReplaceInput(1, undefined); |
- node->ReplaceInput(2, merge); |
- node->TrimInputCount(3); |
+ Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); |
+ Node* phi = graph()->NewNode(common()->EffectPhi(2), load, effect, merge); |
+ |
+ // Replace effect uses of node with the effect phi. |
+ for (UseIter i = node->uses().begin(); i != node->uses().end();) { |
+ if (NodeProperties::IsEffectEdge(i.edge())) { |
+ i = i.UpdateToAndIncrement(phi); |
+ } else { |
+ ++i; |
+ } |
+ } |
+ |
+ node->set_op(common()->Phi(output_type, 2)); |
+ node->ReplaceInput(0, result); |
+ node->ReplaceInput(1, undefined); |
+ node->ReplaceInput(2, merge); |
+ node->TrimInputCount(3); |
+ } |
} |
} |
@@ -1159,23 +1296,35 @@ void SimplifiedLowering::DoStoreElement(Node* node) { |
Node* value = node->InputAt(3); |
Node* effect = node->InputAt(4); |
Node* control = node->InputAt(5); |
- |
Node* check = graph()->NewNode(machine()->Uint32LessThan(), key, length); |
- Node* branch = |
- graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control); |
- Node* if_true = graph()->NewNode(common()->IfTrue(), branch); |
- Node* store = graph()->NewNode(op, base, index, value, effect, if_true); |
+ IntPtrMatcher mbase(base); |
+ if (mbase.HasValue()) { |
+ Node* select = graph()->NewNode( |
+ common()->Select(kMachIntPtr, BranchHint::kTrue), check, index, |
+ jsgraph()->IntPtrConstant(AddressForOutOfBoundsStore() - |
+ mbase.Value())); |
+ |
+ node->set_op(op); |
+ node->ReplaceInput(1, select); |
+ node->RemoveInput(2); |
+ } else { |
+ Node* branch = |
+ graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control); |
+ |
+ Node* if_true = graph()->NewNode(common()->IfTrue(), branch); |
+ Node* store = graph()->NewNode(op, base, index, value, effect, if_true); |
- Node* if_false = graph()->NewNode(common()->IfFalse(), branch); |
+ Node* if_false = graph()->NewNode(common()->IfFalse(), branch); |
- Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); |
+ Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); |
- node->set_op(common()->EffectPhi(2)); |
- node->ReplaceInput(0, store); |
- node->ReplaceInput(1, effect); |
- node->ReplaceInput(2, merge); |
- node->TrimInputCount(3); |
+ node->set_op(common()->EffectPhi(2)); |
+ node->ReplaceInput(0, store); |
+ node->ReplaceInput(1, effect); |
+ node->ReplaceInput(2, merge); |
+ node->TrimInputCount(3); |
+ } |
} |
} |
@@ -1375,7 +1524,6 @@ void SimplifiedLowering::DoStringLessThanOrEqual(Node* node) { |
node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL)); |
} |
- |
} // namespace compiler |
} // namespace internal |
} // namespace v8 |