Fixing register allocation bug.
This commit is contained in:
parent
f55fb17e1b
commit
638d9631af
|
@ -1600,7 +1600,6 @@ void alloy::backend::x64::lowering::RegisterSequences(LoweringTable* table) {
|
|||
[](X64Emitter& e, Instr& i, const Reg& dest_src, const Operand& src) {
|
||||
// RAX = value, RDX = clobbered
|
||||
// TODO(benvanik): make the register allocator put dest_src in RAX?
|
||||
e.db(0xCC);
|
||||
auto Nax = LIKE_REG(e.rax, dest_src);
|
||||
e.mov(Nax, dest_src);
|
||||
if (i.flags & ARITHMETIC_UNSIGNED) {
|
||||
|
@ -1615,7 +1614,6 @@ void alloy::backend::x64::lowering::RegisterSequences(LoweringTable* table) {
|
|||
// TODO(benvanik): make the register allocator put dest_src in RAX?
|
||||
auto Nax = LIKE_REG(e.rax, dest_src);
|
||||
auto Ndx = LIKE_REG(e.rdx, dest_src);
|
||||
e.db(0xCC);
|
||||
e.mov(Nax, dest_src);
|
||||
e.mov(Ndx, src);
|
||||
if (i.flags & ARITHMETIC_UNSIGNED) {
|
||||
|
@ -1635,7 +1633,6 @@ void alloy::backend::x64::lowering::RegisterSequences(LoweringTable* table) {
|
|||
[](X64Emitter& e, Instr& i, const Reg& dest_src, const Operand& src) {
|
||||
// RAX = value, RDX = clobbered
|
||||
// TODO(benvanik): make the register allocator put dest_src in RAX?
|
||||
e.db(0xCC);
|
||||
auto Nax = LIKE_REG(e.rax, dest_src);
|
||||
auto Ndx = LIKE_REG(e.rdx, dest_src);
|
||||
e.mov(Nax, dest_src);
|
||||
|
@ -1651,7 +1648,6 @@ void alloy::backend::x64::lowering::RegisterSequences(LoweringTable* table) {
|
|||
// TODO(benvanik): make the register allocator put dest_src in RAX?
|
||||
auto Nax = LIKE_REG(e.rax, dest_src);
|
||||
auto Ndx = LIKE_REG(e.rdx, dest_src);
|
||||
e.db(0xCC);
|
||||
e.mov(Nax, dest_src);
|
||||
e.mov(Ndx, src);
|
||||
if (i.flags & ARITHMETIC_UNSIGNED) {
|
||||
|
@ -1671,7 +1667,6 @@ void alloy::backend::x64::lowering::RegisterSequences(LoweringTable* table) {
|
|||
[](X64Emitter& e, Instr& i, const Reg& dest_src, const Operand& src) {
|
||||
// RAX = value, RDX = clobbered
|
||||
// TODO(benvanik): make the register allocator put dest_src in RAX?
|
||||
e.db(0xCC);
|
||||
auto Nax = LIKE_REG(e.rax, dest_src);
|
||||
e.mov(Nax, dest_src);
|
||||
if (i.flags & ARITHMETIC_UNSIGNED) {
|
||||
|
@ -1686,7 +1681,6 @@ void alloy::backend::x64::lowering::RegisterSequences(LoweringTable* table) {
|
|||
// TODO(benvanik): make the register allocator put dest_src in RAX?
|
||||
auto Nax = LIKE_REG(e.rax, dest_src);
|
||||
auto Ndx = LIKE_REG(e.rdx, dest_src);
|
||||
e.db(0xCC);
|
||||
e.mov(Nax, dest_src);
|
||||
e.mov(Ndx, src);
|
||||
if (i.flags & ARITHMETIC_UNSIGNED) {
|
||||
|
|
|
@ -143,6 +143,8 @@ int X64Emitter::Emit(HIRBuilder* builder) {
|
|||
|
||||
auto lowering_table = backend_->lowering_table();
|
||||
|
||||
reg_state_.active_regs = reg_state_.live_regs = reserved_regs;
|
||||
|
||||
// Body.
|
||||
auto block = builder->first_block();
|
||||
while (block) {
|
||||
|
@ -156,7 +158,7 @@ int X64Emitter::Emit(HIRBuilder* builder) {
|
|||
// Reset reg allocation state.
|
||||
// If we start keeping regs across blocks this needs to change.
|
||||
// We mark a few active so that the allocator doesn't use them.
|
||||
reg_state_.active_regs = reg_state_.live_regs = reserved_regs;
|
||||
ResetRegisters(reserved_regs);
|
||||
|
||||
// Add instructions.
|
||||
// The table will process sequences of instructions to (try to)
|
||||
|
@ -192,11 +194,27 @@ int X64Emitter::Emit(HIRBuilder* builder) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void X64Emitter::EvictStaleRegs() {
|
||||
void X64Emitter::ResetRegisters(uint32_t reserved_regs) {
|
||||
// Just need to reset the register for each live value.
|
||||
uint32_t live_regs = reg_state_.live_regs;
|
||||
for (size_t n = 0; n < 32; n++, live_regs >>= 1) {
|
||||
if (live_regs & 0x1) {
|
||||
auto v = reg_state_.reg_values[n];
|
||||
if (v) {
|
||||
v->reg = -1;
|
||||
}
|
||||
}
|
||||
reg_state_.reg_values[n] = 0;
|
||||
}
|
||||
reg_state_.active_regs = reg_state_.live_regs = reserved_regs;
|
||||
}
|
||||
|
||||
void X64Emitter::EvictStaleRegisters() {
|
||||
// NOTE: if we are getting called it's because we *need* a register.
|
||||
// We must get rid of something.
|
||||
|
||||
uint32_t current_ordinal = current_instr_->ordinal;
|
||||
uint32_t current_ordinal = current_instr_ ?
|
||||
current_instr_->ordinal : 0xFFFFFFFF;
|
||||
|
||||
// Remove any register with no more uses.
|
||||
uint32_t new_live_regs = 0;
|
||||
|
@ -216,7 +234,12 @@ void X64Emitter::EvictStaleRegs() {
|
|||
auto v = reg_state_.reg_values[n];
|
||||
if (v->last_use->ordinal < current_ordinal) {
|
||||
reg_state_.reg_values[n] = NULL;
|
||||
v->reg = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Register still in use.
|
||||
new_live_regs |= bit;
|
||||
}
|
||||
|
||||
// Hrm. We have spilled.
|
||||
|
@ -225,6 +248,9 @@ void X64Emitter::EvictStaleRegs() {
|
|||
}
|
||||
|
||||
reg_state_.live_regs = new_live_regs;
|
||||
|
||||
// Assert that live is a superset of active.
|
||||
XEASSERTZERO((reg_state_.live_regs ^ reg_state_.active_regs) & reg_state_.active_regs);
|
||||
}
|
||||
|
||||
void X64Emitter::FindFreeRegs(
|
||||
|
@ -234,6 +260,9 @@ void X64Emitter::FindFreeRegs(
|
|||
// Already in a register. Mark active and return.
|
||||
v0_idx = v0->reg;
|
||||
reg_state_.active_regs |= 1 << v0_idx;
|
||||
|
||||
// Assert that live is a superset of active.
|
||||
XEASSERTZERO((reg_state_.live_regs ^ reg_state_.active_regs) & reg_state_.active_regs);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -250,7 +279,7 @@ void X64Emitter::FindFreeRegs(
|
|||
uint32_t free_regs = avail_regs & ~reg_state_.live_regs;
|
||||
if (!free_regs) {
|
||||
// Need to evict something.
|
||||
EvictStaleRegs();
|
||||
EvictStaleRegisters();
|
||||
free_regs = avail_regs & ~reg_state_.live_regs;
|
||||
XEASSERT(free_regs);
|
||||
}
|
||||
|
|
|
@ -112,7 +112,8 @@ public:
|
|||
GetRegBit(r0) | GetRegBit(r1) | GetRegBit(r2) | GetRegBit(r3));
|
||||
}
|
||||
|
||||
void EvictStaleRegs();
|
||||
void ResetRegisters(uint32_t reserved_regs);
|
||||
void EvictStaleRegisters();
|
||||
|
||||
void FindFreeRegs(hir::Value* v0, uint32_t& v0_idx, uint32_t v0_flags);
|
||||
void FindFreeRegs(hir::Value* v0, uint32_t& v0_idx, uint32_t v0_flags,
|
||||
|
|
Loading…
Reference in New Issue