[turbofan][x64] Use the root register for comparisons with certain roots.

Emit code like this

  cmpq reg, [kRootRegister + offset]

when selecting instructions for comparisons with immortal, immovable
roots. This reduces register pressure as we don't need to load those
roots into registers first.

R=jarin@chromium.org
TBR=hpayer@chromium.org

Review-Url: https://codereview.chromium.org/2396923003
Cr-Commit-Position: refs/heads/master@{#40022}
This commit is contained in:
bmeurer 2016-10-06 01:18:58 -07:00 committed by Commit bot
parent 5d6b514192
commit e17ea8ddf2
4 changed files with 40 additions and 3 deletions

View File

@ -392,9 +392,13 @@ void InstructionSelector::SetEffectLevel(Node* node, int effect_level) {
}
bool InstructionSelector::CanAddressRelativeToRootsRegister() const {
return (enable_serialization_ == kDisableSerialization &&
(linkage()->GetIncomingDescriptor()->flags() &
CallDescriptor::kCanUseRoots));
return enable_serialization_ == kDisableSerialization &&
CanUseRootsRegister();
}
bool InstructionSelector::CanUseRootsRegister() const {
return linkage()->GetIncomingDescriptor()->flags() &
CallDescriptor::kCanUseRoots;
}
void InstructionSelector::MarkAsRepresentation(MachineRepresentation rep,

View File

@ -204,6 +204,8 @@ class InstructionSelector final {
// to the roots register, i.e. if both a root register is available for this
// compilation unit and the serializer is disabled.
bool CanAddressRelativeToRootsRegister() const;
// Check if we can use the roots register to access GC roots.
bool CanUseRootsRegister() const;
Isolate* isolate() const { return sequence()->isolate(); }

View File

@ -1775,6 +1775,29 @@ void VisitWordCompare(InstructionSelector* selector, Node* node,
void VisitWord64Compare(InstructionSelector* selector, Node* node,
FlagsContinuation* cont) {
X64OperandGenerator g(selector);
if (selector->CanUseRootsRegister()) {
Heap* const heap = selector->isolate()->heap();
Heap::RootListIndex root_index;
HeapObjectBinopMatcher m(node);
if (m.right().HasValue() &&
heap->IsRootHandle(m.right().Value(), &root_index)) {
if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute();
InstructionCode opcode =
kX64Cmp | AddressingModeField::encode(kMode_Root);
return VisitCompare(
selector, opcode,
g.TempImmediate((root_index * kPointerSize) - kRootRegisterBias),
g.UseRegister(m.left().node()), cont);
} else if (m.left().HasValue() &&
heap->IsRootHandle(m.left().Value(), &root_index)) {
InstructionCode opcode =
kX64Cmp | AddressingModeField::encode(kMode_Root);
return VisitCompare(
selector, opcode,
g.TempImmediate((root_index * kPointerSize) - kRootRegisterBias),
g.UseRegister(m.right().node()), cont);
}
}
Int64BinopMatcher m(node);
if (m.left().IsLoad() && m.right().IsLoadStackPointer()) {
LoadMatcher<ExternalReferenceMatcher> mleft(m.left().node());

View File

@ -1023,6 +1023,14 @@ class Heap {
Handle<Object> root_handle(RootListIndex index) {
return Handle<Object>(&roots_[index]);
}
template <typename T>
bool IsRootHandle(Handle<T> handle, RootListIndex* index) const {
Object** const handle_location = bit_cast<Object**>(handle.address());
if (handle_location >= &roots_[kRootListLength]) return false;
if (handle_location < &roots_[0]) return false;
*index = static_cast<RootListIndex>(handle_location - &roots_[0]);
return true;
}
// Generated code can embed this address to get access to the roots.
Object** roots_array_start() { return roots_; }