[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:
parent
5d6b514192
commit
e17ea8ddf2
@ -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,
|
||||
|
@ -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(); }
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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_; }
|
||||
|
Loading…
Reference in New Issue
Block a user