コード例 #1
0
 def test_compute_liveout_with_attr(self):
     blocks, as_tree = self.build_arbitrary_blocks(
         block_links={"A": ["B"], "B": []},
         code={
             "A": dedent(
                 """\
                                                                 a = 4
                                                                 a.b = 2
                                                                 """
             ),
             "B": dedent(
                 """\
                                                                 c = a.b
                                                                 """
             ),
         },
     )
     cfg_real = Cfg()
     cfg_real.block_list = blocks
     cfg_real.as_tree = as_tree
     cfg_real.root = cfg_real.block_list[0]
     cfg_real.gather_initial_info()
     cfg_real.compute_live_out()
     expected_live_out = {"A": {"a", "a.b"}, "B": set()}
     self.assertLiveOutEqual(cfg_real.block_list, expected_live_out)
コード例 #2
0
    def test_fill_df_given_7_blocks(self):
        r"""
        Note: '|' with no arrows means pointing down
             H
             |
             A  <---          DF(A) = A,
            / \    |          DF(B) = G,
           B   E ---          DF(C) = F
          / \  |              DF(D) = F
         C   D |              DF(E) = A, G
          \ /  |              DF(F) = G
           F   |              DF(G) = None
            \  |              DF(H) = None
              G
        """
        blocks = self.build_arbitrary_blocks(
            block_links={
                "H": ["A"],
                "A": ["B", "E"],
                "B": ["C", "D"],
                "C": ["F"],
                "D": ["F"],
                "E": ["G", "A"],
                "F": ["G"],
                "G": [],
            },
            block_type={
                "A": RawBasicBlock,
                "B": RawBasicBlock,
                "C": RawBasicBlock,
                "D": RawBasicBlock,
                "E": RawBasicBlock,
                "F": RawBasicBlock,
                "G": RawBasicBlock,
                "H": ParentScopeBlock,
            },
        )

        cfg_real = Cfg()
        cfg_real.block_list = blocks
        cfg_real.root = blocks[-1]
        cfg_real.root.blocks = blocks
        cfg_real.fill_df()

        self.assert_df_equal(
            cfg_real, {
                "A": ["A"],
                "B": ["G"],
                "C": ["F"],
                "D": ["F"],
                "E": ["A", "G"],
                "F": ["G"],
                "G": [],
                "H": []
            })
コード例 #3
0
    def test_delete_node(self):
        as_tree = AstBuilder().string_build(
            dedent("""\
             z = 2           # 0th block
             while a < 3:    # 1st block
                 if a < 2:   # 2nd block
                      z = 2  # 3rd block
                 b = 2       # 4th block
             c = 3           # 5th block
             """))

        cfg_real = Cfg(as_tree)
        cfg_real.root = cfg_common.delete_node(cfg_real.root,
                                               RawBasicBlock(1, 1))
コード例 #4
0
    def test_fill_df_given_6_block_with_loop(self):
        r"""
        Note: '|' with no arrows means pointing down

                A (None)
                |                                       DF(A) : None
                B (B) <-----                            DF(B) : B
               / \         |                            DF(C) : F
            C(F)  |        |                            DF(D) : E
             / |  |        |    Dominance Frontier      DF(E) : F
          D(E) |  |        |        ---->               DF(F) : B
            |  /  |        |
            E(F)  |        |
            \    /         |
             F(B) ----------
        """
        blocks = self.build_arbitrary_blocks(
            block_links={
                "A": ["B"],
                "B": ["C", "F"],
                "C": ["D", "E"],
                "D": ["E"],
                "E": ["F"],
                "F": ["B"]
            },
            block_type={
                "A": ParentScopeBlock,
                "B": RawBasicBlock,
                "C": RawBasicBlock,
                "D": RawBasicBlock,
                "E": RawBasicBlock,
                "F": RawBasicBlock,
            },
        )

        cfg_real = Cfg()
        cfg_real.block_list = blocks
        cfg_real.root = blocks[0]
        cfg_real.root.blocks = blocks
        cfg_real.fill_df()
        self.assert_df_equal(cfg_real, {
            "A": [],
            "B": ["B"],
            "C": ["F"],
            "D": ["E"],
            "E": ["F"],
            "F": ["B"]
        })
コード例 #5
0
 def test_compute_liveout_given_5_blocks(self):
     blocks, as_tree = self.build_arbitrary_blocks(
         block_links={"A": ["B"], "B": ["C", "D"], "C": ["D"], "D": ["E", "B"], "E": []},
         code={
             "A": dedent(
                 """\
                                                                 i = 1
                                                                 """
             ),
             "B": dedent(
                 """\
                                                                 if i < 0:
                                                                     pass
                                                                 """
             ),
             "C": dedent(
                 """\
                                                                 s = 0
                                                                 """
             ),
             "D": dedent(
                 """\
                                                                 s = s + i
                                                                 i = i + 1
                                                                 if i < 0:
                                                                     pass
                                                                 """
             ),
             "E": dedent(
                 """\
                                                                 if s < 3:
                                                                     pass
                                                                 """
             ),
         },
     )
     cfg_real = Cfg()
     cfg_real.block_list = blocks
     cfg_real.as_tree = as_tree
     cfg_real.root = cfg_real.block_list[0]
     cfg_real.gather_initial_info()
     cfg_real.compute_live_out()
     expected_live_out = {"A": {"s", "i"}, "B": {"s", "i"}, "C": {"s", "i"}, "D": {"s", "i"}, "E": set()}
     self.assertLiveOutEqual(cfg_real.block_list, expected_live_out)
コード例 #6
0
    def test_fill_dominate_given_if_else(self):
        r"""
          Note: '|' with no arrows means pointing down

           A                      Expected Dominator
         /   \                   A: [B, C, D]
        B     C      ------>     B: []
         \   /                   C: []
           D                     D: []
        """
        blocks = self.build_arbitrary_blocks(
            block_links={
                "A": ["B", "C"],
                "B": ["D"],
                "C": ["D"],
                "D": []
            },
            block_type={
                "A": ParentScopeBlock,
                "B": RawBasicBlock,
                "C": RawBasicBlock,
                "D": RawBasicBlock
            },
        )
        cfg_real = Cfg()
        cfg_real.root = blocks[0]
        cfg_real.root.blocks = blocks
        cfg_real.block_list = blocks

        cfg_real.root.fill_dominates()
        cfg_real.root.fill_idom()
        expected_rev_dominator = {
            "A": {"A"},
            "B": {"A", "B"},
            "C": {"A", "C"},
            "D": {"A", "D"}
        }
        expected_idom = {"A": None, "B": "A", "C": "A", "D": "A"}
        self.assert_dominator_equal(cfg_real, expected_rev_dominator)
        self.assert_rev_idom_equal(cfg_real, expected_idom)
コード例 #7
0
 def test_insert_phi_function_pruned_4_blocks(self):
     blocks, as_tree = self.build_arbitrary_blocks(
         block_links={"A": ["B", "C"], "B": ["D"], "C": ["D"], "D": []},
         code={
             "A": dedent(
                 """\
                                                         pass
                                                         """
             ),
             "B": dedent(
                 """\
                                                         var = 3
                                                         """
             ),
             "C": dedent(
                 """\
                                                         pass
                                                         """
             ),
             "D": dedent(
                 """\
                                                         if var < 3:
                                                             pass
                                                         """
             ),
         },
         block_type={"A": ParentScopeBlock},
     )
     cfg_real = Cfg()
     cfg_real.block_list = blocks
     cfg_real.as_tree = as_tree
     cfg_real.root = cfg_real.block_list[0]
     cfg_real.root.blocks = blocks
     cfg_real.fill_df()
     cfg_real.gather_initial_info()
     cfg_real.compute_live_out()
     cfg_real.ins_phi_function_all()
     expected_phi_list = {"A": set(), "B": set(), "C": set(), "D": {"var"}}
     self.assertPhiListEqual(cfg_real.block_list, expected_phi_list)
コード例 #8
0
    def test_3_blocks_with_loops(self):
        r"""
        A
        |
        B  <--
        |    |
        | ---
        C
        """
        blocks, as_tree = self.build_arbitrary_blocks(
            block_links={
                "A": ["B"],
                "B": ["C", "B"],
                "C": [],
                "D": ["A"]
            },
            block_type={"D": ParentScopeBlock},
            code={
                "A":
                dedent("""\
                                                                    b = 2
                                                                    c = 1
                                                                    a = 0
                                                                    """),
                "B":
                dedent("""\
                                                                    b = a + 1
                                                                    c = c + b
                                                                    a = b * 2
                                                                    a < c
                                                                    """),
                "C":
                dedent("""\
                                                                    c = c
                                                                    """),
                "D":
                "",
            },
        )

        cfg_real = Cfg()
        cfg_real.block_list = blocks
        cfg_real.as_tree = as_tree
        cfg_real.root = cfg_real.block_list[-1]
        for blk in cfg_real.block_list[:-1]:
            blk.scope = cfg_real.block_list[-1]
        cfg_real.root.ast_node = as_tree
        cfg_real.root.ssa_code.code_list.append(as_tree)
        cfg_real.root.blocks = blocks
        cfg_real.convert_to_ssa()
        self.assertBlockSsaList(
            cfg_real.block_list,
            {
                "A":
                dedent("""\
                                              Assign: (b_0,) = 2
                                              Assign: (c_0,) = 1
                                              Assign: (a_0,) = 0
                                              """),
                "B":
                dedent("""\
                                             Assign: (a_1,) = Phi(a_0, a_2)
                                             Assign: (c_1,) = Phi(c_0, c_2)
                                             Assign: (b_1,) = Phi(b_0, b_2)
                                             Assign: (b_2,) = BinOp: a_1 + 1
                                             Assign: (c_2,) = BinOp: c_1 + b_2
                                             Assign: (a_2,) = BinOp: b_2 * 2
                                             a_2 < c_2
                                             """),
                "C":
                dedent("""\
                                              Assign: (c_3,) = c_2
                                              """),
            },
        )
コード例 #9
0
    def test_renaming_given_loop(self):
        r"""

          A
          |
          B  <----
         / \     |
        C  D     |
        \ /      |
         E  -----|
        """
        blocks, as_tree = self.build_arbitrary_blocks(
            block_links={
                "A": ["B"],
                "B": ["C", "D"],
                "C": ["E"],
                "D": ["E"],
                "E": ["B"],
                "F": ["A"]
            },
            block_type={"F": ParentScopeBlock},
            code={
                "A":
                dedent("""\
                                                                    j = 1
                                                                    k = 1
                                                                    I = 0
                                                                    """),
                "B":
                dedent("""\
                                                                    I < 29
                                                                    """),
                "C":
                dedent("""\
                                                                    j = j + 1
                                                                    k = k + 1
                                                                    """),
                "D":
                dedent("""\
                                                                    j = j + 2
                                                                    k = k + 2
                                                                    """),
                "E":
                dedent("""\
                                                                    temp = 1
                                                                    """),
                "F":
                "",
            },
        )

        cfg_real = Cfg()
        cfg_real.block_list = blocks
        cfg_real.as_tree = as_tree
        cfg_real.root = cfg_real.block_list[-1]
        for blk in cfg_real.block_list[:-1]:
            blk.scope = cfg_real.block_list[-1]
        cfg_real.root.ast_node = as_tree
        cfg_real.root.ssa_code.code_list.append(as_tree)
        cfg_real.root.blocks = blocks
        cfg_real.convert_to_ssa()

        self.assertBlockSsaList(
            cfg_real.block_list,
            {
                "A":
                dedent("""\
                                              Assign: (j_0,) = 1
                                              Assign: (k_0,) = 1
                                              Assign: (I_0,) = 0
                                              """),
                "B":
                dedent("""\
                                              Assign: (temp_0,) = Phi(temp, temp_1)
                                              Assign: (k_1,) = Phi(k_0, k_4)
                                              Assign: (j_1,) = Phi(j_0, j_4)
                                              I_0 < 29
                                              """),
                "C":
                dedent("""\
                                              Assign: (j_2,) = BinOp: j_1 + 1
                                              Assign: (k_2,) = BinOp: k_1 + 1
                                              """),
                "D":
                dedent("""\
                                              Assign: (j_3,) = BinOp: j_1 + 2
                                              Assign: (k_3,) = BinOp: k_1 + 2
                                              """),
                "E":
                dedent("""\
                                              Assign: (k_4,) = Phi(k_2, k_3)
                                              Assign: (j_4,) = Phi(j_2, j_3)
                                              Assign: (temp_1,) = 1
                                              """),
                "F":
                "Module ",
            },
        )
コード例 #10
0
    def test_rename_given_custom_4_blocks(self):
        r"""
               A
            /    \
           B      E
          / \     |
         C  D     |
         \ /      |
          F  <----
        """
        blocks, as_tree = self.build_arbitrary_blocks(
            block_links={
                "A": ["B", "E"],
                "B": ["C", "D"],
                "C": ["F"],
                "D": ["F"],
                "E": ["G"],
                "F": ["G"],
                "G": []
            },
            block_type={"A": ParentScopeBlock},
            code={
                "A":
                dedent("""\
                                                            """),
                "B":
                dedent("""\
                                                            a = 1 #a_0
                                                            """),
                "C":
                dedent("""\
                                                            a = 22 #a_1
                                                            """),
                "D":
                dedent("""\
                                                            a = 33 #a_2
                                                            """),
                "E":
                dedent("""\
                                                            a = 44 #a_4
                                                            """),
                "F":
                dedent("""\
                                                            a = 55 #a_3
                                                            """),
                "G":
                dedent("""\
                                                            a = 66 #a_5
                                                            """),
            },
        )

        cfg_real = Cfg()
        cfg_real.block_list = blocks
        cfg_real.as_tree = as_tree
        cfg_real.root = cfg_real.block_list[0]
        cfg_real.root.ast_node = as_tree
        cfg_real.root.ssa_code.code_list.append(as_tree)
        cfg_real.root.blocks = blocks
        cfg_real.fill_df()
        cfg_real.gather_initial_info()
        cfg_real.compute_live_out()

        cfg_real.rename_to_ssa()

        self.assertBlockSsaList(
            cfg_real.block_list,
            {
                "A":
                dedent("""\
                                    Module
                                """),
                "B":
                dedent("""\
                                      Assign: (a_0,) = 1
                                      """),
                "C":
                dedent("""\
                                      Assign: (a_1,) = 22
                                      """),
                "D":
                dedent("""\
                                      Assign: (a_2,) = 33
                                      """),
                "E":
                dedent("""\
                                      Assign: (a_4,) = 44
                                      """),
                "F":
                dedent("""\
                                      Assign: (a_3,) = 55
                                      """),
                "G":
                dedent("""\
                                      Assign: (a_5,) = 66
                                      """),
            },
        )
コード例 #11
0
    def test_insert_phi_function_pruned(self):
        r"""
           Note: '|' with no arrows means pointing down

            A
            |
            B   <------|
         /    \        |
        C      F       |
        |    /  \      |
        |    G   I     |
        |    \   /     |
        |      H       |
         \    /        |
           D-----------|
           |
           E
        """
        blocks, as_tree = self.build_arbitrary_blocks(
            block_links={
                "A": ["B"],
                "B": ["C", "F"],
                "C": ["D"],
                "D": ["E", "B"],
                "E": [],
                "F": ["G", "I"],
                "G": ["H"],
                "H": ["D"],
                "I": ["H"],
            },
            code={
                "A": dedent(
                    """\
                                                            i = 1
                                                            """
                ),
                "B": dedent(
                    """\
                                                            a = temp_0
                                                            c = temp_1
                                                            if a < c:
                                                                pass
                                                            """
                ),
                "C": dedent(
                    """\
                                                            b = temp_2
                                                            c = temp_3
                                                            d = temp_4
                                                            """
                ),
                "D": dedent(
                    """\
                                                            y = a + b
                                                            z = c + d
                                                            i = i + 1
                                                            if i < 100:
                                                                pass
                                                            """
                ),
                "E": "return\n",
                "F": dedent(
                    """\
                                                            a = temp_5
                                                            d = temp_6
                                                            if a < d:
                                                                pass
                                                            """
                ),
                "G": dedent(
                    """\
                                                            d = temp
                                                            """
                ),
                "H": dedent(
                    """\
                                                            b = temp
                                                            """
                ),
                "I": dedent(
                    """\
                                                            c = temp
                                                            """
                ),
            },
            block_type={"A": ParentScopeBlock},
        )
        cfg_real = Cfg()
        cfg_real.block_list = blocks
        cfg_real.as_tree = as_tree
        cfg_real.root = cfg_real.block_list[0]
        cfg_real.root.blocks = blocks
        cfg_real.fill_df()
        cfg_real.gather_initial_info()
        cfg_real.compute_live_out()
        cfg_real.ins_phi_function_all()
        expected_phi_list = {
            "A": set(),
            "B": {"i"},
            "C": set(),
            "D": {"a", "b", "c", "d"},
            "E": set(),
            "F": set(),
            "G": set(),
            "H": {"c", "d"},
            "I": set(),
        }
        self.assertPhiListEqual(cfg_real.block_list, expected_phi_list)
コード例 #12
0
    def test_fill_dominate_given_while(self):
        r"""
        Note: '|' with no arrows means pointing down

                A
                |
                B     <-----
               / \         |                            A': ['B', 'C', 'D', 'E', 'F'],
              C   |        |                            B': ['C', 'D', 'E', 'F'],
             / |  |        |    Expected dominator      C': ['D', 'E'],
            D  |  |        |        ---->               D': [],
            |  /  |        |                            E': [],
            E     |        |                            F': []}
            \    /         |
              F   ----------
        """
        blocks = self.build_arbitrary_blocks(
            block_links={
                "A": ["B"],
                "B": ["C", "F"],
                "C": ["D", "E"],
                "D": ["E"],
                "E": ["F"],
                "F": ["B"]
            },
            block_type={
                "A": ParentScopeBlock,
                "B": RawBasicBlock,
                "C": RawBasicBlock,
                "D": RawBasicBlock,
                "E": RawBasicBlock,
                "F": RawBasicBlock,
            },
        )
        cfg_real = Cfg()
        cfg_real.block_list = blocks
        cfg_real.root = blocks[0]
        cfg_real.root.blocks = blocks

        cfg_real.root.fill_dominates()
        cfg_real.root.fill_idom()

        expected_rev_dominator = {
            "A": {"A"},
            "B": {"A", "B"},
            "C": {"A", "B", "C"},
            "D": {"A", "B", "C", "D"},
            "E": {"A", "B", "C", "E"},
            "F": {"A", "B", "F"},
        }

        expected_idom = {
            "A": None,
            "B": "A",
            "C": "B",
            "D": "C",
            "E": "C",
            "F": "B"
        }

        self.assert_dominator_equal(cfg_real, expected_rev_dominator)
        self.assert_rev_idom_equal(cfg_real, expected_idom)
コード例 #13
0
    def test_dominator_tree_given_13_blocks(self):
        r"""
                Note: '|' with no arrows means pointing down

                +---------> R
                |           |
                |     +-----+------------+
                |     |     |            |
                |     A <-- B            C---------+
                |     |    / \           |         |
                |     D --+   E <-+      |         G
                |     |       |   |      F        / \
                |     L       |   |      |       |  J
                |     |       |   |       \      |  |
                |     +------ H --+         I ---+--+
                |             |             |
                |             +---------+   |
                |                       |   |
                +---------------------- K --+
        """
        blocks = self.build_arbitrary_blocks(
            block_links={
                "A": ["B", "C", "H"],
                "B": ["D"],
                "C": ["B", "D", "F"],
                "D": ["E"],
                "E": ["G"],
                "F": ["G"],
                "G": ["F", "M"],
                "H": ["I", "J"],
                "I": ["L"],
                "J": ["K", "L"],
                "K": ["L"],
                "L": ["M"],
                "M": ["A", "L"],
                "N": ["A"],
            },
            block_type={
                "A": RawBasicBlock,
                "B": RawBasicBlock,
                "C": RawBasicBlock,
                "D": RawBasicBlock,
                "E": RawBasicBlock,
                "F": RawBasicBlock,
                "G": RawBasicBlock,
                "H": RawBasicBlock,
                "I": RawBasicBlock,
                "J": RawBasicBlock,
                "K": RawBasicBlock,
                "L": RawBasicBlock,
                "M": RawBasicBlock,
                "N": ParentScopeBlock,
            },
        )
        cfg_real = Cfg()
        cfg_real.block_list = blocks
        cfg_real.root = blocks[-1]
        cfg_real.root.blocks = blocks
        cfg_real.root.fill_dominates()
        cfg_real.root.fill_idom()
        expected_idom = {
            "A": ["B", "C", "D", "F", "G", "H", "L", "M"],
            "B": [],
            "C": [],
            "D": ["E"],
            "E": [],
            "F": [],
            "G": [],
            "H": ["I", "J"],
            "I": [],
            "J": ["K"],
            "K": [],
            "L": [],
            "M": [],
            "N": ["A"],
        }

        self.assert_idom_equal(cfg_real, expected_idom)
コード例 #14
0
    def test_dominator_tree_given_complex_block(self):
        r"""
                Note: '|' with no arrows means pointing down

                 A                                        A
                 |                                        |
                 B   <------|                             B
              /    \        |     Dominator Tree      /   |   \
             C      F       |       ------->         C    D    F
             |    /  \      |                             |   / | \
             |    G   I     |                             E  G  H  I
             |    \   /     |
             |      H       |
              \    /        |
                D-----------|
                |
                E
        """
        blocks = self.build_arbitrary_blocks(
            block_links={
                "A": ["B"],
                "B": ["C", "F"],
                "C": ["D"],
                "D": ["E", "B"],
                "E": [],
                "F": ["G", "I"],
                "G": ["H"],
                "H": ["D"],
                "I": ["H"],
            },
            block_type={
                "A": ParentScopeBlock,
                "B": RawBasicBlock,
                "C": RawBasicBlock,
                "D": RawBasicBlock,
                "E": RawBasicBlock,
                "F": RawBasicBlock,
                "G": RawBasicBlock,
                "H": RawBasicBlock,
                "I": RawBasicBlock,
            },
        )

        cfg_real = Cfg()
        cfg_real.block_list = blocks
        cfg_real.root = blocks[0]
        cfg_real.root.blocks = blocks
        cfg_real.root.fill_dominates()
        cfg_real.root.fill_idom()

        expected_idom = {
            "A": ["B"],
            "B": ["C", "D", "F"],
            "C": [],
            "D": ["E"],
            "E": [],
            "F": ["G", "H", "I"],
            "G": [],
            "H": [],
            "I": [],
        }
        self.assert_idom_equal(cfg_real, expected_idom)