예제 #1
0
    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)
예제 #2
0
    def test_loop_cfg(self):
        """ Test two blocks in a loop
            a:
            t1 = t4
            t2 = 0x10
            jmp b
            b:
            t3 = t2
            t4 = t1
            jmp a

        """
        t1 = ExampleRegister('t1')
        t2 = ExampleRegister('t2')
        t3 = ExampleRegister('t3')
        t4 = ExampleRegister('t4')
        i1 = DefUse(t1, t4)  # t1 is live
        i3 = DefUse(t3, t2)  # t2, t1, t3 live
        i2 = Def(t2, jumps=[i3])  # t1, t2 is live
        i4 = DefUse(t4, t1, jumps=[i1])  # t1, t3, t4 live
        instrs = [i1, i2, i3, i4]
        cfg = FlowGraph(instrs)
        cfg.calculate_liveness()
        ig = InterferenceGraph()
        ig.calculate_interference(cfg)
        self.assertTrue(ig.interfere(t1, t2))
        self.assertFalse(ig.interfere(t2, t4))
예제 #3
0
    def test_constrained_move_by_alias(self):
        """ Test if aliased registers work and cannot be coalesced. """
        f = Frame('tst')
        t1 = R10
        t2 = R10l
        t3 = ExampleRegister('t3')
        move = Mov(t3, t1, ismove=True)
        f.instructions.append(Def(t1))
        f.instructions.append(move)
        f.instructions.append(DefHalf(t2))
        f.instructions.append(UseHalf(t2))
        f.instructions.append(Use(t3))
        self.register_allocator.alloc_frame(f)

        # Check t1 and t2 are pre-colored:
        self.assertEqual(
            {
                self.register_allocator.node(R10),
                self.register_allocator.node(R10l)
            }, 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)
예제 #4
0
 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)
예제 #5
0
    def test_loop_variable(self):
        """
            See if a variable defined at input and in block itself
            is marked as live out!
            Probably simpler variant of testMultipleDefineInLoop.
        I1: x = 2
        I2: use x
        I3: x = 3
        I4: jmp I5
        I5: jmp I2
        """
        x = ExampleRegister('x')
        i2 = Use(x)
        i1 = Def(x, jumps=[i2])
        i3 = Def(x)
        i5 = Nop(jumps=[i2])
        i4 = Nop(jumps=[i5])
        self.assertSequenceEqual([x], i1.defined_registers)
        instrs = [i1, i2, i3, i4, i5]
        cfg = FlowGraph(instrs)
        cfg.calculate_liveness()

        self.assertEqual(3, len(cfg))
        b1 = cfg.get_node(i1)
        b2 = cfg.get_node(i2)
        b3 = cfg.get_node(i5)
        self.assertEqual(3, len(cfg))
        self.assertEqual({x}, b1.live_out)
        self.assertEqual({x}, b2.live_out)
        self.assertEqual({x}, b3.live_out)
예제 #6
0
    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)
예제 #7
0
 def test_normal_use(self):
     """ Test if interference graph works """
     t1 = ExampleRegister('t1')
     t2 = ExampleRegister('t2')
     t3 = ExampleRegister('t3')
     t4 = ExampleRegister('t4')
     instrs = []
     instrs.append(Def(t1))  # t1 is live
     instrs.append(Def(t2))  # t1, t2 is live
     instrs.append(DefUse(t3, t2))  # t2, t1, t3 live
     instrs.append(DefUse(t4, t1))  # t1, t3, t4 live
     cfg = FlowGraph(instrs)
     cfg.calculate_liveness()
     ig = InterferenceGraph()
     ig.calculate_interference(cfg)
     self.assertTrue(ig.interfere(t1, t2))
     self.assertFalse(ig.interfere(t2, t4))
예제 #8
0
    def test_multiple_define_in_loop(self):
        """
            Test if the following works:
            entry:
        I1:  x = 2
        I2:  a = x
        I3:  x = 3
        I4:  b = x
        I5:  c = b
        I6:  cjmp I2, I7
        I7:  nop
        """
        a = ExampleRegister('a')
        b = ExampleRegister('b')
        c = ExampleRegister('c')
        x = ExampleRegister('x')
        i2 = DefUse(a, x)
        i1 = Def(x, jumps=[i2])
        i3 = Def(x)
        i4 = DefUse(b, x)
        i5 = DefUse(c, b)
        i7 = Nop()
        i6 = Nop(jumps=[i2, i7])
        instrs = [i1, i2, i3, i4, i5, i6, i7]
        cfg = FlowGraph(instrs)
        cfg.calculate_liveness()

        # Check that there are three nodes:
        self.assertEqual(3, len(cfg))
        self.assertTrue(cfg.has_node(i1))
        self.assertTrue(cfg.has_node(i2))
        self.assertTrue(cfg.has_node(i7))
        # Get block 2:
        b2 = cfg.get_node(i2)

        # Check that block2 has two successors:
        self.assertEqual(2, len(b2.successors))
        self.assertEqual(2, len(b2.predecessors))

        # Check that x is live at end of block 2
        self.assertEqual({x}, b2.live_out)
예제 #9
0
    def test_combine(self):
        t1 = ExampleRegister('t1')
        t2 = ExampleRegister('t2')
        t3 = ExampleRegister('t3')
        t4 = ExampleRegister('t4')
        instrs = []
        instrs.append(Def(t1))
        instrs.append(Def(t2))
        instrs.append(Def(t3))
        instrs.append(DefUse(t4, t3))
        instrs.append(Use(t4))
        instrs.append(Use(t1))
        instrs.append(Use(t2))
        cfg = FlowGraph(instrs)
        cfg.calculate_liveness()
        ig = InterferenceGraph()
        ig.calculate_interference(cfg)
        ig.combine(ig.get_node(t4), ig.get_node(t3))
        self.assertIs(ig.get_node(t4), ig.get_node(t3))

        # For repr called:
        self.assertTrue(str(ig.get_node(t4)))
예제 #10
0
 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)
예제 #11
0
    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)