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 {
class NumberingProcessor {
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 PreProcessBasicBlock(MaglevCompilationInfo*, BasicBlock* block) {}
......
......@@ -110,8 +110,7 @@ void MaglevGraphBuilder::BuildRegisterFrameInitialization() {
int register_index = 0;
// TODO(leszeks): Don't emit if not needed.
ValueNode* undefined_value =
AddNewNode<RootConstant>({}, RootIndex::kUndefinedValue);
ValueNode* undefined_value = GetRootConstant(RootIndex::kUndefinedValue);
if (new_target_or_generator_register.is_valid()) {
int new_target_index = new_target_or_generator_register.index();
for (; register_index < new_target_index; register_index++) {
......@@ -295,8 +294,8 @@ void MaglevGraphBuilder::BuildGenericBinaryOperationNode() {
template <Operation kOperation>
void MaglevGraphBuilder::BuildGenericBinarySmiOperationNode() {
ValueNode* left = GetAccumulatorTagged();
Smi constant = Smi::FromInt(iterator_.GetImmediateOperand(0));
ValueNode* right = AddNewNode<SmiConstant>({}, constant);
int constant = iterator_.GetImmediateOperand(0);
ValueNode* right = GetSmiConstant(constant);
FeedbackSlot slot_index = GetSlotOperand(1);
SetAccumulator(AddNewNode<GenericNodeForOperation<kOperation>>(
{left, right}, compiler::FeedbackSource{feedback(), slot_index}));
......@@ -325,7 +324,7 @@ void MaglevGraphBuilder::BuildInt32BinarySmiOperationNode() {
// value, so we can just return.
return;
}
ValueNode* right = AddNewNode<Int32Constant>({}, constant);
ValueNode* right = GetInt32Constant(constant);
SetAccumulator(AddNewInt32BinaryOperationNode<kOperation>({left, right}));
}
......@@ -334,7 +333,7 @@ void MaglevGraphBuilder::BuildFloat64BinarySmiOperationNode() {
// TODO(v8:7700): Do constant folding.
ValueNode* left = GetAccumulatorFloat64();
double constant = static_cast<double>(iterator_.GetImmediateOperand(0));
ValueNode* right = AddNewNode<Float64Constant>({}, constant);
ValueNode* right = GetFloat64Constant(constant);
SetAccumulator(AddNewFloat64BinaryOperationNode<kOperation>({left, right}));
}
......@@ -509,27 +508,25 @@ void MaglevGraphBuilder::VisitLdar() {
interpreter::Register::virtual_accumulator());
}
void MaglevGraphBuilder::VisitLdaZero() {
SetAccumulator(AddNewNode<SmiConstant>({}, Smi::zero()));
}
void MaglevGraphBuilder::VisitLdaZero() { SetAccumulator(GetSmiConstant(0)); }
void MaglevGraphBuilder::VisitLdaSmi() {
Smi constant = Smi::FromInt(iterator_.GetImmediateOperand(0));
SetAccumulator(AddNewNode<SmiConstant>({}, constant));
int constant = iterator_.GetImmediateOperand(0);
SetAccumulator(GetSmiConstant(constant));
}
void MaglevGraphBuilder::VisitLdaUndefined() {
SetAccumulator(AddNewNode<RootConstant>({}, RootIndex::kUndefinedValue));
SetAccumulator(GetRootConstant(RootIndex::kUndefinedValue));
}
void MaglevGraphBuilder::VisitLdaNull() {
SetAccumulator(AddNewNode<RootConstant>({}, RootIndex::kNullValue));
SetAccumulator(GetRootConstant(RootIndex::kNullValue));
}
void MaglevGraphBuilder::VisitLdaTheHole() {
SetAccumulator(AddNewNode<RootConstant>({}, RootIndex::kTheHoleValue));
SetAccumulator(GetRootConstant(RootIndex::kTheHoleValue));
}
void MaglevGraphBuilder::VisitLdaTrue() {
SetAccumulator(AddNewNode<RootConstant>({}, RootIndex::kTrueValue));
SetAccumulator(GetRootConstant(RootIndex::kTrueValue));
}
void MaglevGraphBuilder::VisitLdaFalse() {
SetAccumulator(AddNewNode<RootConstant>({}, RootIndex::kFalseValue));
SetAccumulator(GetRootConstant(RootIndex::kFalseValue));
}
void MaglevGraphBuilder::VisitLdaConstant() {
SetAccumulator(GetConstant(GetRefOperand<HeapObject>(0)));
......@@ -641,8 +638,7 @@ bool MaglevGraphBuilder::TryBuildPropertyCellAccess(
return true;
}
ValueNode* property_cell_node =
AddNewNode<Constant>({}, property_cell.AsHeapObject());
ValueNode* property_cell_node = GetConstant(property_cell.AsHeapObject());
SetAccumulator(AddNewNode<LoadTaggedField>({property_cell_node},
PropertyCell::kValueOffset));
return true;
......@@ -769,12 +765,10 @@ bool MaglevGraphBuilder::TryBuildMonomorphicLoadFromLoadHandler(
}
MaybeObject value = handler.data1(local_isolate_);
if (value.IsSmi()) {
SetAccumulator(AddNewNode<SmiConstant>({}, value.ToSmi()));
SetAccumulator(GetSmiConstant(value.ToSmi().value()));
} else {
SetAccumulator(AddNewNode<Constant>(
{}, MakeRefAssumeMemoryFence(
broker(),
broker()->CanonicalPersistentHandle(value.GetHeapObject()))));
SetAccumulator(GetConstant(MakeRefAssumeMemoryFence(
broker(), broker()->CanonicalPersistentHandle(value.GetHeapObject()))));
}
return true;
}
......@@ -1059,8 +1053,7 @@ void MaglevGraphBuilder::InlineCallFromRegisters(
// created.
RootConstant* undefined_constant;
if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) {
undefined_constant =
AddNewNode<RootConstant>({}, RootIndex::kUndefinedValue);
undefined_constant = GetRootConstant(RootIndex::kUndefinedValue);
}
// Create a new compilation unit and graph builder for the inlined
......@@ -1168,8 +1161,7 @@ void MaglevGraphBuilder::BuildCallFromRegisterList(
CreateNewNode<Call>(input_count, receiver_mode, function, context);
int arg_index = 0;
if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) {
call->set_arg(arg_index++,
AddNewNode<RootConstant>({}, RootIndex::kUndefinedValue));
call->set_arg(arg_index++, GetRootConstant(RootIndex::kUndefinedValue));
}
for (int i = 0; i < args.register_count(); ++i) {
call->set_arg(arg_index++, GetTaggedValue(args[i]));
......@@ -1236,8 +1228,7 @@ void MaglevGraphBuilder::BuildCallFromRegisters(
CreateNewNode<Call>(input_count, receiver_mode, function, context);
if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) {
reg_count = argc_count;
call->set_arg(arg_index++,
AddNewNode<RootConstant>({}, RootIndex::kUndefinedValue));
call->set_arg(arg_index++, GetRootConstant(RootIndex::kUndefinedValue));
}
for (int i = 0; i < reg_count; i++) {
call->set_arg(arg_index++, LoadRegisterTagged(i + 1));
......@@ -1291,8 +1282,7 @@ void MaglevGraphBuilder::VisitConstruct() {
CreateNewNode<Construct>(input_count, constructor, new_target, context);
int arg_index = 0;
// Add undefined receiver.
construct->set_arg(arg_index++,
AddNewNode<RootConstant>({}, RootIndex::kUndefinedValue));
construct->set_arg(arg_index++, GetRootConstant(RootIndex::kUndefinedValue));
for (int i = 0; i < args.register_count(); i++) {
construct->set_arg(arg_index++, GetTaggedValue(args[i]));
}
......
......@@ -5,6 +5,8 @@
#ifndef V8_MAGLEV_MAGLEV_GRAPH_BUILDER_H_
#define V8_MAGLEV_MAGLEV_GRAPH_BUILDER_H_
#include <cmath>
#include <map>
#include <type_traits>
#include "src/base/logging.h"
......@@ -285,12 +287,66 @@ class MaglevGraphBuilder {
operand_index, local_isolate()))));
}
ValueNode* GetConstant(const compiler::ObjectRef& ref) {
if (ref.IsSmi()) {
return AddNewNode<SmiConstant>({}, Smi::FromInt(ref.AsSmi()));
SmiConstant* GetSmiConstant(int constant) {
DCHECK(Smi::IsValid(constant));
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;
}
return it->second;
}
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;
}
// TODO(leszeks): Detect roots and use RootConstant.
return AddNewNode<Constant>({}, ref.AsHeapObject());
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
......@@ -352,7 +408,7 @@ class MaglevGraphBuilder {
if (value->Is<CheckedSmiTag>()) {
return value->input(0).node();
} else if (SmiConstant* constant = value->TryCast<SmiConstant>()) {
return AddNewNode<Int32Constant>({}, constant->value().value());
return GetInt32Constant(constant->value().value());
}
return AddNewConversionNode<CheckedSmiUntag>(reg, value);
}
......@@ -433,7 +489,9 @@ class MaglevGraphBuilder {
// We should only set register values to nodes that were newly created in
// this Visit. Existing nodes should be moved between registers with
// MoveNodeBetweenRegisters.
DCHECK_NE(0, new_nodes_.count(value));
if (!IsConstantNode(value->opcode())) {
DCHECK_NE(0, new_nodes_.count(value));
}
MarkAsLazyDeoptResult(value, target);
current_interpreter_frame_.set(target, value);
}
......
......@@ -54,10 +54,29 @@ class Graph final : public ZoneObject {
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:
uint32_t tagged_stack_slots_ = kMaxUInt32;
uint32_t untagged_stack_slots_ = kMaxUInt32;
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
......
This diff is collapsed.
This diff is collapsed.
......@@ -233,6 +233,22 @@ void StraightForwardRegisterAllocator::AllocateRegisters(Graph* 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_) {
BasicBlock* block = *block_it_;
......@@ -797,7 +813,7 @@ void StraightForwardRegisterAllocator::AssignArbitraryRegisterInput(
input.SetAllocated(allocation);
DCHECK_NE(location, allocation);
AddMoveBeforeCurrentNode(node, location, allocation);
};
}
}
void StraightForwardRegisterAllocator::AssignInputs(NodeBase* node) {
......
......@@ -26,7 +26,23 @@ class MaglevVregAllocationState {
class MaglevVregAllocator {
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) {
for (BasicBlock* block : *graph) {
if (!block->has_phi()) continue;
......@@ -39,7 +55,7 @@ class MaglevVregAllocator {
#define DEF_PROCESS_NODE(NAME) \
void Process(NAME* node, const ProcessingState& state) { \
node->AllocateVreg(&state_, state); \
node->AllocateVreg(&state_); \
}
NODE_BASE_LIST(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