Commit 5d2d46e3 authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Perform element index computation in word64 on 64-bit platforms.

This allows us to fuse the address computation with the actual memory
access operation on x64, which reduces the register pressure and the
number of instructions. There's probably some follow up cleanup that has
to happen to make sure the machine operator optimizations that are
relevant to word64 computations are also available (similar to what is
already available for word32).

R=epertoso@chromium.org

Review-Url: https://codereview.chromium.org/2183043002
Cr-Commit-Position: refs/heads/master@{#38051}
parent 5c2d13a1
...@@ -370,23 +370,28 @@ void MemoryOptimizer::VisitOtherEffect(Node* node, ...@@ -370,23 +370,28 @@ void MemoryOptimizer::VisitOtherEffect(Node* node,
} }
Node* MemoryOptimizer::ComputeIndex(ElementAccess const& access, Node* key) { Node* MemoryOptimizer::ComputeIndex(ElementAccess const& access, Node* key) {
Node* index = key; Node* index;
int element_size_shift = if (machine()->Is64()) {
// On 64-bit platforms, we need to feed a Word64 index to the Load and
// Store operators. Since LoadElement or StoreElement don't do any bounds
// checking themselves, we can be sure that the {key} was already checked
// and is in valid range, so we can do the further address computation on
// Word64 below, which ideally allows us to fuse the address computation
// with the actual memory access operation on Intel platforms.
index = graph()->NewNode(machine()->ChangeUint32ToUint64(), key);
} else {
index = key;
}
int const element_size_shift =
ElementSizeLog2Of(access.machine_type.representation()); ElementSizeLog2Of(access.machine_type.representation());
if (element_size_shift) { if (element_size_shift) {
index = graph()->NewNode(machine()->Word32Shl(), index, index = graph()->NewNode(machine()->WordShl(), index,
jsgraph()->Int32Constant(element_size_shift)); jsgraph()->IntPtrConstant(element_size_shift));
} }
const int fixed_offset = access.header_size - access.tag(); int const fixed_offset = access.header_size - access.tag();
if (fixed_offset) { if (fixed_offset) {
index = graph()->NewNode(machine()->Int32Add(), index, index = graph()->NewNode(machine()->IntAdd(), index,
jsgraph()->Int32Constant(fixed_offset)); jsgraph()->IntPtrConstant(fixed_offset));
}
if (machine()->Is64()) {
// TODO(turbofan): This is probably only correct for typed arrays, and only
// if the typed arrays are at most 2GiB in size, which happens to match
// exactly our current situation.
index = graph()->NewNode(machine()->ChangeUint32ToUint64(), index);
} }
return index; return index;
} }
......
...@@ -1238,23 +1238,38 @@ void CheckFieldAccessArithmetic(FieldAccess access, Node* load_or_store) { ...@@ -1238,23 +1238,38 @@ void CheckFieldAccessArithmetic(FieldAccess access, Node* load_or_store) {
Node* CheckElementAccessArithmetic(ElementAccess access, Node* load_or_store) { Node* CheckElementAccessArithmetic(ElementAccess access, Node* load_or_store) {
Node* index = load_or_store->InputAt(1); Node* index = load_or_store->InputAt(1);
if (kPointerSize == 8) { if (kPointerSize == 8) {
Int64BinopMatcher mindex(index);
CHECK_EQ(IrOpcode::kInt64Add, mindex.node()->opcode());
CHECK(mindex.right().Is(access.header_size - access.tag()));
const int element_size_shift =
ElementSizeLog2Of(access.machine_type.representation());
Node* index;
if (element_size_shift) {
Int64BinopMatcher shl(mindex.left().node());
CHECK_EQ(IrOpcode::kWord64Shl, shl.node()->opcode());
CHECK(shl.right().Is(element_size_shift));
index = shl.left().node();
} else {
index = mindex.left().node();
}
CHECK_EQ(IrOpcode::kChangeUint32ToUint64, index->opcode()); CHECK_EQ(IrOpcode::kChangeUint32ToUint64, index->opcode());
index = index->InputAt(0); return index->InputAt(0);
}
Int32BinopMatcher mindex(index);
CHECK_EQ(IrOpcode::kInt32Add, mindex.node()->opcode());
CHECK(mindex.right().Is(access.header_size - access.tag()));
const int element_size_shift =
ElementSizeLog2Of(access.machine_type.representation());
if (element_size_shift) {
Int32BinopMatcher shl(mindex.left().node());
CHECK_EQ(IrOpcode::kWord32Shl, shl.node()->opcode());
CHECK(shl.right().Is(element_size_shift));
return shl.left().node();
} else { } else {
return mindex.left().node(); Int32BinopMatcher mindex(index);
CHECK_EQ(IrOpcode::kInt32Add, mindex.node()->opcode());
CHECK(mindex.right().Is(access.header_size - access.tag()));
const int element_size_shift =
ElementSizeLog2Of(access.machine_type.representation());
if (element_size_shift) {
Int32BinopMatcher shl(mindex.left().node());
CHECK_EQ(IrOpcode::kWord32Shl, shl.node()->opcode());
CHECK(shl.right().Is(element_size_shift));
return shl.left().node();
} else {
return mindex.left().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