fix & optimize: pointer dereference in if condition
authoryu.dongliang <maja_creater@qq.com>
Tue, 18 Oct 2022 15:03:47 +0000 (23:03 +0800)
committeryu.dongliang <maja_creater@qq.com>
Tue, 18 Oct 2022 15:03:47 +0000 (23:03 +0800)
core/scf_basic_block.c
core/scf_dag.c
core/scf_optimizer_pointer_alias.c
parse/scf_parse2.c

index e1b3ffb8d5fd26bf95dc5a68b1106d71982516c3..323fa135b45f1d6db5519fbedf31803c7bb61958 100644 (file)
@@ -243,8 +243,8 @@ void scf_basic_block_print_list(scf_list_t* h)
 
                        scf_basic_block_t* bb = scf_list_data(l, scf_basic_block_t, list);
 
-                       printf("\033[33mbasic_block: %p, index: %d, dfo_normal: %d, cmp_flag: %d, group: %d, loop: %d\033[0m\n",
-                                       bb, bb->index, bb->dfo_normal, bb->cmp_flag, bb->group_flag, bb->loop_flag);
+                       printf("\033[33mbasic_block: %p, index: %d, dfo_normal: %d, cmp_flag: %d, group: %d, loop: %d, dereference_flag: %d\033[0m\n",
+                                       bb, bb->index, bb->dfo_normal, bb->cmp_flag, bb->group_flag, bb->loop_flag, bb->dereference_flag);
 
                        scf_basic_block_print(bb, sentinel);
 
index ff590b70c0f6ec3b37797d2056ead4a5cb94abe8..0c6cbdba11e26a6dd6e0e7ecf4a6175119056f1b 100644 (file)
@@ -831,12 +831,21 @@ scf_dag_node_t* scf_dag_find_node(scf_list_t* h, const scf_node_t* node)
 
 int scf_dag_get_node(scf_list_t* h, const scf_node_t* node, scf_dag_node_t** pp)
 {
-       scf_variable_t* v  = _scf_operand_get((scf_node_t*)node);
+       const scf_node_t* node2;
+       scf_variable_t*   v;
+       scf_dag_node_t*   dn;
 
-       scf_dag_node_t* dn = scf_dag_find_node(h, node);
+       if (*pp)
+               node2 = (*pp)->node;
+       else
+               node2 = node;
+
+       v  = _scf_operand_get((scf_node_t*)node2);
+
+       dn = scf_dag_find_node(h, node2);
 
        if (!dn) {
-               dn = scf_dag_node_alloc(node->type, v, node);
+               dn = scf_dag_node_alloc(node2->type, v, node2);
                if (!dn)
                        return -ENOMEM;
 
index 6c5a1ba6837be5b6758b9d3729269598c4c9f025..d73035eb460c238b662f81a735b50003747037ee 100644 (file)
@@ -1,23 +1,8 @@
 #include"scf_optimizer.h"
 #include"scf_pointer_alias.h"
 
-static int _3ac_pointer_alias(scf_dag_node_t* alias, scf_3ac_code_t* c, scf_basic_block_t* bb)
+static int _filter_3ac_by_pointer_alias(scf_3ac_operand_t* pointer, scf_list_t* prev, scf_basic_block_t* bb)
 {
-       scf_3ac_operand_t* pointer;
-
-       int ret;
-
-       assert(c->srcs && c->srcs->size >= 1);
-
-       pointer = c->srcs->data[0];
-
-       ret     = scf_vector_del(c->srcs, pointer);
-       if (ret < 0) {
-               scf_loge("\n");
-               return ret;
-       }
-
-#if 1
        scf_3ac_code_t* c2;
        scf_3ac_code_t* c3;
        scf_list_t*     l2;
@@ -26,7 +11,7 @@ static int _3ac_pointer_alias(scf_dag_node_t* alias, scf_3ac_code_t* c, scf_basi
 
        scf_list_init(&h);
 
-       ret = scf_dag_expr_calculate(&h, pointer->dag_node);
+       int ret = scf_dag_expr_calculate(&h, pointer->dag_node);
        if (ret < 0) {
                scf_loge("\n");
                return ret;
@@ -37,7 +22,7 @@ static int _3ac_pointer_alias(scf_dag_node_t* alias, scf_3ac_code_t* c, scf_basi
                c2  = scf_list_data(l2, scf_3ac_code_t, list);
                l2  = scf_list_next(l2);
 
-               for (l3 = scf_list_prev(&c->list); l3 != scf_list_sentinel(&bb->code_list_head); ) {
+               for (l3 = prev; l3 != scf_list_sentinel(&bb->code_list_head); ) {
 
                        c3  = scf_list_data(l3, scf_3ac_code_t, list);
                        l3  = scf_list_prev(l3);
@@ -52,6 +37,30 @@ static int _3ac_pointer_alias(scf_dag_node_t* alias, scf_3ac_code_t* c, scf_basi
                scf_list_del(&c2->list);
                scf_3ac_code_free(c2);
        }
+
+       return 0;
+}
+
+static int _3ac_pointer_alias(scf_dag_node_t* alias, scf_3ac_code_t* c, scf_basic_block_t* bb)
+{
+       scf_3ac_operand_t* pointer;
+
+       int ret;
+
+       assert(c->srcs && c->srcs->size >= 1);
+
+       pointer = c->srcs->data[0];
+
+       ret     = scf_vector_del(c->srcs, pointer);
+       if (ret < 0) {
+               scf_loge("\n");
+               return ret;
+       }
+
+#if 1
+       ret = _filter_3ac_by_pointer_alias(pointer, scf_list_prev(&c->list), bb);
+       if (ret < 0)
+               return ret;
 #endif
 
        pointer->dag_node = alias;
@@ -164,6 +173,76 @@ static int _alias_assign_dereference(scf_vector_t** paliases, scf_dag_node_t* dn
        return 0;
 }
 
+static int __optimize_alias_dereference(scf_3ac_operand_t* pointer, scf_3ac_code_t* c, scf_basic_block_t* bb, scf_list_t* bb_list_head)
+{
+       scf_basic_block_t* bb2;
+       scf_dn_status_t*   ds;
+       scf_dag_node_t*    dn_pointer;
+       scf_dag_node_t*    dn_dereference;
+       scf_vector_t*      aliases;
+       scf_list_t*        l;
+
+       int flag = 0;
+
+       dn_pointer     = pointer->dag_node;
+       dn_dereference = dn_pointer;
+       aliases        = NULL;
+
+       assert(1  == dn_pointer->childs->size);
+       dn_pointer = dn_pointer->childs->data[0];
+
+       int ret = _alias_dereference(&aliases, dn_pointer, c, bb, bb_list_head);
+       if (ret < 0)
+               return ret;
+
+       if (aliases) {
+               flag = 1;
+
+               if (1 == aliases->size) {
+                       ds = aliases->data[0];
+
+                       if (SCF_DN_ALIAS_VAR == ds->alias_type) {
+
+                               l = scf_list_prev(&c->list);
+
+                               if (l == scf_list_sentinel(&bb->code_list_head)) {
+                                       l =  scf_list_prev(&bb->list);
+
+                                       assert(l != scf_list_sentinel(bb_list_head));
+
+                                       bb2 = scf_list_data(l, scf_basic_block_t, list);
+                                       l   = scf_list_tail(&bb2->code_list_head);
+                               } else {
+                                       bb2 = bb;
+                                       l   = scf_list_prev(&c->list);
+                               }
+
+                               ret = _filter_3ac_by_pointer_alias(pointer, l, bb2);
+                               if (ret < 0)
+                                       return ret;
+
+                               pointer->dag_node = ds->alias;
+
+                               ret = scf_basic_block_inited_vars(bb, bb_list_head);
+                               if (ret < 0)
+                                       return ret;
+
+                               flag = 0;
+                       }
+               }
+
+               ret = _bb_copy_aliases(bb, dn_pointer, dn_dereference, aliases);
+
+               scf_vector_free(aliases);
+               aliases = NULL;
+
+               if (ret < 0)
+                       return ret;
+       }
+
+       return flag;
+}
+
 static int __optimize_alias_bb(scf_list_t** pend, scf_list_t* start, scf_basic_block_t* bb, scf_list_t* bb_list_head)
 {
        scf_list_t*        l;
@@ -212,40 +291,45 @@ static int __optimize_alias_bb(scf_list_t** pend, scf_list_t* start, scf_basic_b
 
                        if (SCF_OP_3AC_TEQ == c->op->type || SCF_OP_3AC_CMP == c->op->type) {
 
-                               dn_dereference = dn_pointer;
+                               if (SCF_OP_DEREFERENCE != dn_pointer->type)
+                                       continue;
+
+                               ret = __optimize_alias_dereference(pointer, c, bb, bb_list_head);
+                               if (ret < 0)
+                                       return ret;
 
-                               assert(SCF_OP_DEREFERENCE == dn_pointer->type);
-                               assert(1                  == dn_pointer->childs->size);
+                               flag += ret;
 
-                               dn_pointer = dn_pointer->childs->data[0];
+                       } else if (SCF_OP_DEREFERENCE == c->op->type) {
+
+                               assert(c->dsts && 1 == c->dsts->size);
+                               dst = c->dsts->data[0];
+                               dn_dereference = dst->dag_node;
 
                                ret = _alias_dereference(&aliases, dn_pointer, c, bb, bb_list_head);
 
-                               if (aliases && 1 == aliases->size) {
+                       } else {
+                               if (i > 0)
+                                       break;
 
-                                       ds = aliases->data[0];
+                               pointer    = c->srcs->data[1];
+                               dn_pointer = pointer->dag_node;
 
-                                       if (SCF_DN_ALIAS_VAR == ds->alias_type) {
-                                               pointer->dag_node = ds->alias;
+                               if (SCF_OP_DEREFERENCE == dn_pointer->type) {
 
-                                               scf_vector_free(aliases);
-                                               aliases = NULL;
+                                       ret = __optimize_alias_dereference(pointer, c, bb, bb_list_head);
+                                       if (ret < 0)
+                                               return ret;
 
-                                               ret = scf_basic_block_inited_vars(bb, bb_list_head);
-                                               if (ret < 0)
-                                                       return ret;
-                                       }
+                                       flag += ret;
                                }
 
-                       } else if (SCF_OP_DEREFERENCE == c->op->type) {
+                               pointer        = c->srcs->data[0];
+                               dn_pointer     = pointer->dag_node;
+                               dn_dereference = NULL;
 
-                               assert(c->dsts && 1 == c->dsts->size);
-                               dst = c->dsts->data[0];
-                               dn_dereference = dst->dag_node;
-
-                               ret = _alias_dereference(&aliases, dn_pointer, c, bb, bb_list_head);
-                       } else
                                ret = _alias_assign_dereference(&aliases, dn_pointer, c, bb, bb_list_head);
+                       }
 
                        if (ret < 0)
                                return ret;
index baa3a0e23ce46367a83b0c7347d9ae14b8d131ce..5eface5d2fd252c6dacc8d5e809e36d9b95b0cf4 100644 (file)
@@ -2052,7 +2052,7 @@ int scf_parse_compile_functions(scf_parse_t* parse, scf_native_t* native, scf_ve
                }
 
                assert(scf_list_empty(&h));
-//             scf_basic_block_print_list(&f->basic_block_list_head);
+               scf_basic_block_print_list(&f->basic_block_list_head);
        }
        int64_t tv1 = gettime();
        scf_logw("tv1 - tv0: %ld\n", tv1 - tv0);