update x64 peephole, support VLA in loop, and fix some bugs
authoryu.dongliang <18588496441@163.com>
Thu, 20 Feb 2025 09:37:54 +0000 (17:37 +0800)
committeryu.dongliang <18588496441@163.com>
Thu, 20 Feb 2025 09:37:54 +0000 (17:37 +0800)
23 files changed:
core/scf_3ac.c
core/scf_basic_block.h
core/scf_core_types.h
core/scf_operator_handler_3ac.c
core/scf_optimizer.c
core/scf_optimizer_basic_block.c
core/scf_optimizer_call.c
core/scf_optimizer_common_expr.c
core/scf_optimizer_inline.c
core/scf_optimizer_split_call.c [new file with mode: 0644]
examples/array_pointer_opt2.c [new file with mode: 0644]
examples/inline.c [new file with mode: 0644]
examples/setcc.c [moved from examples/declare_vars.c with 100% similarity]
examples/str.c
examples/vla_2.c [new file with mode: 0644]
lib/x64/scf_object.o
native/x64/scf_x64.c
native/x64/scf_x64_inst.c
native/x64/scf_x64_inst_cmp.c
native/x64/scf_x64_peephole.c
native/x64/scf_x64_rcg.c
native/x64/scf_x64_reg.h
parse/Makefile

index 2f3dce7dd385321b12fb91d9c0377a24c9aefe22..3c59e1388348341babf225683902c428e234148e 100644 (file)
@@ -95,6 +95,7 @@ static scf_3ac_operator_t _3ac_operators[] = {
        {SCF_OP_3AC_JB,          "jb"},
        {SCF_OP_3AC_JBE,         "jbe"},
 
+       {SCF_OP_3AC_DUMP,        "core_dump"},
        {SCF_OP_3AC_NOP,         "nop"},
        {SCF_OP_3AC_END,         "end"},
 
@@ -671,7 +672,7 @@ int scf_3ac_code_to_dag(scf_3ac_code_t* c, scf_list_t* dag)
 
                dn_src = src->dag_node;
 
-               if (dn_src->parents && dn_src->parents->size > 0) {
+               if (dn_src->parents && dn_src->parents->size > 0 && !scf_variable_may_malloced(dn_src->var)) {
                        dn_parent        = dn_src->parents->data[dn_src->parents->size - 1];
 
                        if (SCF_OP_ASSIGN == dn_parent->type) {
@@ -739,7 +740,8 @@ int scf_3ac_code_to_dag(scf_3ac_code_t* c, scf_list_t* dag)
                                return ret;
                }
        } else if (SCF_OP_3AC_CMP == c->op->type
-                       || SCF_OP_3AC_TEQ == c->op->type) {
+                       || SCF_OP_3AC_TEQ == c->op->type
+                       || SCF_OP_3AC_DUMP == c->op->type) {
 
                scf_dag_node_t* dn_cmp = scf_dag_node_alloc(c->op->type, NULL, NULL);
 
@@ -1337,6 +1339,10 @@ static int _3ac_find_basic_block_start(scf_list_t* h)
                        continue;
                }
 #endif
+               if (SCF_OP_3AC_DUMP == c->op->type) {
+                       c->basic_block_start = 1;
+                       continue;
+               }
 
                if (SCF_OP_3AC_END == c->op->type) {
                        c->basic_block_start = 1;
@@ -1530,6 +1536,11 @@ static int _3ac_split_basic_blocks(scf_list_t* h, scf_function_t* f)
                                continue;
                        }
 
+                       if (SCF_OP_3AC_DUMP == c->op->type) {
+                               bb->dump_flag = 1;
+                               continue;
+                       }
+
                        if (SCF_OP_3AC_END == c->op->type) {
                                bb->end_flag = 1;
                                continue;
index d0aab43bc9d12858dc6f77d7501a8cd40734998f..4f193ace4cdb25f2961228b180c278afad68a9e5 100644 (file)
@@ -88,6 +88,7 @@ struct scf_basic_block_s
        uint32_t        vla_flag    :1;
        uint32_t        end_flag    :1;
        uint32_t        varg_flag   :1;
+       uint32_t        dump_flag   :1;
        uint32_t        jmp_dst_flag:1;
 
        uint32_t        dereference_flag:1;
index 6d844ca568189312a2c60718c262d481b8feb602..e67df03ce62d579a0982ca42120cc61c86543b91 100644 (file)
@@ -207,6 +207,7 @@ enum scf_core_types
        SCF_OP_3AC_RELOAD,   // reload a var from memory, only for 3ac & native
        SCF_OP_3AC_RESAVE,   // resave a var to memory, only for 3ac & native
 
+       SCF_OP_3AC_DUMP,
        SCF_OP_3AC_NOP,
        SCF_OP_3AC_END,
 
index 767ba28507a29f1282aec1a9b72a36f98ebe9b98..f627ada2b7f83c34a14624f924c41797f7ec0fd7 100644 (file)
@@ -515,8 +515,7 @@ static int _scf_op_break(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void*
 
        scf_list_add_tail(d->_3ac_list_head, &jmp->list);
 
-       scf_vector_add(d->branch_ops->_breaks, jmp);
-       return 0;
+       return scf_vector_add(d->branch_ops->_breaks, jmp);
 }
 
 static int _scf_op_continue(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* data)
@@ -1070,6 +1069,63 @@ static int _scf_op_vla_alloc(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, v
        assert(4 == nb_nodes);
 
        scf_handler_data_t* d = data;
+       scf_variable_t*     v;
+       scf_type_t*         t;
+       scf_node_t*         parent = nodes[0]->parent;
+       scf_node_t*         zero;
+
+       t = scf_block_find_type_type(ast->current_block, SCF_VAR_INT);
+       v = SCF_VAR_ALLOC_BY_TYPE(NULL, t, 1, 0, NULL);
+       if (!v)
+               return -ENOMEM;
+       v->data.u64 = 0;
+       v->const_literal_flag = 1;
+
+       zero = scf_node_alloc(NULL, v->type, v);
+       scf_variable_free(v);
+       v = NULL;
+       if (!zero)
+               return -ENOMEM;
+
+       int ret = scf_node_add_child(parent, zero);
+       if (ret < 0) {
+               scf_node_free(zero);
+               return ret;
+       }
+
+       scf_3ac_operand_t*  dst;
+       scf_3ac_code_t*     cmp;
+       scf_3ac_code_t*     jgt;
+       scf_3ac_code_t*     core;
+       scf_node_t*         srcs[] = {nodes[1], zero};
+
+       cmp = scf_3ac_code_NN(SCF_OP_3AC_CMP, NULL, 0, srcs, 2);
+       if (!cmp)
+               return -ENOMEM;
+
+       jgt = scf_3ac_jmp_code(SCF_OP_3AC_JGT, NULL, NULL);
+       if (!jgt) {
+               scf_3ac_code_free(cmp);
+               return -ENOMEM;
+       }
+
+       core = scf_3ac_code_NN(SCF_OP_3AC_DUMP, NULL, 0, nodes + 1, 3);
+       if (!core) {
+               scf_3ac_code_free(jgt);
+               scf_3ac_code_free(cmp);
+               return -ENOMEM;
+       }
+
+       scf_list_add_tail(d->_3ac_list_head, &cmp->list);
+       scf_list_add_tail(d->_3ac_list_head, &jgt->list);
+       scf_list_add_tail(d->_3ac_list_head, &core->list);
+
+       dst = jgt->dsts->data[0];
+       dst->code = core;
+
+       ret = scf_vector_add(d->branch_ops->_breaks, jgt);
+       if (ret < 0)
+               return ret;
 
        return _scf_3ac_code_N(d->_3ac_list_head, SCF_OP_VLA_ALLOC, nodes[0], nodes + 1, 3);
 }
index faf4f20b7858ff03b26fe9a950298ed8fc2e0867..49440a9965cf62cc092f17caa2d56e016d920475 100644 (file)
@@ -1,6 +1,7 @@
 #include"scf_optimizer.h"
 
 extern scf_optimizer_t   scf_optimizer_inline;
+extern scf_optimizer_t   scf_optimizer_split_call;
 
 extern scf_optimizer_t   scf_optimizer_dag;
 
@@ -30,6 +31,7 @@ extern scf_optimizer_t   scf_optimizer_generate_loads_saves;
 static scf_optimizer_t*  scf_optimizers[] =
 {
        &scf_optimizer_inline, // global optimizer
+       &scf_optimizer_split_call,
 
        &scf_optimizer_dag,
 
index 27a9caf39222681f35243e806d58679d961a3ee7..bf8ac6281f4b315253ce39787eead5dcc1797deb 100644 (file)
@@ -52,17 +52,36 @@ static void __optimize_assign(scf_dag_node_t* assign)
        }
 }
 
+static void __optimize_dn_free(scf_dag_node_t* dn)
+{
+       scf_dag_node_t* dn2;
+       int i;
+
+       for (i = 0; i < dn->childs->size; ) {
+               dn2       = dn->childs->data[i];
+
+               assert(0 == scf_vector_del(dn ->childs,  dn2));
+               assert(0 == scf_vector_del(dn2->parents, dn));
+
+               if (0 == dn2->parents->size) {
+                       scf_vector_free(dn2->parents);
+                       dn2->parents = NULL;
+               }
+       }
+
+       scf_list_del(&dn->list);
+       scf_dag_node_free(dn);
+       dn = NULL;
+}
+
 static int _bb_dag_update(scf_basic_block_t* bb)
 {
        scf_dag_node_t* dn;
        scf_dag_node_t* dn_bb;
-       scf_dag_node_t* dn_bb2;
        scf_dag_node_t* dn_func;
-       scf_dag_node_t* parent;
+       scf_dag_node_t* base;
        scf_list_t*     l;
 
-       int i;
-
        while (1) {
                int updated = 0;
 
@@ -107,7 +126,6 @@ static int _bb_dag_update(scf_basic_block_t* bb)
                                if (SCF_OP_ADDRESS_OF == dn->type || SCF_OP_DEREFERENCE == dn->type) {
 
                                        dn_func = dn->old;
-
                                } else {
                                        assert(dn_bb->parents && dn_bb->parents->size > 0);
 
@@ -134,23 +152,7 @@ static int _bb_dag_update(scf_basic_block_t* bb)
                                        continue;
                                }
 
-                               for (i = 0; i < dn->childs->size; ) {
-                                       dn_bb     = dn->childs->data[i];
-
-                                       assert(0 == scf_vector_del(dn->childs,     dn_bb));
-                                       assert(0 == scf_vector_del(dn_bb->parents, dn));
-
-                                       if (0 == dn_bb->parents->size) {
-                                               scf_vector_free(dn_bb->parents);
-                                               dn_bb->parents = NULL;
-                                       }
-                               }
-
-                               assert(0 == dn->childs->size);
-                               scf_list_del(&dn->list);
-                               scf_dag_node_free(dn);
-                               dn = NULL;
-
+                               __optimize_dn_free(dn);
                                ++updated;
 
                        } else if (SCF_OP_ADD == dn->type || SCF_OP_SUB == dn->type
@@ -170,21 +172,7 @@ static int _bb_dag_update(scf_basic_block_t* bb)
                                 || scf_vector_find(bb->dn_resaves, dn_func))
                                        continue;
 
-                               for (i = 0; i < dn->childs->size; i++) {
-                                       dn_bb     = dn->childs->data[i];
-
-                                       assert(0 == scf_vector_del(dn_bb->parents, dn));
-
-                                       if (0 == dn_bb->parents->size) {
-                                               scf_vector_free(dn_bb->parents);
-                                               dn_bb->parents = NULL;
-                                       }
-                               }
-
-                               scf_list_del(&dn->list);
-                               scf_dag_node_free(dn);
-                               dn = NULL;
-
+                               __optimize_dn_free(dn);
                                ++updated;
                        }
                }
@@ -271,6 +259,7 @@ static int _optimize_basic_block(scf_ast_t* ast, scf_function_t* f, scf_vector_t
                if (bb->jmp_flag
                                || bb->end_flag
                                || bb->call_flag
+                               || bb->dump_flag
                                || bb->varg_flag) {
                        scf_logd("bb: %p, jmp:%d,ret:%d, end: %d, call:%d, varg:%d, dereference_flag: %d\n",
                                        bb, bb->jmp_flag, bb->ret_flag, bb->end_flag, bb->call_flag, bb->dereference_flag,
index ea870531d826598a4b4e337c85eac4c11d16873b..6c493abecf240ca6f3f719de31a58b2add4cdb5e 100644 (file)
@@ -102,42 +102,13 @@ static int _alias_call(scf_vector_t* aliases, scf_3ac_code_t* c, scf_basic_block
        return 0;
 }
 
-static void _bb_update_dn_status(scf_vector_t* aliases, scf_list_t* start, scf_basic_block_t* bb)
-{
-       scf_list_t*      l;
-       scf_3ac_code_t*  c;
-       scf_dn_status_t* status;
-
-       for (l = start; l != scf_list_sentinel(&bb->code_list_head); l = scf_list_next(l)) {
-
-               c  = scf_list_data(l, scf_3ac_code_t, list);
-
-               if (!c->active_vars)
-                       continue;
-
-               int i;
-               for (i = 0; i < c->active_vars->size; ) {
-                       status    = c->active_vars->data[i];
-
-                       if (scf_vector_find_cmp(aliases, status->dag_node, scf_dn_status_cmp))
-                               assert(0 == scf_vector_del(c->active_vars, status));
-                       else
-                               ++i;
-               }
-       }
-}
-
 static int __optimize_call_bb(scf_3ac_code_t* c, scf_basic_block_t* bb, scf_list_t* bb_list_head)
 {
-       scf_list_t*   l;
-       scf_vector_t* aliases;
-       int ret;
-
-       aliases = scf_vector_alloc();
+       scf_vector_t* aliases = scf_vector_alloc();
        if (!aliases)
                return -ENOMEM;
 
-       ret = _alias_call(aliases, c, bb, bb_list_head);
+       int ret = _alias_call(aliases, c, bb, bb_list_head);
        if (ret < 0) {
                scf_loge("\n");
                scf_vector_free(aliases);
@@ -150,10 +121,6 @@ static int __optimize_call_bb(scf_3ac_code_t* c, scf_basic_block_t* bb, scf_list
                        scf_vector_free(aliases);
                        return ret;
                }
-
-               l = scf_list_head(&bb->code_list_head);
-               l = scf_list_next(l);
-               _bb_update_dn_status(aliases, l, bb);
        }
 
        scf_vector_free(aliases);
@@ -161,69 +128,18 @@ static int __optimize_call_bb(scf_3ac_code_t* c, scf_basic_block_t* bb, scf_list
        return 0;
 }
 
-#define SCF_BB_SPLIT_MOV_CODE(start, bb0, bb1) \
-                       do { \
-                               bb1 = NULL; \
-                               ret = scf_basic_block_split(bb0, &bb1); \
-                               if (ret < 0) \
-                                       return ret; \
-                               bb1->dereference_flag = bb0->dereference_flag; \
-                               bb1->ret_flag         = bb0->ret_flag; \
-                               bb0->ret_flag         = 0; \
-                               scf_list_add_front(&bb0->list, &bb1->list); \
-                               scf_basic_block_mov_code(bb1, start, bb0); \
-                       } while (0)
-
 static int _optimize_call_bb(scf_basic_block_t* bb, scf_list_t* bb_list_head)
 {
-       scf_list_t*   l;
-       scf_list_t*   start;
-       scf_list_t*   sentinel;
-
-       int ret;
-
-       while (1) {
-               scf_3ac_code_t*    c;
-               scf_basic_block_t* bb_child;
-
-               start    = scf_list_head(&bb->code_list_head);
-               sentinel = scf_list_sentinel(&bb->code_list_head);
-
-               for (l = start; l != sentinel; l = scf_list_next(l)) {
-                       c  = scf_list_data(l, scf_3ac_code_t, list);
-
-                       if (SCF_OP_CALL == c->op->type)
-                               break;
-               }
-               if (l == sentinel)
-                       break;
-
-               if (l != start) {
-                       bb->call_flag = 0;
-                       SCF_BB_SPLIT_MOV_CODE(l, bb, bb_child);
-                       bb = bb_child;
-               }
-               bb->call_flag = 1;
-
-               ret = __optimize_call_bb(c, bb, bb_list_head);
-               if (ret < 0) {
-                       scf_loge("\n");
-                       return ret;
-               }
+       scf_3ac_code_t*  c;
+       scf_list_t*      l;
 
-               l = scf_list_head(&bb->code_list_head);
-               l = scf_list_next(l);
-               if (l == scf_list_sentinel(&bb->code_list_head))
-                       break;
+       l = scf_list_head(&bb->code_list_head);
+       c = scf_list_data(l, scf_3ac_code_t, list);
 
-               SCF_BB_SPLIT_MOV_CODE(l, bb, bb_child);
-               bb = bb_child;
+       assert(SCF_OP_CALL == c->op->type);
+       assert(scf_list_next(l) == scf_list_sentinel(&bb->code_list_head));
 
-               ret = scf_basic_block_inited_vars(bb, bb_list_head);
-               if (ret < 0)
-                       return ret;
-       }
-       return 0;
+       return __optimize_call_bb(c, bb, bb_list_head);
 }
 
 static int _optimize_call(scf_ast_t* ast, scf_function_t* f, scf_vector_t* functions)
@@ -254,6 +170,7 @@ static int _optimize_call(scf_ast_t* ast, scf_function_t* f, scf_vector_t* funct
                        return ret;
        }
 
+//     scf_basic_block_print_list(bb_list_head);
        return 0;
 }
 
index f8bb2c41a1ce19382b00937a5d16344d886c5378..ef924cc8cefcc5f09842db47ecd29072670dce70 100644 (file)
@@ -105,6 +105,7 @@ static int _optimize_common_expr(scf_ast_t* ast, scf_function_t* f, scf_vector_t
                if (bb->jmp_flag
                                || bb->end_flag
                                || bb->call_flag
+                               || bb->dump_flag
                                || bb->varg_flag) {
                        scf_logd("bb: %p, jmp:%d,ret:%d, end: %d, call:%d, varg:%d, dereference_flag: %d\n",
                                        bb, bb->jmp_flag, bb->ret_flag, bb->end_flag, bb->call_flag, bb->dereference_flag,
@@ -123,7 +124,6 @@ static int _optimize_common_expr(scf_ast_t* ast, scf_function_t* f, scf_vector_t
                        return ret;
        }
 
-//     scf_basic_block_print_list(bb_list_head);
        return 0;
 }
 
index eb0606525a0ca5f572d5006fee473025991d74cb..5a433ea70a5b204ca16c4865595b1e7b7373d34b 100644 (file)
@@ -375,7 +375,7 @@ static int _optimize_inline2(scf_ast_t* ast, scf_function_t* f)
                if (!bb->call_flag)
                        continue;
 
-               int call_flag = 0;
+               int n_calls = 0;
 
                bb_cur = bb;
 
@@ -393,7 +393,7 @@ static int _optimize_inline2(scf_ast_t* ast, scf_function_t* f)
                        if (SCF_OP_CALL != c->op->type)
                                continue;
 
-                       call_flag = 1;
+                       n_calls++;
 
                        src = c->srcs->data[0];
                        v   = _scf_operand_get(src->node);
@@ -418,6 +418,8 @@ static int _optimize_inline2(scf_ast_t* ast, scf_function_t* f)
                        bb2 = bb_cur;
                        bb_cur->call_flag = 0;
 
+                       n_calls--;
+
                        int ret = _do_inline(ast, c, &bb_cur, f, f2);
                        if (ret < 0)
                                return ret;
@@ -426,8 +428,7 @@ static int _optimize_inline2(scf_ast_t* ast, scf_function_t* f)
                        scf_3ac_code_free(c);
                        c = NULL;
 
-                       bb2->call_flag |= call_flag;
-                       call_flag       = 0;
+                       bb2->call_flag |= n_calls > 0;
 
                        if (bb2->ret_flag) {
                                bb2->ret_flag    = 0;
@@ -436,8 +437,7 @@ static int _optimize_inline2(scf_ast_t* ast, scf_function_t* f)
 #endif
                }
 
-               bb_cur->call_flag |= call_flag;
-               call_flag = 0;
+               bb_cur->call_flag |= n_calls > 0;
        }
 
 #if 0
diff --git a/core/scf_optimizer_split_call.c b/core/scf_optimizer_split_call.c
new file mode 100644 (file)
index 0000000..0fc10ca
--- /dev/null
@@ -0,0 +1,105 @@
+#include"scf_optimizer.h"
+#include"scf_pointer_alias.h"
+
+#define SCF_BB_SPLIT(bb0, bb1) \
+       do { \
+               bb1 = NULL; \
+               int ret = scf_basic_block_split(bb0, &bb1); \
+               if (ret < 0) \
+                   return ret; \
+               bb1->dereference_flag = bb0->dereference_flag; \
+               bb1->ret_flag         = bb0->ret_flag; \
+               bb0->ret_flag         = 0; \
+               scf_list_add_front(&bb0->list, &bb1->list); \
+       } while (0)
+
+static int _optimize_split_call_bb(scf_basic_block_t* bb, scf_list_t* bb_list_head)
+{
+       scf_basic_block_t* cur_bb = bb;
+       scf_basic_block_t* bb2;
+       scf_3ac_code_t*    c;
+       scf_list_t*        l;
+
+       int split_flag = 0;
+
+       for (l = scf_list_head(&bb->code_list_head); l != scf_list_sentinel(&bb->code_list_head); ) {
+
+               c  = scf_list_data(l, scf_3ac_code_t, list);
+               l  = scf_list_next(l);
+
+               if (split_flag) {
+                       split_flag = 0;
+
+                       SCF_BB_SPLIT(cur_bb, bb2);
+                       cur_bb = bb2;
+               }
+
+               if (cur_bb != bb) {
+                       scf_list_del(&c->list);
+                       scf_list_add_tail(&cur_bb->code_list_head, &c->list);
+
+                       c->basic_block = cur_bb;
+               }
+
+               if (SCF_OP_CALL == c->op->type) {
+                       split_flag = 1;
+
+                       if (scf_list_prev(&c->list) != scf_list_sentinel(&cur_bb->code_list_head)) {
+                               SCF_BB_SPLIT(cur_bb, bb2);
+
+                               cur_bb->call_flag = 0;
+
+                               scf_list_del(&c->list);
+                               scf_list_add_tail(&bb2->code_list_head, &c->list);
+
+                               c->basic_block = bb2;
+
+                               cur_bb = bb2;
+                       }
+
+                       cur_bb->call_flag = 1;
+               }
+       }
+
+       return 0;
+}
+
+static int _optimize_split_call(scf_ast_t* ast, scf_function_t* f, scf_vector_t* functions)
+{
+       if (!f)
+               return -EINVAL;
+
+       scf_list_t*        bb_list_head = &f->basic_block_list_head;
+       scf_list_t*        l;
+       scf_basic_block_t* bb;
+
+       if (scf_list_empty(bb_list_head))
+               return 0;
+
+       for (l = scf_list_head(bb_list_head); l != scf_list_sentinel(bb_list_head); ) {
+
+               bb = scf_list_data(l, scf_basic_block_t, list);
+               l  = scf_list_next(l);
+
+               if (bb->jmp_flag || bb->end_flag || bb->cmp_flag)
+                       continue;
+
+               if (!bb->call_flag)
+                       continue;
+
+               int ret = _optimize_split_call_bb(bb, bb_list_head);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
+scf_optimizer_t  scf_optimizer_split_call =
+{
+       .name     =  "split_call",
+
+       .optimize =  _optimize_split_call,
+
+       .flags    = SCF_OPTIMIZER_LOCAL,
+};
diff --git a/examples/array_pointer_opt2.c b/examples/array_pointer_opt2.c
new file mode 100644 (file)
index 0000000..6b9ff3c
--- /dev/null
@@ -0,0 +1,25 @@
+int printf(const char* fmt, ...);
+
+int f()
+{
+       int a[2];
+
+       int* p = a;
+
+       a[0] = 1;
+       a[1] = 2;
+
+       *p += 3;
+       int b = *p;
+       return b;
+}
+
+int main()
+{
+       int i = 1;
+       int a = 2;
+       int b = 3;
+
+       printf("%d\n", f());
+       return 0;
+}
diff --git a/examples/inline.c b/examples/inline.c
new file mode 100644 (file)
index 0000000..83d7da4
--- /dev/null
@@ -0,0 +1,17 @@
+//第 7 ç« /inline.c
+
+int printf(const char* fmt, ...);
+
+inline int add(int i, int j)
+{
+       return i + j;
+}
+
+int main()
+{
+       int a = 1;
+       int b = 2;
+       int c = add(a, b);
+       printf("%d\n", c);
+       return 0;
+}
similarity index 100%
rename from examples/declare_vars.c
rename to examples/setcc.c
index 335b19b9fface1882473ee0695c39e0a149a0e27..d9a0ff0c2bca730ec1c1247e7dde0545e9dffd6c 100644 (file)
@@ -1,4 +1,3 @@
-
 #include "../lib/scf_capi.c"
 
 struct str
@@ -9,7 +8,7 @@ struct str
 
        int __init(str* this)
        {
-               this->len      = 0;
+               this->len = 0;
                this->capacity = 16;
 
                this->data = scf__auto_malloc(16);
@@ -27,15 +26,14 @@ struct str
        }
 };
 
-
 int main()
 {
        str* p0;
        str* p1;
-       int  i;
 
        p0 = create str();
+       p1 = p0;
 
-       printf("%s\n", p0->data);
+       printf("%s\n", p1->data);
        return 0;
 }
diff --git a/examples/vla_2.c b/examples/vla_2.c
new file mode 100644 (file)
index 0000000..d93f8f1
--- /dev/null
@@ -0,0 +1,20 @@
+int printf(const char* fmt, ...);
+
+int main(int argc, char* argv[])
+{
+       int i;
+       int j;
+
+       for (i = 1; i < 4; i++) {
+               char a[i];
+
+               for (j = 0; j < i; j++) {
+
+                       a[j] = '1';
+
+                       printf("i: %d, j: %d, a: %c, %lg\n", i, j, a[j], 3.14);
+               }
+       }
+
+       return 0;
+}
index 902ff7897c9b6a8cce015a9cd8a6bc5d6f73c275..0ef68f52f5cf28abde6654895f42f1e7c0afffa3 100644 (file)
Binary files a/lib/x64/scf_object.o and b/lib/x64/scf_object.o differ
index 1278ca67e1caefe2e8bb4b2e11fda67afdb6e028..3d7aa7ee78239c4cff76fa724c6615b5bdcab9b2 100644 (file)
@@ -217,11 +217,8 @@ static int _x64_function_finish(scf_function_t* f)
        l   = scf_list_tail(&bb->code_list_head);
        end = scf_list_data(l, scf_3ac_code_t, list);
 
-       int err = x64_pop_callee_regs(end, f);
-       if (err < 0)
-               return err;
+       if (f->bp_used_flag || f->vla_flag) {
 
-       if (f->bp_used_flag) {
                inst = x64_make_inst_G2E(mov, rsp, rbp);
                X64_INST_ADD_CHECK(end->instructions, inst);
                end->inst_bytes += inst->len;
@@ -231,17 +228,30 @@ static int _x64_function_finish(scf_function_t* f)
                X64_INST_ADD_CHECK(end->instructions, inst);
                end->inst_bytes += inst->len;
                bb ->code_bytes += inst->len;
+       }
+
+       int err = x64_pop_callee_regs(end, f);
+       if (err < 0)
+               return err;
+
+       f->init_code_bytes = 0;
+
+       err = x64_push_callee_regs(f->init_code, f);
+       if (err < 0)
+               return err;
+
+       uint32_t local = f->bp_used_flag ? f->local_vars_size : 0;
+
+       if (f->bp_used_flag || f->vla_flag) {
 
                inst = x64_make_inst_G(push, rbp);
                X64_INST_ADD_CHECK(f->init_code->instructions, inst);
-               f->init_code_bytes  = inst->len;
+               f->init_code_bytes += inst->len;
 
                inst = x64_make_inst_G2E(mov, rbp, rsp);
                X64_INST_ADD_CHECK(f->init_code->instructions, inst);
                f->init_code_bytes += inst->len;
 
-               uint32_t local = f->local_vars_size;
-
                if (f->callee_saved_size & 0xf) {
                        if (!(local & 0xf))
                                local += 8;
@@ -260,34 +270,8 @@ static int _x64_function_finish(scf_function_t* f)
                int err = _x64_save_rabi(f);
                if (err < 0)
                        return err;
-       } else {
-               if (f->vla_flag) {
-                       inst = x64_make_inst_G2E(mov, rsp, rbp);
-                       X64_INST_ADD_CHECK(end->instructions, inst);
-                       end->inst_bytes += inst->len;
-                       bb ->code_bytes += inst->len;
-               }
-
-               inst = x64_make_inst_G(pop, rbp);
-               X64_INST_ADD_CHECK(end->instructions, inst);
-               end->inst_bytes += inst->len;
-               bb ->code_bytes += inst->len;
-
-               inst = x64_make_inst_G(push, rbp);
-               X64_INST_ADD_CHECK(f->init_code->instructions, inst);
-               f->init_code_bytes  = inst->len;
-
-               if (f->vla_flag) {
-                       inst = x64_make_inst_G2E(mov, rbp, rsp);
-                       X64_INST_ADD_CHECK(f->init_code->instructions, inst);
-                       f->init_code_bytes += inst->len;
-               }
        }
 
-       err = x64_push_callee_regs(f->init_code, f);
-       if (err < 0)
-               return err;
-
        inst = x64_make_inst(ret, 8);
        X64_INST_ADD_CHECK(end->instructions, inst);
        end->inst_bytes += inst->len;
@@ -1113,7 +1097,6 @@ int       _scf_x64_select_inst(scf_native_t* ctx)
        _x64_set_offsets(f);
 
        _x64_set_offset_for_jmps( ctx, f);
-
        return 0;
 }
 
index 3283407bdda0e9f0ac9803ce9bf9a82615d85c19..726f7601cb595396bef13857182dce4cb0f91d6c 100644 (file)
@@ -1438,28 +1438,17 @@ static int _x64_inst_mod_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c)
        return _div_mod_assign(ctx, c, 1);
 }
 
-static int _x64_inst_vla_alloc_handler(scf_native_t* ctx, scf_3ac_code_t* c)
+static int _x64_inst_dump_handler(scf_native_t* ctx, scf_3ac_code_t* c)
 {
-       if (!c->dsts || c->dsts->size != 1)
-               return -EINVAL;
-
        if (!c->srcs || c->srcs->size != 3)
                return -EINVAL;
 
        scf_x64_context_t* x64  = ctx->priv;
        scf_function_t*    f    = x64->f;
-
-       scf_3ac_operand_t* dst  = c->dsts->data[0];
        scf_3ac_operand_t* src  = c->srcs->data[0];
        scf_3ac_operand_t* logf = c->srcs->data[1];
        scf_3ac_operand_t* msg  = c->srcs->data[2];
 
-       if (!dst || !dst->dag_node)
-               return -EINVAL;
-
-       if (!src || !src->dag_node)
-               return -EINVAL;
-
        if (!logf || !logf->dag_node)
                return -EINVAL;
 
@@ -1467,23 +1456,16 @@ static int _x64_inst_vla_alloc_handler(scf_native_t* ctx, scf_3ac_code_t* c)
                return -EINVAL;
 
        scf_instruction_t*  inst = NULL;
-       scf_instruction_t*  jcc  = NULL;
        scf_register_t*     rs   = NULL;
        scf_register_t*     rd   = NULL;
-       scf_register_t*     rsp  = x64_find_register("rsp");
        scf_register_t*     rdi  = x64_find_register("rdi");
        scf_register_t*     rsi  = x64_find_register("rsi");
        scf_register_t*     rax  = x64_find_register("rax");
 
-       scf_x64_OpCode_t*   cmp  = x64_find_OpCode(SCF_X64_CMP, 1, 4, SCF_X64_I2E);
-       scf_x64_OpCode_t*   jg   = x64_find_OpCode(SCF_X64_JG , 1, 1, SCF_X64_I);
        scf_x64_OpCode_t*   lea  = x64_find_OpCode(SCF_X64_LEA, 8, 8, SCF_X64_E2G);
        scf_x64_OpCode_t*   call = x64_find_OpCode(SCF_X64_CALL,4, 4, SCF_X64_I);
-       scf_x64_OpCode_t*   sub  = x64_find_OpCode(SCF_X64_SUB, 8, 8, SCF_X64_E2G);
-       scf_x64_OpCode_t*   add  = x64_find_OpCode(SCF_X64_ADD, 4, 8, SCF_X64_I2E);
-       scf_x64_OpCode_t*   and  = x64_find_OpCode(SCF_X64_AND, 4, 8, SCF_X64_I2E);
-       scf_x64_OpCode_t*   mov  = x64_find_OpCode(SCF_X64_MOV, 8, 8, SCF_X64_G2E);
        scf_x64_OpCode_t*   xor  = x64_find_OpCode(SCF_X64_XOR, 8, 8, SCF_X64_G2E);
+       scf_x64_OpCode_t*   mov  = x64_find_OpCode(SCF_X64_MOV, 8, 8, SCF_X64_G2E);
 
        if (!c->instructions) {
                c->instructions = scf_vector_alloc();
@@ -1492,22 +1474,11 @@ static int _x64_inst_vla_alloc_handler(scf_native_t* ctx, scf_3ac_code_t* c)
        }
 
        X64_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1);
-       X64_SELECT_REG_CHECK(&rd, dst->dag_node, c, f, 0);
 
-       // if src > 0
-       uint32_t imm = 0;
-       inst = x64_make_inst_I2E(cmp, rs, (uint8_t*)&imm, 1);
+       inst = x64_make_inst_G2E(mov, rsi, rs);
        X64_INST_ADD_CHECK(c->instructions, inst);
 
-       jcc = x64_make_inst_I(jg, (uint8_t*)&imm, 1);
-       X64_INST_ADD_CHECK(c->instructions, jcc);
-
-       // process error when src <= 0
        scf_rela_t* rela = NULL;
-       int i = c->instructions->size;
-
-       inst = x64_make_inst_G2E(mov, rsi, rs);
-       X64_INST_ADD_CHECK(c->instructions, inst);
 
        inst = x64_make_inst_M2G(&rela, lea, rdi, NULL, msg->dag_node->var);
        X64_INST_ADD_CHECK(c->instructions, inst);
@@ -1517,6 +1488,7 @@ static int _x64_inst_vla_alloc_handler(scf_native_t* ctx, scf_3ac_code_t* c)
        X64_INST_ADD_CHECK(c->instructions, inst);
 
        // call printf() to show msg
+       uint32_t imm = 0;
        inst = x64_make_inst_I(call, (uint8_t*)&imm, sizeof(imm));
        X64_INST_ADD_CHECK(c->instructions, inst);
 
@@ -1531,14 +1503,47 @@ static int _x64_inst_vla_alloc_handler(scf_native_t* ctx, scf_3ac_code_t* c)
 
        inst = x64_make_inst_G2P(mov, rax, 0, rax);
        X64_INST_ADD_CHECK(c->instructions, inst);
+       return 0;
+}
+
+static int _x64_inst_vla_alloc_handler(scf_native_t* ctx, scf_3ac_code_t* c)
+{
+       if (!c->dsts || c->dsts->size != 1)
+               return -EINVAL;
+
+       if (!c->srcs || c->srcs->size != 3)
+               return -EINVAL;
 
-       for ( ; i < c->instructions->size; i++) {
-               inst  = c->instructions->data[i];
-               jcc->code[1] += inst->len;
+       scf_x64_context_t* x64  = ctx->priv;
+       scf_function_t*    f    = x64->f;
+       scf_3ac_operand_t* dst  = c->dsts->data[0];
+       scf_3ac_operand_t* src  = c->srcs->data[0];
+
+       if (!dst || !dst->dag_node)
+               return -EINVAL;
+
+       if (!src || !src->dag_node)
+               return -EINVAL;
+
+       scf_instruction_t*  inst = NULL;
+       scf_register_t*     rs   = NULL;
+       scf_register_t*     rd   = NULL;
+       scf_register_t*     rsp  = x64_find_register("rsp");
+
+       scf_x64_OpCode_t*   add  = x64_find_OpCode(SCF_X64_ADD, 4, 8, SCF_X64_I2E);
+       scf_x64_OpCode_t*   and  = x64_find_OpCode(SCF_X64_AND, 4, 8, SCF_X64_I2E);
+       scf_x64_OpCode_t*   sub  = x64_find_OpCode(SCF_X64_SUB, 8, 8, SCF_X64_E2G);
+       scf_x64_OpCode_t*   mov  = x64_find_OpCode(SCF_X64_MOV, 8, 8, SCF_X64_G2E);
+
+       if (!c->instructions) {
+               c->instructions = scf_vector_alloc();
+               if (!c->instructions)
+                       return -ENOMEM;
        }
 
-       // alloc VLA
-       imm  = 0xf;
+       X64_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1);
+
+       uint32_t imm  = 0xf;
        inst = x64_make_inst_I2E(add, rs, (uint8_t*)&imm, sizeof(imm));
        X64_INST_ADD_CHECK(c->instructions, inst);
 
@@ -1549,10 +1554,15 @@ static int _x64_inst_vla_alloc_handler(scf_native_t* ctx, scf_3ac_code_t* c)
        inst = x64_make_inst_E2G(sub, rsp, rs);
        X64_INST_ADD_CHECK(c->instructions, inst);
 
+       int ret = x64_save_var(src->dag_node, c, f);
+       if (ret < 0)
+               return ret;
+
+       X64_SELECT_REG_CHECK(&rd, dst->dag_node, c, f, 0);
+
        inst = x64_make_inst_G2E(mov, rd, rsp);
        X64_INST_ADD_CHECK(c->instructions, inst);
-
-       return x64_save_var(src->dag_node, c, f);
+       return 0;
 }
 
 static int _x64_inst_vla_free_handler(scf_native_t* ctx, scf_3ac_code_t* c)
@@ -2432,6 +2442,8 @@ static x64_inst_handler_pt  x64_inst_handlers[] =
        [SCF_OP_RETURN      ]  =  _x64_inst_return_handler,
        [SCF_OP_GOTO        ]  =  _x64_inst_goto_handler,
 
+       [SCF_OP_3AC_DUMP    ]  =  _x64_inst_dump_handler,
+
        [SCF_OP_3AC_JZ      ]  =  _x64_inst_jz_handler,
        [SCF_OP_3AC_JNZ     ]  =  _x64_inst_jnz_handler,
        [SCF_OP_3AC_JGT     ]  =  _x64_inst_jgt_handler,
index ad7f0981e8cd5cacfb9901cbc2ffcfa4e89588ed..ad09f1a6b06a4c28187180d01b067892b751dd30 100644 (file)
@@ -114,10 +114,10 @@ int x64_inst_teq(scf_native_t* ctx, scf_3ac_code_t* c)
        if (!c->srcs || c->srcs->size != 1)
                return -EINVAL;
 
-       scf_x64_context_t*  x64  = ctx->priv;
-       scf_function_t*     f    = x64->f;
-       scf_3ac_operand_t*  src  = c->srcs->data[0];
-       scf_variable_t*     var  = src->dag_node->var;
+       scf_x64_context_t*  x64 = ctx->priv;
+       scf_function_t*     f   = x64->f;
+       scf_3ac_operand_t*  src = c->srcs->data[0];
+       scf_variable_t*     v   = src->dag_node->var;
 
        scf_x64_OpCode_t*   test;
        scf_instruction_t*  inst;
@@ -126,34 +126,22 @@ int x64_inst_teq(scf_native_t* ctx, scf_3ac_code_t* c)
        if (!src || !src->dag_node)
                return -EINVAL;
 
-       if (!c->instructions) {
-               c->instructions = scf_vector_alloc();
-               if (!c->instructions)
-                       return -ENOMEM;
-       }
-
        if (0 == src->dag_node->color) {
                scf_loge("src->dag_node->var: %p\n", src->dag_node->var);
                return -1;
        }
 
-       if (src->dag_node->color > 0) {
-               X64_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 0);
-               test = x64_find_OpCode(SCF_X64_TEST, var->size, var->size, SCF_X64_G2E);
-               inst = x64_make_inst_G2E(test, rs, rs);
-               X64_INST_ADD_CHECK(c->instructions, inst);
-
-       } else {
-               scf_rela_t* rela = NULL;
-               int         size = var->size > 4 ? 4 : var->size;
-               uint32_t    imm  = 0xffffffff;
-
-               test = x64_find_OpCode(SCF_X64_TEST, size, var->size, SCF_X64_I2E);
-               inst = x64_make_inst_I2M(&rela, test, var, NULL, (uint8_t*)&imm, size);
-               X64_INST_ADD_CHECK(c->instructions, inst);
-               X64_RELA_ADD_CHECK(f->data_relas, rela, c, var, NULL);
+       if (!c->instructions) {
+               c->instructions = scf_vector_alloc();
+               if (!c->instructions)
+                       return -ENOMEM;
        }
 
+       X64_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1);
+
+       test = x64_find_OpCode(SCF_X64_TEST, v->size, v->size, SCF_X64_G2E);
+       inst = x64_make_inst_G2E(test, rs, rs);
+       X64_INST_ADD_CHECK(c->instructions, inst);
        return 0;
 }
 
index 1c4353cd54ccfa8495fcc9c23e10392dc6acae98..c454bac9b90af2c434a26f1cbe1951958f09fc3f 100644 (file)
@@ -3,7 +3,7 @@
 #include"scf_basic_block.h"
 #include"scf_3ac.h"
 
-static int _x64_peephole_common(scf_vector_t* std_insts, scf_instruction_t* inst)
+static int _x64_peephole_mov(scf_vector_t* std_insts, scf_instruction_t* inst)
 {
        scf_3ac_code_t*    c  = inst->c;
        scf_basic_block_t* bb = c->basic_block;
@@ -24,6 +24,37 @@ static int _x64_peephole_common(scf_vector_t* std_insts, scf_instruction_t* inst
                scf_instruction_print(inst);
                printf("\n");
 #endif
+               if (SCF_X64_LEA == std->OpCode->type) {
+
+                       if (scf_inst_data_same(&std->dst, &inst->src)
+                                       && x64_inst_data_is_reg(&inst->dst)) {
+
+                               if (std->src.index)
+                                       inst2 = x64_make_inst_SIB2G((scf_x64_OpCode_t*)std->OpCode,
+                                                       inst->dst.base,
+                                                       std->src.base, std->src.index, std->src.scale, std->src.disp);
+                               else
+                                       inst2 = x64_make_inst_P2G((scf_x64_OpCode_t*)std->OpCode, inst->dst.base, std->src.base, std->src.disp);
+
+                               if (!inst2)
+                                       return -ENOMEM;
+
+                               memcpy(inst->code, inst2->code, inst2->len);
+                               inst->len = inst2->len;
+
+                               inst->OpCode    = std->OpCode;
+                               inst->src.base  = std->src.base;
+                               inst->src.index = std->src.index;
+                               inst->src.scale = std->src.scale;
+                               inst->src.disp  = std->src.disp;
+                               inst->src.flag  = std->src.flag;
+
+                               free(inst2);
+                               inst2 = NULL;
+                       }
+                       break;
+               }
+
                if (scf_inst_data_same(&std->dst, &inst->dst)) {
 
                        if (scf_inst_data_same(&std->src, &inst->src)) {
@@ -45,10 +76,30 @@ static int _x64_peephole_common(scf_vector_t* std_insts, scf_instruction_t* inst
                        free(std);
                        std = NULL;
                        continue;
+
                } else if (scf_inst_data_same(&std->src, &inst->src)) {
+
+                       if (std->src.flag && std->dst.base->bytes == inst->dst.base->bytes) {
+
+                               inst2 = x64_make_inst_E2G((scf_x64_OpCode_t*)inst->OpCode, inst->dst.base, std->dst.base);
+                               if (!inst2)
+                                       return -ENOMEM;
+
+                               memcpy(inst->code, inst2->code, inst2->len);
+                               inst->len = inst2->len;
+
+                               inst->src.base  = std->dst.base;
+                               inst->src.index = NULL;
+                               inst->src.scale = 0;
+                               inst->src.disp  = 0;
+                               inst->src.flag  = 0;
+
+                               free(inst2);
+                               inst2 = NULL;
+                       }
                        continue;
-               } else if (scf_inst_data_same(&std->dst, &inst->src)) {
 
+               } else if (scf_inst_data_same(&std->dst, &inst->src)) {
                        std->nb_used++;
 
                        if (scf_inst_data_same(&std->src, &inst->dst)) {
@@ -162,6 +213,9 @@ static int _x64_peephole_cmp(scf_vector_t* std_insts, scf_instruction_t* inst)
        for (j  = std_insts->size - 1; j >= 0; j--) {
                std = std_insts->data[j];
 
+               if (SCF_X64_LEA == std->OpCode->type)
+                       break;
+
                if (inst->src.flag) {
 
                        if (scf_inst_data_same(&inst->src, &std->src))
@@ -230,141 +284,216 @@ check:
                }
 
                if (scf_inst_data_same(&inst->src, &std->dst)
-                || scf_inst_data_same(&inst->dst, &std->dst)) {
-
-                       assert(0 == scf_vector_del(std_insts, std));
-               }
+                || scf_inst_data_same(&inst->dst, &std->dst))
+                       std->nb_used++;
        }
 
        return 0;
 }
 
-static void _x64_peephole_function(scf_vector_t* tmp_insts, scf_function_t* f, int jmp_back_flag)
+static int _x64_peephole_movx(scf_vector_t* std_insts, scf_instruction_t* inst)
 {
-       scf_register_t* rax = x64_find_register("rax");
-       scf_register_t* rsp = x64_find_register("rsp");
-       scf_register_t* rbp = x64_find_register("rbp");
+       if (!x64_inst_data_is_reg(&inst->src) || !x64_inst_data_is_reg(&inst->dst)) {
+               scf_vector_clear(std_insts, NULL);
+               return 0;
+       }
+
+       scf_3ac_code_t*    c  = inst->c;
+       scf_basic_block_t* bb = c->basic_block;
+       scf_instruction_t* std;
+       scf_x64_OpCode_t*  OpCode;
+       int j;
 
-       scf_register_t* rdi = x64_find_register("rdi");
-       scf_register_t* rsi = x64_find_register("rsi");
-       scf_register_t* rdx = x64_find_register("rdx");
-       scf_register_t* rcx = x64_find_register("rcx");
-       scf_register_t* r8  = x64_find_register("r8");
-       scf_register_t* r9  = x64_find_register("r9");
+       for (j  = std_insts->size - 1; j >= 0; j--) {
+               std = std_insts->data[j];
 
-       scf_instruction_t*  inst;
-       scf_instruction_t*  inst2;
-       scf_basic_block_t*  bb;
-       scf_3ac_code_t*     c;
-       scf_list_t*         l;
+               if (scf_inst_data_same(&std->dst, &inst->src)) {
+                       std->nb_used++;
 
-       int i;
-       int j;
-       int k;
+                       if (std->OpCode == inst->OpCode
+                                       && scf_inst_data_same(&std->src, &inst->src)
+                                       && scf_inst_data_same(&std->dst, &inst->dst)) {
 
-       for (i   = tmp_insts->size - 1; i >= 0; i--) {
-               inst = tmp_insts->data[i];
+                               assert(0 == scf_vector_del(inst->c->instructions, inst));
+
+                               free(inst);
+                               inst = NULL;
+                               return X64_PEEPHOLE_DEL;
+                       }
+               }
+       }
 
-               scf_register_t* r0;
-               scf_register_t* r1;
-               scf_register_t* r2;
+       assert(0 == scf_vector_add_unique(std_insts, inst));
+       return 0;
+}
 
-               if (!inst)
-                       continue;
+static int x64_inst_is_useful(scf_instruction_t* inst, scf_instruction_t* std)
+{
+       if (scf_inst_data_same(&inst->dst, &std->src))
+               return 1;
 
-               if (SCF_X64_MOV != inst->OpCode->type)
-                       continue;
+       if (x64_inst_data_is_reg(&inst->dst)) {
 
-               if (x64_inst_data_is_reg(&inst->dst)) {
+               scf_register_t* r0 = inst->dst.base;
+               scf_register_t* r1 = std->src.base;
 
-                       r0 = inst->dst.base;
+               if (SCF_X64_CALL == std->OpCode->type) {
 
-                       for (k = 0; k < X64_ABI_RET_NB; k++) {
-                               r2 = x64_find_register_type_id_bytes(0, x64_abi_ret_regs[k], 8);
+                       if (X64_COLOR_CONFLICT(r0->color,        x64_find_register("rdi")->color)
+                                       || X64_COLOR_CONFLICT(r0->color, x64_find_register("rsi")->color)
+                                       || X64_COLOR_CONFLICT(r0->color, x64_find_register("rdx")->color)
+                                       || X64_COLOR_CONFLICT(r0->color, x64_find_register("rcx")->color)
+                                       || X64_COLOR_CONFLICT(r0->color, x64_find_register("r8")->color)
+                                       || X64_COLOR_CONFLICT(r0->color, x64_find_register("r9")->color))
+                               return 1;
 
-                               if (X64_COLOR_CONFLICT(r2->color, r0->color))
-                                       break;
+               } else {
+                       if (x64_inst_data_is_reg(&std->src)) {
+                               if (X64_COLOR_CONFLICT(r0->color, r1->color))
+                                       return 1;
                        }
 
-                       if (k < X64_ABI_RET_NB)
-                               continue;
+                       if (std->src.base  == inst->dst.base
+                                       || std->src.index == inst->dst.base
+                                       || std->dst.index == inst->dst.base
+                                       || std->dst.base  == inst->dst.base)
+                               return 1;
+               }
 
-               } else if (!x64_inst_data_is_local(&inst->dst))
-                       continue;
+       } else if (x64_inst_data_is_local(&inst->dst)) {
 
-               if (jmp_back_flag)
-                       j = 0;
-               else
-                       j = i + 1;
+               if (scf_inst_data_same(&inst->dst, &std->src))
+                       return 1;
 
-               for ( ; j < tmp_insts->size; j++) {
-                       inst2 = tmp_insts->data[j];
+               if (x64_find_register("rsp") == inst->dst.base)
+                       return 1;
 
-                       if (!inst2 || inst == inst2)
-                               continue;
+               if (SCF_OP_VA_START == inst->c->op->type
+                               || SCF_OP_VA_ARG == inst->c->op->type
+                               || SCF_OP_VA_END == inst->c->op->type)
+                       return 1;
+
+               if (x64_inst_data_is_pointer(&std->dst) || x64_inst_data_is_pointer(&std->src))
+                       return 1;
 
-                       if (scf_inst_data_same(&inst->dst, &inst2->src))
+               switch (std->OpCode->type)
+               {
+                       case SCF_X64_CMP:
+                       case SCF_X64_TEST:
+                               if (scf_inst_data_same(&inst->dst, &std->dst))
+                                       return 1;
                                break;
 
-                       if (x64_inst_data_is_reg(&inst->dst)) {
+                       case SCF_X64_MOV:
+                       case SCF_X64_LEA:
+                               if (std->src.base == inst->dst.base) // maybe array member
+                                       return 1;
+                               break;
+                       default:
+                               break;
+               };
+       }
+       return 0;
+}
 
-                               r0 = inst ->dst.base;
-                               r1 = inst2->src.base;
+static int x64_inst_useful_3ac(scf_instruction_t* inst, scf_3ac_code_t* c)
+{
+       scf_instruction_t* inst2;
+       int j = 0;
 
-                               if (SCF_X64_CALL == inst2->OpCode->type) {
+       if (inst->c == c) {
+               for ( ; j < c->instructions->size; j++) {
+                       inst2 = c->instructions->data[j];
 
-                                       if (X64_COLOR_CONFLICT(r0->color, rdi->color)
-                                                       || X64_COLOR_CONFLICT(r0->color, rsi->color)
-                                                       || X64_COLOR_CONFLICT(r0->color, rdx->color)
-                                                       || X64_COLOR_CONFLICT(r0->color, rcx->color)
-                                                       || X64_COLOR_CONFLICT(r0->color, r8->color)
-                                                       || X64_COLOR_CONFLICT(r0->color, r9->color))
-                                               break;
+                       if (inst2 == inst)
+                               break;
+               }
 
-                               } else {
-                                       if (x64_inst_data_is_reg(&inst2->src)) {
-                                               if (X64_COLOR_CONFLICT(r0->color, r1->color))
-                                                       break;
-                                       }
+               assert(j < c->instructions->size);
+               ++j;
+       }
 
-                                       if (inst2->src.base  == inst->dst.base
-                                                       || inst2->src.index == inst->dst.base
-                                                       || inst2->dst.index == inst->dst.base
-                                                       || inst2->dst.base  == inst->dst.base)
-                                               break;
-                               }
+       if (c->instructions) {
+               for ( ; j < c->instructions->size; j++) {
+                       inst2 = c->instructions->data[j];
 
-                       } else if (x64_inst_data_is_local(&inst->dst)) {
+                       if (x64_inst_is_useful(inst, inst2))
+                               return 1;
+               }
+       }
+       return 0;
+}
 
-                               if (scf_inst_data_same(&inst->dst, &inst2->src))
-                                       break;
-                               else if (rsp == inst->dst.base)
-                                       break;
-                               else if (SCF_OP_VA_START == inst->c->op->type
-                                               || SCF_OP_VA_ARG == inst->c->op->type
-                                               || SCF_OP_VA_END == inst->c->op->type)
-                                       break;
+static int x64_inst_useful_bb(scf_instruction_t* inst, scf_basic_block_t* bb)
+{
+       scf_3ac_code_t* c;
+       scf_list_t*     l;
 
-                               else if (SCF_X64_CMP    == inst2->OpCode->type
-                                               || SCF_X64_TEST == inst2->OpCode->type) {
+       if (bb == inst->c->basic_block)
+               l  = &inst->c->list;
+       else
+               l = scf_list_head(&bb->code_list_head);
 
-                                       if (scf_inst_data_same(&inst->dst, &inst2->dst))
-                                               break;
+       for ( ; l != scf_list_sentinel(&bb->code_list_head); l = scf_list_next(l)) {
+               c      = scf_list_data(l, scf_3ac_code_t, list);
 
-                               } else if (SCF_X64_LEA  == inst2->OpCode->type
-                                               || SCF_X64_MOV  == inst2->OpCode->type) {
+               if (x64_inst_useful_3ac(inst, c))
+                       return 1;
+       }
 
-                                       if (inst2->src.base == inst->dst.base
-                                                       && inst2->src.index) // maybe array member
-                                               break;
-                               }
-                       }
-               }
+       return 0;
+}
 
-               if (j < tmp_insts->size)
+static int __x64_inst_useful_bb_next(scf_basic_block_t* bb, void* data, scf_vector_t* queue)
+{
+       scf_instruction_t* inst = data;
+       scf_basic_block_t* bb2;
+       int j;
+
+       if (x64_inst_useful_bb(inst, bb))
+               return 1;
+
+       for (j = 0; j < bb->nexts->size; j++) {
+               bb2       = bb->nexts->data[j];
+
+               int ret = scf_vector_add(queue, bb2);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int _x64_peephole_function(scf_vector_t* tmp_insts, scf_function_t* f)
+{
+       scf_instruction_t*  inst;
+       scf_basic_block_t*  bb;
+       scf_3ac_code_t*     c;
+       int i;
+
+       for (i   = tmp_insts->size - 1; i >= 0; i--) {
+               inst = tmp_insts->data[i];
+
+               if (SCF_X64_MOV != inst->OpCode->type)
+                       continue;
+
+               if (x64_inst_data_is_reg(&inst->dst)) {
+
+                       if (x64_reg_is_retval(inst->dst.base))
+                               continue;
+
+               } else if (!x64_inst_data_is_local(&inst->dst))
                        continue;
 
                c  = inst->c;
+               bb = c->basic_block;
+
+               int ret = scf_basic_block_search_bfs(bb, __x64_inst_useful_bb_next, inst);
+               if (ret < 0)
+                       return ret;
+
+               if (ret > 0)
+                       continue;
 
                assert(0 == scf_vector_del(c->instructions,  inst));
                assert(0 == scf_vector_del(tmp_insts,        inst));
@@ -376,25 +505,22 @@ static void _x64_peephole_function(scf_vector_t* tmp_insts, scf_function_t* f, i
                inst = NULL;
        }
 
-       int nb_locals = 0;
+       int n_locals = 0;
 
        for (i = 0; i < tmp_insts->size; i++) {
                inst      = tmp_insts->data[i];
 
-               if (!inst)
-                       continue;
-
-               if (x64_inst_data_is_local(&inst->src)
-                               || x64_inst_data_is_local(&inst->dst))
-                       nb_locals++;
+               if (x64_inst_data_is_local(&inst->src) || x64_inst_data_is_local(&inst->dst))
+                       n_locals++;
        }
 
-       if (nb_locals > 0)
+       if (n_locals > 0)
                f->bp_used_flag = 1;
        else
                f->bp_used_flag = 0;
 
        scf_logw("%s(), f->bp_used_flag: %d\n", f->node.w->text->data, f->bp_used_flag);
+       return 0;
 }
 
 int x64_optimize_peephole(scf_native_t* ctx, scf_function_t* f)
@@ -434,10 +560,6 @@ int x64_optimize_peephole(scf_native_t* ctx, scf_function_t* f)
                if (bb->jmp_flag) {
                        scf_vector_clear(std_insts, NULL);
 
-                       ret = scf_vector_add(tmp_insts, NULL);
-                       if (ret < 0)
-                               goto error;
-
                        l2 = scf_list_head(&bb->code_list_head);
                        c  = scf_list_data(l2, scf_3ac_code_t, list);
 
@@ -451,10 +573,6 @@ int x64_optimize_peephole(scf_native_t* ctx, scf_function_t* f)
 
                if (bb->jmp_dst_flag) {
                        scf_vector_clear(std_insts, NULL);
-
-                       ret = scf_vector_add(tmp_insts, NULL);
-                       if (ret < 0)
-                               goto error;
                }
 
                for (l2 = scf_list_head(&bb->code_list_head); l2 != scf_list_sentinel(&bb->code_list_head);
@@ -473,24 +591,35 @@ int x64_optimize_peephole(scf_native_t* ctx, scf_function_t* f)
                                inst->c = c;
 //                             scf_instruction_print(inst);
 
-                               if (SCF_X64_CMP == inst->OpCode->type || SCF_X64_TEST == inst->OpCode->type) {
+                               ret = 0;
+                               switch (inst->OpCode->type) {
 
-                                       ret = _x64_peephole_cmp(std_insts, inst);
-                                       if (ret < 0)
-                                               goto error;
+                                       case SCF_X64_CMP:
+                                       case SCF_X64_TEST:
+                                               ret = _x64_peephole_cmp(std_insts, inst);
+                                               break;
 
-                               } else if (SCF_X64_MOV == inst->OpCode->type) {
+                                       case SCF_X64_MOV:
+                                               ret = _x64_peephole_mov(std_insts, inst);
+                                               break;
 
-                                       ret = _x64_peephole_common(std_insts, inst);
-                                       if (ret < 0)
-                                               goto error;
+                                       case SCF_X64_LEA:
+                                               ret = scf_vector_add_unique(std_insts, inst);
+                                               break;
 
-                                       if (X64_PEEPHOLE_DEL == ret)
-                                               continue;
+                                       case SCF_X64_MOVSS:
+                                       case SCF_X64_MOVSD:
+                                               break;
+                                       default:
+                                               scf_vector_clear(std_insts, NULL);
+                                               break;
+                               };
 
-                               } else {
-                                       scf_vector_clear(std_insts, NULL);
-                               }
+                               if (ret < 0)
+                                       goto error;
+
+                               if (X64_PEEPHOLE_DEL == ret)
+                                       continue;
 
                                ret = scf_vector_add(tmp_insts, inst);
                                if (ret < 0)
@@ -500,38 +629,7 @@ int x64_optimize_peephole(scf_native_t* ctx, scf_function_t* f)
                }
        }
 
-       _x64_peephole_function(tmp_insts, f, jmp_back_flag);
-#if 0
-       for (i = 0; i < tmp_insts->size; i++) {
-               inst      = tmp_insts->data[i];
-
-               if (!inst)
-                       continue;
-
-               if (SCF_X64_MOV != inst->OpCode->type
-                               || !x64_inst_data_is_local(&inst->src))
-                       continue;
-
-               scf_logw("\n");
-               scf_instruction_print(inst);
-
-               for (j = i - 1; j >= 0; j--) {
-                       std = tmp_insts->data[j];
-
-                       if (!std)
-                               break;
-
-                       if (scf_inst_data_same(&std->dst, &inst->src)
-                                       || scf_inst_data_same(&std->dst, &inst->dst)) {
-                               printf("-------\n");
-                               scf_instruction_print(std);
-                               break;
-                       }
-               }
-               printf("\n");
-       }
-#endif
-       ret = 0;
+       ret = _x64_peephole_function(tmp_insts, f);
 error:
        scf_vector_free(tmp_insts);
        scf_vector_free(std_insts);
index 25cbab8c17c0de0d4904cb8750b1770e4671dd4a..2e356c81f329681091134bfd0835630913466362 100644 (file)
@@ -761,6 +761,15 @@ static int _x64_rcg_bit_or_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_gra
        return _x64_rcg_make(c, g, dst->dag_node, NULL, NULL);
 }
 
+static int _x64_rcg_dump_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g)
+{
+       int ret = _x64_rcg_make2(c, NULL, NULL, NULL);
+       if (ret < 0)
+               return ret;
+
+       return _x64_rcg_make(c, g, NULL, NULL, NULL);
+}
+
 static int _x64_rcg_cmp_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g)
 {
        int ret = _x64_rcg_make2(c, NULL, NULL, NULL);
@@ -1310,6 +1319,7 @@ static x64_rcg_handler_pt  x64_rcg_handlers[SCF_N_3AC_OPS] =
 
        [SCF_OP_3AC_CMP     ]  =  _x64_rcg_cmp_handler,
        [SCF_OP_3AC_TEQ     ]  =  _x64_rcg_teq_handler,
+       [SCF_OP_3AC_DUMP    ]  =  _x64_rcg_dump_handler,
 
        [SCF_OP_3AC_SETZ    ]  =  _x64_rcg_setz_handler,
        [SCF_OP_3AC_SETNZ   ]  =  _x64_rcg_setnz_handler,
index 6c90f72c624426511d229311cf42217d3836312d..cd4cdfdd633e0ecc2ef982d2fa7323f0ccb1db53 100644 (file)
@@ -162,6 +162,20 @@ int                 x64_array_index_reg(x64_sib_t* sib, scf_dag_node_t* base, sc
 
 void                x64_call_rabi(int* p_nints, int* p_nfloats, scf_3ac_code_t* c);
 
+static inline int   x64_reg_is_retval(scf_register_t* r)
+{
+       scf_register_t* r2;
+       int k;
+
+       for (k = 0; k < X64_ABI_RET_NB; k++) {
+               r2 = x64_find_register_type_id_bytes(0, x64_abi_ret_regs[k], 8);
+
+               if (X64_COLOR_CONFLICT(r2->color, r->color))
+                       return 1;
+       }
+
+       return 0;
+}
 
 static inline int   x64_inst_data_is_reg(scf_inst_data_t* id)
 {
@@ -197,4 +211,14 @@ static inline int   x64_inst_data_is_const(scf_inst_data_t* id)
        return 0;
 }
 
+static inline int   x64_inst_data_is_pointer(scf_inst_data_t* id)
+{
+       scf_register_t* rbp = x64_find_register("rbp");
+       scf_register_t* rsp = x64_find_register("rsp");
+
+       if (id->flag && id->base && id->base != rbp && id->base != rsp)
+               return 1;
+       return 0;
+}
+
 #endif
index e6dddae2167bab21bcca56be4459a52a83e813b9..900c49f049ba571370d58440b2b188d60f8ec7e6 100644 (file)
@@ -103,6 +103,7 @@ CFILES += ../core/scf_pointer_alias.c
 CFILES += ../core/scf_optimizer.c
 CFILES += ../core/scf_optimizer_dag.c
 CFILES += ../core/scf_optimizer_inline.c
+CFILES += ../core/scf_optimizer_split_call.c
 CFILES += ../core/scf_optimizer_call.c
 CFILES += ../core/scf_optimizer_common_expr.c
 CFILES += ../core/scf_optimizer_pointer_alias.c