def test_constrained_move(self): """ Test a constrained move. Do this by creating two pre-colored registers. Move one and add the other with the copy of the first. The move can then not be coalesced, and will be frozen. """ f = Frame('tst') t1 = R0 t2 = R0 t3 = ExampleRegister('t3') t4 = ExampleRegister('t4') f.instructions.append(Def(t1)) move = Mov(t3, t1, ismove=True) f.instructions.append(move) f.instructions.append(Def(t2)) f.instructions.append(Add(t4, t2, t3)) f.instructions.append(Use(t4)) self.register_allocator.alloc_frame(f) # Check t1 and t2 are pre-colored: self.assertEqual({self.register_allocator.node(R0)}, self.register_allocator.precolored) self.assertEqual(set(), self.register_allocator.coalescedMoves) self.assertEqual({move}, self.register_allocator.constrainedMoves) self.conflict(t2, t3) self.assertEqual(set(), self.register_allocator.frozenMoves) self.assertIn(move, f.instructions)
def test_register_allocation(self): f = Frame('tst') t1 = ExampleRegister('t1') t2 = ExampleRegister('t2') t3 = ExampleRegister('t3') t4 = ExampleRegister('t4') t5 = ExampleRegister('t5') f.instructions.append(Def(t1)) f.instructions.append(Def(t2)) f.instructions.append(Def(t3)) f.instructions.append(Add(t4, t1, t2)) f.instructions.append(Add(t5, t4, t3)) f.instructions.append(Use(t5)) self.register_allocator.alloc_frame(f) self.conflict(t1, t2) self.conflict(t2, t3)
def test_register_coalescing(self): """ Register coalescing happens when a move can be eliminated """ f = Frame('tst') t1 = ExampleRegister('t1') t2 = ExampleRegister('t2') t3 = ExampleRegister('t3') t4 = ExampleRegister('t4') t5 = ExampleRegister('t5') t6 = ExampleRegister('t6') f.instructions.append(Def(t1)) f.instructions.append(Def(t2)) f.instructions.append(Def(t3)) f.instructions.append(Add(t4, t2, t1)) f.instructions.append(Mov(t5, t3)) f.instructions.append(Add(t5, t4, t5)) f.instructions.append(Mov(t6, t5)) f.instructions.append(Use(t6)) self.register_allocator.alloc_frame(f) self.conflict(t1, t2) self.conflict(t2, t3) self.conflict(t1, t3)
def test_freeze(self): """ Create a situation where no select and no coalesc is possible """ f = Frame('tst') t4 = ExampleRegister('t4') t5 = ExampleRegister('t5') f.instructions.append(Def(R0)) move = Mov(R1, R0, ismove=True) f.instructions.append(move) f.instructions.append(Def(t4)) f.instructions.append(Add(t5, t4, R1)) f.instructions.append(Use(t5)) self.register_allocator.alloc_frame(f) self.assertEqual(set(), self.register_allocator.coalescedMoves) # self.assertEqual({move}, self.register_allocator.frozenMoves) self.conflict(R1, R0)
def test_multiple_successors(self): """ Example from wikipedia about liveness """ a = ExampleRegister('a') b = ExampleRegister('b') c = ExampleRegister('c') d = ExampleRegister('d') x = ExampleRegister('x') i1 = Def(a) # a = 3 i2 = Def(b) # b = 5 i3 = Def(d) # d = 4 i4 = Def(x) # x = 100 i6 = Add(c, a, b) # c = a + b i8 = Def(c) # c = 4 i7 = Def(d, jumps=[i8]) # d = 2 i9 = Use3(b, d, c) # return b * d + c i5 = Cmp(a, b, jumps=[i6, i8]) # if a > b instrs = [i1, i2, i3, i4, i5, i6, i7, i8, i9] cfg = FlowGraph(instrs) cfg.calculate_liveness() # Get blocks: b1 = cfg.get_node(i1) b2 = cfg.get_node(i6) b3 = cfg.get_node(i8) # Should be 3 nodes: self.assertEqual(3, len(cfg)) # Check successors: self.assertEqual({b2, b3}, b1.successors) self.assertEqual({b3}, b2.successors) self.assertEqual(set(), b3.successors) # Check predecessors: self.assertEqual(set(), b1.predecessors) self.assertEqual({b1}, b2.predecessors) self.assertEqual({b2, b1}, b3.predecessors) # Check block 1: self.assertEqual(5, len(b1.instructions)) self.assertEqual(set(), b1.gen) self.assertEqual({a, b, d, x}, b1.kill) # Check block 2 gen and killl: self.assertEqual(2, len(b2.instructions)) self.assertEqual({a, b}, b2.gen) self.assertEqual({c, d}, b2.kill) # Check block 3: self.assertEqual(2, len(b3.instructions)) self.assertEqual({b, d}, b3.gen) self.assertEqual({c}, b3.kill) # Check block 1 live in and out: self.assertEqual(set(), b1.live_in) self.assertEqual({a, b, d}, b1.live_out) # Check block 2: self.assertEqual({a, b}, b2.live_in) self.assertEqual({b, d}, b2.live_out) # Check block 3: self.assertEqual({b, d}, b3.live_in) self.assertEqual(set(), b3.live_out) # Create interference graph: ig = InterferenceGraph() ig.calculate_interference(cfg)