optimizations/register_allocation: init
This commit is contained in:
parent
393615b234
commit
c29d4cd9ec
3 changed files with 62 additions and 0 deletions
|
|
@ -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}"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
1
compiler/optimizations/__init__.py
Normal file
1
compiler/optimizations/__init__.py
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
from .register_allocation import RegisterAllocation
|
||||||
58
compiler/optimizations/register_allocation.py
Normal file
58
compiler/optimizations/register_allocation.py
Normal 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}')")
|
||||||
Loading…
Add table
Add a link
Reference in a new issue