Commit 6a7fd05d authored by Santiago Aboy Solanes's avatar Santiago Aboy Solanes Committed by Commit Bot

[ptr-compr][Turbofan] Reducing the comparison of two decompresses

Added the comparison of two decompresses to the DecompressionElimination
AdvancedReducer. Note that it works in the case that lhs is equal to rhs.

Also added tests for its implementation.

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
Change-Id: I21676a78b592859692768c3499ea11117d3bb5a5
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1609793
Commit-Queue: Santiago Aboy Solanes <solanes@chromium.org>
Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#61647}
parent 823ad576
......@@ -3,13 +3,15 @@
// found in the LICENSE file.
#include "src/compiler/decompression-elimination.h"
#include "src/compiler/node-properties.h"
namespace v8 {
namespace internal {
namespace compiler {
DecompressionElimination::DecompressionElimination(Editor* editor)
: AdvancedReducer(editor) {}
DecompressionElimination::DecompressionElimination(
Editor* editor, Graph* graph, MachineOperatorBuilder* machine)
: AdvancedReducer(editor), graph_(graph), machine_(machine) {}
bool DecompressionElimination::IsValidDecompress(
IrOpcode::Value compressOpcode, IrOpcode::Value decompressOpcode) {
......@@ -24,9 +26,8 @@ bool DecompressionElimination::IsValidDecompress(
IrOpcode::kChangeCompressedPointerToTaggedPointer ||
decompressOpcode == IrOpcode::kChangeCompressedToTagged;
default:
break;
UNREACHABLE();
}
UNREACHABLE();
}
Reduction DecompressionElimination::ReduceCompress(Node* node) {
......@@ -43,6 +44,27 @@ Reduction DecompressionElimination::ReduceCompress(Node* node) {
}
}
Reduction DecompressionElimination::ReduceWord64Equal(Node* node) {
DCHECK_EQ(node->opcode(), IrOpcode::kWord64Equal);
DCHECK_EQ(node->InputCount(), 2);
Node* lhs = node->InputAt(0);
Node* rhs = node->InputAt(1);
if (IrOpcode::IsDecompressOpcode(lhs->opcode()) &&
IrOpcode::IsDecompressOpcode(rhs->opcode())) {
// Do a Word32Equal on the two input nodes before they are decompressed.
DCHECK_EQ(lhs->InputCount(), 1);
node->ReplaceInput(0, lhs->InputAt(0));
DCHECK_EQ(rhs->InputCount(), 1);
node->ReplaceInput(1, rhs->InputAt(0));
NodeProperties::ChangeOp(node, machine()->Word32Equal());
return Changed(node);
}
return NoChange();
}
Reduction DecompressionElimination::Reduce(Node* node) {
DisallowHeapAccess no_heap_access;
......@@ -51,6 +73,8 @@ Reduction DecompressionElimination::Reduce(Node* node) {
case IrOpcode::kChangeTaggedSignedToCompressedSigned:
case IrOpcode::kChangeTaggedPointerToCompressedPointer:
return ReduceCompress(node);
case IrOpcode::kWord64Equal:
return ReduceWord64Equal(node);
default:
break;
}
......
......@@ -6,6 +6,8 @@
#define V8_COMPILER_DECOMPRESSION_ELIMINATION_H_
#include "src/compiler/graph-reducer.h"
#include "src/compiler/graph.h"
#include "src/compiler/machine-operator.h"
namespace v8 {
namespace internal {
......@@ -15,7 +17,8 @@ namespace compiler {
class V8_EXPORT_PRIVATE DecompressionElimination final
: public NON_EXPORTED_BASE(AdvancedReducer) {
public:
explicit DecompressionElimination(Editor* editor);
explicit DecompressionElimination(Editor* editor, Graph* graph,
MachineOperatorBuilder* machine);
~DecompressionElimination() final = default;
const char* reducer_name() const override {
......@@ -32,9 +35,19 @@ class V8_EXPORT_PRIVATE DecompressionElimination final
// Can be used for Any, Signed, and Pointer compressions.
Reduction ReduceCompress(Node* node);
// Replaces a Word64Equal with a Word32Equal if both of its inputs are
// Decompress nodes. In that case, it uses the inputs to each of the
// Decompress nodes.
Reduction ReduceWord64Equal(Node* node);
// Returns true if the decompress opcode is valid for the compressed one.
bool IsValidDecompress(IrOpcode::Value compressOpcode,
IrOpcode::Value decompressOpcode);
Graph* graph() const { return graph_; }
MachineOperatorBuilder* machine() const { return machine_; }
Graph* const graph_;
MachineOperatorBuilder* const machine_;
};
} // namespace compiler
......
......@@ -1540,7 +1540,8 @@ struct LateOptimizationPhase {
SelectLowering select_lowering(data->jsgraph()->graph(),
data->jsgraph()->common());
#ifdef V8_COMPRESS_POINTERS
DecompressionElimination decompression_elimination(&graph_reducer);
DecompressionElimination decompression_elimination(
&graph_reducer, data->graph(), data->machine());
AddReducer(data, &graph_reducer, &decompression_elimination);
#endif
AddReducer(data, &graph_reducer, &branch_condition_elimination);
......
......@@ -26,7 +26,8 @@ class DecompressionEliminationTest : public GraphTest {
protected:
Reduction Reduce(Node* node) {
StrictMock<MockAdvancedReducerEditor> editor;
DecompressionElimination decompression_elimination(&editor);
DecompressionElimination decompression_elimination(&editor, graph(),
machine());
return decompression_elimination.Reduce(node);
}
MachineOperatorBuilder* machine() { return &machine_; }
......@@ -249,6 +250,59 @@ TEST_F(DecompressionEliminationTest,
EXPECT_EQ(load, r.replacement());
}
// -----------------------------------------------------------------------------
// Comparison of two decompressions
TEST_F(DecompressionEliminationTest, TwoDecompressionComparison) {
// 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);
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 (rhs)
for (size_t k = 0; k < arraysize(DecompressionOps); ++k) {
// Create the graph
Node* load1 =
graph()->NewNode(simplified()->LoadElement(ElementAccesses[j]),
object, index, effect, control);
Node* changeToTagged1 = graph()->NewNode(DecompressionOps[j], load1);
Node* load2 =
graph()->NewNode(simplified()->LoadElement(ElementAccesses[k]),
object, index, effect, control);
Node* changeToTagged2 = graph()->NewNode(DecompressionOps[j], load2);
Node* comparison = graph()->NewNode(machine()->Word64Equal(),
changeToTagged1, changeToTagged2);
// Reduce
Reduction r = Reduce(comparison);
ASSERT_TRUE(r.Changed());
EXPECT_EQ(r.replacement()->opcode(), IrOpcode::kWord32Equal);
}
}
}
} // namespace compiler
} // namespace internal
} // namespace v8
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