| 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
|
|
|