diff --git a/MiniC/README-SSA.md b/MiniC/README-SSA.md index 82bd87a..f751c42 100644 --- a/MiniC/README-SSA.md +++ b/MiniC/README-SSA.md @@ -1,21 +1,30 @@ # 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 -YOUR NAME HERE +Augustin LUCAS # Contents -TODO: -- Explain any design choices you may have made. -- Do not forget to remove all debug traces from your code! -- Did you implement an extension? +Extension implemented : Optimizing swap +- Cycles of size 1 : skip +- Cycles of size 2 : use 3 XOR operations to swap the registers values without any temporary register use # 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 -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). \ No newline at end of file diff --git a/MiniC/README-alloc.md b/MiniC/README-alloc.md index b25af3e..83fd3e6 100644 --- a/MiniC/README-alloc.md +++ b/MiniC/README-alloc.md @@ -1,5 +1,5 @@ # MiniC Compiler -LAB5 (smart code generation), MIF08 / CAP 2022-23 +LAB5 (smart code generation), MIF08 / CAP 2023-24 # Authors diff --git a/MiniC/README-codegen.md b/MiniC/README-codegen.md index e9d29bd..71e422e 100644 --- a/MiniC/README-codegen.md +++ b/MiniC/README-codegen.md @@ -1,5 +1,5 @@ # MiniC Compiler -LAB4 (simple code generation), MIF08 / CAP 2022-23 +LAB4 (simple code generation), MIF08 / CAP 2023-24 # Authors diff --git a/MiniC/README-functions.md b/MiniC/README-functions.md index 36ca0f6..3662a48 100644 --- a/MiniC/README-functions.md +++ b/MiniC/README-functions.md @@ -1,5 +1,5 @@ # MiniC Compiler -LAB6 (code generation for functions), MIF08 / CAP 2022-23 +LAB6 (code generation for functions), MIF08 / CAP 2023-24 # Authors diff --git a/MiniC/README-interpreter.md b/MiniC/README-interpreter.md index d37e9f1..0c98de8 100644 --- a/MiniC/README-interpreter.md +++ b/MiniC/README-interpreter.md @@ -1,5 +1,5 @@ # MiniC interpreter and typer -LAB3, MIF08 / CAP / CS444 2022-23 +LAB3, MIF08 / CAP / CS444 2023-24 # Authors diff --git a/MiniC/TP05/LivenessSSA.py b/MiniC/TP05/LivenessSSA.py index be19ccf..3c1937e 100644 --- a/MiniC/TP05/LivenessSSA.py +++ b/MiniC/TP05/LivenessSSA.py @@ -69,7 +69,7 @@ class LivenessSSA: if var not in self._seen[block]: self._seen[block].add(var) self.liveout_at_instruction(block, len(block.get_all_statements())-1, var) - + def gather_uses(self) -> Dict[Temporary, Set[Tuple[Block, int]]]: """ diff --git a/MiniC/TP05/SequentializeMoves.py b/MiniC/TP05/SequentializeMoves.py index 88f9cfe..21093d5 100644 --- a/MiniC/TP05/SequentializeMoves.py +++ b/MiniC/TP05/SequentializeMoves.py @@ -19,7 +19,7 @@ def generate_smart_move(dest: DataLocation, src: DataLocation) -> List[BlockInst """ instr: List[BlockInstr] = [] tmp: Register = S[1] - + match dest, src: case Register(), Register(): instr.append(RiscV.mv(dest, src)) @@ -36,6 +36,15 @@ def generate_smart_move(dest: DataLocation, src: DataLocation) -> List[BlockInst 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]] ) -> List[BlockInstr]: """ @@ -52,7 +61,7 @@ def sequentialize_moves(parallel_moves: Set[Tuple[DataLocation, DataLocation]] move_graph.add_edge((src, dest)) # List for the sequentialized moves to do # 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 vars_without_successor = {src for src, dests in move_graph.neighbourhoods() @@ -71,6 +80,9 @@ def sequentialize_moves(parallel_moves: Set[Tuple[DataLocation, DataLocation]] for cycle in cycles: if len(cycle) == 1: continue + if len(cycle) == 2 and isinstance(cycle[0], Register) and isinstance(cycle[1], Register): + moves += swap_registers(*cycle) + continue previous = tmp for var in reversed(cycle): moves.append((previous, var)) @@ -78,7 +90,10 @@ def sequentialize_moves(parallel_moves: Set[Tuple[DataLocation, DataLocation]] moves.append((previous, tmp)) # Transform the moves to do in actual RiscV instructions moves_instr: List[BlockInstr] = [] - for dest, src in moves: - instrs = generate_smart_move(dest, src) + for val in moves: + if isinstance(val, BlockInstr): + moves_instr.append(val) + continue + instrs = generate_smart_move(*val) moves_instr.extend(instrs) return moves_instr