From 84004e1a7fe8e35608d8987e40f1b2db440f91a8 Mon Sep 17 00:00:00 2001 From: "yu.dongliang" Date: Tue, 18 Oct 2022 18:22:57 +0800 Subject: [PATCH] fix & optimize: dereference & assign in if condition, such as: if (*p = i > 0 && j > 1 && k > 2) return -1; return 0; --- core/scf_3ac.c | 25 ++++++- core/scf_operator_handler_3ac.c | 16 +++++ core/scf_optimizer_pointer_alias.c | 108 +++++++++++++++++++---------- 3 files changed, 111 insertions(+), 38 deletions(-) diff --git a/core/scf_3ac.c b/core/scf_3ac.c index 3813a97..6089384 100644 --- a/core/scf_3ac.c +++ b/core/scf_3ac.c @@ -1421,8 +1421,11 @@ static int _3ac_split_basic_blocks(scf_list_t* h, scf_function_t* f) if (SCF_OP_3AC_CMP == c->op->type || SCF_OP_3AC_TEQ == c->op->type) { - scf_list_t* l2; - scf_3ac_code_t* c2; + scf_3ac_operand_t* src; + scf_3ac_code_t* c2; + scf_list_t* l2; + scf_node_t* e; + int i; for (l2 = scf_list_next(&c->list); l2 != scf_list_sentinel(h); l2 = scf_list_next(l2)) { @@ -1431,8 +1434,24 @@ static int _3ac_split_basic_blocks(scf_list_t* h, scf_function_t* f) if (scf_type_is_setcc(c2->op->type)) continue; - if (scf_type_is_jmp(c2->op->type)) + if (scf_type_is_jmp(c2->op->type)) { bb->cmp_flag = 1; + + if (c->srcs) { + + for (i = 0; i < c->srcs->size; i++) { + src = c->srcs->data[i]; + e = src->node; + + while (e && SCF_OP_EXPR == e->type) + e = e->nodes[0]; + assert(e); + + if (SCF_OP_DEREFERENCE == e->type) + bb->dereference_flag = 1; + } + } + } break; } diff --git a/core/scf_operator_handler_3ac.c b/core/scf_operator_handler_3ac.c index 4be21a1..0ceac0a 100644 --- a/core/scf_operator_handler_3ac.c +++ b/core/scf_operator_handler_3ac.c @@ -803,10 +803,26 @@ static int _scf_op_cond(scf_ast_t* ast, scf_expr_t* e, scf_handler_data_t* d) break; default: + if (scf_type_is_assign(e->type)) { + + e = e->nodes[0]; + + while (e && SCF_OP_EXPR == e->type) + e = e->nodes[0]; + + assert(e); + + if (_scf_expr_calculate_internal(ast, e, d) < 0) { + scf_loge("\n"); + return -1; + } + } + if (_scf_3ac_code_1(d->_3ac_list_head, SCF_OP_3AC_TEQ, e) < 0) { scf_loge("\n"); return -1; } + jmp_op = SCF_OP_3AC_JZ; is_default = 1; break; diff --git a/core/scf_optimizer_pointer_alias.c b/core/scf_optimizer_pointer_alias.c index 7261f8f..6c5a1ba 100644 --- a/core/scf_optimizer_pointer_alias.c +++ b/core/scf_optimizer_pointer_alias.c @@ -170,6 +170,7 @@ static int __optimize_alias_bb(scf_list_t** pend, scf_list_t* start, scf_basic_b scf_3ac_code_t* c; scf_3ac_operand_t* pointer; scf_3ac_operand_t* dst; + scf_dn_status_t* ds; scf_dag_node_t* dn_pointer; scf_dag_node_t* dn_dereference; scf_vector_t* aliases; @@ -181,52 +182,90 @@ static int __optimize_alias_bb(scf_list_t** pend, scf_list_t* start, scf_basic_b c = scf_list_data(l, scf_3ac_code_t, list); if (!scf_type_is_assign_dereference(c->op->type) - && SCF_OP_DEREFERENCE != c->op->type) + && SCF_OP_DEREFERENCE != c->op->type + && SCF_OP_3AC_TEQ != c->op->type + && SCF_OP_3AC_CMP != c->op->type) continue; assert(c->srcs && c->srcs->size >= 1); - pointer = c->srcs->data[0]; - dn_pointer = pointer->dag_node; - aliases = NULL; - dn_dereference = NULL; - - if (dn_pointer->var->arg_flag) { - scf_variable_t* v = dn_pointer->var; - scf_logd("arg: v_%d_%d/%s\n", v->w->line, v->w->pos, v->w->text->data); - continue; - } - if (dn_pointer->var->global_flag) { - scf_variable_t* v = dn_pointer->var; - scf_logd("global: v_%d_%d/%s\n", v->w->line, v->w->pos, v->w->text->data); - continue; - } + int flag = 0; + int i; + for (i = 0; i < c->srcs->size; i++) { - if (SCF_OP_DEREFERENCE == c->op->type) { + pointer = c->srcs->data[i]; + dn_pointer = pointer->dag_node; + aliases = NULL; + dn_dereference = NULL; - assert(c->dsts && 1 == c->dsts->size); - dst = c->dsts->data[0]; - dn_dereference = dst->dag_node; + if (dn_pointer->var->arg_flag) { + scf_variable_t* v = dn_pointer->var; + scf_logd("arg: v_%d_%d/%s\n", v->w->line, v->w->pos, v->w->text->data); + continue; + } - ret = _alias_dereference(&aliases, dn_pointer, c, bb, bb_list_head); - } else { - ret = _alias_assign_dereference(&aliases, dn_pointer, c, bb, bb_list_head); - } + if (dn_pointer->var->global_flag) { + scf_variable_t* v = dn_pointer->var; + scf_logd("global: v_%d_%d/%s\n", v->w->line, v->w->pos, v->w->text->data); + continue; + } - if (ret < 0) - return ret; + if (SCF_OP_3AC_TEQ == c->op->type || SCF_OP_3AC_CMP == c->op->type) { - if (aliases) { - scf_logd("bb: %p, bb->index: %d, aliases->size: %d\n", bb, bb->index, aliases->size); - scf_variable_t* v = dn_pointer->var; - scf_logd("v_%d_%d/%s\n", v->w->line, v->w->pos, v->w->text->data); + dn_dereference = dn_pointer; + + assert(SCF_OP_DEREFERENCE == dn_pointer->type); + assert(1 == dn_pointer->childs->size); + + dn_pointer = dn_pointer->childs->data[0]; + + ret = _alias_dereference(&aliases, dn_pointer, c, bb, bb_list_head); + + if (aliases && 1 == aliases->size) { + + ds = aliases->data[0]; + + if (SCF_DN_ALIAS_VAR == ds->alias_type) { + pointer->dag_node = ds->alias; + + scf_vector_free(aliases); + aliases = NULL; + + ret = scf_basic_block_inited_vars(bb, bb_list_head); + if (ret < 0) + return ret; + } + } + + } else if (SCF_OP_DEREFERENCE == c->op->type) { + + assert(c->dsts && 1 == c->dsts->size); + dst = c->dsts->data[0]; + dn_dereference = dst->dag_node; + + ret = _alias_dereference(&aliases, dn_pointer, c, bb, bb_list_head); + } else + ret = _alias_assign_dereference(&aliases, dn_pointer, c, bb, bb_list_head); - ret = _bb_copy_aliases(bb, dn_pointer, dn_dereference, aliases); - scf_vector_free(aliases); - aliases = NULL; if (ret < 0) return ret; + if (aliases) { + scf_logd("bb: %p, bb->index: %d, aliases->size: %d\n", bb, bb->index, aliases->size); + scf_variable_t* v = dn_pointer->var; + scf_logd("v_%d_%d/%s\n", v->w->line, v->w->pos, v->w->text->data); + + ret = _bb_copy_aliases(bb, dn_pointer, dn_dereference, aliases); + scf_vector_free(aliases); + aliases = NULL; + if (ret < 0) + return ret; + + flag = 1; + } + } + + if (flag) { *pend = l; break; } @@ -298,7 +337,7 @@ static int _optimize_pointer_alias(scf_ast_t* ast, scf_function_t* f, scf_list_t 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) + if (bb->jmp_flag || bb->end_flag) continue; if (!bb->dereference_flag) @@ -309,7 +348,6 @@ static int _optimize_pointer_alias(scf_ast_t* ast, scf_function_t* f, scf_list_t return ret; } -// scf_basic_block_print_list(bb_list_head); ret = 0; error: return ret; -- 2.25.1