From b48cfafcfa379ce76435bdec861d8363b94dfbe4 Mon Sep 17 00:00:00 2001 From: "yu.dongliang" <18588496441@163.com> Date: Thu, 20 Feb 2025 17:37:54 +0800 Subject: [PATCH] update x64 peephole, support VLA in loop, and fix some bugs --- core/scf_3ac.c | 15 +- core/scf_basic_block.h | 1 + core/scf_core_types.h | 1 + core/scf_operator_handler_3ac.c | 60 +++- core/scf_optimizer.c | 2 + core/scf_optimizer_basic_block.c | 63 ++-- core/scf_optimizer_call.c | 103 +------ core/scf_optimizer_common_expr.c | 2 +- core/scf_optimizer_inline.c | 12 +- core/scf_optimizer_split_call.c | 105 +++++++ examples/array_pointer_opt2.c | 25 ++ examples/inline.c | 17 ++ examples/{declare_vars.c => setcc.c} | 0 examples/str.c | 8 +- examples/vla_2.c | 20 ++ lib/x64/scf_object.o | Bin 7391 -> 6973 bytes native/x64/scf_x64.c | 51 ++-- native/x64/scf_x64_inst.c | 90 +++--- native/x64/scf_x64_inst_cmp.c | 38 +-- native/x64/scf_x64_peephole.c | 412 +++++++++++++++++---------- native/x64/scf_x64_rcg.c | 10 + native/x64/scf_x64_reg.h | 24 ++ parse/Makefile | 1 + 23 files changed, 659 insertions(+), 401 deletions(-) create mode 100644 core/scf_optimizer_split_call.c create mode 100644 examples/array_pointer_opt2.c create mode 100644 examples/inline.c rename examples/{declare_vars.c => setcc.c} (100%) create mode 100644 examples/vla_2.c diff --git a/core/scf_3ac.c b/core/scf_3ac.c index 2f3dce7..3c59e13 100644 --- a/core/scf_3ac.c +++ b/core/scf_3ac.c @@ -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; diff --git a/core/scf_basic_block.h b/core/scf_basic_block.h index d0aab43..4f193ac 100644 --- a/core/scf_basic_block.h +++ b/core/scf_basic_block.h @@ -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; diff --git a/core/scf_core_types.h b/core/scf_core_types.h index 6d844ca..e67df03 100644 --- a/core/scf_core_types.h +++ b/core/scf_core_types.h @@ -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, diff --git a/core/scf_operator_handler_3ac.c b/core/scf_operator_handler_3ac.c index 767ba28..f627ada 100644 --- a/core/scf_operator_handler_3ac.c +++ b/core/scf_operator_handler_3ac.c @@ -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); } diff --git a/core/scf_optimizer.c b/core/scf_optimizer.c index faf4f20..49440a9 100644 --- a/core/scf_optimizer.c +++ b/core/scf_optimizer.c @@ -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, diff --git a/core/scf_optimizer_basic_block.c b/core/scf_optimizer_basic_block.c index 27a9caf..bf8ac62 100644 --- a/core/scf_optimizer_basic_block.c +++ b/core/scf_optimizer_basic_block.c @@ -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, diff --git a/core/scf_optimizer_call.c b/core/scf_optimizer_call.c index ea87053..6c493ab 100644 --- a/core/scf_optimizer_call.c +++ b/core/scf_optimizer_call.c @@ -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; } diff --git a/core/scf_optimizer_common_expr.c b/core/scf_optimizer_common_expr.c index f8bb2c4..ef924cc 100644 --- a/core/scf_optimizer_common_expr.c +++ b/core/scf_optimizer_common_expr.c @@ -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; } diff --git a/core/scf_optimizer_inline.c b/core/scf_optimizer_inline.c index eb06065..5a433ea 100644 --- a/core/scf_optimizer_inline.c +++ b/core/scf_optimizer_inline.c @@ -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 index 0000000..0fc10ca --- /dev/null +++ b/core/scf_optimizer_split_call.c @@ -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 index 0000000..6b9ff3c --- /dev/null +++ b/examples/array_pointer_opt2.c @@ -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 index 0000000..83d7da4 --- /dev/null +++ b/examples/inline.c @@ -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; +} diff --git a/examples/declare_vars.c b/examples/setcc.c similarity index 100% rename from examples/declare_vars.c rename to examples/setcc.c diff --git a/examples/str.c b/examples/str.c index 335b19b..d9a0ff0 100644 --- a/examples/str.c +++ b/examples/str.c @@ -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 index 0000000..d93f8f1 --- /dev/null +++ b/examples/vla_2.c @@ -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; +} diff --git a/lib/x64/scf_object.o b/lib/x64/scf_object.o index 902ff7897c9b6a8cce015a9cd8a6bc5d6f73c275..0ef68f52f5cf28abde6654895f42f1e7c0afffa3 100644 GIT binary patch delta 2877 zcmZ`*eNa?Y6o2ntmO#+O2fKV~R+`x43{FOvKyHC^7Z(K_9HhY{B{eNgm;8(c##i2+ zub?M0ju~n-)=Z5$F-%rskbj7Olx8!S)&xz~z~Ii~T?w6vP>-&xDGj{$_8 zPLWs&Q|~hV+8E>An<9}2`&zZ-C-FUu561Pis4{+JytJ9=y^YCCXi+)3j+q6F_pC$< zP&Q1|0h$joqkN1R^S}mVArMAQWkh;!a0;_M-|KQ@6v5#vzs=00 zfD1_G1jaigk-BCG1!J~z!+UCA!^|gRq`6)JBJfcsze3EAhyOR$sw$E1+FIZpX8O6H zhwBVsjn`yetEwX3gO*>4c^S=*!WzKNTp%c+<7i-ZY0RR~y*Y)_oJJWg#vfx`W>@T^ zDIP;zEX5+j)x$E&7_r{#)~6H9R5fIJ0+8l9%43PPli(T&{R6FqHvGKZ21Z@D-4 z`>kxD>k-K{w}yFLm>DY)z)r-^FZ)j>2wsXJlgW5LLIPi) zFZaGaX~R~*AaXqyfxtcoLKfe=M_@~*0yy#m)U-L;MUL@sq;Hzw$p*8SiYW zXitU2-171vZg&!lt#KCb71ziS>;qmpCMd{3o?jYvn;hgNM)`1wA%X=iv3&P)kE-|{EQfh&VO?-9+)p(X}Id&6(sI%!Q!Ob?CDXGZA|Rx=wi z2XsW^2!H46)1QfeL@;tj{JMRQs(ZlV;6q4!Ks>2kRB}{su6h z?PE;}c^kge8Flc)Ho>*hIy5PJ;pT=74fR_ZK=&@lNc$%H=%ex|Ky7^fMMa&x8?+MX zFnp=Sh?EOA6t0!z9d}-69I03$t#xfu)Y3OWkLM)JGZF?+x2)R%PW{`2dbr88PEpI` zW~j-gz$Aq*u>Ty))J^DfPaHg8UBDW`QV-(OwYkAM?hfRKqi0`@MlSs}M*S+}TRhZ( zP&M&*R8baKb5drxn&Bc_W<8hU3w=p4G?J|a$z;vjdFd40K0p&`6UozP0*Gnyr!?5w z2{wmlh)mIZMFEnjk!f0h60m7YrQ3-|qltgeMgX8mbR(Ie(Mz4Wdf5QU(&*MQ`cfO6 zS_tqD0U0=-qtVr9J(VsasT%E9$SjS%0#vWkq&B+s>h>zS1$=g<2Y?vK)pnCgEsbtz zqe)(XATzZ#4}d{r6X^!z0kjK|`qb9ev;YL2qj?L7$LgFsq|UWMT6*SsnKuQ?pAEk| zFh{t$t>d75&!NTtSw*#_K5UJ_4)%4=;*P0yTS z*B5gtu=Fnb8ZPp!!Hr1hZQFK5Csg(lms^Y|MO`LGPhgvJsyjeHxmd00_ zu8e$lk-h{rQo zd+laKwKJz{;;m+nm%JR`wcm4$)JKOGOQ0!gY?$qkciQsUXo3J%JN(f8-tjqV%g1M- K>!XZ{8V7 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 Dg|XLB diff --git a/native/x64/scf_x64.c b/native/x64/scf_x64.c index 1278ca6..3d7aa7e 100644 --- a/native/x64/scf_x64.c +++ b/native/x64/scf_x64.c @@ -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; } diff --git a/native/x64/scf_x64_inst.c b/native/x64/scf_x64_inst.c index 3283407..726f760 100644 --- a/native/x64/scf_x64_inst.c +++ b/native/x64/scf_x64_inst.c @@ -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, diff --git a/native/x64/scf_x64_inst_cmp.c b/native/x64/scf_x64_inst_cmp.c index ad7f098..ad09f1a 100644 --- a/native/x64/scf_x64_inst_cmp.c +++ b/native/x64/scf_x64_inst_cmp.c @@ -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; } diff --git a/native/x64/scf_x64_peephole.c b/native/x64/scf_x64_peephole.c index 1c4353c..c454bac 100644 --- a/native/x64/scf_x64_peephole.c +++ b/native/x64/scf_x64_peephole.c @@ -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); diff --git a/native/x64/scf_x64_rcg.c b/native/x64/scf_x64_rcg.c index 25cbab8..2e356c8 100644 --- a/native/x64/scf_x64_rcg.c +++ b/native/x64/scf_x64_rcg.c @@ -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, diff --git a/native/x64/scf_x64_reg.h b/native/x64/scf_x64_reg.h index 6c90f72..cd4cdfd 100644 --- a/native/x64/scf_x64_reg.h +++ b/native/x64/scf_x64_reg.h @@ -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 diff --git a/parse/Makefile b/parse/Makefile index e6dddae..900c49f 100644 --- a/parse/Makefile +++ b/parse/Makefile @@ -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 -- 2.25.1