예제 #1
0
    def test_get_lvn_stmt_all_possibilities(self):
        as_tree = ast.parse(
            ms("""\
           a = b + 4    # 2 = 0 + 1
           c = 33 + d   # 5 = 3 + 4
           e = f + g    # 8 = 6 + 7
           h = 24       # ...
           i = j
           k = - 38
           l = - m
           """))

        ssa_code = SsaCode(as_tree)
        lvn_dict = LvnDict()
        lvn_stmt_list = []
        for ssa in ssa_code:
            lvn_dict.variable_dict.enumerate(ssa)
            lvn_stmt = lvn_dict.get_lvn_stmt(ssa)
            lvn_stmt_list.append(lvn_stmt)

        expected_lvn_stmt_list = [(2, 0, 'Add', 1), (5, 3, 'Add', 4),
                                  (8, 6, 'Add', 7), (10, 9, None, None),
                                  (12, 11, None, None), (14, None, 'USub', 13),
                                  (16, None, 'USub', 15)]

        self.assert_lvn_stmt_list(lvn_stmt_list, *expected_lvn_stmt_list)
예제 #2
0
    def test_enumerate_given_a_update(self):
        as_tree = ast.parse(
            ms("""\
                               a = x + y
                               b = x + y
                               a = 2
                               c = x + y
                               d = 3 + x
                               f = y + 4"""))

        ssa_code = SsaCode(as_tree)
        lvn_dict = LvnDict()
        for ssa in ssa_code:
            lvn_dict.variable_dict.enumerate(ssa)

        expected_value_dict = {
            'a_0': 2,
            'x_0': 0,
            'y_0': 1,
            'b_0': 3,
            '2': 4,
            'a_1': 5,
            'c_0': 6,
            '3': 7,
            'd_0': 8,
            '4': 9,
            'f_0': 10
        }
        self.assertDictEqual(lvn_dict.variable_dict, expected_value_dict)
예제 #3
0
    def test_enumerate_given_multiple_time(self):
        as_tree = ast.parse(
            ms("""\
            a = 3   # a = 0
            a = 4   # a = 1
            a = b   # b = 2, a = 3
            a = c   # c = 4, a = 5
            a = d   # d = 6, a = 7
            """))

        ssa_code = SsaCode(as_tree)
        lvn_dict = LvnDict()
        for ssa in ssa_code:
            lvn_dict.variable_dict.enumerate(ssa)

        expected_value_dict = {
            'a_0': 1,
            'a_1': 3,
            'a_2': 5,
            'b_0': 4,
            'c_0': 6,
            'a_3': 7,
            'd_0': 8,
            'a_4': 9,
            '3': 0,
            '4': 2
        }
        self.assertDictEqual(lvn_dict.variable_dict, expected_value_dict)
예제 #4
0
    def test_get_lvn_stmt_given_const(self):
        as_tree = ast.parse(
            ms("""\
            c = 33      # 1 = 0
            a = c + d   # 3 = 1 + 2
            """))

        ssa_code = SsaCode(as_tree)
        lvn_dict = LvnDict()
        lvn_stmt_list = []
        for ssa in ssa_code:
            lvn_dict.variable_dict.enumerate(ssa)
            lvn_stmt = lvn_dict.get_lvn_stmt(ssa)
            lvn_stmt_list.append((lvn_stmt))

        expected_lvn_stmt_list = [(1, 0, None, None), (3, 1, 'Add', 2)]

        self.assert_lvn_stmt_list(lvn_stmt_list, *expected_lvn_stmt_list)
예제 #5
0
    def test_value_number_to_var_list(self):
        as_tree = ast.parse(
            ms("""\
               a = x + y
               b = x - z
               a = 2"""))

        ssa_code = SsaCode(as_tree)
        lvn_dict = LvnDict()
        for ssa in ssa_code:
            lvn_dict.variable_dict.enumerate(ssa)

        expected_list = [
            SsaVariable("x"),
            SsaVariable("y"),
            SsaVariable("a"),
            SsaVariable("z"),
            SsaVariable("b"),
            SsaVariable(2),
            SsaVariable("a", 1)
        ]

        self.assert_variable_list_equal(
            lvn_dict.variable_dict.val_num_var_list, expected_list)
예제 #6
0
파일: lvn.py 프로젝트: chaosAD/python-ast
 def __init__(self):
     self.lvn_dict = LvnDict()
     self.alg_ident = AlgIdent()
예제 #7
0
파일: lvn.py 프로젝트: chaosAD/python-ast
class Lvn:
    def __init__(self):
        self.lvn_dict = LvnDict()
        self.alg_ident = AlgIdent()

    def optimize(self, ssa_code):
        for ssa in ssa_code:
            self.lvn_dict.variable_dict.enumerate(ssa)
            ssa.left_oprd, ssa.operator, ssa.right_oprd = self.alg_ident.optimize_alg_identities(
                ssa.left_oprd, ssa.operator, ssa.right_oprd)

            lvn_stmt = self.lvn_dict.get_lvn_stmt(ssa)
            if lvn_stmt.is_simple_assignment():
                # try to replace the left operand
                if self.lvn_dict.variable_dict.is_both_var_same(
                        lvn_stmt.target, lvn_stmt.left):
                    continue
                lvn_stmt.left = self.lvn_dict.simple_assign_dict.find_substitute(
                    lvn_stmt.left)
                if self.lvn_dict.variable_dict.is_both_var_same(
                        lvn_stmt.target, lvn_stmt.left):
                    continue
                self.lvn_dict.simple_assign_dict.update_simp_assgn(
                    lvn_stmt.target, lvn_stmt.left)

            else:
                lvn_stmt.left = self.lvn_dict.simple_assign_dict.find_substitute(
                    lvn_stmt.left)
                lvn_stmt.right = self.lvn_dict.simple_assign_dict.find_substitute(
                    lvn_stmt.right)
                if self.lvn_dict.variable_dict.is_const(lvn_stmt.left) and \
                   self.lvn_dict.variable_dict.is_const(lvn_stmt.right):
                    # fold it by eval the string
                    self.fold_lvn_stmt(lvn_stmt)

                else:
                    lvn_stmt.reorder_selected_operands()
                    lvn_stmt = self.lvn_dict.find_substitute(lvn_stmt)

                    if not lvn_stmt.is_simple_assignment():
                        self.lvn_dict.add_expr(lvn_stmt.get_expr(),
                                               lvn_stmt.target)
                    else:
                        # it's simple expr, add into simple_assign_dict
                        if self.lvn_dict.variable_dict.is_both_var_same(
                                lvn_stmt.target, lvn_stmt.left):
                            continue
                        self.lvn_dict.simple_assign_dict.update_simp_assgn(
                            lvn_stmt.target, lvn_stmt.left)

            self.lvn_dict.lvn_code_tuples_list.append_lvn_stmt(lvn_stmt)

        ssa_optimized_code = self.lvn_code_to_ssa_code()
        return ssa_optimized_code

    def lvn_code_to_ssa_code(self):
        ssa_code = SsaCode()
        for lvn_code_tuple in self.lvn_dict.lvn_code_tuples_list:
            target, left, op, right = None, None, None, None

            target = self.lvn_dict.variable_dict.val_num_var_list[
                lvn_code_tuple[0]]
            # left is constant
            left = self.lvn_dict.variable_dict.val_num_var_list[
                lvn_code_tuple[1]]
            if lvn_code_tuple[2] is not None and lvn_code_tuple[3] is not None:
                op = self.get_real_operator(lvn_code_tuple[2])
                right = self.lvn_dict.variable_dict.val_num_var_list[
                    lvn_code_tuple[3]]

            ssa = Ssa(target, left, op, right)
            ssa_code.code_list.append(ssa)

        return ssa_code

    def fold_lvn_stmt(self, lvn_stmt):
        eval_string = str(self.lvn_dict.variable_dict.get_variable(lvn_stmt.left)) + \
                      operator_dict.get(lvn_stmt.operator) + \
                      str(self.lvn_dict.variable_dict.get_variable(lvn_stmt.right))
        val_after_folded = eval(eval_string)
        lvn_stmt.left = self.lvn_dict.variable_dict._add_to_variable_dict(
            SsaVariable(val_after_folded))
        lvn_stmt.operator = None
        lvn_stmt.right = None
        self.lvn_dict.simple_assign_dict.update_simp_assgn(
            lvn_stmt.target, lvn_stmt.left)

    @staticmethod
    def get_operand_type(lvn_code_tuple):
        return lvn_code_tuple[4]

    def get_real_operator(self, string):
        return operator_dict.get(string)

    @staticmethod
    def is_constant(lvn_code_tuple):
        if lvn_code_tuple[4] == 1:
            return True
        return False