[cpp20] Fixes undefined behaviour on mid tier regalloc
Fixes undefined behavior, which manifests as a compiler error in C++20 in Google3. This was caused by using members of vector<T> before T has been defined. This change just massages the code a bit to get everything in the proper order. See cl/468678068 on Google3. Bug: chromium:1284275 Change-Id: I0b65e7f850e8dd1ed482be1b5cc0b8d9d77776eb Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3859343 Auto-Submit: Victor Gomes <victorgomes@chromium.org> Reviewed-by: Nico Hartmann <nicohartmann@chromium.org> Commit-Queue: Nico Hartmann <nicohartmann@chromium.org> Cr-Commit-Position: refs/heads/main@{#82745}
This commit is contained in:
parent
32b7b8e903
commit
bcda1e7647
@ -24,89 +24,6 @@ namespace compiler {
|
||||
class RegisterState;
|
||||
class DeferredBlocksRegion;
|
||||
|
||||
// BlockState stores details associated with a particular basic block.
|
||||
class BlockState final {
|
||||
public:
|
||||
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
|
||||
// point.
|
||||
RegisterState* register_in_state(RegisterKind kind);
|
||||
void set_register_in_state(RegisterState* register_state, RegisterKind kind);
|
||||
|
||||
// Returns a bitvector representing all the basic blocks that are dominated
|
||||
// by this basic block.
|
||||
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.
|
||||
int successors_phi_index() const { return successors_phi_index_; }
|
||||
void set_successors_phi_index(int index) {
|
||||
DCHECK_EQ(successors_phi_index_, -1);
|
||||
successors_phi_index_ = index;
|
||||
}
|
||||
|
||||
// If this block is deferred, this represents region of deferred blocks
|
||||
// that are directly reachable from this block.
|
||||
DeferredBlocksRegion* deferred_blocks_region() const {
|
||||
return deferred_blocks_region_;
|
||||
}
|
||||
void set_deferred_blocks_region(DeferredBlocksRegion* region) {
|
||||
DCHECK_NULL(deferred_blocks_region_);
|
||||
deferred_blocks_region_ = region;
|
||||
}
|
||||
|
||||
// Returns true if this block represents either a transition from
|
||||
// non-deferred to deferred or vice versa.
|
||||
bool is_deferred_block_boundary() const {
|
||||
return is_deferred_block_boundary_;
|
||||
}
|
||||
void MarkAsDeferredBlockBoundary() { is_deferred_block_boundary_ = true; }
|
||||
|
||||
private:
|
||||
RegisterState* general_registers_in_state_ = nullptr;
|
||||
RegisterState* double_registers_in_state_ = nullptr;
|
||||
RegisterState* simd128_registers_in_state_ = nullptr;
|
||||
|
||||
DeferredBlocksRegion* deferred_blocks_region_ = nullptr;
|
||||
|
||||
SparseBitVector dominated_blocks_;
|
||||
int successors_phi_index_ = -1;
|
||||
bool is_deferred_block_boundary_ = false;
|
||||
};
|
||||
|
||||
RegisterState* BlockState::register_in_state(RegisterKind kind) {
|
||||
switch (kind) {
|
||||
case RegisterKind::kGeneral:
|
||||
return general_registers_in_state_;
|
||||
case RegisterKind::kDouble:
|
||||
return double_registers_in_state_;
|
||||
case RegisterKind::kSimd128:
|
||||
return simd128_registers_in_state_;
|
||||
}
|
||||
}
|
||||
|
||||
void BlockState::set_register_in_state(RegisterState* register_state,
|
||||
RegisterKind kind) {
|
||||
switch (kind) {
|
||||
case RegisterKind::kGeneral:
|
||||
DCHECK_NULL(general_registers_in_state_);
|
||||
general_registers_in_state_ = register_state;
|
||||
break;
|
||||
case RegisterKind::kDouble:
|
||||
DCHECK_NULL(double_registers_in_state_);
|
||||
double_registers_in_state_ = register_state;
|
||||
break;
|
||||
case RegisterKind::kSimd128:
|
||||
DCHECK_NULL(simd128_registers_in_state_);
|
||||
simd128_registers_in_state_ = register_state;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// A Range from [start, end] of instructions, inclusive of start and end.
|
||||
class Range {
|
||||
public:
|
||||
@ -134,41 +51,6 @@ class Range {
|
||||
int end_;
|
||||
};
|
||||
|
||||
// Represents a connected region of deferred basic blocks.
|
||||
class DeferredBlocksRegion final {
|
||||
public:
|
||||
explicit DeferredBlocksRegion(Zone* zone)
|
||||
: spilled_vregs_(zone), blocks_covered_(zone) {}
|
||||
|
||||
void AddBlock(RpoNumber block, MidTierRegisterAllocationData* data) {
|
||||
DCHECK(data->GetBlock(block)->IsDeferred());
|
||||
blocks_covered_.Add(block.ToInt());
|
||||
data->block_state(block).set_deferred_blocks_region(this);
|
||||
}
|
||||
|
||||
// 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(); }
|
||||
|
||||
const SparseBitVector* blocks_covered() const { return &blocks_covered_; }
|
||||
|
||||
private:
|
||||
ZoneSet<int> spilled_vregs_;
|
||||
SparseBitVector blocks_covered_;
|
||||
bool is_frozen_ = false;
|
||||
};
|
||||
|
||||
// VirtualRegisterData stores data specific to a particular virtual register,
|
||||
// and tracks spilled operands for that virtual register.
|
||||
class VirtualRegisterData final {
|
||||
@ -335,20 +217,7 @@ class VirtualRegisterData final {
|
||||
void ExtendRangeTo(int instr_index) { live_range_.AddInstr(instr_index); }
|
||||
|
||||
void AddDeferredSpillOutput(AllocatedOperand allocated_op, int instr_index,
|
||||
MidTierRegisterAllocationData* data) {
|
||||
if (deferred_spill_outputs_ == nullptr) {
|
||||
Zone* zone = data->allocation_zone();
|
||||
deferred_spill_outputs_ =
|
||||
zone->New<ZoneVector<DeferredSpillSlotOutput>>(zone);
|
||||
}
|
||||
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 SparseBitVector* deferred_blocks =
|
||||
block_state.deferred_blocks_region()->blocks_covered();
|
||||
deferred_spill_outputs_->emplace_back(instr_index, allocated_op,
|
||||
deferred_blocks);
|
||||
}
|
||||
MidTierRegisterAllocationData* data);
|
||||
|
||||
void ClearDeferredBlockSpills() { deferred_spill_outputs_ = nullptr; }
|
||||
bool HasDeferredBlockSpills() const {
|
||||
@ -399,6 +268,124 @@ class VirtualRegisterData final {
|
||||
bool is_exceptional_call_output_ : 1;
|
||||
};
|
||||
|
||||
// BlockState stores details associated with a particular basic block.
|
||||
class BlockState final {
|
||||
public:
|
||||
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
|
||||
// point.
|
||||
RegisterState* register_in_state(RegisterKind kind);
|
||||
void set_register_in_state(RegisterState* register_state, RegisterKind kind);
|
||||
|
||||
// Returns a bitvector representing all the basic blocks that are dominated
|
||||
// by this basic block.
|
||||
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.
|
||||
int successors_phi_index() const { return successors_phi_index_; }
|
||||
void set_successors_phi_index(int index) {
|
||||
DCHECK_EQ(successors_phi_index_, -1);
|
||||
successors_phi_index_ = index;
|
||||
}
|
||||
|
||||
// If this block is deferred, this represents region of deferred blocks
|
||||
// that are directly reachable from this block.
|
||||
DeferredBlocksRegion* deferred_blocks_region() const {
|
||||
return deferred_blocks_region_;
|
||||
}
|
||||
void set_deferred_blocks_region(DeferredBlocksRegion* region) {
|
||||
DCHECK_NULL(deferred_blocks_region_);
|
||||
deferred_blocks_region_ = region;
|
||||
}
|
||||
|
||||
// Returns true if this block represents either a transition from
|
||||
// non-deferred to deferred or vice versa.
|
||||
bool is_deferred_block_boundary() const {
|
||||
return is_deferred_block_boundary_;
|
||||
}
|
||||
void MarkAsDeferredBlockBoundary() { is_deferred_block_boundary_ = true; }
|
||||
|
||||
private:
|
||||
RegisterState* general_registers_in_state_ = nullptr;
|
||||
RegisterState* double_registers_in_state_ = nullptr;
|
||||
RegisterState* simd128_registers_in_state_ = nullptr;
|
||||
|
||||
DeferredBlocksRegion* deferred_blocks_region_ = nullptr;
|
||||
|
||||
SparseBitVector dominated_blocks_;
|
||||
int successors_phi_index_ = -1;
|
||||
bool is_deferred_block_boundary_ = false;
|
||||
};
|
||||
|
||||
// Represents a connected region of deferred basic blocks.
|
||||
class DeferredBlocksRegion final {
|
||||
public:
|
||||
explicit DeferredBlocksRegion(Zone* zone)
|
||||
: spilled_vregs_(zone), blocks_covered_(zone) {}
|
||||
|
||||
void AddBlock(RpoNumber block, MidTierRegisterAllocationData* data) {
|
||||
DCHECK(data->GetBlock(block)->IsDeferred());
|
||||
blocks_covered_.Add(block.ToInt());
|
||||
data->block_state(block).set_deferred_blocks_region(this);
|
||||
}
|
||||
|
||||
// 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(); }
|
||||
|
||||
const SparseBitVector* blocks_covered() const { return &blocks_covered_; }
|
||||
|
||||
private:
|
||||
ZoneSet<int> spilled_vregs_;
|
||||
SparseBitVector blocks_covered_;
|
||||
bool is_frozen_ = false;
|
||||
};
|
||||
|
||||
RegisterState* BlockState::register_in_state(RegisterKind kind) {
|
||||
switch (kind) {
|
||||
case RegisterKind::kGeneral:
|
||||
return general_registers_in_state_;
|
||||
case RegisterKind::kDouble:
|
||||
return double_registers_in_state_;
|
||||
case RegisterKind::kSimd128:
|
||||
return simd128_registers_in_state_;
|
||||
}
|
||||
}
|
||||
|
||||
void BlockState::set_register_in_state(RegisterState* register_state,
|
||||
RegisterKind kind) {
|
||||
switch (kind) {
|
||||
case RegisterKind::kGeneral:
|
||||
DCHECK_NULL(general_registers_in_state_);
|
||||
general_registers_in_state_ = register_state;
|
||||
break;
|
||||
case RegisterKind::kDouble:
|
||||
DCHECK_NULL(double_registers_in_state_);
|
||||
double_registers_in_state_ = register_state;
|
||||
break;
|
||||
case RegisterKind::kSimd128:
|
||||
DCHECK_NULL(simd128_registers_in_state_);
|
||||
simd128_registers_in_state_ = register_state;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
MidTierRegisterAllocationData::MidTierRegisterAllocationData(
|
||||
const RegisterConfiguration* config, Zone* zone, Frame* frame,
|
||||
InstructionSequence* code, TickCounter* tick_counter,
|
||||
@ -421,6 +408,23 @@ MidTierRegisterAllocationData::MidTierRegisterAllocationData(
|
||||
}
|
||||
}
|
||||
|
||||
void VirtualRegisterData::SpillRange::AddDeferredSpillOutput(
|
||||
AllocatedOperand allocated_op, int instr_index,
|
||||
MidTierRegisterAllocationData* data) {
|
||||
if (deferred_spill_outputs_ == nullptr) {
|
||||
Zone* zone = data->allocation_zone();
|
||||
deferred_spill_outputs_ =
|
||||
zone->New<ZoneVector<DeferredSpillSlotOutput>>(zone);
|
||||
}
|
||||
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 SparseBitVector* deferred_blocks =
|
||||
block_state.deferred_blocks_region()->blocks_covered();
|
||||
deferred_spill_outputs_->emplace_back(instr_index, allocated_op,
|
||||
deferred_blocks);
|
||||
}
|
||||
|
||||
MoveOperands* MidTierRegisterAllocationData::AddGapMove(
|
||||
int instr_index, Instruction::GapPosition position,
|
||||
const InstructionOperand& from, const InstructionOperand& to) {
|
||||
|
Loading…
Reference in New Issue
Block a user