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

[TurboFan] Use SparseBitVector in top-tier register allocator

Similar to https://crrev.com/c/3634781, this switches some {BitVector}s
in the regular top-tier register allocator to {SparseBitVector}. For
functions with a huge amount of virtual registers, this would save a
significant amount of memory, and also performance.

For small number of registers though we probably introduce a slight
regression, because there is one more dynamic check to be performed
before accessing the bits.

R=mslekova@chromium.org

Bug: chromium:1313379, v8:12780
Change-Id: Ib65d22ad0a8e2c933f7178f4fefc36e500be623c
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3650602Reviewed-by: 's avatarMaya Lekova <mslekova@chromium.org>
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80806}
parent 7e32d8a5
...@@ -1885,23 +1885,23 @@ LiveRangeBuilder::LiveRangeBuilder(TopTierRegisterAllocationData* data, ...@@ -1885,23 +1885,23 @@ LiveRangeBuilder::LiveRangeBuilder(TopTierRegisterAllocationData* data,
Zone* local_zone) Zone* local_zone)
: data_(data), phi_hints_(local_zone) {} : data_(data), phi_hints_(local_zone) {}
BitVector* LiveRangeBuilder::ComputeLiveOut( SparseBitVector* LiveRangeBuilder::ComputeLiveOut(
const InstructionBlock* block, TopTierRegisterAllocationData* data) { const InstructionBlock* block, TopTierRegisterAllocationData* data) {
size_t block_index = block->rpo_number().ToSize(); size_t block_index = block->rpo_number().ToSize();
BitVector* live_out = data->live_out_sets()[block_index]; SparseBitVector* live_out = data->live_out_sets()[block_index];
if (live_out == nullptr) { if (live_out == nullptr) {
// Compute live out for the given block, except not including backward // Compute live out for the given block, except not including backward
// successor edges. // successor edges.
Zone* zone = data->allocation_zone(); Zone* zone = data->allocation_zone();
const InstructionSequence* code = data->code(); const InstructionSequence* code = data->code();
live_out = zone->New<BitVector>(code->VirtualRegisterCount(), zone); live_out = zone->New<SparseBitVector>(zone);
// Process all successor blocks. // Process all successor blocks.
for (const RpoNumber& succ : block->successors()) { for (const RpoNumber& succ : block->successors()) {
// Add values live on entry to the successor. // Add values live on entry to the successor.
if (succ <= block->rpo_number()) continue; if (succ <= block->rpo_number()) continue;
BitVector* live_in = data->live_in_sets()[succ.ToSize()]; SparseBitVector* live_in = data->live_in_sets()[succ.ToSize()];
if (live_in != nullptr) live_out->Union(*live_in); if (live_in != nullptr) live_out->Union(*live_in);
// All phi input operands corresponding to this successor edge are live // All phi input operands corresponding to this successor edge are live
...@@ -1919,7 +1919,7 @@ BitVector* LiveRangeBuilder::ComputeLiveOut( ...@@ -1919,7 +1919,7 @@ BitVector* LiveRangeBuilder::ComputeLiveOut(
} }
void LiveRangeBuilder::AddInitialIntervals(const InstructionBlock* block, void LiveRangeBuilder::AddInitialIntervals(const InstructionBlock* block,
BitVector* live_out) { SparseBitVector* live_out) {
// Add an interval that includes the entire block to the live range for // Add an interval that includes the entire block to the live range for
// each live_out value. // each live_out value.
LifetimePosition start = LifetimePosition::GapFromInstructionIndex( LifetimePosition start = LifetimePosition::GapFromInstructionIndex(
...@@ -2114,7 +2114,7 @@ UsePosition* LiveRangeBuilder::Use(LifetimePosition block_start, ...@@ -2114,7 +2114,7 @@ UsePosition* LiveRangeBuilder::Use(LifetimePosition block_start,
} }
void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block, void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block,
BitVector* live) { SparseBitVector* live) {
int block_start = block->first_instruction_index(); int block_start = block->first_instruction_index();
LifetimePosition block_start_position = LifetimePosition block_start_position =
LifetimePosition::GapFromInstructionIndex(block_start); LifetimePosition::GapFromInstructionIndex(block_start);
...@@ -2348,7 +2348,7 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block, ...@@ -2348,7 +2348,7 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block,
} }
void LiveRangeBuilder::ProcessPhis(const InstructionBlock* block, void LiveRangeBuilder::ProcessPhis(const InstructionBlock* block,
BitVector* live) { SparseBitVector* live) {
for (PhiInstruction* phi : block->phis()) { for (PhiInstruction* phi : block->phis()) {
// The live range interval already ends at the first instruction of the // The live range interval already ends at the first instruction of the
// block. // block.
...@@ -2470,7 +2470,7 @@ void LiveRangeBuilder::ProcessPhis(const InstructionBlock* block, ...@@ -2470,7 +2470,7 @@ void LiveRangeBuilder::ProcessPhis(const InstructionBlock* block,
} }
void LiveRangeBuilder::ProcessLoopHeader(const InstructionBlock* block, void LiveRangeBuilder::ProcessLoopHeader(const InstructionBlock* block,
BitVector* live) { SparseBitVector* live) {
DCHECK(block->IsLoopHeader()); DCHECK(block->IsLoopHeader());
// Add a live range stretching from the first loop instruction to the last // Add a live range stretching from the first loop instruction to the last
// for each value live on entry to the header. // for each value live on entry to the header.
...@@ -2498,7 +2498,7 @@ void LiveRangeBuilder::BuildLiveRanges() { ...@@ -2498,7 +2498,7 @@ void LiveRangeBuilder::BuildLiveRanges() {
data_->tick_counter()->TickAndMaybeEnterSafepoint(); data_->tick_counter()->TickAndMaybeEnterSafepoint();
InstructionBlock* block = InstructionBlock* block =
code()->InstructionBlockAt(RpoNumber::FromInt(block_id)); code()->InstructionBlockAt(RpoNumber::FromInt(block_id));
BitVector* live = ComputeLiveOut(block, data()); SparseBitVector* live = ComputeLiveOut(block, data());
// Initially consider all live_out values live for the entire block. We // Initially consider all live_out values live for the entire block. We
// will shorten these intervals if necessary. // will shorten these intervals if necessary.
AddInitialIntervals(block, live); AddInitialIntervals(block, live);
...@@ -4877,10 +4877,10 @@ bool LiveRangeConnector::CanEagerlyResolveControlFlow( ...@@ -4877,10 +4877,10 @@ bool LiveRangeConnector::CanEagerlyResolveControlFlow(
void LiveRangeConnector::ResolveControlFlow(Zone* local_zone) { void LiveRangeConnector::ResolveControlFlow(Zone* local_zone) {
// Lazily linearize live ranges in memory for fast lookup. // Lazily linearize live ranges in memory for fast lookup.
LiveRangeFinder finder(data(), local_zone); LiveRangeFinder finder(data(), local_zone);
ZoneVector<BitVector*>& live_in_sets = data()->live_in_sets(); ZoneVector<SparseBitVector*>& live_in_sets = data()->live_in_sets();
for (const InstructionBlock* block : code()->instruction_blocks()) { for (const InstructionBlock* block : code()->instruction_blocks()) {
if (CanEagerlyResolveControlFlow(block)) continue; if (CanEagerlyResolveControlFlow(block)) continue;
BitVector* live = live_in_sets[block->rpo_number().ToInt()]; SparseBitVector* live = live_in_sets[block->rpo_number().ToInt()];
auto it = live->begin(); auto it = live->begin();
auto end = live->end(); auto end = live->end();
while (it != end) { while (it != end) {
...@@ -5133,9 +5133,7 @@ void LiveRangeConnector::CommitSpillsInDeferredBlocks( ...@@ -5133,9 +5133,7 @@ void LiveRangeConnector::CommitSpillsInDeferredBlocks(
ZoneSet<std::pair<RpoNumber, int>> done_moves(temp_zone); ZoneSet<std::pair<RpoNumber, int>> done_moves(temp_zone);
// Seek the deferred blocks that dominate locations requiring spill operands, // Seek the deferred blocks that dominate locations requiring spill operands,
// and spill there. We only need to spill at the start of such blocks. // and spill there. We only need to spill at the start of such blocks.
BitVector done_blocks( SparseBitVector done_blocks(temp_zone);
range->GetListOfBlocksRequiringSpillOperands(data())->length(),
temp_zone);
while (!worklist.empty()) { while (!worklist.empty()) {
int block_id = worklist.front(); int block_id = worklist.front();
worklist.pop(); worklist.pop();
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "src/compiler/backend/register-allocation.h" #include "src/compiler/backend/register-allocation.h"
#include "src/flags/flags.h" #include "src/flags/flags.h"
#include "src/utils/ostreams.h" #include "src/utils/ostreams.h"
#include "src/utils/sparse-bit-vector.h"
#include "src/zone/zone-containers.h" #include "src/zone/zone-containers.h"
namespace v8 { namespace v8 {
...@@ -285,8 +286,8 @@ class TopTierRegisterAllocationData final : public RegisterAllocationData { ...@@ -285,8 +286,8 @@ class TopTierRegisterAllocationData final : public RegisterAllocationData {
const ZoneVector<TopLevelLiveRange*>& fixed_simd128_live_ranges() const { const ZoneVector<TopLevelLiveRange*>& fixed_simd128_live_ranges() const {
return fixed_simd128_live_ranges_; return fixed_simd128_live_ranges_;
} }
ZoneVector<BitVector*>& live_in_sets() { return live_in_sets_; } ZoneVector<SparseBitVector*>& live_in_sets() { return live_in_sets_; }
ZoneVector<BitVector*>& live_out_sets() { return live_out_sets_; } ZoneVector<SparseBitVector*>& live_out_sets() { return live_out_sets_; }
ZoneVector<SpillRange*>& spill_ranges() { return spill_ranges_; } ZoneVector<SpillRange*>& spill_ranges() { return spill_ranges_; }
DelayedReferences& delayed_references() { return delayed_references_; } DelayedReferences& delayed_references() { return delayed_references_; }
InstructionSequence* code() const { return code_; } InstructionSequence* code() const { return code_; }
...@@ -361,8 +362,8 @@ class TopTierRegisterAllocationData final : public RegisterAllocationData { ...@@ -361,8 +362,8 @@ class TopTierRegisterAllocationData final : public RegisterAllocationData {
const char* const debug_name_; const char* const debug_name_;
const RegisterConfiguration* const config_; const RegisterConfiguration* const config_;
PhiMap phi_map_; PhiMap phi_map_;
ZoneVector<BitVector*> live_in_sets_; ZoneVector<SparseBitVector*> live_in_sets_;
ZoneVector<BitVector*> live_out_sets_; ZoneVector<SparseBitVector*> live_out_sets_;
ZoneVector<TopLevelLiveRange*> live_ranges_; ZoneVector<TopLevelLiveRange*> live_ranges_;
ZoneVector<TopLevelLiveRange*> fixed_live_ranges_; ZoneVector<TopLevelLiveRange*> fixed_live_ranges_;
ZoneVector<TopLevelLiveRange*> fixed_float_live_ranges_; ZoneVector<TopLevelLiveRange*> fixed_float_live_ranges_;
...@@ -931,8 +932,7 @@ class V8_EXPORT_PRIVATE TopLevelLiveRange final : public LiveRange { ...@@ -931,8 +932,7 @@ class V8_EXPORT_PRIVATE TopLevelLiveRange final : public LiveRange {
spill_start_index_ = -1; spill_start_index_ = -1;
spilled_in_deferred_blocks_ = true; spilled_in_deferred_blocks_ = true;
spill_move_insertion_locations_ = nullptr; spill_move_insertion_locations_ = nullptr;
list_of_blocks_requiring_spill_operands_ = list_of_blocks_requiring_spill_operands_ = zone->New<SparseBitVector>(zone);
zone->New<BitVector>(total_block_count, zone);
} }
// Updates internal data structures to reflect that this range is not // Updates internal data structures to reflect that this range is not
...@@ -940,8 +940,7 @@ class V8_EXPORT_PRIVATE TopLevelLiveRange final : public LiveRange { ...@@ -940,8 +940,7 @@ class V8_EXPORT_PRIVATE TopLevelLiveRange final : public LiveRange {
void TransitionRangeToDeferredSpill(Zone* zone, int total_block_count) { void TransitionRangeToDeferredSpill(Zone* zone, int total_block_count) {
spill_start_index_ = -1; spill_start_index_ = -1;
spill_move_insertion_locations_ = nullptr; spill_move_insertion_locations_ = nullptr;
list_of_blocks_requiring_spill_operands_ = list_of_blocks_requiring_spill_operands_ = zone->New<SparseBitVector>(zone);
zone->New<BitVector>(total_block_count, zone);
} }
// Promotes this range to spill at definition if it was marked for spilling // Promotes this range to spill at definition if it was marked for spilling
...@@ -1014,7 +1013,7 @@ class V8_EXPORT_PRIVATE TopLevelLiveRange final : public LiveRange { ...@@ -1014,7 +1013,7 @@ class V8_EXPORT_PRIVATE TopLevelLiveRange final : public LiveRange {
GetListOfBlocksRequiringSpillOperands(data)->Add(block_id.ToInt()); GetListOfBlocksRequiringSpillOperands(data)->Add(block_id.ToInt());
} }
BitVector* GetListOfBlocksRequiringSpillOperands( SparseBitVector* GetListOfBlocksRequiringSpillOperands(
const TopTierRegisterAllocationData* data) const { const TopTierRegisterAllocationData* data) const {
DCHECK(IsSpilledOnlyInDeferredBlocks(data)); DCHECK(IsSpilledOnlyInDeferredBlocks(data));
return list_of_blocks_requiring_spill_operands_; return list_of_blocks_requiring_spill_operands_;
...@@ -1049,7 +1048,7 @@ class V8_EXPORT_PRIVATE TopLevelLiveRange final : public LiveRange { ...@@ -1049,7 +1048,7 @@ class V8_EXPORT_PRIVATE TopLevelLiveRange final : public LiveRange {
union { union {
SpillMoveInsertionList* spill_move_insertion_locations_; SpillMoveInsertionList* spill_move_insertion_locations_;
BitVector* list_of_blocks_requiring_spill_operands_; SparseBitVector* list_of_blocks_requiring_spill_operands_;
}; };
// TODO(mtrofin): generalize spilling after definition, currently specialized // TODO(mtrofin): generalize spilling after definition, currently specialized
...@@ -1211,8 +1210,8 @@ class LiveRangeBuilder final : public ZoneObject { ...@@ -1211,8 +1210,8 @@ class LiveRangeBuilder final : public ZoneObject {
// Phase 3: compute liveness of all virtual register. // Phase 3: compute liveness of all virtual register.
void BuildLiveRanges(); void BuildLiveRanges();
static BitVector* ComputeLiveOut(const InstructionBlock* block, static SparseBitVector* ComputeLiveOut(const InstructionBlock* block,
TopTierRegisterAllocationData* data); TopTierRegisterAllocationData* data);
private: private:
using SpillMode = TopTierRegisterAllocationData::SpillMode; using SpillMode = TopTierRegisterAllocationData::SpillMode;
...@@ -1224,7 +1223,7 @@ class LiveRangeBuilder final : public ZoneObject { ...@@ -1224,7 +1223,7 @@ class LiveRangeBuilder final : public ZoneObject {
Zone* allocation_zone() const { return data()->allocation_zone(); } Zone* allocation_zone() const { return data()->allocation_zone(); }
Zone* code_zone() const { return code()->zone(); } Zone* code_zone() const { return code()->zone(); }
const RegisterConfiguration* config() const { return data()->config(); } const RegisterConfiguration* config() const { return data()->config(); }
ZoneVector<BitVector*>& live_in_sets() const { ZoneVector<SparseBitVector*>& live_in_sets() const {
return data()->live_in_sets(); return data()->live_in_sets();
} }
...@@ -1236,10 +1235,12 @@ class LiveRangeBuilder final : public ZoneObject { ...@@ -1236,10 +1235,12 @@ class LiveRangeBuilder final : public ZoneObject {
bool NextIntervalStartsInDifferentBlocks(const UseInterval* interval) const; bool NextIntervalStartsInDifferentBlocks(const UseInterval* interval) const;
// Liveness analysis support. // Liveness analysis support.
void AddInitialIntervals(const InstructionBlock* block, BitVector* live_out); void AddInitialIntervals(const InstructionBlock* block,
void ProcessInstructions(const InstructionBlock* block, BitVector* live); SparseBitVector* live_out);
void ProcessPhis(const InstructionBlock* block, BitVector* live); void ProcessInstructions(const InstructionBlock* block,
void ProcessLoopHeader(const InstructionBlock* block, BitVector* live); SparseBitVector* live);
void ProcessPhis(const InstructionBlock* block, SparseBitVector* live);
void ProcessLoopHeader(const InstructionBlock* block, SparseBitVector* live);
static int FixedLiveRangeID(int index) { return -index - 1; } static int FixedLiveRangeID(int index) { return -index - 1; }
int FixedFPLiveRangeID(int index, MachineRepresentation rep); int FixedFPLiveRangeID(int index, MachineRepresentation rep);
......
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