Commit e1d3e0ab authored by Clemens Backes's avatar Clemens Backes Committed by V8 LUCI CQ

[TurboFan] Use SparseBitVector in mid-tier register allocator

This uses a SparseBitVector instead of a BitVector for storing sets of
blocks. As we only use the mid-tier register allocator for huge
functions, this should generally be a win in both compile time and
memory usage.

R=mslekova@chromium.org

Bug: chromium:1313379, v8:12780
Change-Id: Icf5b50c62f1c5fd69877cd54833d9dea8d1c37e1
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3634781Reviewed-by: 's avatarMaya Lekova <mslekova@chromium.org>
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80554}
parent 0598bb38
......@@ -13,12 +13,9 @@
#include "src/codegen/machine-type.h"
#include "src/codegen/register-configuration.h"
#include "src/codegen/tick-counter.h"
#include "src/common/globals.h"
#include "src/compiler/backend/instruction.h"
#include "src/compiler/linkage.h"
#include "src/logging/counters.h"
#include "src/utils/bit-vector.h"
#include "src/zone/zone-containers.h"
namespace v8 {
namespace internal {
......@@ -30,13 +27,9 @@ class DeferredBlocksRegion;
// BlockState stores details associated with a particular basic block.
class BlockState final {
public:
BlockState(int block_count, Zone* zone)
: general_registers_in_state_(nullptr),
double_registers_in_state_(nullptr),
deferred_blocks_region_(nullptr),
dominated_blocks_(block_count, zone),
successors_phi_index_(-1),
is_deferred_block_boundary_(false) {}
MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(BlockState);
explicit BlockState(Zone* zone) : dominated_blocks_(zone) {}
// Returns the RegisterState that applies to the input of this block. Can be
// |nullptr| if the no registers of |kind| have been allocated up to this
......@@ -46,7 +39,7 @@ class BlockState final {
// Returns a bitvector representing all the basic blocks that are dominated
// by this basic block.
BitVector* dominated_blocks() { return &dominated_blocks_; }
SparseBitVector* dominated_blocks() { return &dominated_blocks_; }
// Set / get this block's index for successor's phi operations. Will return
// -1 if this block has no successor's with phi operations.
......@@ -73,18 +66,16 @@ class BlockState final {
}
void MarkAsDeferredBlockBoundary() { is_deferred_block_boundary_ = true; }
MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(BlockState);
private:
RegisterState* general_registers_in_state_;
RegisterState* double_registers_in_state_;
RegisterState* simd128_registers_in_state_;
RegisterState* general_registers_in_state_ = nullptr;
RegisterState* double_registers_in_state_ = nullptr;
RegisterState* simd128_registers_in_state_ = nullptr;
DeferredBlocksRegion* deferred_blocks_region_;
DeferredBlocksRegion* deferred_blocks_region_ = nullptr;
BitVector dominated_blocks_;
int successors_phi_index_;
bool is_deferred_block_boundary_;
SparseBitVector dominated_blocks_;
int successors_phi_index_ = -1;
bool is_deferred_block_boundary_ = false;
};
RegisterState* BlockState::register_in_state(RegisterKind kind) {
......@@ -126,16 +117,15 @@ MidTierRegisterAllocationData::MidTierRegisterAllocationData(
code_(code),
debug_name_(debug_name),
config_(config),
virtual_register_data_(code->VirtualRegisterCount(), allocation_zone()),
block_states_(allocation_zone()),
reference_map_instructions_(allocation_zone()),
spilled_virtual_registers_(code->VirtualRegisterCount(),
allocation_zone()),
virtual_register_data_(code->VirtualRegisterCount(), zone),
block_states_(zone),
reference_map_instructions_(zone),
spilled_virtual_registers_(code->VirtualRegisterCount(), zone),
tick_counter_(tick_counter) {
int basic_block_count = code->InstructionBlockCount();
block_states_.reserve(basic_block_count);
for (int i = 0; i < basic_block_count; i++) {
block_states_.emplace_back(basic_block_count, allocation_zone());
block_states_.emplace_back(zone);
}
}
......@@ -166,7 +156,7 @@ const InstructionBlock* MidTierRegisterAllocationData::GetBlock(
return code()->InstructionAt(instr_index)->block();
}
const BitVector* MidTierRegisterAllocationData::GetBlocksDominatedBy(
const SparseBitVector* MidTierRegisterAllocationData::GetBlocksDominatedBy(
const InstructionBlock* block) {
return block_state(block->rpo_number()).dominated_blocks();
}
......@@ -250,10 +240,8 @@ class Range {
// Represents a connected region of deferred basic blocks.
class DeferredBlocksRegion final {
public:
explicit DeferredBlocksRegion(Zone* zone, int number_of_blocks)
: spilled_vregs_(zone),
blocks_covered_(number_of_blocks, zone),
is_frozen_(false) {}
explicit DeferredBlocksRegion(Zone* zone)
: spilled_vregs_(zone), blocks_covered_(zone) {}
void AddBlock(RpoNumber block, MidTierRegisterAllocationData* data) {
DCHECK(data->GetBlock(block)->IsDeferred());
......@@ -276,12 +264,12 @@ class DeferredBlocksRegion final {
ZoneSet<int>::const_iterator begin() const { return spilled_vregs_.begin(); }
ZoneSet<int>::const_iterator end() const { return spilled_vregs_.end(); }
const BitVector* blocks_covered() const { return &blocks_covered_; }
const SparseBitVector* blocks_covered() const { return &blocks_covered_; }
private:
ZoneSet<int> spilled_vregs_;
BitVector blocks_covered_;
bool is_frozen_;
SparseBitVector blocks_covered_;
bool is_frozen_ = false;
};
// VirtualRegisterData stores data specific to a particular virtual register,
......@@ -388,12 +376,12 @@ class VirtualRegisterData final {
struct DeferredSpillSlotOutput {
public:
explicit DeferredSpillSlotOutput(int instr, AllocatedOperand op,
const BitVector* blocks)
const SparseBitVector* blocks)
: instr_index(instr), operand(op), live_blocks(blocks) {}
int instr_index;
AllocatedOperand operand;
const BitVector* live_blocks;
const SparseBitVector* live_blocks;
};
// Represents the range of instructions for which this virtual register needs
......@@ -459,7 +447,7 @@ class VirtualRegisterData final {
const InstructionBlock* block = data->GetBlock(instr_index);
DCHECK_EQ(block->first_instruction_index(), instr_index);
BlockState& block_state = data->block_state(block->rpo_number());
const BitVector* deferred_blocks =
const SparseBitVector* deferred_blocks =
block_state.deferred_blocks_region()->blocks_covered();
deferred_spill_outputs_->emplace_back(instr_index, allocated_op,
deferred_blocks);
......@@ -478,7 +466,7 @@ class VirtualRegisterData final {
private:
Range live_range_;
const BitVector* live_blocks_;
const SparseBitVector* live_blocks_;
ZoneVector<DeferredSpillSlotOutput>* deferred_spill_outputs_;
};
......@@ -2798,8 +2786,7 @@ MidTierOutputProcessor::MidTierOutputProcessor(
void MidTierOutputProcessor::PopulateDeferredBlockRegion(
RpoNumber initial_block) {
DeferredBlocksRegion* deferred_blocks_region =
zone()->New<DeferredBlocksRegion>(zone(),
code()->InstructionBlockCount());
zone()->New<DeferredBlocksRegion>(zone());
DCHECK(deferred_blocks_worklist_.empty());
deferred_blocks_worklist_.push(initial_block);
deferred_blocks_processed_.insert(initial_block);
......
......@@ -9,8 +9,8 @@
#include "src/common/globals.h"
#include "src/compiler/backend/instruction.h"
#include "src/compiler/backend/register-allocation.h"
#include "src/flags/flags.h"
#include "src/utils/bit-vector.h"
#include "src/utils/sparse-bit-vector.h"
#include "src/zone/zone-containers.h"
#include "src/zone/zone.h"
......@@ -60,7 +60,7 @@ class MidTierRegisterAllocationData final : public RegisterAllocationData {
// Returns a bitvector representing all the blocks that are dominated by the
// output of the instruction in |block|.
const BitVector* GetBlocksDominatedBy(const InstructionBlock* block);
const SparseBitVector* GetBlocksDominatedBy(const InstructionBlock* block);
// List of all instruction indexs that require a reference map.
ZoneVector<int>& reference_map_instructions() {
......
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