TP05b : Optimize two register swap, update README
This commit is contained in:
parent
d91c1df685
commit
a30f035d06
@ -1,21 +1,30 @@
|
|||||||
# MiniC Compiler
|
# MiniC Compiler
|
||||||
LAB5a (Control Flow Graph in SSA Form) & LAB5b (Smart Register Allocation), CAP 2022-23
|
LAB5a (Control Flow Graph in SSA Form) & LAB5b (Smart Register Allocation), CAP 2023-24
|
||||||
|
|
||||||
# Authors
|
# Authors
|
||||||
|
|
||||||
YOUR NAME HERE
|
Augustin LUCAS
|
||||||
|
|
||||||
# Contents
|
# Contents
|
||||||
|
|
||||||
TODO:
|
Extension implemented : Optimizing swap
|
||||||
- Explain any design choices you may have made.
|
- Cycles of size 1 : skip
|
||||||
- Do not forget to remove all debug traces from your code!
|
- Cycles of size 2 : use 3 XOR operations to swap the registers values without any temporary register use
|
||||||
- Did you implement an extension?
|
|
||||||
|
|
||||||
# Test design
|
# Test design
|
||||||
|
|
||||||
TODO: give the main objectives of your tests.
|
No tests were added since some of the `students`' tests from lab4 still failed to execute properly.
|
||||||
|
|
||||||
# Known bugs
|
# Known bugs
|
||||||
|
|
||||||
TODO: bugs you could not fix (if any).
|
Failing tests:
|
||||||
|
- `./TP04/tests/students/ext-for-fortran/test_imbricated_for.c`
|
||||||
|
- `./TP04/tests/students/ext-for-fortran/test_for.c`
|
||||||
|
- `./TP04/tests/students/base/test_nested_while.c`
|
||||||
|
- `./TP04/tests/students/base/test_fibonacci.c`
|
||||||
|
- `./TP04/tests/provided/dataflow/df03.c`
|
||||||
|
|
||||||
|
The bug seems to be related to the handling of Offsets because a lot more tests will fail if temporaries are only assigned to memory (no registers).
|
||||||
|
This can be done by commenting `TP05/SmartAllocator.py:124`.
|
||||||
|
|
||||||
|
This seems to affect `while` and `for` loops as well as regular variables (because variables may not be stored/loaded correctly).
|
@ -1,5 +1,5 @@
|
|||||||
# MiniC Compiler
|
# MiniC Compiler
|
||||||
LAB5 (smart code generation), MIF08 / CAP 2022-23
|
LAB5 (smart code generation), MIF08 / CAP 2023-24
|
||||||
|
|
||||||
# Authors
|
# Authors
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# MiniC Compiler
|
# MiniC Compiler
|
||||||
LAB4 (simple code generation), MIF08 / CAP 2022-23
|
LAB4 (simple code generation), MIF08 / CAP 2023-24
|
||||||
|
|
||||||
# Authors
|
# Authors
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# MiniC Compiler
|
# MiniC Compiler
|
||||||
LAB6 (code generation for functions), MIF08 / CAP 2022-23
|
LAB6 (code generation for functions), MIF08 / CAP 2023-24
|
||||||
|
|
||||||
# Authors
|
# Authors
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# MiniC interpreter and typer
|
# MiniC interpreter and typer
|
||||||
LAB3, MIF08 / CAP / CS444 2022-23
|
LAB3, MIF08 / CAP / CS444 2023-24
|
||||||
|
|
||||||
|
|
||||||
# Authors
|
# Authors
|
||||||
|
@ -69,7 +69,7 @@ class LivenessSSA:
|
|||||||
if var not in self._seen[block]:
|
if var not in self._seen[block]:
|
||||||
self._seen[block].add(var)
|
self._seen[block].add(var)
|
||||||
self.liveout_at_instruction(block, len(block.get_all_statements())-1, var)
|
self.liveout_at_instruction(block, len(block.get_all_statements())-1, var)
|
||||||
|
|
||||||
|
|
||||||
def gather_uses(self) -> Dict[Temporary, Set[Tuple[Block, int]]]:
|
def gather_uses(self) -> Dict[Temporary, Set[Tuple[Block, int]]]:
|
||||||
"""
|
"""
|
||||||
|
@ -19,7 +19,7 @@ def generate_smart_move(dest: DataLocation, src: DataLocation) -> List[BlockInst
|
|||||||
"""
|
"""
|
||||||
instr: List[BlockInstr] = []
|
instr: List[BlockInstr] = []
|
||||||
tmp: Register = S[1]
|
tmp: Register = S[1]
|
||||||
|
|
||||||
match dest, src:
|
match dest, src:
|
||||||
case Register(), Register():
|
case Register(), Register():
|
||||||
instr.append(RiscV.mv(dest, src))
|
instr.append(RiscV.mv(dest, src))
|
||||||
@ -36,6 +36,15 @@ def generate_smart_move(dest: DataLocation, src: DataLocation) -> List[BlockInst
|
|||||||
return instr
|
return instr
|
||||||
|
|
||||||
|
|
||||||
|
def swap_registers(r1: Register, r2: Register) -> List[BlockInstr]:
|
||||||
|
"""Swap two registers"""
|
||||||
|
return [
|
||||||
|
RiscV.xor(r1, r1, r2),
|
||||||
|
RiscV.xor(r2, r1, r2),
|
||||||
|
RiscV.xor(r1, r1, r2)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def sequentialize_moves(parallel_moves: Set[Tuple[DataLocation, DataLocation]]
|
def sequentialize_moves(parallel_moves: Set[Tuple[DataLocation, DataLocation]]
|
||||||
) -> List[BlockInstr]:
|
) -> List[BlockInstr]:
|
||||||
"""
|
"""
|
||||||
@ -52,7 +61,7 @@ def sequentialize_moves(parallel_moves: Set[Tuple[DataLocation, DataLocation]]
|
|||||||
move_graph.add_edge((src, dest))
|
move_graph.add_edge((src, dest))
|
||||||
# List for the sequentialized moves to do
|
# List for the sequentialized moves to do
|
||||||
# Convention: in moves we put (dest, src) for each move
|
# Convention: in moves we put (dest, src) for each move
|
||||||
moves: List[Tuple[DataLocation, DataLocation]] = []
|
moves: List[Tuple[DataLocation, DataLocation] | BlockInstr] = []
|
||||||
# First iteratively remove all the vertices without successors
|
# First iteratively remove all the vertices without successors
|
||||||
vars_without_successor = {src
|
vars_without_successor = {src
|
||||||
for src, dests in move_graph.neighbourhoods()
|
for src, dests in move_graph.neighbourhoods()
|
||||||
@ -71,6 +80,9 @@ def sequentialize_moves(parallel_moves: Set[Tuple[DataLocation, DataLocation]]
|
|||||||
for cycle in cycles:
|
for cycle in cycles:
|
||||||
if len(cycle) == 1:
|
if len(cycle) == 1:
|
||||||
continue
|
continue
|
||||||
|
if len(cycle) == 2 and isinstance(cycle[0], Register) and isinstance(cycle[1], Register):
|
||||||
|
moves += swap_registers(*cycle)
|
||||||
|
continue
|
||||||
previous = tmp
|
previous = tmp
|
||||||
for var in reversed(cycle):
|
for var in reversed(cycle):
|
||||||
moves.append((previous, var))
|
moves.append((previous, var))
|
||||||
@ -78,7 +90,10 @@ def sequentialize_moves(parallel_moves: Set[Tuple[DataLocation, DataLocation]]
|
|||||||
moves.append((previous, tmp))
|
moves.append((previous, tmp))
|
||||||
# Transform the moves to do in actual RiscV instructions
|
# Transform the moves to do in actual RiscV instructions
|
||||||
moves_instr: List[BlockInstr] = []
|
moves_instr: List[BlockInstr] = []
|
||||||
for dest, src in moves:
|
for val in moves:
|
||||||
instrs = generate_smart_move(dest, src)
|
if isinstance(val, BlockInstr):
|
||||||
|
moves_instr.append(val)
|
||||||
|
continue
|
||||||
|
instrs = generate_smart_move(*val)
|
||||||
moves_instr.extend(instrs)
|
moves_instr.extend(instrs)
|
||||||
return moves_instr
|
return moves_instr
|
||||||
|
Loading…
Reference in New Issue
Block a user