Commit 21eb4b9d authored by Santiago Aboy Solanes's avatar Santiago Aboy Solanes Committed by Commit Bot

[cleanup][ptr-compr][turbofan] DecompressionElimination test cleanup

This is a CL that aims to do a general cleanup of DecompressionElimination
to make it easier for devs to look at it, and to create new test cases.

Combined direct decompression & compression tests since they can be
summarized with a for loop in just one test that tries out
all the combinations.

Also created 'global' accesses to stop repeating them in every test.
Same for compression and decompression ops.

Added EXPECT in test cases that had none.

Added dots after comments.

Variables now use underscore instead of camelCase.

Cq-Include-Trybots: luci.v8.try:v8_linux64_pointer_compression_rel_ng
Cq-Include-Trybots: luci.v8.try:v8_linux64_arm64_pointer_compression_rel_ng
Bug: v8:8977, v8:7703, v8:9183
Change-Id: I38a5c6549e0b4ff89c3271ead23b626e8b6b4843
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1628788Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Commit-Queue: Ross McIlroy <rmcilroy@chromium.org>
Auto-Submit: Santiago Aboy Solanes <solanes@chromium.org>
Cr-Commit-Position: refs/heads/master@{#62345}
parent 9ae5a9a1
......@@ -38,7 +38,7 @@ class V8_EXPORT_PRIVATE DecompressionElimination final
// elimination.
bool IsReducibleConstantOpcode(IrOpcode::Value opcode);
// Get the new 32 bit node constant given the 64 bit one
// Get the new 32 bit node constant given the 64 bit one.
Node* GetCompressedConstant(Node* constant);
// Removes direct Decompressions & Compressions, going from
......
......@@ -50,6 +50,46 @@ class DecompressionEliminationTest : public GraphTest {
// Return the value use of node after the reduction, if there is exactly one
return value_use;
}
const Operator* DecompressionOpFromAccess(const ElementAccess access) {
switch (access.machine_type.representation()) {
case MachineRepresentation::kCompressed:
return machine()->ChangeCompressedToTagged();
case MachineRepresentation::kCompressedSigned:
return machine()->ChangeCompressedSignedToTaggedSigned();
case MachineRepresentation::kCompressedPointer:
return machine()->ChangeCompressedPointerToTaggedPointer();
default:
UNREACHABLE();
}
}
const Operator* CompressionOpFromAccess(const ElementAccess access) {
switch (access.machine_type.representation()) {
case MachineRepresentation::kCompressed:
return machine()->ChangeTaggedToCompressed();
case MachineRepresentation::kCompressedSigned:
return machine()->ChangeTaggedSignedToCompressedSigned();
case MachineRepresentation::kCompressedPointer:
return machine()->ChangeTaggedPointerToCompressedPointer();
default:
UNREACHABLE();
}
}
// 'Global' accesses used to simplify the tests.
ElementAccess const any_access = {kTaggedBase, kTaggedSize, Type::Any(),
MachineType::AnyCompressed(),
kNoWriteBarrier};
ElementAccess const signed_access = {kTaggedBase, kTaggedSize, Type::Any(),
MachineType::CompressedSigned(),
kNoWriteBarrier};
ElementAccess const pointer_access = {kTaggedBase, kTaggedSize, Type::Any(),
MachineType::CompressedPointer(),
kNoWriteBarrier};
const ElementAccess element_accesses[3] = {any_access, signed_access,
pointer_access};
MachineOperatorBuilder* machine() { return &machine_; }
SimplifiedOperatorBuilder* simplified() { return &simplified_; }
......@@ -59,222 +99,90 @@ class DecompressionEliminationTest : public GraphTest {
};
// -----------------------------------------------------------------------------
// Direct Decompression & Compression
// Direct Decompression & Compression.
TEST_F(DecompressionEliminationTest, BasicDecompressionCompression) {
// Skip test if pointer compression is not enabled
// Skip test if pointer compression is not enabled.
if (!COMPRESS_POINTERS_BOOL) {
return;
}
// Define variables
// Define variables.
Node* const control = graph()->start();
Node* object = Parameter(Type::Any(), 0);
Node* effect = graph()->start();
Node* index = Parameter(Type::UnsignedSmall(), 1);
ElementAccess const access = {kTaggedBase, kTaggedSize, Type::Any(),
MachineType::AnyTagged(), kNoWriteBarrier};
// Create the graph
Node* load = graph()->NewNode(simplified()->LoadElement(access), object,
index, effect, control);
Node* changeToTagged =
graph()->NewNode(machine()->ChangeCompressedToTagged(), load);
Node* changeToCompressed =
graph()->NewNode(machine()->ChangeTaggedToCompressed(), changeToTagged);
effect = graph()->NewNode(simplified()->StoreElement(access), object, index,
changeToCompressed, effect, control);
// Reduce
Reduction r = Reduce(changeToCompressed);
ASSERT_TRUE(r.Changed());
EXPECT_EQ(load, r.replacement());
}
TEST_F(DecompressionEliminationTest, BasicDecompressionCompressionSigned) {
// Skip test if pointer compression is not enabled
if (!COMPRESS_POINTERS_BOOL) {
return;
}
// Define variables
Node* const control = graph()->start();
Node* object = Parameter(Type::Any(), 0);
Node* effect = graph()->start();
Node* index = Parameter(Type::UnsignedSmall(), 1);
ElementAccess const access = {kTaggedBase, kTaggedSize, Type::Any(),
MachineType::TaggedSigned(), kNoWriteBarrier};
// Create the graph
Node* load = graph()->NewNode(simplified()->LoadElement(access), object,
index, effect, control);
Node* changeToTagged =
graph()->NewNode(machine()->ChangeCompressedSignedToTaggedSigned(), load);
Node* changeToCompressed = graph()->NewNode(
machine()->ChangeTaggedSignedToCompressedSigned(), changeToTagged);
effect = graph()->NewNode(simplified()->StoreElement(access), object, index,
changeToCompressed, effect, control);
// Reduce
Reduction r = Reduce(changeToCompressed);
ASSERT_TRUE(r.Changed());
EXPECT_EQ(load, r.replacement());
}
// Pairs of <load, store> accesses
const std::pair<ElementAccess, ElementAccess> accesses[] = {
{any_access, any_access}, {signed_access, any_access},
{pointer_access, any_access}, {any_access, signed_access},
{signed_access, signed_access}, {any_access, pointer_access},
{pointer_access, pointer_access}};
TEST_F(DecompressionEliminationTest, BasicDecompressionCompressionPointer) {
// Skip test if pointer compression is not enabled
if (!COMPRESS_POINTERS_BOOL) {
return;
for (size_t i = 0; i < arraysize(accesses); ++i) {
// Create the graph.
Node* load = graph()->NewNode(simplified()->LoadElement(accesses[i].first),
object, index, effect, control);
Node* change_to_tagged =
graph()->NewNode(DecompressionOpFromAccess(accesses[i].first), load);
Node* change_to_compressed = graph()->NewNode(
CompressionOpFromAccess(accesses[i].second), change_to_tagged);
effect =
graph()->NewNode(simplified()->StoreElement(accesses[i].second), object,
index, change_to_compressed, effect, control);
// Reduce.
Reduction r = Reduce(change_to_compressed);
ASSERT_TRUE(r.Changed());
EXPECT_EQ(load, r.replacement());
}
// Define variables
Node* const control = graph()->start();
Node* object = Parameter(Type::Any(), 0);
Node* effect = graph()->start();
Node* index = Parameter(Type::UnsignedSmall(), 1);
ElementAccess const access = {kTaggedBase, kTaggedSize, Type::Any(),
MachineType::TaggedPointer(), kNoWriteBarrier};
// Create the graph
Node* load = graph()->NewNode(simplified()->LoadElement(access), object,
index, effect, control);
Node* changeToTagged = graph()->NewNode(
machine()->ChangeCompressedPointerToTaggedPointer(), load);
Node* changeToCompressed = graph()->NewNode(
machine()->ChangeTaggedPointerToCompressedPointer(), changeToTagged);
effect = graph()->NewNode(simplified()->StoreElement(access), object, index,
changeToCompressed, effect, control);
// Reduce
Reduction r = Reduce(changeToCompressed);
ASSERT_TRUE(r.Changed());
EXPECT_EQ(load, r.replacement());
}
// -----------------------------------------------------------------------------
// Direct Decompression & Compression - border cases
// For example, if we are lowering a CheckedCompressedToTaggedPointer in the
// effect linearization phase we will change that to
// ChangeCompressedPointerToTaggedPointer. Then, we might end up with a chain of
// Parent <- ChangeCompressedPointerToTaggedPointer <- ChangeTaggedToCompressed
// <- Child.
// Similarly, we have cases with Signed instead of pointer.
// The following border case tests will test that the functionality is robust
// enough to handle that.
TEST_F(DecompressionEliminationTest,
BasicDecompressionCompressionBorderCaseSigned) {
// Skip test if pointer compression is not enabled
if (!COMPRESS_POINTERS_BOOL) {
return;
}
// Define variables
Node* const control = graph()->start();
Node* object = Parameter(Type::Any(), 0);
Node* effect = graph()->start();
Node* index = Parameter(Type::UnsignedSmall(), 1);
ElementAccess const loadAccess = {kTaggedBase, kTaggedSize, Type::Any(),
MachineType::AnyTagged(), kNoWriteBarrier};
ElementAccess const storeAccess = {kTaggedBase, kTaggedSize, Type::Any(),
MachineType::TaggedSigned(),
kNoWriteBarrier};
// Create the graph
Node* load = graph()->NewNode(simplified()->LoadElement(loadAccess), object,
index, effect, control);
Node* changeToTagged =
graph()->NewNode(machine()->ChangeCompressedSignedToTaggedSigned(), load);
Node* changeToCompressed =
graph()->NewNode(machine()->ChangeTaggedToCompressed(), changeToTagged);
effect = graph()->NewNode(simplified()->StoreElement(storeAccess), object,
index, changeToCompressed, effect, control);
// Reduce
Reduction r = Reduce(changeToCompressed);
ASSERT_TRUE(r.Changed());
EXPECT_EQ(load, r.replacement());
}
// Direct Compression & Decompression
TEST_F(DecompressionEliminationTest,
BasicDecompressionCompressionBorderCasePointer) {
// Skip test if pointer compression is not enabled
TEST_F(DecompressionEliminationTest, BasicCompressionDecompression) {
// Skip test if pointer compression is not enabled.
if (!COMPRESS_POINTERS_BOOL) {
return;
}
// Define variables
// Define variables.
Node* const control = graph()->start();
Node* object = Parameter(Type::Any(), 0);
Node* effect = graph()->start();
Node* index = Parameter(Type::UnsignedSmall(), 1);
ElementAccess const loadAccess = {kTaggedBase, kTaggedSize, Type::Any(),
MachineType::AnyTagged(), kNoWriteBarrier};
ElementAccess const storeAccess = {kTaggedBase, kTaggedSize, Type::Any(),
MachineType::TaggedPointer(),
kNoWriteBarrier};
// Create the graph
Node* load = graph()->NewNode(simplified()->LoadElement(loadAccess), object,
index, effect, control);
Node* changeToTagged = graph()->NewNode(
machine()->ChangeCompressedPointerToTaggedPointer(), load);
Node* changeToCompressed =
graph()->NewNode(machine()->ChangeTaggedToCompressed(), changeToTagged);
effect = graph()->NewNode(simplified()->StoreElement(storeAccess), object,
index, changeToCompressed, effect, control);
// Reduce
Reduction r = Reduce(changeToCompressed);
ASSERT_TRUE(r.Changed());
EXPECT_EQ(load, r.replacement());
}
// We also have cases of ChangeCompressedToTagged <-
// ChangeTaggedPointerToCompressedPointer, where the
// ChangeTaggedPointerToCompressedPointer was introduced while lowering a
// NewConsString on effect control linearizer
// Pairs of <load, store> accesses
const std::pair<ElementAccess, ElementAccess> accesses[] = {
{any_access, any_access}, {signed_access, any_access},
{pointer_access, any_access}, {any_access, signed_access},
{signed_access, signed_access}, {any_access, pointer_access},
{pointer_access, pointer_access}};
TEST_F(DecompressionEliminationTest,
BasicDecompressionCompressionBorderCasePointerDecompression) {
// Skip test if pointer compression is not enabled
if (!COMPRESS_POINTERS_BOOL) {
return;
for (size_t i = 0; i < arraysize(accesses); ++i) {
// Create the graph.
Node* load = graph()->NewNode(simplified()->LoadElement(accesses[i].first),
object, index, effect, control);
Node* change_to_compressed =
graph()->NewNode(CompressionOpFromAccess(accesses[i].first), load);
Node* change_to_tagged = graph()->NewNode(
DecompressionOpFromAccess(accesses[i].second), change_to_compressed);
effect = graph()->NewNode(simplified()->StoreElement(accesses[i].second),
object, index, change_to_tagged, effect, control);
// Reduce.
Reduction r = Reduce(change_to_tagged);
ASSERT_TRUE(r.Changed());
EXPECT_EQ(load, r.replacement());
}
// Define variables
Node* const control = graph()->start();
Node* object = Parameter(Type::Any(), 0);
Node* effect = graph()->start();
Node* index = Parameter(Type::UnsignedSmall(), 1);
ElementAccess const loadAccess = {kTaggedBase, kTaggedSize, Type::Any(),
MachineType::TaggedPointer(),
kNoWriteBarrier};
ElementAccess const storeAccess = {kTaggedBase, kTaggedSize, Type::Any(),
MachineType::AnyTagged(), kNoWriteBarrier};
// Create the graph
Node* load = graph()->NewNode(simplified()->LoadElement(loadAccess), object,
index, effect, control);
Node* changeToTagged = graph()->NewNode(
machine()->ChangeCompressedPointerToTaggedPointer(), load);
Node* changeToCompressed =
graph()->NewNode(machine()->ChangeTaggedToCompressed(), changeToTagged);
effect = graph()->NewNode(simplified()->StoreElement(storeAccess), object,
index, changeToCompressed, effect, control);
// Reduce
Reduction r = Reduce(changeToCompressed);
ASSERT_TRUE(r.Changed());
EXPECT_EQ(load, r.replacement());
}
// -----------------------------------------------------------------------------
// Compress after constant
// Compress after constant.
TEST_F(DecompressionEliminationTest,
DecompressionConstantStoreElementInt64Constant) {
TEST_F(DecompressionEliminationTest, CompressionAfterInt64Constant) {
// Skip test if pointer compression is not enabled.
if (!COMPRESS_POINTERS_BOOL) {
return;
......@@ -286,21 +194,6 @@ TEST_F(DecompressionEliminationTest,
Node* effect = graph()->start();
Node* index = Parameter(Type::UnsignedSmall(), 1);
const ElementAccess element_accesses[] = {
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::AnyCompressed(),
kNoWriteBarrier},
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::CompressedSigned(),
kNoWriteBarrier},
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::CompressedPointer(),
kNoWriteBarrier}};
const Operator* compression_ops[] = {
machine()->ChangeTaggedToCompressed(),
machine()->ChangeTaggedSignedToCompressedSigned(),
machine()->ChangeTaggedPointerToCompressedPointer()};
ASSERT_EQ(arraysize(compression_ops), arraysize(element_accesses));
const int64_t constants[] = {static_cast<int64_t>(0x0000000000000000),
static_cast<int64_t>(0x0000000000000001),
static_cast<int64_t>(0x0000FFFFFFFF0000),
......@@ -311,26 +204,26 @@ TEST_F(DecompressionEliminationTest,
static_cast<int64_t>(0x8FFFFFFFFFFFFFFF),
static_cast<int64_t>(0xFFFFFFFFFFFFFFFF)};
// For every compression.
for (size_t i = 0; i < arraysize(compression_ops); ++i) {
// For every access.
for (size_t i = 0; i < arraysize(element_accesses); ++i) {
// For every Int64Constant.
for (size_t j = 0; j < arraysize(constants); ++j) {
// Create the graph.
Node* constant = graph()->NewNode(common()->Int64Constant(constants[j]));
Node* changeToCompressed = graph()->NewNode(compression_ops[i], constant);
effect =
graph()->NewNode(simplified()->StoreElement(element_accesses[i]),
object, index, changeToCompressed, effect, control);
Node* change_to_compressed = graph()->NewNode(
CompressionOpFromAccess(element_accesses[i]), constant);
effect = graph()->NewNode(simplified()->StoreElement(element_accesses[i]),
object, index, change_to_compressed, effect,
control);
// Reduce.
Reduction r = Reduce(changeToCompressed);
Reduction r = Reduce(change_to_compressed);
ASSERT_TRUE(r.Changed());
EXPECT_EQ(r.replacement()->opcode(), IrOpcode::kInt32Constant);
}
}
}
TEST_F(DecompressionEliminationTest,
DecompressionConstantStoreElementHeapConstant) {
TEST_F(DecompressionEliminationTest, CompressionAfterHeapConstant) {
// Skip test if pointer compression is not enabled.
if (!COMPRESS_POINTERS_BOOL) {
return;
......@@ -342,21 +235,6 @@ TEST_F(DecompressionEliminationTest,
Node* effect = graph()->start();
Node* index = Parameter(Type::UnsignedSmall(), 1);
const ElementAccess element_accesses[] = {
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::AnyCompressed(),
kNoWriteBarrier},
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::CompressedSigned(),
kNoWriteBarrier},
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::CompressedPointer(),
kNoWriteBarrier}};
const Operator* compression_ops[] = {
machine()->ChangeTaggedToCompressed(),
machine()->ChangeTaggedSignedToCompressedSigned(),
machine()->ChangeTaggedPointerToCompressedPointer()};
ASSERT_EQ(arraysize(compression_ops), arraysize(element_accesses));
const Handle<HeapNumber> heap_constants[] = {
factory()->NewHeapNumber(0.0),
factory()->NewHeapNumber(-0.0),
......@@ -374,19 +252,20 @@ TEST_F(DecompressionEliminationTest,
factory()->NewHeapNumber(0x8FFFFFFFFFFFFFFF),
factory()->NewHeapNumber(0xFFFFFFFFFFFFFFFF)};
// For every compression.
for (size_t i = 0; i < arraysize(compression_ops); ++i) {
// For every access.
for (size_t i = 0; i < arraysize(element_accesses); ++i) {
// For every HeapNumber.
for (size_t j = 0; j < arraysize(heap_constants); ++j) {
// Create the graph.
Node* constant =
graph()->NewNode(common()->HeapConstant(heap_constants[j]));
Node* changeToCompressed = graph()->NewNode(compression_ops[i], constant);
effect =
graph()->NewNode(simplified()->StoreElement(element_accesses[i]),
object, index, changeToCompressed, effect, control);
Node* change_to_compressed = graph()->NewNode(
CompressionOpFromAccess(element_accesses[i]), constant);
effect = graph()->NewNode(simplified()->StoreElement(element_accesses[i]),
object, index, change_to_compressed, effect,
control);
// Reduce.
Reduction r = Reduce(changeToCompressed);
Reduction r = Reduce(change_to_compressed);
ASSERT_TRUE(r.Changed());
EXPECT_EQ(r.replacement()->opcode(), IrOpcode::kCompressedHeapConstant);
}
......@@ -394,134 +273,62 @@ TEST_F(DecompressionEliminationTest,
}
// -----------------------------------------------------------------------------
// Direct Compression & Decompression
TEST_F(DecompressionEliminationTest, BasicCompressionDecompression) {
// Skip test if pointer compression is not enabled
if (!COMPRESS_POINTERS_BOOL) {
return;
}
// Define variables
Node* const control = graph()->start();
Node* object = Parameter(Type::Any(), 0);
Node* effect = graph()->start();
Node* index = Parameter(Type::UnsignedSmall(), 1);
ElementAccess const access = {kTaggedBase, kTaggedSize, Type::Any(),
MachineType::AnyTagged(), kNoWriteBarrier};
// Create the graph
Node* load = graph()->NewNode(simplified()->LoadElement(access), object,
index, effect, control);
Node* changeToCompressed =
graph()->NewNode(machine()->ChangeTaggedToCompressed(), load);
Node* changeToTagged = graph()->NewNode(machine()->ChangeCompressedToTagged(),
changeToCompressed);
effect = graph()->NewNode(simplified()->StoreElement(access), object, index,
changeToTagged, effect, control);
// Reduce
Reduction r = Reduce(changeToTagged);
ASSERT_TRUE(r.Changed());
EXPECT_EQ(load, r.replacement());
}
// -----------------------------------------------------------------------------
// Phi
// Phi.
TEST_F(DecompressionEliminationTest, PhiOneDecompress) {
// Skip test if pointer compression is not enabled
// Skip test if pointer compression is not enabled.
if (!COMPRESS_POINTERS_BOOL) {
return;
}
// Define variables
// Define variables.
Node* const control = graph()->start();
Node* object = Parameter(Type::Any(), 0);
Node* effect = graph()->start();
Node* index = Parameter(Type::UnsignedSmall(), 1);
const int number_of_inputs = 1;
const Operator* decompression_ops[] = {
machine()->ChangeCompressedToTagged(),
machine()->ChangeCompressedSignedToTaggedSigned(),
machine()->ChangeCompressedPointerToTaggedPointer()};
const ElementAccess element_accesses[] = {
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::AnyCompressed(),
kNoWriteBarrier},
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::TaggedSigned(),
kNoWriteBarrier},
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::TaggedPointer(),
kNoWriteBarrier}};
const IrOpcode::Value opcodes[] = {
IrOpcode::kChangeCompressedToTagged,
IrOpcode::kChangeCompressedSignedToTaggedSigned,
IrOpcode::kChangeCompressedPointerToTaggedPointer};
ASSERT_EQ(arraysize(decompression_ops), arraysize(element_accesses));
ASSERT_EQ(arraysize(opcodes), arraysize(element_accesses));
// For every access
// For every access.
for (size_t i = 0; i < arraysize(element_accesses); ++i) {
// Create the graph
// Create the graph.
Node* load =
graph()->NewNode(simplified()->LoadElement(element_accesses[i]), object,
index, effect, control);
Node* change_to_tagged = graph()->NewNode(decompression_ops[i], load);
Node* change_to_tagged =
graph()->NewNode(DecompressionOpFromAccess(element_accesses[i]), load);
Node* phi = graph()->NewNode(
common()->Phi(MachineRepresentation::kTagged, number_of_inputs),
change_to_tagged, control);
// Reduce
// Reduce.
StrictMock<MockAdvancedReducerEditor> editor;
EXPECT_CALL(editor, ReplaceWithValue(phi, _, _, _));
Reduction r = Reduce(&editor, phi);
ASSERT_TRUE(r.Changed());
// Get the actual decompress after the Phi, and check against the expected
// one.
Node* decompress = GetUniqueValueUse(phi);
EXPECT_NE(nullptr, decompress);
EXPECT_EQ(opcodes[i], decompress->opcode());
EXPECT_EQ(DecompressionOpFromAccess(element_accesses[i]), decompress->op());
}
}
TEST_F(DecompressionEliminationTest, PhiThreeDecompressSameRepresentation) {
// Skip test if pointer compression is not enabled
// Skip test if pointer compression is not enabled.
if (!COMPRESS_POINTERS_BOOL) {
return;
}
// Define variables
// Define variables.
Node* const control = graph()->start();
Node* object = Parameter(Type::Any(), 0);
Node* effect = graph()->start();
Node* index = Parameter(Type::UnsignedSmall(), 1);
const int number_of_inputs = 3;
const Operator* decompression_ops[] = {
machine()->ChangeCompressedToTagged(),
machine()->ChangeCompressedSignedToTaggedSigned(),
machine()->ChangeCompressedPointerToTaggedPointer()};
const ElementAccess element_accesses[] = {
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::AnyCompressed(),
kNoWriteBarrier},
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::CompressedSigned(),
kNoWriteBarrier},
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::CompressedPointer(),
kNoWriteBarrier}};
const IrOpcode::Value opcodes[] = {
IrOpcode::kChangeCompressedToTagged,
IrOpcode::kChangeCompressedSignedToTaggedSigned,
IrOpcode::kChangeCompressedPointerToTaggedPointer};
ASSERT_EQ(arraysize(decompression_ops), arraysize(element_accesses));
ASSERT_EQ(arraysize(opcodes), arraysize(element_accesses));
// For every access
// For every access.
for (size_t i = 0; i < arraysize(element_accesses); ++i) {
// Create the graph
// Create the graph.
Node* load1 =
graph()->NewNode(simplified()->LoadElement(element_accesses[i]), object,
index, effect, control);
......@@ -531,123 +338,98 @@ TEST_F(DecompressionEliminationTest, PhiThreeDecompressSameRepresentation) {
Node* load3 =
graph()->NewNode(simplified()->LoadElement(element_accesses[i]), object,
index, effect, control);
Node* change_to_tagged1 = graph()->NewNode(decompression_ops[i], load1);
Node* change_to_tagged2 = graph()->NewNode(decompression_ops[i], load2);
Node* change_to_tagged3 = graph()->NewNode(decompression_ops[i], load3);
Node* change_to_tagged_1 =
graph()->NewNode(DecompressionOpFromAccess(element_accesses[i]), load1);
Node* change_to_tagged_2 =
graph()->NewNode(DecompressionOpFromAccess(element_accesses[i]), load2);
Node* change_to_tagged_3 =
graph()->NewNode(DecompressionOpFromAccess(element_accesses[i]), load3);
Node* phi = graph()->NewNode(
common()->Phi(MachineRepresentation::kTagged, number_of_inputs),
change_to_tagged1, change_to_tagged2, change_to_tagged3, control);
change_to_tagged_1, change_to_tagged_2, change_to_tagged_3, control);
// Reduce
// Reduce.
StrictMock<MockAdvancedReducerEditor> editor;
EXPECT_CALL(editor, ReplaceWithValue(phi, _, _, _));
Reduction r = Reduce(&editor, phi);
ASSERT_TRUE(r.Changed());
// Get the actual decompress after the Phi, and check against the expected
// one.
Node* decompress = GetUniqueValueUse(phi);
EXPECT_NE(nullptr, decompress);
EXPECT_EQ(opcodes[i], decompress->opcode());
EXPECT_EQ(DecompressionOpFromAccess(element_accesses[i]), decompress->op());
}
}
TEST_F(DecompressionEliminationTest, PhiThreeDecompressOneAnyRepresentation) {
// Skip test if pointer compression is not enabled
// Skip test if pointer compression is not enabled.
if (!COMPRESS_POINTERS_BOOL) {
return;
}
// Define variables
// Define variables.
Node* const control = graph()->start();
Node* object = Parameter(Type::Any(), 0);
Node* effect = graph()->start();
Node* index = Parameter(Type::UnsignedSmall(), 1);
const int number_of_inputs = 3;
const Operator* decompression_ops[] = {
machine()->ChangeCompressedSignedToTaggedSigned(),
machine()->ChangeCompressedPointerToTaggedPointer()};
const ElementAccess element_accesses[] = {
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::CompressedSigned(),
kNoWriteBarrier},
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::CompressedPointer(),
kNoWriteBarrier}};
const ElementAccess any_access = {kTaggedBase, kTaggedSize, Type::Any(),
MachineType::AnyCompressed(),
kNoWriteBarrier};
ASSERT_EQ(arraysize(decompression_ops), arraysize(element_accesses));
// Signed and Pointer (and not Any) accesses.
const ElementAccess not_any_accesses[] = {signed_access, pointer_access};
// For every access
for (size_t i = 0; i < arraysize(element_accesses); ++i) {
// Create the graph
// For every access.
for (size_t i = 0; i < arraysize(not_any_accesses); ++i) {
// Create the graph.
Node* load1 =
graph()->NewNode(simplified()->LoadElement(element_accesses[i]), object,
graph()->NewNode(simplified()->LoadElement(not_any_accesses[i]), object,
index, effect, control);
Node* load2 =
graph()->NewNode(simplified()->LoadElement(element_accesses[i]), object,
graph()->NewNode(simplified()->LoadElement(not_any_accesses[i]), object,
index, effect, control);
// Note that load3 loads a CompressedAny instead of element_accesses[i]
// Note that load3 loads a CompressedAny instead of not_any_accesses[i]
Node* load3 = graph()->NewNode(simplified()->LoadElement(any_access),
object, index, effect, control);
Node* change_to_tagged1 = graph()->NewNode(decompression_ops[i], load1);
Node* change_to_tagged2 = graph()->NewNode(decompression_ops[i], load2);
Node* change_to_tagged3 =
Node* change_to_tagged_1 =
graph()->NewNode(DecompressionOpFromAccess(not_any_accesses[i]), load1);
Node* change_to_tagged_2 =
graph()->NewNode(DecompressionOpFromAccess(not_any_accesses[i]), load2);
Node* change_to_tagged_3 =
graph()->NewNode(machine()->ChangeCompressedToTagged(), load3);
Node* phi = graph()->NewNode(
common()->Phi(MachineRepresentation::kTagged, number_of_inputs),
change_to_tagged1, change_to_tagged2, change_to_tagged3, control);
change_to_tagged_1, change_to_tagged_2, change_to_tagged_3, control);
// Reduce
// Reduce.
StrictMock<MockAdvancedReducerEditor> editor;
EXPECT_CALL(editor, ReplaceWithValue(phi, _, _, _));
Reduction r = Reduce(&editor, phi);
ASSERT_TRUE(r.Changed());
// Get the actual decompress after the Phi, and check against the expected
// one.
Node* decompress = GetUniqueValueUse(phi);
EXPECT_NE(nullptr, decompress);
EXPECT_EQ(IrOpcode::kChangeCompressedToTagged, decompress->opcode());
EXPECT_EQ(machine()->ChangeCompressedToTagged(), decompress->op());
}
}
TEST_F(DecompressionEliminationTest, PhiThreeInputsOneNotDecompressed) {
// Skip test if pointer compression is not enabled
// Skip test if pointer compression is not enabled.
if (!COMPRESS_POINTERS_BOOL) {
return;
}
// Define variables
// Define variables.
Node* const control = graph()->start();
Node* object = Parameter(Type::Any(), 0);
Node* effect = graph()->start();
Node* index = Parameter(Type::UnsignedSmall(), 1);
const int number_of_inputs = 3;
const Operator* decompression_ops[] = {
machine()->ChangeCompressedToTagged(),
machine()->ChangeCompressedSignedToTaggedSigned(),
machine()->ChangeCompressedPointerToTaggedPointer()};
const ElementAccess element_accesses[] = {
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::AnyCompressed(),
kNoWriteBarrier},
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::CompressedSigned(),
kNoWriteBarrier},
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::CompressedPointer(),
kNoWriteBarrier}};
const IrOpcode::Value opcodes[] = {
IrOpcode::kChangeCompressedToTagged,
IrOpcode::kChangeCompressedSignedToTaggedSigned,
IrOpcode::kChangeCompressedPointerToTaggedPointer};
ASSERT_EQ(arraysize(decompression_ops), arraysize(element_accesses));
ASSERT_EQ(arraysize(opcodes), arraysize(element_accesses));
// For every access
// For every access.
for (size_t i = 0; i < arraysize(element_accesses); ++i) {
// Create the graph
// Create the graph.
Node* load1 =
graph()->NewNode(simplified()->LoadElement(element_accesses[i]), object,
index, effect, control);
......@@ -657,14 +439,16 @@ TEST_F(DecompressionEliminationTest, PhiThreeInputsOneNotDecompressed) {
Node* load3 =
graph()->NewNode(simplified()->LoadElement(element_accesses[i]), object,
index, effect, control);
Node* change_to_tagged1 = graph()->NewNode(decompression_ops[i], load1);
Node* change_to_tagged2 = graph()->NewNode(decompression_ops[i], load2);
Node* change_to_tagged_1 =
graph()->NewNode(DecompressionOpFromAccess(element_accesses[i]), load1);
Node* change_to_tagged_2 =
graph()->NewNode(DecompressionOpFromAccess(element_accesses[i]), load2);
Node* phi = graph()->NewNode(
common()->Phi(MachineRepresentation::kTagged, number_of_inputs),
change_to_tagged1, change_to_tagged2, load3, control);
change_to_tagged_1, change_to_tagged_2, load3, control);
// Reduce
// Reduce.
Reduction r = Reduce(phi);
ASSERT_FALSE(r.Changed());
}
......@@ -673,291 +457,251 @@ TEST_F(DecompressionEliminationTest, PhiThreeInputsOneNotDecompressed) {
// In the case of having one decompress Signed and one Pointer, we have to
// generate the conservative decompress any after the Phi.
TEST_F(DecompressionEliminationTest, PhiTwoDecompressesOneSignedOnePointer) {
// Skip test if pointer compression is not enabled
// Skip test if pointer compression is not enabled.
if (!COMPRESS_POINTERS_BOOL) {
return;
}
// Define variables
// Define variables.
Node* const control = graph()->start();
Node* object = Parameter(Type::Any(), 0);
Node* effect = graph()->start();
Node* index = Parameter(Type::UnsignedSmall(), 1);
const int number_of_inputs = 2;
const ElementAccess signed_access = {kTaggedBase, kTaggedSize, Type::Any(),
MachineType::CompressedSigned(),
kNoWriteBarrier};
const ElementAccess pointer_access = {kTaggedBase, kTaggedSize, Type::Any(),
MachineType::CompressedPointer(),
kNoWriteBarrier};
// Create the graph
// Create the graph.
Node* load1 = graph()->NewNode(simplified()->LoadElement(signed_access),
object, index, effect, control);
Node* load2 = graph()->NewNode(simplified()->LoadElement(pointer_access),
object, index, effect, control);
Node* change_to_tagged1 = graph()->NewNode(
machine()->ChangeCompressedSignedToTaggedSigned(), load1);
Node* change_to_tagged2 = graph()->NewNode(
machine()->ChangeCompressedPointerToTaggedPointer(), load2);
Node* change_to_tagged_1 =
graph()->NewNode(DecompressionOpFromAccess(signed_access), load1);
Node* change_to_tagged_2 =
graph()->NewNode(DecompressionOpFromAccess(pointer_access), load2);
Node* phi = graph()->NewNode(
common()->Phi(MachineRepresentation::kTagged, number_of_inputs),
change_to_tagged1, change_to_tagged2, control);
change_to_tagged_1, change_to_tagged_2, control);
// Reduce
// Reduce.
StrictMock<MockAdvancedReducerEditor> editor;
EXPECT_CALL(editor, ReplaceWithValue(phi, _, _, _));
Reduction r = Reduce(&editor, phi);
ASSERT_TRUE(r.Changed());
// Get the actual decompress after the Phi, and check against the expected
// one.
Node* decompress = GetUniqueValueUse(phi);
EXPECT_NE(nullptr, decompress);
EXPECT_EQ(IrOpcode::kChangeCompressedToTagged, decompress->opcode());
EXPECT_EQ(machine()->ChangeCompressedToTagged(), decompress->op());
}
// -----------------------------------------------------------------------------
// TypedStateValues
// TypedStateValues.
TEST_F(DecompressionEliminationTest, TypedStateValuesOneDecompress) {
// Skip test if pointer compression is not enabled
// Skip test if pointer compression is not enabled.
if (!COMPRESS_POINTERS_BOOL) {
return;
}
// Define variables
// Define variables.
Node* const control = graph()->start();
Node* object = Parameter(Type::Any(), 0);
Node* effect = graph()->start();
Node* index = Parameter(Type::UnsignedSmall(), 1);
const int numberOfInputs = 1;
const int number_of_inputs = 1;
const ZoneVector<MachineType>* types =
new (graph()->zone()->New(sizeof(ZoneVector<MachineType>)))
ZoneVector<MachineType>(numberOfInputs, graph()->zone());
ZoneVector<MachineType>(number_of_inputs, graph()->zone());
SparseInputMask dense = SparseInputMask::Dense();
const ElementAccess ElementAccesses[] = {
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::AnyTagged(),
kNoWriteBarrier},
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::TaggedSigned(),
kNoWriteBarrier},
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::TaggedPointer(),
kNoWriteBarrier}};
// For every access
for (size_t i = 0; i < arraysize(ElementAccesses); ++i) {
// Create the graph
Node* load = graph()->NewNode(simplified()->LoadElement(ElementAccesses[i]),
object, index, effect, control);
Node* changeToTagged = graph()->NewNode(
machine()->ChangeCompressedPointerToTaggedPointer(), load);
Node* typedStateValuesOneDecompress = graph()->NewNode(
common()->TypedStateValues(types, dense), changeToTagged);
// For every access.
for (size_t i = 0; i < arraysize(element_accesses); ++i) {
// Create the graph.
Node* load =
graph()->NewNode(simplified()->LoadElement(element_accesses[i]), object,
index, effect, control);
Node* change_to_tagged =
graph()->NewNode(DecompressionOpFromAccess(element_accesses[i]), load);
Node* typedStateValues = graph()->NewNode(
common()->TypedStateValues(types, dense), change_to_tagged);
// Reduce
// Reduce.
StrictMock<MockAdvancedReducerEditor> editor;
DecompressionElimination decompression_elimination(&editor, graph(),
machine(), common());
Reduction r =
decompression_elimination.Reduce(typedStateValuesOneDecompress);
Reduction r = decompression_elimination.Reduce(typedStateValues);
ASSERT_TRUE(r.Changed());
EXPECT_EQ(r.replacement()->InputAt(0), load);
}
}
TEST_F(DecompressionEliminationTest, TypedStateValuesTwoDecompresses) {
// Skip test if pointer compression is not enabled
// Skip test if pointer compression is not enabled.
if (!COMPRESS_POINTERS_BOOL) {
return;
}
// Define variables
// Define variables.
Node* const control = graph()->start();
Node* object = Parameter(Type::Any(), 0);
Node* effect = graph()->start();
Node* index = Parameter(Type::UnsignedSmall(), 1);
const int numberOfInputs = 3;
const int number_of_inputs = 3;
const ZoneVector<MachineType>* types =
new (graph()->zone()->New(sizeof(ZoneVector<MachineType>)))
ZoneVector<MachineType>(numberOfInputs, graph()->zone());
ZoneVector<MachineType>(number_of_inputs, graph()->zone());
SparseInputMask dense = SparseInputMask::Dense();
const ElementAccess ElementAccesses[] = {
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::AnyTagged(),
kNoWriteBarrier},
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::TaggedSigned(),
kNoWriteBarrier},
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::TaggedPointer(),
kNoWriteBarrier}};
// For every access
for (size_t i = 0; i < arraysize(ElementAccesses); ++i) {
// Create the graph
// For every access.
for (size_t i = 0; i < arraysize(element_accesses); ++i) {
// Create the graph.
Node* load1 =
graph()->NewNode(simplified()->LoadElement(ElementAccesses[i]), object,
graph()->NewNode(simplified()->LoadElement(element_accesses[i]), object,
index, effect, control);
Node* changeToTagged1 = graph()->NewNode(
machine()->ChangeCompressedPointerToTaggedPointer(), load1);
Node* change_to_tagged_1 =
graph()->NewNode(DecompressionOpFromAccess(element_accesses[i]), load1);
Node* load2 =
graph()->NewNode(simplified()->LoadElement(ElementAccesses[i]), object,
graph()->NewNode(simplified()->LoadElement(element_accesses[i]), object,
index, effect, control);
Node* changeToTagged2 = graph()->NewNode(
machine()->ChangeCompressedPointerToTaggedPointer(), load2);
Node* typedStateValuesOneDecompress =
Node* change_to_tagged_2 =
graph()->NewNode(DecompressionOpFromAccess(element_accesses[i]), load2);
Node* typedStateValues =
graph()->NewNode(common()->TypedStateValues(types, dense),
changeToTagged1, load1, changeToTagged2);
change_to_tagged_1, load1, change_to_tagged_2);
// Reduce
// Reduce.
StrictMock<MockAdvancedReducerEditor> editor;
DecompressionElimination decompression_elimination(&editor, graph(),
machine(), common());
Reduction r =
decompression_elimination.Reduce(typedStateValuesOneDecompress);
Reduction r = decompression_elimination.Reduce(typedStateValues);
ASSERT_TRUE(r.Changed());
EXPECT_EQ(r.replacement()->InputAt(0), load1);
// Note that the input at index 1 didn't change.
EXPECT_EQ(r.replacement()->InputAt(1), load1);
EXPECT_EQ(r.replacement()->InputAt(2), load2);
}
}
TEST_F(DecompressionEliminationTest, TypedStateValuesAllDecompresses) {
// Skip test if pointer compression is not enabled
// Skip test if pointer compression is not enabled.
if (!COMPRESS_POINTERS_BOOL) {
return;
}
// Define variables
// Define variables.
Node* const control = graph()->start();
Node* object = Parameter(Type::Any(), 0);
Node* effect = graph()->start();
Node* index = Parameter(Type::UnsignedSmall(), 1);
const int numberOfInputs = 3;
const int number_of_inputs = 3;
const ZoneVector<MachineType>* types =
new (graph()->zone()->New(sizeof(ZoneVector<MachineType>)))
ZoneVector<MachineType>(numberOfInputs, graph()->zone());
ZoneVector<MachineType>(number_of_inputs, graph()->zone());
SparseInputMask dense = SparseInputMask::Dense();
const ElementAccess ElementAccesses[] = {
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::AnyTagged(),
kNoWriteBarrier},
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::TaggedSigned(),
kNoWriteBarrier},
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::TaggedPointer(),
kNoWriteBarrier}};
// For every access
for (size_t i = 0; i < arraysize(ElementAccesses); ++i) {
// Create the graph
// For every access.
for (size_t i = 0; i < arraysize(element_accesses); ++i) {
// Create the graph.
Node* load1 =
graph()->NewNode(simplified()->LoadElement(ElementAccesses[i]), object,
graph()->NewNode(simplified()->LoadElement(element_accesses[i]), object,
index, effect, control);
Node* changeToTagged1 = graph()->NewNode(
machine()->ChangeCompressedPointerToTaggedPointer(), load1);
Node* change_to_tagged_1 =
graph()->NewNode(DecompressionOpFromAccess(element_accesses[i]), load1);
Node* load2 =
graph()->NewNode(simplified()->LoadElement(ElementAccesses[i]), object,
graph()->NewNode(simplified()->LoadElement(element_accesses[i]), object,
index, effect, control);
Node* changeToTagged2 = graph()->NewNode(
machine()->ChangeCompressedPointerToTaggedPointer(), load2);
Node* change_to_tagged_2 =
graph()->NewNode(DecompressionOpFromAccess(element_accesses[i]), load2);
Node* load3 =
graph()->NewNode(simplified()->LoadElement(ElementAccesses[i]), object,
graph()->NewNode(simplified()->LoadElement(element_accesses[i]), object,
index, effect, control);
Node* changeToTagged3 = graph()->NewNode(
machine()->ChangeCompressedPointerToTaggedPointer(), load3);
Node* typedStateValuesOneDecompress =
graph()->NewNode(common()->TypedStateValues(types, dense),
changeToTagged1, changeToTagged2, changeToTagged3);
Node* change_to_tagged_3 =
graph()->NewNode(DecompressionOpFromAccess(element_accesses[i]), load3);
Node* typedStateValues = graph()->NewNode(
common()->TypedStateValues(types, dense), change_to_tagged_1,
change_to_tagged_2, change_to_tagged_3);
// Reduce
// Reduce.
StrictMock<MockAdvancedReducerEditor> editor;
DecompressionElimination decompression_elimination(&editor, graph(),
machine(), common());
Reduction r =
decompression_elimination.Reduce(typedStateValuesOneDecompress);
Reduction r = decompression_elimination.Reduce(typedStateValues);
ASSERT_TRUE(r.Changed());
EXPECT_EQ(r.replacement()->InputAt(0), load1);
EXPECT_EQ(r.replacement()->InputAt(1), load2);
EXPECT_EQ(r.replacement()->InputAt(2), load3);
}
}
TEST_F(DecompressionEliminationTest, TypedStateValuesNoDecompresses) {
// Skip test if pointer compression is not enabled
// Skip test if pointer compression is not enabled.
if (!COMPRESS_POINTERS_BOOL) {
return;
}
// Define variables
// Define variables.
Node* const control = graph()->start();
Node* object = Parameter(Type::Any(), 0);
Node* effect = graph()->start();
Node* index = Parameter(Type::UnsignedSmall(), 1);
const int numberOfInputs = 3;
const int number_of_inputs = 3;
const ZoneVector<MachineType>* types =
new (graph()->zone()->New(sizeof(ZoneVector<MachineType>)))
ZoneVector<MachineType>(numberOfInputs, graph()->zone());
ZoneVector<MachineType>(number_of_inputs, graph()->zone());
SparseInputMask dense = SparseInputMask::Dense();
const ElementAccess ElementAccesses[] = {
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::AnyTagged(),
kNoWriteBarrier},
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::TaggedSigned(),
kNoWriteBarrier},
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::TaggedPointer(),
kNoWriteBarrier}};
// For every access
for (size_t i = 0; i < arraysize(ElementAccesses); ++i) {
// Create the graph
Node* load = graph()->NewNode(simplified()->LoadElement(ElementAccesses[i]),
object, index, effect, control);
Node* typedStateValuesOneDecompress = graph()->NewNode(
// For every access.
for (size_t i = 0; i < arraysize(element_accesses); ++i) {
// Create the graph.
Node* load =
graph()->NewNode(simplified()->LoadElement(element_accesses[i]), object,
index, effect, control);
Node* typedStateValues = graph()->NewNode(
common()->TypedStateValues(types, dense), load, load, load);
// Reduce
// Reduce.
StrictMock<MockAdvancedReducerEditor> editor;
DecompressionElimination decompression_elimination(&editor, graph(),
machine(), common());
Reduction r =
decompression_elimination.Reduce(typedStateValuesOneDecompress);
Reduction r = decompression_elimination.Reduce(typedStateValues);
ASSERT_FALSE(r.Changed());
}
}
// -----------------------------------------------------------------------------
// Word64Equal comparison of two decompressions
// Word64Equal comparison of two decompressions.
TEST_F(DecompressionEliminationTest, TwoDecompressionWord64Equal) {
// Skip test if pointer compression is not enabled
// Skip test if pointer compression is not enabled.
if (!COMPRESS_POINTERS_BOOL) {
return;
}
// Define variables
// Define variables.
Node* const control = graph()->start();
Node* object = Parameter(Type::Any(), 0);
Node* effect = graph()->start();
Node* index = Parameter(Type::UnsignedSmall(), 1);
const Operator* DecompressionOps[] = {
machine()->ChangeCompressedToTagged(),
machine()->ChangeCompressedSignedToTaggedSigned(),
machine()->ChangeCompressedPointerToTaggedPointer()};
const ElementAccess ElementAccesses[] = {
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::AnyTagged(),
kNoWriteBarrier},
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::TaggedSigned(),
kNoWriteBarrier},
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::TaggedPointer(),
kNoWriteBarrier}};
ASSERT_EQ(arraysize(DecompressionOps), arraysize(ElementAccesses));
// For every decompression (lhs)
for (size_t j = 0; j < arraysize(DecompressionOps); ++j) {
// For every decompression (lhs).
for (size_t i = 0; i < arraysize(element_accesses); ++i) {
// For every decompression (rhs)
for (size_t k = 0; k < arraysize(DecompressionOps); ++k) {
// Create the graph
for (size_t j = 0; j < arraysize(element_accesses); ++j) {
// Create the graph.
Node* load1 =
graph()->NewNode(simplified()->LoadElement(ElementAccesses[j]),
graph()->NewNode(simplified()->LoadElement(element_accesses[i]),
object, index, effect, control);
Node* changeToTagged1 = graph()->NewNode(DecompressionOps[j], load1);
Node* change_to_tagged_1 = graph()->NewNode(
DecompressionOpFromAccess(element_accesses[i]), load1);
Node* load2 =
graph()->NewNode(simplified()->LoadElement(ElementAccesses[k]),
graph()->NewNode(simplified()->LoadElement(element_accesses[j]),
object, index, effect, control);
Node* changeToTagged2 = graph()->NewNode(DecompressionOps[j], load2);
Node* comparison = graph()->NewNode(machine()->Word64Equal(),
changeToTagged1, changeToTagged2);
// Reduce
Node* change_to_tagged_2 = graph()->NewNode(
DecompressionOpFromAccess(element_accesses[i]), load2);
Node* comparison = graph()->NewNode(
machine()->Word64Equal(), change_to_tagged_1, change_to_tagged_2);
// Reduce.
Reduction r = Reduce(comparison);
ASSERT_TRUE(r.Changed());
EXPECT_EQ(r.replacement()->opcode(), IrOpcode::kWord32Equal);
......@@ -966,44 +710,31 @@ TEST_F(DecompressionEliminationTest, TwoDecompressionWord64Equal) {
}
// -----------------------------------------------------------------------------
// Word64Equal comparison of two decompressions, where lhs == rhs
// Word64Equal comparison of two decompressions, where lhs == rhs.
TEST_F(DecompressionEliminationTest, TwoDecompressionWord64EqualSameInput) {
// Skip test if pointer compression is not enabled
// Skip test if pointer compression is not enabled.
if (!COMPRESS_POINTERS_BOOL) {
return;
}
// Define variables
// Define variables.
Node* const control = graph()->start();
Node* object = Parameter(Type::Any(), 0);
Node* effect = graph()->start();
Node* index = Parameter(Type::UnsignedSmall(), 1);
const Operator* DecompressionOps[] = {
machine()->ChangeCompressedToTagged(),
machine()->ChangeCompressedSignedToTaggedSigned(),
machine()->ChangeCompressedPointerToTaggedPointer()};
const ElementAccess ElementAccesses[] = {
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::AnyTagged(),
kNoWriteBarrier},
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::TaggedSigned(),
kNoWriteBarrier},
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::TaggedPointer(),
kNoWriteBarrier}};
ASSERT_EQ(arraysize(DecompressionOps), arraysize(ElementAccesses));
// For every decompression (same for lhs and rhs)
for (size_t j = 0; j < arraysize(DecompressionOps); ++j) {
// Create the graph
Node* load = graph()->NewNode(simplified()->LoadElement(ElementAccesses[j]),
object, index, effect, control);
Node* changeToTagged = graph()->NewNode(DecompressionOps[j], load);
// For every access. (same for lhs and rhs)
for (size_t i = 0; i < arraysize(element_accesses); ++i) {
// Create the graph.
Node* load =
graph()->NewNode(simplified()->LoadElement(element_accesses[i]), object,
index, effect, control);
Node* change_to_tagged =
graph()->NewNode(DecompressionOpFromAccess(element_accesses[i]), load);
Node* comparison = graph()->NewNode(machine()->Word64Equal(),
changeToTagged, changeToTagged);
// Reduce
change_to_tagged, change_to_tagged);
// Reduce.
Reduction r = Reduce(comparison);
ASSERT_TRUE(r.Changed());
EXPECT_EQ(r.replacement()->opcode(), IrOpcode::kWord32Equal);
......@@ -1011,35 +742,20 @@ TEST_F(DecompressionEliminationTest, TwoDecompressionWord64EqualSameInput) {
}
// -----------------------------------------------------------------------------
// Word64Equal comparison of decompress and a constant
// Word64Equal comparison of decompress and a constant.
TEST_F(DecompressionEliminationTest, DecompressionConstantWord64Equal) {
// Skip test if pointer compression is not enabled
// Skip test if pointer compression is not enabled.
if (!COMPRESS_POINTERS_BOOL) {
return;
}
// Define variables
// Define variables.
Node* const control = graph()->start();
Node* object = Parameter(Type::Any(), 0);
Node* effect = graph()->start();
Node* index = Parameter(Type::UnsignedSmall(), 1);
const Operator* DecompressionOps[] = {
machine()->ChangeCompressedToTagged(),
machine()->ChangeCompressedSignedToTaggedSigned(),
machine()->ChangeCompressedPointerToTaggedPointer()};
const ElementAccess ElementAccesses[] = {
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::AnyTagged(),
kNoWriteBarrier},
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::TaggedSigned(),
kNoWriteBarrier},
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::TaggedPointer(),
kNoWriteBarrier}};
ASSERT_EQ(arraysize(DecompressionOps), arraysize(ElementAccesses));
const int64_t constants[] = {static_cast<int64_t>(0x0000000000000000),
static_cast<int64_t>(0x0000000000000001),
static_cast<int64_t>(0x0000FFFFFFFF0000),
......@@ -1050,24 +766,25 @@ TEST_F(DecompressionEliminationTest, DecompressionConstantWord64Equal) {
static_cast<int64_t>(0x8FFFFFFFFFFFFFFF),
static_cast<int64_t>(0xFFFFFFFFFFFFFFFF)};
// For every decompression (lhs)
for (size_t j = 0; j < arraysize(DecompressionOps); ++j) {
// For every constant (rhs)
for (size_t k = 0; k < arraysize(constants); ++k) {
// Test with both (lhs, rhs) combinations
for (bool lhsIsDecompression : {false, true}) {
// Create the graph
// For every decompression (lhs).
for (size_t i = 0; i < arraysize(element_accesses); ++i) {
// For every constant (rhs).
for (size_t j = 0; j < arraysize(constants); ++j) {
// Test with both (lhs, rhs) combinations.
for (bool lhs_is_decompression : {false, true}) {
// Create the graph.
Node* load =
graph()->NewNode(simplified()->LoadElement(ElementAccesses[j]),
graph()->NewNode(simplified()->LoadElement(element_accesses[i]),
object, index, effect, control);
Node* changeToTagged = graph()->NewNode(DecompressionOps[j], load);
Node* change_to_tagged = graph()->NewNode(
DecompressionOpFromAccess(element_accesses[i]), load);
Node* constant =
graph()->NewNode(common()->Int64Constant(constants[k]));
graph()->NewNode(common()->Int64Constant(constants[j]));
Node* lhs = lhsIsDecompression ? changeToTagged : constant;
Node* rhs = lhsIsDecompression ? constant : changeToTagged;
Node* lhs = lhs_is_decompression ? change_to_tagged : constant;
Node* rhs = lhs_is_decompression ? constant : change_to_tagged;
Node* comparison = graph()->NewNode(machine()->Word64Equal(), lhs, rhs);
// Reduce
// Reduce.
Reduction r = Reduce(comparison);
ASSERT_TRUE(r.Changed());
EXPECT_EQ(r.replacement()->opcode(), IrOpcode::kWord32Equal);
......@@ -1077,33 +794,18 @@ TEST_F(DecompressionEliminationTest, DecompressionConstantWord64Equal) {
}
TEST_F(DecompressionEliminationTest, DecompressionHeapConstantWord64Equal) {
// Skip test if pointer compression is not enabled
// Skip test if pointer compression is not enabled.
if (!COMPRESS_POINTERS_BOOL) {
return;
}
// Define variables
// Define variables.
Node* const control = graph()->start();
Node* object = Parameter(Type::Any(), 0);
Node* effect = graph()->start();
Node* index = Parameter(Type::UnsignedSmall(), 1);
const Operator* DecompressionOps[] = {
machine()->ChangeCompressedToTagged(),
machine()->ChangeCompressedSignedToTaggedSigned(),
machine()->ChangeCompressedPointerToTaggedPointer()};
const ElementAccess ElementAccesses[] = {
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::AnyTagged(),
kNoWriteBarrier},
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::TaggedSigned(),
kNoWriteBarrier},
{kTaggedBase, kTaggedSize, Type::Any(), MachineType::TaggedPointer(),
kNoWriteBarrier}};
ASSERT_EQ(arraysize(DecompressionOps), arraysize(ElementAccesses));
const Handle<HeapNumber> heapConstants[] = {
const Handle<HeapNumber> heap_constants[] = {
factory()->NewHeapNumber(0.0),
factory()->NewHeapNumber(-0.0),
factory()->NewHeapNumber(11.2),
......@@ -1120,24 +822,25 @@ TEST_F(DecompressionEliminationTest, DecompressionHeapConstantWord64Equal) {
factory()->NewHeapNumber(0x8FFFFFFFFFFFFFFF),
factory()->NewHeapNumber(0xFFFFFFFFFFFFFFFF)};
// For every decompression (lhs)
for (size_t j = 0; j < arraysize(DecompressionOps); ++j) {
// For every constant (rhs)
for (size_t k = 0; k < arraysize(heapConstants); ++k) {
// Test with both (lhs, rhs) combinations
for (bool lhsIsDecompression : {false, true}) {
// Create the graph
// For every decompression (lhs).
for (size_t i = 0; i < arraysize(element_accesses); ++i) {
// For every constant (rhs).
for (size_t j = 0; j < arraysize(heap_constants); ++j) {
// Test with both (lhs, rhs) combinations.
for (bool lhs_is_decompression : {false, true}) {
// Create the graph.
Node* load =
graph()->NewNode(simplified()->LoadElement(ElementAccesses[j]),
graph()->NewNode(simplified()->LoadElement(element_accesses[i]),
object, index, effect, control);
Node* changeToTagged = graph()->NewNode(DecompressionOps[j], load);
Node* change_to_tagged = graph()->NewNode(
DecompressionOpFromAccess(element_accesses[i]), load);
Node* constant =
graph()->NewNode(common()->HeapConstant(heapConstants[k]));
graph()->NewNode(common()->HeapConstant(heap_constants[j]));
Node* lhs = lhsIsDecompression ? changeToTagged : constant;
Node* rhs = lhsIsDecompression ? constant : changeToTagged;
Node* lhs = lhs_is_decompression ? change_to_tagged : constant;
Node* rhs = lhs_is_decompression ? constant : change_to_tagged;
Node* comparison = graph()->NewNode(machine()->Word64Equal(), lhs, rhs);
// Reduce
// Reduce.
Reduction r = Reduce(comparison);
ASSERT_TRUE(r.Changed());
EXPECT_EQ(r.replacement()->opcode(), IrOpcode::kWord32Equal);
......
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