2019-10-17 15:19:58 +00:00
|
|
|
// Copyright 2019 the V8 project authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file.
|
|
|
|
|
|
|
|
#include "src/compiler/decompression-optimizer.h"
|
|
|
|
|
|
|
|
#include "test/unittests/compiler/graph-unittest.h"
|
|
|
|
|
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
|
|
|
namespace compiler {
|
|
|
|
|
|
|
|
class DecompressionOptimizerTest : public GraphTest {
|
|
|
|
public:
|
|
|
|
DecompressionOptimizerTest()
|
|
|
|
: GraphTest(),
|
|
|
|
machine_(zone(), MachineType::PointerRepresentation(),
|
|
|
|
MachineOperatorBuilder::kNoFlags) {}
|
|
|
|
~DecompressionOptimizerTest() override = default;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
void Reduce() {
|
2019-10-22 11:05:43 +00:00
|
|
|
DecompressionOptimizer decompression_optimizer(zone(), graph(), common(),
|
|
|
|
machine());
|
2019-10-17 15:19:58 +00:00
|
|
|
decompression_optimizer.Reduce();
|
|
|
|
}
|
|
|
|
|
|
|
|
MachineRepresentation CompressedMachRep(MachineRepresentation mach_rep) {
|
|
|
|
if (mach_rep == MachineRepresentation::kTagged) {
|
|
|
|
return MachineRepresentation::kCompressed;
|
|
|
|
} else {
|
|
|
|
DCHECK_EQ(mach_rep, MachineRepresentation::kTaggedPointer);
|
|
|
|
return MachineRepresentation::kCompressedPointer;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MachineRepresentation CompressedMachRep(MachineType type) {
|
|
|
|
return CompressedMachRep(type.representation());
|
|
|
|
}
|
|
|
|
|
|
|
|
MachineRepresentation LoadMachRep(Node* node) {
|
|
|
|
return LoadRepresentationOf(node->op()).representation();
|
|
|
|
}
|
|
|
|
StoreRepresentation CreateStoreRep(MachineType type) {
|
|
|
|
return StoreRepresentation(type.representation(),
|
|
|
|
WriteBarrierKind::kFullWriteBarrier);
|
|
|
|
}
|
|
|
|
|
2019-10-28 15:56:12 +00:00
|
|
|
const MachineType types[2] = {MachineType::AnyTagged(),
|
|
|
|
MachineType::TaggedPointer()};
|
|
|
|
|
|
|
|
const Handle<HeapNumber> heap_constants[15] = {
|
|
|
|
factory()->NewHeapNumber(0.0),
|
|
|
|
factory()->NewHeapNumber(-0.0),
|
|
|
|
factory()->NewHeapNumber(11.2),
|
|
|
|
factory()->NewHeapNumber(-11.2),
|
|
|
|
factory()->NewHeapNumber(3.1415 + 1.4142),
|
|
|
|
factory()->NewHeapNumber(3.1415 - 1.4142),
|
|
|
|
factory()->NewHeapNumber(0x0000000000000000),
|
|
|
|
factory()->NewHeapNumber(0x0000000000000001),
|
|
|
|
factory()->NewHeapNumber(0x0000FFFFFFFF0000),
|
|
|
|
factory()->NewHeapNumber(0x7FFFFFFFFFFFFFFF),
|
|
|
|
factory()->NewHeapNumber(0x8000000000000000),
|
|
|
|
factory()->NewHeapNumber(0x8000000000000001),
|
|
|
|
factory()->NewHeapNumber(0x8000FFFFFFFF0000),
|
|
|
|
factory()->NewHeapNumber(0x8FFFFFFFFFFFFFFF),
|
|
|
|
factory()->NewHeapNumber(0xFFFFFFFFFFFFFFFF)};
|
|
|
|
|
2019-10-17 15:19:58 +00:00
|
|
|
MachineOperatorBuilder* machine() { return &machine_; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
MachineOperatorBuilder machine_;
|
|
|
|
};
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// Direct Load into Store.
|
|
|
|
|
|
|
|
TEST_F(DecompressionOptimizerTest, DirectLoadStore) {
|
|
|
|
// Define variables.
|
|
|
|
Node* const control = graph()->start();
|
|
|
|
Node* object = Parameter(Type::Any(), 0);
|
|
|
|
Node* effect = graph()->start();
|
|
|
|
Node* index = Parameter(Type::UnsignedSmall(), 1);
|
|
|
|
|
|
|
|
// Test for both AnyTagged and TaggedPointer.
|
|
|
|
for (size_t i = 0; i < arraysize(types); ++i) {
|
|
|
|
// Create the graph.
|
|
|
|
Node* base_pointer = graph()->NewNode(machine()->Load(types[i]), object,
|
|
|
|
index, effect, control);
|
|
|
|
Node* value = graph()->NewNode(machine()->Load(types[i]), base_pointer,
|
|
|
|
index, effect, control);
|
|
|
|
graph()->SetEnd(graph()->NewNode(machine()->Store(CreateStoreRep(types[i])),
|
|
|
|
object, index, value, effect, control));
|
|
|
|
|
2019-10-23 11:44:29 +00:00
|
|
|
// Change the nodes, and test the change.
|
2019-10-17 15:19:58 +00:00
|
|
|
Reduce();
|
|
|
|
EXPECT_EQ(LoadMachRep(base_pointer), types[i].representation());
|
|
|
|
EXPECT_EQ(LoadMachRep(value), CompressedMachRep(types[i]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-23 11:44:29 +00:00
|
|
|
// -----------------------------------------------------------------------------
|
2019-10-30 10:23:44 +00:00
|
|
|
// Word32 Operations.
|
2019-10-23 11:44:29 +00:00
|
|
|
|
|
|
|
TEST_F(DecompressionOptimizerTest, Word32EqualTwoDecompresses) {
|
|
|
|
// Define variables.
|
|
|
|
Node* const control = graph()->start();
|
|
|
|
Node* object = Parameter(Type::Any(), 0);
|
|
|
|
Node* effect = graph()->start();
|
|
|
|
Node* index = Parameter(Type::UnsignedSmall(), 1);
|
|
|
|
|
|
|
|
// Test for both AnyTagged and TaggedPointer, for both loads.
|
|
|
|
for (size_t i = 0; i < arraysize(types); ++i) {
|
|
|
|
for (size_t j = 0; j < arraysize(types); ++j) {
|
|
|
|
// Create the graph.
|
|
|
|
Node* load_1 = graph()->NewNode(machine()->Load(types[i]), object, index,
|
|
|
|
effect, control);
|
|
|
|
Node* load_2 = graph()->NewNode(machine()->Load(types[j]), object, index,
|
|
|
|
effect, control);
|
2020-01-08 13:30:43 +00:00
|
|
|
Node* equal = graph()->NewNode(machine()->Word32Equal(), load_1, load_2);
|
2019-11-27 15:37:39 +00:00
|
|
|
graph()->SetEnd(equal);
|
2019-10-23 11:44:29 +00:00
|
|
|
|
|
|
|
// Change the nodes, and test the change.
|
|
|
|
Reduce();
|
|
|
|
EXPECT_EQ(LoadMachRep(load_1), CompressedMachRep(types[i]));
|
|
|
|
EXPECT_EQ(LoadMachRep(load_2), CompressedMachRep(types[j]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-30 10:23:44 +00:00
|
|
|
TEST_F(DecompressionOptimizerTest, Word32EqualDecompressAndConstant) {
|
2019-10-23 11:44:29 +00:00
|
|
|
// Define variables.
|
|
|
|
Node* const control = graph()->start();
|
|
|
|
Node* object = Parameter(Type::Any(), 0);
|
|
|
|
Node* effect = graph()->start();
|
|
|
|
Node* index = Parameter(Type::UnsignedSmall(), 1);
|
|
|
|
|
2019-10-28 15:56:12 +00:00
|
|
|
// Test for both AnyTagged and TaggedPointer.
|
2019-10-23 11:44:29 +00:00
|
|
|
for (size_t i = 0; i < arraysize(types); ++i) {
|
|
|
|
for (size_t j = 0; j < arraysize(heap_constants); ++j) {
|
|
|
|
// Create the graph.
|
|
|
|
Node* load = graph()->NewNode(machine()->Load(types[i]), object, index,
|
|
|
|
effect, control);
|
|
|
|
Node* constant =
|
2019-10-28 15:56:12 +00:00
|
|
|
graph()->NewNode(common()->HeapConstant(heap_constants[j]));
|
2020-01-08 13:30:43 +00:00
|
|
|
Node* equal = graph()->NewNode(machine()->Word32Equal(), load, constant);
|
2019-11-27 15:37:39 +00:00
|
|
|
graph()->SetEnd(equal);
|
2019-10-23 11:44:29 +00:00
|
|
|
|
|
|
|
// Change the nodes, and test the change.
|
|
|
|
Reduce();
|
|
|
|
EXPECT_EQ(LoadMachRep(load), CompressedMachRep(types[i]));
|
2019-10-28 15:56:12 +00:00
|
|
|
EXPECT_EQ(constant->opcode(), IrOpcode::kCompressedHeapConstant);
|
2019-10-23 11:44:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-30 10:23:44 +00:00
|
|
|
TEST_F(DecompressionOptimizerTest, Word32AndSmiCheck) {
|
|
|
|
// Define variables.
|
|
|
|
Node* const control = graph()->start();
|
|
|
|
Node* object = Parameter(Type::Any(), 0);
|
|
|
|
Node* effect = graph()->start();
|
|
|
|
Node* index = Parameter(Type::UnsignedSmall(), 1);
|
|
|
|
|
|
|
|
// Test for both AnyTagged and TaggedPointer.
|
|
|
|
for (size_t i = 0; i < arraysize(types); ++i) {
|
|
|
|
// Create the graph.
|
|
|
|
Node* load = graph()->NewNode(machine()->Load(types[i]), object, index,
|
|
|
|
effect, control);
|
|
|
|
Node* smi_tag_mask = graph()->NewNode(common()->Int32Constant(kSmiTagMask));
|
|
|
|
Node* word32_and =
|
|
|
|
graph()->NewNode(machine()->Word32And(), load, smi_tag_mask);
|
|
|
|
Node* smi_tag = graph()->NewNode(common()->Int32Constant(kSmiTag));
|
|
|
|
graph()->SetEnd(
|
|
|
|
graph()->NewNode(machine()->Word32Equal(), word32_and, smi_tag));
|
|
|
|
// Change the nodes, and test the change.
|
|
|
|
Reduce();
|
|
|
|
EXPECT_EQ(LoadMachRep(load), CompressedMachRep(types[i]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-30 11:20:56 +00:00
|
|
|
TEST_F(DecompressionOptimizerTest, Word32ShlSmiTag) {
|
|
|
|
// Define variables.
|
|
|
|
Node* const control = graph()->start();
|
|
|
|
Node* object = Parameter(Type::Any(), 0);
|
|
|
|
Node* effect = graph()->start();
|
|
|
|
Node* index = Parameter(Type::UnsignedSmall(), 1);
|
|
|
|
|
|
|
|
// Test only for AnyTagged, since TaggedPointer can't be Smi tagged.
|
|
|
|
// Create the graph.
|
|
|
|
Node* load = graph()->NewNode(machine()->Load(MachineType::AnyTagged()),
|
|
|
|
object, index, effect, control);
|
|
|
|
Node* smi_shift_bits =
|
|
|
|
graph()->NewNode(common()->Int32Constant(kSmiShiftSize + kSmiTagSize));
|
2019-11-13 11:58:01 +00:00
|
|
|
Node* word32_shl =
|
2019-11-21 17:21:29 +00:00
|
|
|
graph()->NewNode(machine()->Word32Shl(), load, smi_shift_bits);
|
2019-10-30 11:20:56 +00:00
|
|
|
graph()->SetEnd(
|
2019-11-21 17:21:29 +00:00
|
|
|
graph()->NewNode(machine()->BitcastWord32ToWord64(), word32_shl));
|
2019-10-30 11:20:56 +00:00
|
|
|
// Change the nodes, and test the change.
|
|
|
|
Reduce();
|
|
|
|
EXPECT_EQ(LoadMachRep(load), CompressedMachRep(MachineType::AnyTagged()));
|
|
|
|
}
|
|
|
|
|
2019-10-28 15:54:37 +00:00
|
|
|
TEST_F(DecompressionOptimizerTest, Word32SarSmiUntag) {
|
|
|
|
// Define variables.
|
|
|
|
Node* const control = graph()->start();
|
|
|
|
Node* object = Parameter(Type::Any(), 0);
|
|
|
|
Node* effect = graph()->start();
|
|
|
|
Node* index = Parameter(Type::UnsignedSmall(), 1);
|
|
|
|
|
|
|
|
// Test only for AnyTagged, since TaggedPointer can't be Smi tagged.
|
|
|
|
// Create the graph.
|
|
|
|
Node* load = graph()->NewNode(machine()->Load(MachineType::AnyTagged()),
|
|
|
|
object, index, effect, control);
|
|
|
|
Node* truncation = graph()->NewNode(machine()->TruncateInt64ToInt32(), load);
|
|
|
|
Node* smi_shift_bits =
|
|
|
|
graph()->NewNode(common()->Int32Constant(kSmiShiftSize + kSmiTagSize));
|
|
|
|
Node* word32_sar =
|
|
|
|
graph()->NewNode(machine()->Word32Sar(), truncation, smi_shift_bits);
|
|
|
|
graph()->SetEnd(
|
|
|
|
graph()->NewNode(machine()->ChangeInt32ToInt64(), word32_sar));
|
|
|
|
// Change the nodes, and test the change.
|
|
|
|
Reduce();
|
|
|
|
EXPECT_EQ(LoadMachRep(load), CompressedMachRep(MachineType::AnyTagged()));
|
|
|
|
}
|
|
|
|
|
2019-11-04 11:28:42 +00:00
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// FrameState and TypedStateValues interaction.
|
|
|
|
|
|
|
|
TEST_F(DecompressionOptimizerTest, TypedStateValues) {
|
|
|
|
// 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 ZoneVector<MachineType>* types_for_state_values =
|
|
|
|
new (graph()->zone()->New(sizeof(ZoneVector<MachineType>)))
|
|
|
|
ZoneVector<MachineType>(number_of_inputs, graph()->zone());
|
|
|
|
SparseInputMask dense = SparseInputMask::Dense();
|
|
|
|
|
|
|
|
// Test for both AnyTagged and TaggedPointer.
|
|
|
|
for (size_t i = 0; i < arraysize(types); ++i) {
|
|
|
|
for (size_t j = 0; j < arraysize(heap_constants); ++j) {
|
|
|
|
// Create the graph.
|
|
|
|
Node* load = graph()->NewNode(machine()->Load(types[i]), object, index,
|
|
|
|
effect, control);
|
|
|
|
Node* constant_1 =
|
|
|
|
graph()->NewNode(common()->HeapConstant(heap_constants[j]));
|
|
|
|
Node* typed_state_values = graph()->NewNode(
|
|
|
|
common()->TypedStateValues(types_for_state_values, dense), load,
|
|
|
|
constant_1);
|
|
|
|
Node* constant_2 =
|
|
|
|
graph()->NewNode(common()->HeapConstant(heap_constants[j]));
|
|
|
|
graph()->SetEnd(graph()->NewNode(
|
|
|
|
common()->FrameState(BailoutId::None(),
|
|
|
|
OutputFrameStateCombine::Ignore(), nullptr),
|
|
|
|
typed_state_values, typed_state_values, typed_state_values,
|
|
|
|
constant_2, UndefinedConstant(), graph()->start()));
|
|
|
|
|
|
|
|
// Change the nodes, and test the change.
|
|
|
|
Reduce();
|
|
|
|
EXPECT_EQ(LoadMachRep(load), CompressedMachRep(types[i]));
|
|
|
|
EXPECT_EQ(constant_1->opcode(), IrOpcode::kCompressedHeapConstant);
|
|
|
|
EXPECT_EQ(constant_2->opcode(), IrOpcode::kCompressedHeapConstant);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-04 13:43:25 +00:00
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// Phi
|
|
|
|
|
|
|
|
TEST_F(DecompressionOptimizerTest, PhiDecompressOrNot) {
|
|
|
|
// 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;
|
|
|
|
|
|
|
|
// Test for both AnyTagged and TaggedPointer.
|
|
|
|
for (size_t i = 0; i < arraysize(types); ++i) {
|
|
|
|
for (size_t j = 0; j < arraysize(heap_constants); ++j) {
|
|
|
|
// Create the graph.
|
|
|
|
// Base pointer
|
|
|
|
Node* load_1 = graph()->NewNode(machine()->Load(types[i]), object, index,
|
|
|
|
effect, control);
|
|
|
|
Node* constant_1 =
|
|
|
|
graph()->NewNode(common()->HeapConstant(heap_constants[j]));
|
|
|
|
Node* phi_1 = graph()->NewNode(
|
|
|
|
common()->Phi(types[i].representation(), number_of_inputs), load_1,
|
|
|
|
constant_1, control);
|
|
|
|
|
|
|
|
// Value
|
|
|
|
Node* load_2 = graph()->NewNode(machine()->Load(types[i]), object, index,
|
|
|
|
effect, control);
|
|
|
|
Node* constant_2 =
|
|
|
|
graph()->NewNode(common()->HeapConstant(heap_constants[j]));
|
|
|
|
Node* phi_2 = graph()->NewNode(
|
|
|
|
common()->Phi(types[i].representation(), number_of_inputs), load_2,
|
|
|
|
constant_2, control);
|
|
|
|
|
|
|
|
graph()->SetEnd(
|
|
|
|
graph()->NewNode(machine()->Store(CreateStoreRep(types[i])), phi_1,
|
|
|
|
index, phi_2, effect, control));
|
|
|
|
|
|
|
|
// Change the nodes, and test the change.
|
|
|
|
Reduce();
|
|
|
|
// Base pointer should not be compressed.
|
|
|
|
EXPECT_EQ(LoadMachRep(load_1), types[i].representation());
|
|
|
|
EXPECT_EQ(constant_1->opcode(), IrOpcode::kHeapConstant);
|
|
|
|
EXPECT_EQ(PhiRepresentationOf(phi_1->op()), types[i].representation());
|
|
|
|
// Value should be compressed.
|
|
|
|
EXPECT_EQ(LoadMachRep(load_2), CompressedMachRep(types[i]));
|
|
|
|
EXPECT_EQ(constant_2->opcode(), IrOpcode::kCompressedHeapConstant);
|
|
|
|
EXPECT_EQ(PhiRepresentationOf(phi_2->op()), CompressedMachRep(types[i]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DecompressionOptimizerTest, CascadingPhi) {
|
|
|
|
// 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;
|
|
|
|
|
|
|
|
// Test for both AnyTagged and TaggedPointer.
|
|
|
|
for (size_t i = 0; i < arraysize(types); ++i) {
|
|
|
|
// Create the graph.
|
|
|
|
Node* load_1 = graph()->NewNode(machine()->Load(types[i]), object, index,
|
|
|
|
effect, control);
|
|
|
|
Node* load_2 = graph()->NewNode(machine()->Load(types[i]), object, index,
|
|
|
|
effect, control);
|
|
|
|
Node* load_3 = graph()->NewNode(machine()->Load(types[i]), object, index,
|
|
|
|
effect, control);
|
|
|
|
Node* load_4 = graph()->NewNode(machine()->Load(types[i]), object, index,
|
|
|
|
effect, control);
|
|
|
|
|
|
|
|
Node* phi_1 = graph()->NewNode(
|
|
|
|
common()->Phi(types[i].representation(), number_of_inputs), load_1,
|
|
|
|
load_2, control);
|
|
|
|
Node* phi_2 = graph()->NewNode(
|
|
|
|
common()->Phi(types[i].representation(), number_of_inputs), load_3,
|
|
|
|
load_4, control);
|
|
|
|
|
|
|
|
Node* final_phi = graph()->NewNode(
|
|
|
|
common()->Phi(types[i].representation(), number_of_inputs), phi_1,
|
|
|
|
phi_2, control);
|
|
|
|
|
|
|
|
// Value
|
|
|
|
graph()->SetEnd(final_phi);
|
|
|
|
// Change the nodes, and test the change.
|
|
|
|
Reduce();
|
|
|
|
// Loads are all compressed
|
|
|
|
EXPECT_EQ(LoadMachRep(load_1), CompressedMachRep(types[i]));
|
|
|
|
EXPECT_EQ(LoadMachRep(load_2), CompressedMachRep(types[i]));
|
|
|
|
EXPECT_EQ(LoadMachRep(load_3), CompressedMachRep(types[i]));
|
|
|
|
EXPECT_EQ(LoadMachRep(load_4), CompressedMachRep(types[i]));
|
|
|
|
// Phis too
|
|
|
|
EXPECT_EQ(PhiRepresentationOf(phi_1->op()), CompressedMachRep(types[i]));
|
|
|
|
EXPECT_EQ(PhiRepresentationOf(phi_2->op()), CompressedMachRep(types[i]));
|
|
|
|
EXPECT_EQ(PhiRepresentationOf(final_phi->op()),
|
|
|
|
CompressedMachRep(types[i]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DecompressionOptimizerTest, PhiWithOneCompressedAndOneTagged) {
|
|
|
|
// 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;
|
|
|
|
|
|
|
|
// Test for both AnyTagged and TaggedPointer.
|
|
|
|
for (size_t i = 0; i < arraysize(types); ++i) {
|
|
|
|
for (size_t j = 0; j < arraysize(heap_constants); ++j) {
|
|
|
|
// Create the graph.
|
|
|
|
// Base pointer in load_2, and phi input for value
|
|
|
|
Node* load_1 = graph()->NewNode(machine()->Load(types[i]), object, index,
|
|
|
|
effect, control);
|
|
|
|
|
|
|
|
// load_2 blocks load_1 from being compressed.
|
|
|
|
Node* load_2 = graph()->NewNode(machine()->Load(types[i]), load_1, index,
|
|
|
|
effect, control);
|
|
|
|
Node* phi = graph()->NewNode(
|
|
|
|
common()->Phi(types[i].representation(), number_of_inputs), load_1,
|
|
|
|
load_2, control);
|
|
|
|
|
|
|
|
graph()->SetEnd(
|
|
|
|
graph()->NewNode(machine()->Store(CreateStoreRep(types[i])), object,
|
|
|
|
index, phi, effect, control));
|
|
|
|
|
|
|
|
// Change the nodes, and test the change.
|
|
|
|
Reduce();
|
|
|
|
EXPECT_EQ(LoadMachRep(load_1), types[i].representation());
|
|
|
|
EXPECT_EQ(LoadMachRep(load_2), CompressedMachRep(types[i]));
|
|
|
|
EXPECT_EQ(PhiRepresentationOf(phi->op()), CompressedMachRep(types[i]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-04 13:44:19 +00:00
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// Int cases.
|
|
|
|
|
|
|
|
TEST_F(DecompressionOptimizerTest, Int32LessThanOrEqualFromSpeculative) {
|
|
|
|
// This case tests for what SpeculativeNumberLessThanOrEqual is lowered to.
|
|
|
|
// Define variables.
|
|
|
|
Node* const control = graph()->start();
|
|
|
|
Node* object = Parameter(Type::Any(), 0);
|
|
|
|
Node* effect = graph()->start();
|
|
|
|
Node* index = Parameter(Type::UnsignedSmall(), 1);
|
|
|
|
|
|
|
|
// Test only for AnyTagged, since TaggedPointer can't be a Smi.
|
|
|
|
// Create the graph.
|
|
|
|
Node* load = graph()->NewNode(machine()->Load(MachineType::AnyTagged()),
|
|
|
|
object, index, effect, control);
|
|
|
|
Node* constant = graph()->NewNode(common()->Int64Constant(5));
|
|
|
|
graph()->SetEnd(
|
|
|
|
graph()->NewNode(machine()->Int32LessThanOrEqual(), load, constant));
|
|
|
|
// Change the nodes, and test the change.
|
|
|
|
Reduce();
|
|
|
|
EXPECT_EQ(LoadMachRep(load), CompressedMachRep(MachineType::AnyTagged()));
|
|
|
|
}
|
|
|
|
|
2020-01-08 14:43:10 +00:00
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// Bitcast cases.
|
|
|
|
|
|
|
|
TEST_F(DecompressionOptimizerTest, BitcastTaggedToWord) {
|
|
|
|
// Define variables.
|
|
|
|
Node* const control = graph()->start();
|
|
|
|
Node* object = Parameter(Type::Any(), 0);
|
|
|
|
Node* effect = graph()->start();
|
|
|
|
Node* index = Parameter(Type::UnsignedSmall(), 1);
|
|
|
|
|
|
|
|
// Test for both AnyTagged and TaggedPointer, for both loads.
|
|
|
|
for (size_t i = 0; i < arraysize(types); ++i) {
|
|
|
|
for (size_t j = 0; j < arraysize(types); ++j) {
|
|
|
|
// Create the graph.
|
|
|
|
Node* load_1 = graph()->NewNode(machine()->Load(types[i]), object, index,
|
|
|
|
effect, control);
|
|
|
|
Node* bitcast_1 = graph()->NewNode(machine()->BitcastTaggedToWord(),
|
|
|
|
load_1, effect, control);
|
|
|
|
Node* load_2 = graph()->NewNode(machine()->Load(types[j]), object, index,
|
|
|
|
effect, control);
|
|
|
|
Node* bitcast_2 = graph()->NewNode(machine()->BitcastTaggedToWord(),
|
|
|
|
load_2, effect, control);
|
|
|
|
Node* equal =
|
|
|
|
graph()->NewNode(machine()->Word32Equal(), bitcast_1, bitcast_2);
|
|
|
|
graph()->SetEnd(equal);
|
|
|
|
|
|
|
|
// Change the nodes, and test the change.
|
|
|
|
Reduce();
|
|
|
|
EXPECT_EQ(LoadMachRep(load_1), CompressedMachRep(types[i]));
|
|
|
|
EXPECT_EQ(LoadMachRep(load_2), CompressedMachRep(types[j]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DecompressionOptimizerTest, BitcastTaggedToWordForTagAndSmiBits) {
|
|
|
|
// Define variables.
|
|
|
|
Node* const control = graph()->start();
|
|
|
|
Node* object = Parameter(Type::Any(), 0);
|
|
|
|
Node* effect = graph()->start();
|
|
|
|
Node* index = Parameter(Type::UnsignedSmall(), 1);
|
|
|
|
|
|
|
|
// Test for both AnyTagged and TaggedPointer, for both loads.
|
|
|
|
for (size_t i = 0; i < arraysize(types); ++i) {
|
|
|
|
for (size_t j = 0; j < arraysize(types); ++j) {
|
|
|
|
// Create the graph.
|
|
|
|
Node* load_1 = graph()->NewNode(machine()->Load(types[i]), object, index,
|
|
|
|
effect, control);
|
|
|
|
Node* bitcast_1 = graph()->NewNode(
|
|
|
|
machine()->BitcastTaggedToWordForTagAndSmiBits(), load_1);
|
|
|
|
Node* load_2 = graph()->NewNode(machine()->Load(types[j]), object, index,
|
|
|
|
effect, control);
|
|
|
|
Node* bitcast_2 = graph()->NewNode(
|
|
|
|
machine()->BitcastTaggedToWordForTagAndSmiBits(), load_2);
|
|
|
|
Node* equal =
|
|
|
|
graph()->NewNode(machine()->Word32Equal(), bitcast_1, bitcast_2);
|
|
|
|
graph()->SetEnd(equal);
|
|
|
|
|
|
|
|
// Change the nodes, and test the change.
|
|
|
|
Reduce();
|
|
|
|
EXPECT_EQ(LoadMachRep(load_1), CompressedMachRep(types[i]));
|
|
|
|
EXPECT_EQ(LoadMachRep(load_2), CompressedMachRep(types[j]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-17 15:19:58 +00:00
|
|
|
} // namespace compiler
|
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|