[ptr-compr][turbofan][x64] Improve comparisons with compressed heap objects

So Word32Equal(YYY, CompressedHeapConstant(XXX)) is now generated as
  cmpl [r13+0xXXX], rYYY

instead of
  movq rXXX,[r13+0xXXX]
  cmpl rYYY, rXXX

Bug: v8:8948
Change-Id: I346c3e9bdb17ae5443e9e488da0eefa07e391b33
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1841353
Reviewed-by: Tobias Tebbi <tebbi@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#64135}
This commit is contained in:
Igor Sheludko 2019-10-04 16:23:45 +02:00 committed by Commit Bot
parent 0759c506e2
commit 0910613a08
2 changed files with 45 additions and 29 deletions

View File

@ -1848,17 +1848,15 @@ void VisitWordCompare(InstructionSelector* selector, Node* node,
node->op()->HasProperty(Operator::kCommutative));
}
// Shared routine for 64-bit word comparison operations.
void VisitWord64Compare(InstructionSelector* selector, Node* node,
FlagsContinuation* cont) {
X64OperandGenerator g(selector);
void VisitWord64EqualImpl(InstructionSelector* selector, Node* node,
FlagsContinuation* cont) {
if (selector->CanUseRootsRegister()) {
X64OperandGenerator g(selector);
const RootsTable& roots_table = selector->isolate()->roots_table();
RootIndex root_index;
HeapObjectBinopMatcher m(node);
if (m.right().HasValue() &&
roots_table.IsRootHandle(m.right().Value(), &root_index)) {
if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute();
InstructionCode opcode =
kX64Cmp | AddressingModeField::encode(kMode_Root);
return VisitCompare(
@ -1866,18 +1864,30 @@ void VisitWord64Compare(InstructionSelector* selector, Node* node,
g.TempImmediate(
TurboAssemblerBase::RootRegisterOffsetForRootIndex(root_index)),
g.UseRegister(m.left().node()), cont);
} else if (m.left().HasValue() &&
roots_table.IsRootHandle(m.left().Value(), &root_index)) {
}
}
VisitWordCompare(selector, node, kX64Cmp, cont);
}
void VisitWord32EqualImpl(InstructionSelector* selector, Node* node,
FlagsContinuation* cont) {
if (COMPRESS_POINTERS_BOOL && selector->CanUseRootsRegister()) {
X64OperandGenerator g(selector);
const RootsTable& roots_table = selector->isolate()->roots_table();
RootIndex root_index;
CompressedHeapObjectBinopMatcher m(node);
if (m.right().HasValue() &&
roots_table.IsRootHandle(m.right().Value(), &root_index)) {
InstructionCode opcode =
kX64Cmp | AddressingModeField::encode(kMode_Root);
kX64Cmp32 | AddressingModeField::encode(kMode_Root);
return VisitCompare(
selector, opcode,
g.TempImmediate(
TurboAssemblerBase::RootRegisterOffsetForRootIndex(root_index)),
g.UseRegister(m.right().node()), cont);
g.UseRegister(m.left().node()), cont);
}
}
VisitWordCompare(selector, node, kX64Cmp, cont);
VisitWordCompare(selector, node, kX64Cmp32, cont);
}
// Shared routine for comparison with zero.
@ -2053,7 +2063,7 @@ void InstructionSelector::VisitWordCompareZero(Node* user, Node* value,
switch (value->opcode()) {
case IrOpcode::kWord32Equal:
cont->OverwriteAndNegateIfEqual(kEqual);
return VisitWordCompare(this, value, kX64Cmp32, cont);
return VisitWord32EqualImpl(this, value, cont);
case IrOpcode::kInt32LessThan:
cont->OverwriteAndNegateIfEqual(kSignedLessThan);
return VisitWordCompare(this, value, kX64Cmp32, cont);
@ -2076,7 +2086,7 @@ void InstructionSelector::VisitWordCompareZero(Node* user, Node* value,
if (CanCover(user, value)) {
switch (value->opcode()) {
case IrOpcode::kInt64Sub:
return VisitWord64Compare(this, value, cont);
return VisitWordCompare(this, value, kX64Cmp, cont);
case IrOpcode::kWord64And:
return VisitWordCompare(this, value, kX64Test, cont);
default:
@ -2085,20 +2095,20 @@ void InstructionSelector::VisitWordCompareZero(Node* user, Node* value,
}
return VisitCompareZero(this, user, value, kX64Cmp, cont);
}
return VisitWord64Compare(this, value, cont);
return VisitWord64EqualImpl(this, value, cont);
}
case IrOpcode::kInt64LessThan:
cont->OverwriteAndNegateIfEqual(kSignedLessThan);
return VisitWord64Compare(this, value, cont);
return VisitWordCompare(this, value, kX64Cmp, cont);
case IrOpcode::kInt64LessThanOrEqual:
cont->OverwriteAndNegateIfEqual(kSignedLessThanOrEqual);
return VisitWord64Compare(this, value, cont);
return VisitWordCompare(this, value, kX64Cmp, cont);
case IrOpcode::kUint64LessThan:
cont->OverwriteAndNegateIfEqual(kUnsignedLessThan);
return VisitWord64Compare(this, value, cont);
return VisitWordCompare(this, value, kX64Cmp, cont);
case IrOpcode::kUint64LessThanOrEqual:
cont->OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual);
return VisitWord64Compare(this, value, cont);
return VisitWordCompare(this, value, kX64Cmp, cont);
case IrOpcode::kFloat32Equal:
cont->OverwriteAndNegateIfEqual(kUnorderedEqual);
return VisitFloat32Compare(this, value, cont);
@ -2226,7 +2236,7 @@ void InstructionSelector::VisitWord32Equal(Node* const node) {
if (m.right().Is(0)) {
return VisitWordCompareZero(m.node(), m.left().node(), &cont);
}
VisitWordCompare(this, node, kX64Cmp32, &cont);
VisitWord32EqualImpl(this, node, &cont);
}
void InstructionSelector::VisitInt32LessThan(Node* node) {
@ -2251,7 +2261,7 @@ void InstructionSelector::VisitUint32LessThanOrEqual(Node* node) {
VisitWordCompare(this, node, kX64Cmp32, &cont);
}
void InstructionSelector::VisitWord64Equal(Node* const node) {
void InstructionSelector::VisitWord64Equal(Node* node) {
FlagsContinuation cont = FlagsContinuation::ForSet(kEqual, node);
Int64BinopMatcher m(node);
if (m.right().Is(0)) {
@ -2261,7 +2271,7 @@ void InstructionSelector::VisitWord64Equal(Node* const node) {
if (CanCover(user, value)) {
switch (value->opcode()) {
case IrOpcode::kInt64Sub:
return VisitWord64Compare(this, value, &cont);
return VisitWordCompare(this, value, kX64Cmp, &cont);
case IrOpcode::kWord64And:
return VisitWordCompare(this, value, kX64Test, &cont);
default:
@ -2269,7 +2279,7 @@ void InstructionSelector::VisitWord64Equal(Node* const node) {
}
}
}
VisitWord64Compare(this, node, &cont);
VisitWord64EqualImpl(this, node, &cont);
}
void InstructionSelector::VisitInt32AddWithOverflow(Node* node) {
@ -2292,24 +2302,24 @@ void InstructionSelector::VisitInt32SubWithOverflow(Node* node) {
void InstructionSelector::VisitInt64LessThan(Node* node) {
FlagsContinuation cont = FlagsContinuation::ForSet(kSignedLessThan, node);
VisitWord64Compare(this, node, &cont);
VisitWordCompare(this, node, kX64Cmp, &cont);
}
void InstructionSelector::VisitInt64LessThanOrEqual(Node* node) {
FlagsContinuation cont =
FlagsContinuation::ForSet(kSignedLessThanOrEqual, node);
VisitWord64Compare(this, node, &cont);
VisitWordCompare(this, node, kX64Cmp, &cont);
}
void InstructionSelector::VisitUint64LessThan(Node* node) {
FlagsContinuation cont = FlagsContinuation::ForSet(kUnsignedLessThan, node);
VisitWord64Compare(this, node, &cont);
VisitWordCompare(this, node, kX64Cmp, &cont);
}
void InstructionSelector::VisitUint64LessThanOrEqual(Node* node) {
FlagsContinuation cont =
FlagsContinuation::ForSet(kUnsignedLessThanOrEqual, node);
VisitWord64Compare(this, node, &cont);
VisitWordCompare(this, node, kX64Cmp, &cont);
}
void InstructionSelector::VisitFloat32Equal(Node* node) {

View File

@ -187,10 +187,11 @@ using Float64Matcher = FloatMatcher<double, IrOpcode::kFloat64Constant>;
using NumberMatcher = FloatMatcher<double, IrOpcode::kNumberConstant>;
// A pattern matcher for heap object constants.
struct HeapObjectMatcher final
: public ValueMatcher<Handle<HeapObject>, IrOpcode::kHeapConstant> {
explicit HeapObjectMatcher(Node* node)
: ValueMatcher<Handle<HeapObject>, IrOpcode::kHeapConstant>(node) {}
template <IrOpcode::Value kHeapConstantOpcode>
struct HeapObjectMatcherImpl final
: public ValueMatcher<Handle<HeapObject>, kHeapConstantOpcode> {
explicit HeapObjectMatcherImpl(Node* node)
: ValueMatcher<Handle<HeapObject>, kHeapConstantOpcode>(node) {}
bool Is(Handle<HeapObject> const& value) const {
return this->HasValue() && this->Value().address() == value.address();
@ -201,6 +202,9 @@ struct HeapObjectMatcher final
}
};
using HeapObjectMatcher = HeapObjectMatcherImpl<IrOpcode::kHeapConstant>;
using CompressedHeapObjectMatcher =
HeapObjectMatcherImpl<IrOpcode::kCompressedHeapConstant>;
// A pattern matcher for external reference constants.
struct ExternalReferenceMatcher final
@ -295,6 +299,8 @@ using Float64BinopMatcher = BinopMatcher<Float64Matcher, Float64Matcher>;
using NumberBinopMatcher = BinopMatcher<NumberMatcher, NumberMatcher>;
using HeapObjectBinopMatcher =
BinopMatcher<HeapObjectMatcher, HeapObjectMatcher>;
using CompressedHeapObjectBinopMatcher =
BinopMatcher<CompressedHeapObjectMatcher, CompressedHeapObjectMatcher>;
template <class BinopMatcher, IrOpcode::Value kMulOpcode,
IrOpcode::Value kShiftOpcode>