optimizations/register_allocation: init

This commit is contained in:
Antoine Viallon 2024-01-05 23:29:53 +01:00
parent 393615b234
commit c29d4cd9ec
Signed by: aviallon
GPG key ID: 186FC35EDEB25716
3 changed files with 62 additions and 0 deletions

View file

@ -152,6 +152,7 @@ class IRRegister(IRAssignable):
def __init__(self, location: SourceLocation): def __init__(self, location: SourceLocation):
super().__init__(location) super().__init__(location)
self.id = IRRegister.register_id self.id = IRRegister.register_id
self.real = None
IRRegister.register_id += 1 IRRegister.register_id += 1
IRRegister.registers[self.id] = self IRRegister.registers[self.id] = self
@ -162,6 +163,8 @@ class IRRegister(IRAssignable):
del IRRegister.registers[self.id] del IRRegister.registers[self.id]
def codegen(self): def codegen(self):
if self.real is not None:
return f"%r{self.real}"
return f"%r{self.id}" return f"%r{self.id}"

View file

@ -0,0 +1 @@
from .register_allocation import RegisterAllocation

View file

@ -0,0 +1,58 @@
from .. import ir
from ..errors import CompilationError
from ..logger import Logger
logger = Logger(__name__)
class RegisterAllocation:
"""
Rules:
Read After Write: write (a) MUST be before read (b)
Read After Read: order does not matter
Write After Read: write (b) MUST be after read (a)
Write After Write: order should be preserved
This means we must allocate a new register on its first u
"""
def __init__(self, intermediate_representation: list[ir.IRItem]):
self.intermediate_representation = intermediate_representation
self.used_registers: dict[int, bool] = {}
for register in ir.IRRegister.registers:
self.used_registers[register] = True
def alloc_register(self) -> int:
for register, free in self.used_registers.items():
if free:
self.used_registers[register] = False
return register
def free_register(self, identifier: int):
self.used_registers[identifier] = True
def analyze(self):
for i, item in enumerate(self.intermediate_representation):
if not isinstance(item, ir.IRAction):
raise CompilationError(item.location, f"Expected an action, got {item}")
action: ir.IRAction = item
for assignable in (action.reads + action.writes):
if not isinstance(assignable, ir.IRRegister):
continue
register: ir.IRRegister = assignable
sorted_users = register.sorted_users
# This is the first use, allocate a new register
if sorted_users[0].ir_location.line == i:
logger.debug(f"Try to allocate new register for virtual register '{register}'")
new_register = self.alloc_register()
register.real = new_register
logger.debug(f"Allocated new register '{new_register}' for virtual register '{register}'")
if sorted_users[-1].ir_location.line == i:
self.free_register(register.real)
logger.debug(f"Freed register '{register.real}' (was last used by virt. register '{register}')")