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)
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)
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)
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)
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)
def __init__(self): self.lvn_dict = LvnDict() self.alg_ident = AlgIdent()
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