[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/+/3021178 Reviewed-by: Nico Hartmann <nicohartmann@chromium.org> Commit-Queue: Ross McIlroy <rmcilroy@chromium.org> Cr-Commit-Position: refs/heads/master@{#75704}
This commit is contained in:
parent
2105d237fa
commit
17871396f7
@ -241,7 +241,9 @@ class Range {
|
||||
class DeferredBlocksRegion final {
|
||||
public:
|
||||
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) {
|
||||
DCHECK(data->GetBlock(block)->IsDeferred());
|
||||
@ -249,9 +251,17 @@ class DeferredBlocksRegion final {
|
||||
data->block_state(block).set_deferred_blocks_region(this);
|
||||
}
|
||||
|
||||
// Adds |vreg| to the list of variables to potentially defer their output to
|
||||
// a spill slot until we enter this deferred block region.
|
||||
void DeferSpillOutputUntilEntry(int vreg) { spilled_vregs_.insert(vreg); }
|
||||
// Trys to adds |vreg| to the list of variables to potentially defer their
|
||||
// output to a spill slot until we enter this deferred block region. Returns
|
||||
// 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 end() const { return spilled_vregs_.end(); }
|
||||
@ -261,6 +271,7 @@ class DeferredBlocksRegion final {
|
||||
private:
|
||||
ZoneSet<int> spilled_vregs_;
|
||||
BitVector blocks_covered_;
|
||||
bool is_frozen_;
|
||||
};
|
||||
|
||||
// VirtualRegisterData stores data specific to a particular virtual register,
|
||||
@ -477,7 +488,8 @@ class VirtualRegisterData final {
|
||||
void AddSpillUse(int instr_index, MidTierRegisterAllocationData* data);
|
||||
void AddPendingSpillOperand(PendingOperand* pending_operand);
|
||||
void EnsureSpillRange(MidTierRegisterAllocationData* data);
|
||||
bool CouldSpillOnEntryToDeferred(const InstructionBlock* block);
|
||||
bool TrySpillOnEntryToDeferred(MidTierRegisterAllocationData* data,
|
||||
const InstructionBlock* block);
|
||||
|
||||
InstructionOperand* spill_operand_;
|
||||
SpillRange* spill_range_;
|
||||
@ -586,12 +598,7 @@ void VirtualRegisterData::AddSpillUse(int instr_index,
|
||||
spill_range_->ExtendRangeTo(instr_index);
|
||||
|
||||
const InstructionBlock* block = data->GetBlock(instr_index);
|
||||
if (CouldSpillOnEntryToDeferred(block)) {
|
||||
DCHECK(HasSpillRange());
|
||||
data->block_state(block->rpo_number())
|
||||
.deferred_blocks_region()
|
||||
->DeferSpillOutputUntilEntry(vreg());
|
||||
} else {
|
||||
if (!TrySpillOnEntryToDeferred(data, block)) {
|
||||
MarkAsNeedsSpillAtOutput();
|
||||
}
|
||||
}
|
||||
@ -603,10 +610,15 @@ void VirtualRegisterData::AddDeferredSpillUse(
|
||||
AddSpillUse(instr_index, data);
|
||||
}
|
||||
|
||||
bool VirtualRegisterData::CouldSpillOnEntryToDeferred(
|
||||
const InstructionBlock* block) {
|
||||
return !NeedsSpillAtOutput() && block->IsDeferred() &&
|
||||
!is_defined_in_deferred_block() && !is_constant();
|
||||
bool VirtualRegisterData::TrySpillOnEntryToDeferred(
|
||||
MidTierRegisterAllocationData* data, const InstructionBlock* block) {
|
||||
BlockState& block_state = data->block_state(block->rpo_number());
|
||||
if (!NeedsSpillAtOutput() && block->IsDeferred() &&
|
||||
!is_defined_in_deferred_block() && !is_constant()) {
|
||||
return block_state.deferred_blocks_region()->TryDeferSpillOutputUntilEntry(
|
||||
vreg());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void VirtualRegisterData::AddDeferredSpillOutput(
|
||||
@ -2818,8 +2830,13 @@ void MidTierRegisterAllocator::AllocateRegisters(
|
||||
for (RpoNumber successor : block->successors()) {
|
||||
if (!data()->GetBlock(successor)->IsDeferred()) continue;
|
||||
DCHECK_GT(successor, block_rpo);
|
||||
for (const int virtual_register :
|
||||
*data()->block_state(successor).deferred_blocks_region()) {
|
||||
DeferredBlocksRegion* deferred_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 =
|
||||
VirtualRegisterDataFor(virtual_register);
|
||||
AllocatorFor(vreg_data.rep())
|
||||
|
15
test/mjsunit/regress/regress-1227568.js
Normal file
15
test/mjsunit/regress/regress-1227568.js
Normal file
@ -0,0 +1,15 @@
|
||||
// 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; }
|
Loading…
Reference in New Issue
Block a user