Commit bd304e12 authored by Toon Verwaest's avatar Toon Verwaest Committed by V8 LUCI CQ

[maglev] Reuse constants across the graph

This moves constant nodes to separate data structures on the graph so
they can be looked up there. Graph processors walk the constants before
walking other nodes.

Bug: v8:7700
Change-Id: Id4bec2c2a26011dcacf3355fe17d821451f79397
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3706625
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/main@{#81195}
parent aeddf8c4
...@@ -47,7 +47,24 @@ namespace maglev { ...@@ -47,7 +47,24 @@ namespace maglev {
class NumberingProcessor { class NumberingProcessor {
public: public:
void PreProcessGraph(MaglevCompilationInfo*, Graph* graph) { node_id_ = 1; } void PreProcessGraph(MaglevCompilationInfo*, Graph* graph) {
node_id_ = 1;
for (Constant* constant : graph->constants()) {
constant->set_id(node_id_++);
}
for (const auto& [index, constant] : graph->root()) {
constant->set_id(node_id_++);
}
for (const auto& [index, constant] : graph->smi()) {
constant->set_id(node_id_++);
}
for (const auto& [index, constant] : graph->int32()) {
constant->set_id(node_id_++);
}
for (const auto& [index, constant] : graph->float64()) {
constant->set_id(node_id_++);
}
}
void PostProcessGraph(MaglevCompilationInfo*, Graph* graph) {} void PostProcessGraph(MaglevCompilationInfo*, Graph* graph) {}
void PreProcessBasicBlock(MaglevCompilationInfo*, BasicBlock* block) {} void PreProcessBasicBlock(MaglevCompilationInfo*, BasicBlock* block) {}
......
...@@ -110,8 +110,7 @@ void MaglevGraphBuilder::BuildRegisterFrameInitialization() { ...@@ -110,8 +110,7 @@ void MaglevGraphBuilder::BuildRegisterFrameInitialization() {
int register_index = 0; int register_index = 0;
// TODO(leszeks): Don't emit if not needed. // TODO(leszeks): Don't emit if not needed.
ValueNode* undefined_value = ValueNode* undefined_value = GetRootConstant(RootIndex::kUndefinedValue);
AddNewNode<RootConstant>({}, RootIndex::kUndefinedValue);
if (new_target_or_generator_register.is_valid()) { if (new_target_or_generator_register.is_valid()) {
int new_target_index = new_target_or_generator_register.index(); int new_target_index = new_target_or_generator_register.index();
for (; register_index < new_target_index; register_index++) { for (; register_index < new_target_index; register_index++) {
...@@ -295,8 +294,8 @@ void MaglevGraphBuilder::BuildGenericBinaryOperationNode() { ...@@ -295,8 +294,8 @@ void MaglevGraphBuilder::BuildGenericBinaryOperationNode() {
template <Operation kOperation> template <Operation kOperation>
void MaglevGraphBuilder::BuildGenericBinarySmiOperationNode() { void MaglevGraphBuilder::BuildGenericBinarySmiOperationNode() {
ValueNode* left = GetAccumulatorTagged(); ValueNode* left = GetAccumulatorTagged();
Smi constant = Smi::FromInt(iterator_.GetImmediateOperand(0)); int constant = iterator_.GetImmediateOperand(0);
ValueNode* right = AddNewNode<SmiConstant>({}, constant); ValueNode* right = GetSmiConstant(constant);
FeedbackSlot slot_index = GetSlotOperand(1); FeedbackSlot slot_index = GetSlotOperand(1);
SetAccumulator(AddNewNode<GenericNodeForOperation<kOperation>>( SetAccumulator(AddNewNode<GenericNodeForOperation<kOperation>>(
{left, right}, compiler::FeedbackSource{feedback(), slot_index})); {left, right}, compiler::FeedbackSource{feedback(), slot_index}));
...@@ -325,7 +324,7 @@ void MaglevGraphBuilder::BuildInt32BinarySmiOperationNode() { ...@@ -325,7 +324,7 @@ void MaglevGraphBuilder::BuildInt32BinarySmiOperationNode() {
// value, so we can just return. // value, so we can just return.
return; return;
} }
ValueNode* right = AddNewNode<Int32Constant>({}, constant); ValueNode* right = GetInt32Constant(constant);
SetAccumulator(AddNewInt32BinaryOperationNode<kOperation>({left, right})); SetAccumulator(AddNewInt32BinaryOperationNode<kOperation>({left, right}));
} }
...@@ -334,7 +333,7 @@ void MaglevGraphBuilder::BuildFloat64BinarySmiOperationNode() { ...@@ -334,7 +333,7 @@ void MaglevGraphBuilder::BuildFloat64BinarySmiOperationNode() {
// TODO(v8:7700): Do constant folding. // TODO(v8:7700): Do constant folding.
ValueNode* left = GetAccumulatorFloat64(); ValueNode* left = GetAccumulatorFloat64();
double constant = static_cast<double>(iterator_.GetImmediateOperand(0)); double constant = static_cast<double>(iterator_.GetImmediateOperand(0));
ValueNode* right = AddNewNode<Float64Constant>({}, constant); ValueNode* right = GetFloat64Constant(constant);
SetAccumulator(AddNewFloat64BinaryOperationNode<kOperation>({left, right})); SetAccumulator(AddNewFloat64BinaryOperationNode<kOperation>({left, right}));
} }
...@@ -509,27 +508,25 @@ void MaglevGraphBuilder::VisitLdar() { ...@@ -509,27 +508,25 @@ void MaglevGraphBuilder::VisitLdar() {
interpreter::Register::virtual_accumulator()); interpreter::Register::virtual_accumulator());
} }
void MaglevGraphBuilder::VisitLdaZero() { void MaglevGraphBuilder::VisitLdaZero() { SetAccumulator(GetSmiConstant(0)); }
SetAccumulator(AddNewNode<SmiConstant>({}, Smi::zero()));
}
void MaglevGraphBuilder::VisitLdaSmi() { void MaglevGraphBuilder::VisitLdaSmi() {
Smi constant = Smi::FromInt(iterator_.GetImmediateOperand(0)); int constant = iterator_.GetImmediateOperand(0);
SetAccumulator(AddNewNode<SmiConstant>({}, constant)); SetAccumulator(GetSmiConstant(constant));
} }
void MaglevGraphBuilder::VisitLdaUndefined() { void MaglevGraphBuilder::VisitLdaUndefined() {
SetAccumulator(AddNewNode<RootConstant>({}, RootIndex::kUndefinedValue)); SetAccumulator(GetRootConstant(RootIndex::kUndefinedValue));
} }
void MaglevGraphBuilder::VisitLdaNull() { void MaglevGraphBuilder::VisitLdaNull() {
SetAccumulator(AddNewNode<RootConstant>({}, RootIndex::kNullValue)); SetAccumulator(GetRootConstant(RootIndex::kNullValue));
} }
void MaglevGraphBuilder::VisitLdaTheHole() { void MaglevGraphBuilder::VisitLdaTheHole() {
SetAccumulator(AddNewNode<RootConstant>({}, RootIndex::kTheHoleValue)); SetAccumulator(GetRootConstant(RootIndex::kTheHoleValue));
} }
void MaglevGraphBuilder::VisitLdaTrue() { void MaglevGraphBuilder::VisitLdaTrue() {
SetAccumulator(AddNewNode<RootConstant>({}, RootIndex::kTrueValue)); SetAccumulator(GetRootConstant(RootIndex::kTrueValue));
} }
void MaglevGraphBuilder::VisitLdaFalse() { void MaglevGraphBuilder::VisitLdaFalse() {
SetAccumulator(AddNewNode<RootConstant>({}, RootIndex::kFalseValue)); SetAccumulator(GetRootConstant(RootIndex::kFalseValue));
} }
void MaglevGraphBuilder::VisitLdaConstant() { void MaglevGraphBuilder::VisitLdaConstant() {
SetAccumulator(GetConstant(GetRefOperand<HeapObject>(0))); SetAccumulator(GetConstant(GetRefOperand<HeapObject>(0)));
...@@ -641,8 +638,7 @@ bool MaglevGraphBuilder::TryBuildPropertyCellAccess( ...@@ -641,8 +638,7 @@ bool MaglevGraphBuilder::TryBuildPropertyCellAccess(
return true; return true;
} }
ValueNode* property_cell_node = ValueNode* property_cell_node = GetConstant(property_cell.AsHeapObject());
AddNewNode<Constant>({}, property_cell.AsHeapObject());
SetAccumulator(AddNewNode<LoadTaggedField>({property_cell_node}, SetAccumulator(AddNewNode<LoadTaggedField>({property_cell_node},
PropertyCell::kValueOffset)); PropertyCell::kValueOffset));
return true; return true;
...@@ -769,12 +765,10 @@ bool MaglevGraphBuilder::TryBuildMonomorphicLoadFromLoadHandler( ...@@ -769,12 +765,10 @@ bool MaglevGraphBuilder::TryBuildMonomorphicLoadFromLoadHandler(
} }
MaybeObject value = handler.data1(local_isolate_); MaybeObject value = handler.data1(local_isolate_);
if (value.IsSmi()) { if (value.IsSmi()) {
SetAccumulator(AddNewNode<SmiConstant>({}, value.ToSmi())); SetAccumulator(GetSmiConstant(value.ToSmi().value()));
} else { } else {
SetAccumulator(AddNewNode<Constant>( SetAccumulator(GetConstant(MakeRefAssumeMemoryFence(
{}, MakeRefAssumeMemoryFence( broker(), broker()->CanonicalPersistentHandle(value.GetHeapObject()))));
broker(),
broker()->CanonicalPersistentHandle(value.GetHeapObject()))));
} }
return true; return true;
} }
...@@ -1059,8 +1053,7 @@ void MaglevGraphBuilder::InlineCallFromRegisters( ...@@ -1059,8 +1053,7 @@ void MaglevGraphBuilder::InlineCallFromRegisters(
// created. // created.
RootConstant* undefined_constant; RootConstant* undefined_constant;
if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) { if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) {
undefined_constant = undefined_constant = GetRootConstant(RootIndex::kUndefinedValue);
AddNewNode<RootConstant>({}, RootIndex::kUndefinedValue);
} }
// Create a new compilation unit and graph builder for the inlined // Create a new compilation unit and graph builder for the inlined
...@@ -1168,8 +1161,7 @@ void MaglevGraphBuilder::BuildCallFromRegisterList( ...@@ -1168,8 +1161,7 @@ void MaglevGraphBuilder::BuildCallFromRegisterList(
CreateNewNode<Call>(input_count, receiver_mode, function, context); CreateNewNode<Call>(input_count, receiver_mode, function, context);
int arg_index = 0; int arg_index = 0;
if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) { if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) {
call->set_arg(arg_index++, call->set_arg(arg_index++, GetRootConstant(RootIndex::kUndefinedValue));
AddNewNode<RootConstant>({}, RootIndex::kUndefinedValue));
} }
for (int i = 0; i < args.register_count(); ++i) { for (int i = 0; i < args.register_count(); ++i) {
call->set_arg(arg_index++, GetTaggedValue(args[i])); call->set_arg(arg_index++, GetTaggedValue(args[i]));
...@@ -1236,8 +1228,7 @@ void MaglevGraphBuilder::BuildCallFromRegisters( ...@@ -1236,8 +1228,7 @@ void MaglevGraphBuilder::BuildCallFromRegisters(
CreateNewNode<Call>(input_count, receiver_mode, function, context); CreateNewNode<Call>(input_count, receiver_mode, function, context);
if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) { if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) {
reg_count = argc_count; reg_count = argc_count;
call->set_arg(arg_index++, call->set_arg(arg_index++, GetRootConstant(RootIndex::kUndefinedValue));
AddNewNode<RootConstant>({}, RootIndex::kUndefinedValue));
} }
for (int i = 0; i < reg_count; i++) { for (int i = 0; i < reg_count; i++) {
call->set_arg(arg_index++, LoadRegisterTagged(i + 1)); call->set_arg(arg_index++, LoadRegisterTagged(i + 1));
...@@ -1291,8 +1282,7 @@ void MaglevGraphBuilder::VisitConstruct() { ...@@ -1291,8 +1282,7 @@ void MaglevGraphBuilder::VisitConstruct() {
CreateNewNode<Construct>(input_count, constructor, new_target, context); CreateNewNode<Construct>(input_count, constructor, new_target, context);
int arg_index = 0; int arg_index = 0;
// Add undefined receiver. // Add undefined receiver.
construct->set_arg(arg_index++, construct->set_arg(arg_index++, GetRootConstant(RootIndex::kUndefinedValue));
AddNewNode<RootConstant>({}, RootIndex::kUndefinedValue));
for (int i = 0; i < args.register_count(); i++) { for (int i = 0; i < args.register_count(); i++) {
construct->set_arg(arg_index++, GetTaggedValue(args[i])); construct->set_arg(arg_index++, GetTaggedValue(args[i]));
} }
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
#ifndef V8_MAGLEV_MAGLEV_GRAPH_BUILDER_H_ #ifndef V8_MAGLEV_MAGLEV_GRAPH_BUILDER_H_
#define V8_MAGLEV_MAGLEV_GRAPH_BUILDER_H_ #define V8_MAGLEV_MAGLEV_GRAPH_BUILDER_H_
#include <cmath>
#include <map>
#include <type_traits> #include <type_traits>
#include "src/base/logging.h" #include "src/base/logging.h"
...@@ -285,12 +287,66 @@ class MaglevGraphBuilder { ...@@ -285,12 +287,66 @@ class MaglevGraphBuilder {
operand_index, local_isolate())))); operand_index, local_isolate()))));
} }
ValueNode* GetConstant(const compiler::ObjectRef& ref) { SmiConstant* GetSmiConstant(int constant) {
if (ref.IsSmi()) { DCHECK(Smi::IsValid(constant));
return AddNewNode<SmiConstant>({}, Smi::FromInt(ref.AsSmi())); auto it = graph_->smi().find(constant);
if (it == graph_->smi().end()) {
SmiConstant* node = CreateNewNode<SmiConstant>(0, Smi::FromInt(constant));
if (has_graph_labeller()) graph_labeller()->RegisterNode(node);
graph_->smi().emplace(constant, node);
return node;
}
return it->second;
}
RootConstant* GetRootConstant(RootIndex index) {
auto it = graph_->root().find(index);
if (it == graph_->root().end()) {
RootConstant* node = CreateNewNode<RootConstant>(0, index);
if (has_graph_labeller()) graph_labeller()->RegisterNode(node);
graph_->root().emplace(index, node);
return node;
} }
// TODO(leszeks): Detect roots and use RootConstant. return it->second;
return AddNewNode<Constant>({}, ref.AsHeapObject()); }
Int32Constant* GetInt32Constant(int constant) {
auto it = graph_->int32().find(constant);
if (it == graph_->int32().end()) {
Int32Constant* node = CreateNewNode<Int32Constant>(0, constant);
if (has_graph_labeller()) graph_labeller()->RegisterNode(node);
graph_->int32().emplace(constant, node);
return node;
}
return it->second;
}
Float64Constant* GetFloat64Constant(double constant) {
if (constant != constant) {
if (graph_->nan() == nullptr) {
graph_->set_nan(CreateNewNode<Float64Constant>(0, constant));
}
return graph_->nan();
}
auto it = graph_->float64().find(constant);
if (it == graph_->float64().end()) {
Float64Constant* node = CreateNewNode<Float64Constant>(0, constant);
if (has_graph_labeller()) graph_labeller()->RegisterNode(node);
graph_->float64().emplace(constant, node);
return node;
}
return it->second;
}
ValueNode* GetConstant(const compiler::ObjectRef& ref) {
if (ref.IsSmi()) return GetSmiConstant(ref.AsSmi());
// TODO(verwaest): Cache and handle roots.
const compiler::HeapObjectRef& constant = ref.AsHeapObject();
Constant* node = CreateNewNode<Constant>(0, constant);
if (has_graph_labeller()) graph_labeller()->RegisterNode(node);
graph_->AddConstant(node);
return node;
} }
// Move an existing ValueNode between two registers. You can pass // Move an existing ValueNode between two registers. You can pass
...@@ -352,7 +408,7 @@ class MaglevGraphBuilder { ...@@ -352,7 +408,7 @@ class MaglevGraphBuilder {
if (value->Is<CheckedSmiTag>()) { if (value->Is<CheckedSmiTag>()) {
return value->input(0).node(); return value->input(0).node();
} else if (SmiConstant* constant = value->TryCast<SmiConstant>()) { } else if (SmiConstant* constant = value->TryCast<SmiConstant>()) {
return AddNewNode<Int32Constant>({}, constant->value().value()); return GetInt32Constant(constant->value().value());
} }
return AddNewConversionNode<CheckedSmiUntag>(reg, value); return AddNewConversionNode<CheckedSmiUntag>(reg, value);
} }
...@@ -433,7 +489,9 @@ class MaglevGraphBuilder { ...@@ -433,7 +489,9 @@ class MaglevGraphBuilder {
// We should only set register values to nodes that were newly created in // We should only set register values to nodes that were newly created in
// this Visit. Existing nodes should be moved between registers with // this Visit. Existing nodes should be moved between registers with
// MoveNodeBetweenRegisters. // MoveNodeBetweenRegisters.
if (!IsConstantNode(value->opcode())) {
DCHECK_NE(0, new_nodes_.count(value)); DCHECK_NE(0, new_nodes_.count(value));
}
MarkAsLazyDeoptResult(value, target); MarkAsLazyDeoptResult(value, target);
current_interpreter_frame_.set(target, value); current_interpreter_frame_.set(target, value);
} }
......
...@@ -54,10 +54,29 @@ class Graph final : public ZoneObject { ...@@ -54,10 +54,29 @@ class Graph final : public ZoneObject {
untagged_stack_slots_ = stack_slots; untagged_stack_slots_ = stack_slots;
} }
std::map<RootIndex, RootConstant*>& root() { return root_; }
std::map<int, SmiConstant*>& smi() { return smi_; }
std::map<int, Int32Constant*>& int32() { return int_; }
std::map<double, Float64Constant*>& float64() { return float_; }
std::vector<Constant*>& constants() { return constants_; }
Float64Constant* nan() const { return nan_; }
void set_nan(Float64Constant* nan) {
DCHECK_NULL(nan_);
nan_ = nan;
}
void AddConstant(Constant* constant) { constants_.emplace_back(constant); }
private: private:
uint32_t tagged_stack_slots_ = kMaxUInt32; uint32_t tagged_stack_slots_ = kMaxUInt32;
uint32_t untagged_stack_slots_ = kMaxUInt32; uint32_t untagged_stack_slots_ = kMaxUInt32;
ZoneVector<BasicBlock*> blocks_; ZoneVector<BasicBlock*> blocks_;
std::map<RootIndex, RootConstant*> root_;
std::map<int, SmiConstant*> smi_;
std::map<int, Int32Constant*> int_;
std::map<double, Float64Constant*> float_;
std::vector<Constant*> constants_;
Float64Constant* nan_ = nullptr;
}; };
} // namespace maglev } // namespace maglev
......
This diff is collapsed.
This diff is collapsed.
...@@ -233,6 +233,22 @@ void StraightForwardRegisterAllocator::AllocateRegisters(Graph* graph) { ...@@ -233,6 +233,22 @@ void StraightForwardRegisterAllocator::AllocateRegisters(Graph* graph) {
printing_visitor_->PreProcessGraph(compilation_info_, graph); printing_visitor_->PreProcessGraph(compilation_info_, graph);
} }
for (Constant* constant : graph->constants()) {
constant->SetConstantLocation();
}
for (const auto& [index, constant] : graph->root()) {
constant->SetConstantLocation();
}
for (const auto& [value, constant] : graph->smi()) {
constant->SetConstantLocation();
}
for (const auto& [value, constant] : graph->int32()) {
constant->SetConstantLocation();
}
for (const auto& [value, constant] : graph->float64()) {
constant->SetConstantLocation();
}
for (block_it_ = graph->begin(); block_it_ != graph->end(); ++block_it_) { for (block_it_ = graph->begin(); block_it_ != graph->end(); ++block_it_) {
BasicBlock* block = *block_it_; BasicBlock* block = *block_it_;
...@@ -797,7 +813,7 @@ void StraightForwardRegisterAllocator::AssignArbitraryRegisterInput( ...@@ -797,7 +813,7 @@ void StraightForwardRegisterAllocator::AssignArbitraryRegisterInput(
input.SetAllocated(allocation); input.SetAllocated(allocation);
DCHECK_NE(location, allocation); DCHECK_NE(location, allocation);
AddMoveBeforeCurrentNode(node, location, allocation); AddMoveBeforeCurrentNode(node, location, allocation);
}; }
} }
void StraightForwardRegisterAllocator::AssignInputs(NodeBase* node) { void StraightForwardRegisterAllocator::AssignInputs(NodeBase* node) {
......
...@@ -26,7 +26,23 @@ class MaglevVregAllocationState { ...@@ -26,7 +26,23 @@ class MaglevVregAllocationState {
class MaglevVregAllocator { class MaglevVregAllocator {
public: public:
void PreProcessGraph(MaglevCompilationInfo*, Graph* graph) {} void PreProcessGraph(MaglevCompilationInfo*, Graph* graph) {
for (Constant* constant : graph->constants()) {
constant->AllocateVreg(&state_);
}
for (const auto& [index, constant] : graph->root()) {
constant->AllocateVreg(&state_);
}
for (const auto& [index, constant] : graph->smi()) {
constant->AllocateVreg(&state_);
}
for (const auto& [index, constant] : graph->int32()) {
constant->AllocateVreg(&state_);
}
for (const auto& [index, constant] : graph->float64()) {
constant->AllocateVreg(&state_);
}
}
void PostProcessGraph(MaglevCompilationInfo*, Graph* graph) { void PostProcessGraph(MaglevCompilationInfo*, Graph* graph) {
for (BasicBlock* block : *graph) { for (BasicBlock* block : *graph) {
if (!block->has_phi()) continue; if (!block->has_phi()) continue;
...@@ -39,7 +55,7 @@ class MaglevVregAllocator { ...@@ -39,7 +55,7 @@ class MaglevVregAllocator {
#define DEF_PROCESS_NODE(NAME) \ #define DEF_PROCESS_NODE(NAME) \
void Process(NAME* node, const ProcessingState& state) { \ void Process(NAME* node, const ProcessingState& state) { \
node->AllocateVreg(&state_, state); \ node->AllocateVreg(&state_); \
} }
NODE_BASE_LIST(DEF_PROCESS_NODE) NODE_BASE_LIST(DEF_PROCESS_NODE)
#undef DEF_PROCESS_NODE #undef DEF_PROCESS_NODE
......
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