Ajout du smart allocator .... disfonctionnel
This commit is contained in:
parent
2c50bbaaa0
commit
0a8c02ec83
@ -11,10 +11,15 @@ TODO:
|
|||||||
- Explain any design choices you may have made.
|
- Explain any design choices you may have made.
|
||||||
- Do not forget to remove all debug traces from your code!
|
- Do not forget to remove all debug traces from your code!
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Test design
|
# Test design
|
||||||
|
|
||||||
TODO: give the main objectives of your tests.
|
TODO: give the main objectives of your tests.
|
||||||
|
|
||||||
# Known bugs
|
# Known bugs
|
||||||
|
|
||||||
TODO: bugs you could not fix (if any).
|
There was an issue with the subject, because we implemented «smart moves» in ExitSSA, we had to replace
|
||||||
|
temporaries at the exit of the SSA. So when the SSA is exited, some temporaries are already replaced
|
||||||
|
with real data locations (that is, the instructions that comes from the reduction
|
||||||
|
of phi-statements.
|
||||||
|
|||||||
@ -29,12 +29,6 @@ class AllInMemAllocator(Allocator):
|
|||||||
if(isinstance(arg, Temporary)):
|
if(isinstance(arg, Temporary)):
|
||||||
after.append(RiscV.sd(subst[arg],self._fdata._pool.get_alloced_loc(arg)))
|
after.append(RiscV.sd(subst[arg],self._fdata._pool.get_alloced_loc(arg)))
|
||||||
|
|
||||||
|
|
||||||
# TODO (Exercise 7): compute before,after,args.
|
|
||||||
# TODO (Exercise 7): iterate over old_args, check which argument
|
|
||||||
# TODO (Exercise 7): is a temporary (e.g. isinstance(..., Temporary)),
|
|
||||||
# TODO (Exercise 7): and if so, generate ld/sd accordingly. Replace the
|
|
||||||
# TODO (Exercise 7): temporary with S[1], S[2] or S[3] physical registers.
|
|
||||||
try:
|
try:
|
||||||
new_instr = old_instr.substitute(subst)
|
new_instr = old_instr.substitute(subst)
|
||||||
except Exception:
|
except Exception:
|
||||||
|
|||||||
@ -10,10 +10,11 @@ from Lib.Graphes import DiGraph
|
|||||||
from Lib.CFG import Block, BlockInstr, CFG
|
from Lib.CFG import Block, BlockInstr, CFG
|
||||||
from Lib.Operands import (
|
from Lib.Operands import (
|
||||||
Register, DataLocation,
|
Register, DataLocation,
|
||||||
Temporary)
|
Temporary, TemporaryPool)
|
||||||
from Lib.Statement import AbsoluteJump
|
from Lib.Statement import AbsoluteJump
|
||||||
from Lib.Terminator import BranchingTerminator, Return
|
from Lib.Terminator import BranchingTerminator, Return
|
||||||
from Lib.PhiNode import PhiNode
|
from Lib.PhiNode import PhiNode
|
||||||
|
from TP05.SequentializeMoves import sequentialize_moves
|
||||||
|
|
||||||
|
|
||||||
def generate_moves_from_phis(phis: List[PhiNode], parent: Block) -> List[BlockInstr]:
|
def generate_moves_from_phis(phis: List[PhiNode], parent: Block) -> List[BlockInstr]:
|
||||||
@ -32,6 +33,31 @@ def generate_moves_from_phis(phis: List[PhiNode], parent: Block) -> List[BlockIn
|
|||||||
return moves
|
return moves
|
||||||
|
|
||||||
|
|
||||||
|
def generate_moves_from_phis_smart(pool: TemporaryPool, phis: List[PhiNode], parent: Block) -> List[BlockInstr]:
|
||||||
|
"""
|
||||||
|
`generate_moves_from_phis_smart(phis, parent)` builds a list of move instructions
|
||||||
|
to be inserted in a new block between `parent` and the block with phi nodes
|
||||||
|
`phis`. This function is working with smart allocation, unlike its «dump» counterpart
|
||||||
|
that makes allocations in no particular order.
|
||||||
|
|
||||||
|
This is an helper function called during SSA exit.
|
||||||
|
"""
|
||||||
|
moves: List[Tuple[DataLocation,DataLocation]] = []
|
||||||
|
plabel = parent.get_label()
|
||||||
|
for phi in phis:
|
||||||
|
if(plabel in phi.used()):
|
||||||
|
src = phi.var
|
||||||
|
dest = phi.used()[plabel]
|
||||||
|
if(isinstance(src,Temporary)):
|
||||||
|
src = pool.get_alloced_loc(src)
|
||||||
|
if(isinstance(dest,Temporary)):
|
||||||
|
dest = pool.get_alloced_loc(dest)
|
||||||
|
assert(isinstance(dest,DataLocation))
|
||||||
|
moves.append((dest,src))
|
||||||
|
realmoves = sequentialize_moves(set(moves))
|
||||||
|
return realmoves
|
||||||
|
|
||||||
|
|
||||||
def exit_ssa(cfg: CFG, is_smart: bool) -> None:
|
def exit_ssa(cfg: CFG, is_smart: bool) -> None:
|
||||||
"""
|
"""
|
||||||
`exit_ssa(cfg)` replaces phi nodes with move instructions to exit SSA form.
|
`exit_ssa(cfg)` replaces phi nodes with move instructions to exit SSA form.
|
||||||
@ -44,7 +70,7 @@ def exit_ssa(cfg: CFG, is_smart: bool) -> None:
|
|||||||
blabel = b.get_label()
|
blabel = b.get_label()
|
||||||
parents: List[Block] = b.get_in().copy() # Copy as we modify it by adding blocks
|
parents: List[Block] = b.get_in().copy() # Copy as we modify it by adding blocks
|
||||||
for p in parents:
|
for p in parents:
|
||||||
moves = generate_moves_from_phis(phis, p)
|
moves = generate_moves_from_phis_smart(cfg.fdata._pool,phis, p) if is_smart else generate_moves_from_phis(phis, p)
|
||||||
if(len(moves)==0):
|
if(len(moves)==0):
|
||||||
continue
|
continue
|
||||||
# Creating the block
|
# Creating the block
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
from typing import List, Set, Tuple
|
from typing import List, Set, Tuple
|
||||||
|
from Lib.Errors import MiniCInternalError
|
||||||
from Lib import RiscV
|
from Lib import RiscV
|
||||||
from Lib.Graphes import DiGraph
|
from Lib.Graphes import DiGraph
|
||||||
from Lib.CFG import BlockInstr
|
from Lib.CFG import BlockInstr
|
||||||
from Lib.Operands import (Register, DataLocation, S)
|
from Lib.Operands import (Offset, Register, DataLocation, S)
|
||||||
|
|
||||||
|
|
||||||
def generate_smart_move(dest: DataLocation, src: DataLocation) -> List[BlockInstr]:
|
def generate_smart_move(dest: DataLocation, src: DataLocation) -> List[BlockInstr]:
|
||||||
@ -12,8 +13,22 @@ def generate_smart_move(dest: DataLocation, src: DataLocation) -> List[BlockInst
|
|||||||
This is an helper function for `sequentialize_moves`.
|
This is an helper function for `sequentialize_moves`.
|
||||||
"""
|
"""
|
||||||
instr: List[BlockInstr] = []
|
instr: List[BlockInstr] = []
|
||||||
# TODO Compute the moves (Lab 5b, Exercise 4)
|
tmp: Register = S[1]
|
||||||
raise NotImplementedError("generate_smart_move")
|
if(isinstance(dest,Offset) and isinstance(src,Offset)):
|
||||||
|
# We read the source in tmp and write it to destination
|
||||||
|
instr.append(RiscV.ld(tmp,src))
|
||||||
|
instr.append(RiscV.sd(tmp,dest))
|
||||||
|
elif(isinstance(dest,Offset) and isinstance(src,Register)):
|
||||||
|
# We write the register to destination
|
||||||
|
instr.append(RiscV.sd(src,dest))
|
||||||
|
elif(isinstance(dest,Register) and isinstance(src,Offset)):
|
||||||
|
# We read the source into the register
|
||||||
|
instr.append(RiscV.ld(dest,src))
|
||||||
|
elif(isinstance(dest,Register) and isinstance(src,Register)):
|
||||||
|
# Classic move
|
||||||
|
instr.append(RiscV.mv(src,dest))
|
||||||
|
else:
|
||||||
|
raise MiniCInternalError("Cannot generate smart move from parameters that are no Offset or Register:",src,dest)
|
||||||
return instr
|
return instr
|
||||||
|
|
||||||
|
|
||||||
@ -39,13 +54,33 @@ def sequentialize_moves(parallel_moves: Set[Tuple[DataLocation, DataLocation]]
|
|||||||
for src, dests in move_graph.neighbourhoods()
|
for src, dests in move_graph.neighbourhoods()
|
||||||
if len(dests) == 0}
|
if len(dests) == 0}
|
||||||
while vars_without_successor:
|
while vars_without_successor:
|
||||||
# TODO Remove the leaves iteratively (Lab 5b, Exercise 4)
|
head = vars_without_successor.pop()
|
||||||
raise NotImplementedError("sequentialize_moves: leaves")
|
while(head is not None):
|
||||||
|
preds = move_graph.pred(head)
|
||||||
|
if(len(preds)==0):
|
||||||
|
head = None
|
||||||
|
else:
|
||||||
|
pred = preds.pop()
|
||||||
|
moves.append((pred,head))
|
||||||
|
move_graph.delete_vertex(head)
|
||||||
|
head = pred
|
||||||
|
|
||||||
# Then handle the cycles
|
# Then handle the cycles
|
||||||
cycles: List = move_graph.connected_components()
|
cycles: List = move_graph.connected_components()
|
||||||
for cycle in cycles:
|
for cycle in cycles:
|
||||||
# TODO Handle each cycle (Lab 5b, Exercise 4)
|
if(len(cycle)==1):
|
||||||
raise NotImplementedError("sequentialize_moves: cycles")
|
# No moves to do
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
head = cycle[0]
|
||||||
|
moves.append((head,tmp))
|
||||||
|
while True:
|
||||||
|
pred = move_graph.pred(head).pop()
|
||||||
|
if(pred==cycle[0]):
|
||||||
|
break
|
||||||
|
moves.append((pred,head))
|
||||||
|
head = pred
|
||||||
|
moves.append((tmp,head))
|
||||||
# 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 dest, src in moves:
|
||||||
|
|||||||
@ -28,12 +28,43 @@ class SmartAllocator(Allocator):
|
|||||||
before: List[Instruction] = []
|
before: List[Instruction] = []
|
||||||
after: List[Instruction] = []
|
after: List[Instruction] = []
|
||||||
subst: Dict[Operand, Operand] = {}
|
subst: Dict[Operand, Operand] = {}
|
||||||
# TODO (lab5): Compute before, after, subst. This is similar to what
|
|
||||||
# TODO (lab5): replace from the Naive and AllInMem Allocators do (Lab 4).
|
old_args = old_instr.args()
|
||||||
raise NotImplementedError("Smart Replace (lab5)") # TODO
|
numreg = 1
|
||||||
|
for arg in old_args:
|
||||||
|
if(isinstance(arg, Temporary)): # Else we don't change anything
|
||||||
|
dest = self._fdata._pool.get_alloced_loc(arg)
|
||||||
|
if(isinstance(dest,Register)):
|
||||||
|
# We use the provided register
|
||||||
|
subst[arg] = dest
|
||||||
|
elif(isinstance(dest,Offset)):
|
||||||
|
# We use a s register in which we will read|write
|
||||||
|
subst[arg] = S[numreg]
|
||||||
|
numreg += 1
|
||||||
|
else:
|
||||||
|
raise MiniCInternalError("Unsupported dataLocation for smart replace")
|
||||||
|
for arg in old_instr.used():
|
||||||
|
if(isinstance(arg, Temporary)):
|
||||||
|
# If the argument has an Offset substitution
|
||||||
|
if(isinstance(self._fdata._pool.get_alloced_loc(arg),Offset)):
|
||||||
|
# We have to read it from memory
|
||||||
|
before.append(RiscV.ld(subst[arg],self._fdata._pool.get_alloced_loc(arg)))
|
||||||
|
for arg in old_instr.defined():
|
||||||
|
if(isinstance(arg, Temporary)):
|
||||||
|
# If the argument has an Offset substitution
|
||||||
|
if(isinstance(self._fdata._pool.get_alloced_loc(arg),Offset)):
|
||||||
|
# We have to write them after to memory
|
||||||
|
after.append(RiscV.sd(subst[arg],self._fdata._pool.get_alloced_loc(arg)))
|
||||||
|
|
||||||
# And now return the new list!
|
# And now return the new list!
|
||||||
instr = old_instr.substitute(subst)
|
|
||||||
return before + [instr] + after
|
print(old_instr,"->",before,subst,after)
|
||||||
|
try:
|
||||||
|
new_instr = old_instr.substitute(subst)
|
||||||
|
except Exception:
|
||||||
|
# We have an instruction that doesn't need substitution
|
||||||
|
return [old_instr]
|
||||||
|
return before + [new_instr] + after
|
||||||
|
|
||||||
def prepare(self) -> None:
|
def prepare(self) -> None:
|
||||||
"""
|
"""
|
||||||
@ -70,7 +101,17 @@ class SmartAllocator(Allocator):
|
|||||||
# Iterate over self._liveness._liveout (dictionary containing all
|
# Iterate over self._liveness._liveout (dictionary containing all
|
||||||
# live out temporaries for each instruction), and for each conflict use
|
# live out temporaries for each instruction), and for each conflict use
|
||||||
# self._igraph.add_edge((t1, t2)) to add the corresponding edge.
|
# self._igraph.add_edge((t1, t2)) to add the corresponding edge.
|
||||||
raise NotImplementedError("build_interference_graph (lab5)") # TODO
|
for st,varz in self._liveness._liveout.items():
|
||||||
|
for x in varz:
|
||||||
|
if(isinstance(x,Temporary)):
|
||||||
|
# First condition
|
||||||
|
for y in varz:
|
||||||
|
if x!=y and isinstance(y,Temporary):
|
||||||
|
self._igraph.add_edge((x,y))
|
||||||
|
# Second/third condition
|
||||||
|
for y in st.defined():
|
||||||
|
if x!=y and isinstance(y,Temporary): # x is alive after x definition
|
||||||
|
self._igraph.add_edge((x,y))
|
||||||
|
|
||||||
def smart_alloc(self) -> None:
|
def smart_alloc(self) -> None:
|
||||||
"""
|
"""
|
||||||
@ -92,7 +133,16 @@ class SmartAllocator(Allocator):
|
|||||||
alloc_dict: Dict[Temporary, DataLocation] = dict()
|
alloc_dict: Dict[Temporary, DataLocation] = dict()
|
||||||
# Use the coloring `coloringreg` to fill `alloc_dict`.
|
# Use the coloring `coloringreg` to fill `alloc_dict`.
|
||||||
# Our version is less than 5 lines of code.
|
# Our version is less than 5 lines of code.
|
||||||
raise NotImplementedError("Allocation based on graph coloring (lab5)") # TODO
|
moreColors_alloc_dict: Dict[int, DataLocation] = dict()
|
||||||
|
|
||||||
|
for var,col in coloringreg.items():
|
||||||
|
if(col<len(GP_REGS)):
|
||||||
|
alloc_dict[var] = GP_REGS[col]
|
||||||
|
else:
|
||||||
|
if(not col in moreColors_alloc_dict):
|
||||||
|
moreColors_alloc_dict[col] = self._fdata.fresh_offset()
|
||||||
|
alloc_dict[var] = moreColors_alloc_dict[col]
|
||||||
|
|
||||||
if self._debug:
|
if self._debug:
|
||||||
print("Allocation:")
|
print("Allocation:")
|
||||||
print(alloc_dict)
|
print(alloc_dict)
|
||||||
|
|||||||
40
MiniC/TP05/tests/students/testEq-min.c
Normal file
40
MiniC/TP05/tests/students/testEq-min.c
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#include "printlib.h"
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
|
||||||
|
// Testing ==
|
||||||
|
if( 11 == 11 ){
|
||||||
|
println_int(61);
|
||||||
|
}else{
|
||||||
|
println_int(420);
|
||||||
|
}
|
||||||
|
if( -22 == -22 ){
|
||||||
|
println_int(62);
|
||||||
|
}else{
|
||||||
|
println_int(420);
|
||||||
|
}
|
||||||
|
if( true == true ){
|
||||||
|
println_int(63);
|
||||||
|
}else{
|
||||||
|
println_int(420);
|
||||||
|
}
|
||||||
|
if( true == false ){
|
||||||
|
println_int(420);
|
||||||
|
}else{
|
||||||
|
println_int(64);
|
||||||
|
}
|
||||||
|
if( false == false ){
|
||||||
|
println_int(65);
|
||||||
|
}else{
|
||||||
|
println_int(420);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXPECTED
|
||||||
|
// 61
|
||||||
|
// 62
|
||||||
|
// 63
|
||||||
|
// 64
|
||||||
|
// 65
|
||||||
Loading…
x
Reference in New Issue
Block a user