Commit 17871396 authored by Ross McIlroy's avatar Ross McIlroy Committed by V8 LUCI CQ

[Turboprop] Fix refmaps for multi-entry deferred block regions.

When there are multiple entries into a deferred block region, ensure
that we freeze the set of deferred spill virtual registers when we have
processed the first entry point to that deferred block. This ensures
that we don't add another vreg into the set of deferred spills, and
then specify that that deferred spill slot is live across the whole
deferred block, when it is only live from certain entry points.

BUG=chromium:1227568,v8:9684

Change-Id: I647851be9a00fba262768e4f1a7846669b585a2e
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3021178Reviewed-by: 's avatarNico Hartmann <nicohartmann@chromium.org>
Commit-Queue: Ross McIlroy <rmcilroy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#75704}
parent 2105d237
...@@ -241,7 +241,9 @@ class Range { ...@@ -241,7 +241,9 @@ class Range {
class DeferredBlocksRegion final { class DeferredBlocksRegion final {
public: public:
explicit DeferredBlocksRegion(Zone* zone, int number_of_blocks) explicit DeferredBlocksRegion(Zone* zone, int number_of_blocks)
: spilled_vregs_(zone), blocks_covered_(number_of_blocks, zone) {} : spilled_vregs_(zone),
blocks_covered_(number_of_blocks, zone),
is_frozen_(false) {}
void AddBlock(RpoNumber block, MidTierRegisterAllocationData* data) { void AddBlock(RpoNumber block, MidTierRegisterAllocationData* data) {
DCHECK(data->GetBlock(block)->IsDeferred()); DCHECK(data->GetBlock(block)->IsDeferred());
...@@ -249,9 +251,17 @@ class DeferredBlocksRegion final { ...@@ -249,9 +251,17 @@ class DeferredBlocksRegion final {
data->block_state(block).set_deferred_blocks_region(this); data->block_state(block).set_deferred_blocks_region(this);
} }
// Adds |vreg| to the list of variables to potentially defer their output to // Trys to adds |vreg| to the list of variables to potentially defer their
// a spill slot until we enter this deferred block region. // output to a spill slot until we enter this deferred block region. Returns
void DeferSpillOutputUntilEntry(int vreg) { spilled_vregs_.insert(vreg); } // true if successful.
bool TryDeferSpillOutputUntilEntry(int vreg) {
if (spilled_vregs_.count(vreg) != 0) return true;
if (is_frozen_) return false;
spilled_vregs_.insert(vreg);
return true;
}
void FreezeDeferredSpills() { is_frozen_ = true; }
ZoneSet<int>::const_iterator begin() const { return spilled_vregs_.begin(); } ZoneSet<int>::const_iterator begin() const { return spilled_vregs_.begin(); }
ZoneSet<int>::const_iterator end() const { return spilled_vregs_.end(); } ZoneSet<int>::const_iterator end() const { return spilled_vregs_.end(); }
...@@ -261,6 +271,7 @@ class DeferredBlocksRegion final { ...@@ -261,6 +271,7 @@ class DeferredBlocksRegion final {
private: private:
ZoneSet<int> spilled_vregs_; ZoneSet<int> spilled_vregs_;
BitVector blocks_covered_; BitVector blocks_covered_;
bool is_frozen_;
}; };
// VirtualRegisterData stores data specific to a particular virtual register, // VirtualRegisterData stores data specific to a particular virtual register,
...@@ -477,7 +488,8 @@ class VirtualRegisterData final { ...@@ -477,7 +488,8 @@ class VirtualRegisterData final {
void AddSpillUse(int instr_index, MidTierRegisterAllocationData* data); void AddSpillUse(int instr_index, MidTierRegisterAllocationData* data);
void AddPendingSpillOperand(PendingOperand* pending_operand); void AddPendingSpillOperand(PendingOperand* pending_operand);
void EnsureSpillRange(MidTierRegisterAllocationData* data); void EnsureSpillRange(MidTierRegisterAllocationData* data);
bool CouldSpillOnEntryToDeferred(const InstructionBlock* block); bool TrySpillOnEntryToDeferred(MidTierRegisterAllocationData* data,
const InstructionBlock* block);
InstructionOperand* spill_operand_; InstructionOperand* spill_operand_;
SpillRange* spill_range_; SpillRange* spill_range_;
...@@ -586,12 +598,7 @@ void VirtualRegisterData::AddSpillUse(int instr_index, ...@@ -586,12 +598,7 @@ void VirtualRegisterData::AddSpillUse(int instr_index,
spill_range_->ExtendRangeTo(instr_index); spill_range_->ExtendRangeTo(instr_index);
const InstructionBlock* block = data->GetBlock(instr_index); const InstructionBlock* block = data->GetBlock(instr_index);
if (CouldSpillOnEntryToDeferred(block)) { if (!TrySpillOnEntryToDeferred(data, block)) {
DCHECK(HasSpillRange());
data->block_state(block->rpo_number())
.deferred_blocks_region()
->DeferSpillOutputUntilEntry(vreg());
} else {
MarkAsNeedsSpillAtOutput(); MarkAsNeedsSpillAtOutput();
} }
} }
...@@ -603,10 +610,15 @@ void VirtualRegisterData::AddDeferredSpillUse( ...@@ -603,10 +610,15 @@ void VirtualRegisterData::AddDeferredSpillUse(
AddSpillUse(instr_index, data); AddSpillUse(instr_index, data);
} }
bool VirtualRegisterData::CouldSpillOnEntryToDeferred( bool VirtualRegisterData::TrySpillOnEntryToDeferred(
const InstructionBlock* block) { MidTierRegisterAllocationData* data, const InstructionBlock* block) {
return !NeedsSpillAtOutput() && block->IsDeferred() && BlockState& block_state = data->block_state(block->rpo_number());
!is_defined_in_deferred_block() && !is_constant(); if (!NeedsSpillAtOutput() && block->IsDeferred() &&
!is_defined_in_deferred_block() && !is_constant()) {
return block_state.deferred_blocks_region()->TryDeferSpillOutputUntilEntry(
vreg());
}
return false;
} }
void VirtualRegisterData::AddDeferredSpillOutput( void VirtualRegisterData::AddDeferredSpillOutput(
...@@ -2818,8 +2830,13 @@ void MidTierRegisterAllocator::AllocateRegisters( ...@@ -2818,8 +2830,13 @@ void MidTierRegisterAllocator::AllocateRegisters(
for (RpoNumber successor : block->successors()) { for (RpoNumber successor : block->successors()) {
if (!data()->GetBlock(successor)->IsDeferred()) continue; if (!data()->GetBlock(successor)->IsDeferred()) continue;
DCHECK_GT(successor, block_rpo); DCHECK_GT(successor, block_rpo);
for (const int virtual_register : DeferredBlocksRegion* deferred_region =
*data()->block_state(successor).deferred_blocks_region()) { data()->block_state(successor).deferred_blocks_region();
// Freeze the deferred spills on the region to ensure no more are added to
// this region after the spills for this entry point have already been
// emitted.
deferred_region->FreezeDeferredSpills();
for (const int virtual_register : *deferred_region) {
VirtualRegisterData& vreg_data = VirtualRegisterData& vreg_data =
VirtualRegisterDataFor(virtual_register); VirtualRegisterDataFor(virtual_register);
AllocatorFor(vreg_data.rep()) AllocatorFor(vreg_data.rep())
......
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --turboprop --no-analyze-environment-liveness
// Flags:--interrupt-budget=100
var val = {};
try {
arr = [{}, [], {}];
for (var i in arr) {
for (var val = 0; val < 100; val++) {
}
}
} catch(e) { "Caught: " + e; }
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