From: yu.dongliang Date: Wed, 19 Oct 2022 09:45:25 +0000 (+0800) Subject: optimize: pointer dereference when the variable pointed can be identified, X-Git-Url: http://baseworks.info/?a=commitdiff_plain;h=03c4d20cddbeb9bbc0c7cde982a538d40160eab6;p=scf.git optimize: pointer dereference when the variable pointed can be identified, such as: int a = 1; int* p = &a; int** pp = &p; **pp += 2; // this will be instead of 'a += 2', and 'p = &a; pp = &p' will be deleted. --- diff --git a/core/scf_3ac.c b/core/scf_3ac.c index 6089384..1d8f807 100644 --- a/core/scf_3ac.c +++ b/core/scf_3ac.c @@ -687,6 +687,7 @@ int scf_3ac_code_to_dag(scf_3ac_code_t* c, scf_list_t* dag) return ret; } else if (scf_type_is_assign_array_index(c->op->type) + || scf_type_is_assign_dereference(c->op->type) || scf_type_is_assign_pointer(c->op->type)) { scf_3ac_operand_t* src; diff --git a/core/scf_optimizer_basic_block.c b/core/scf_optimizer_basic_block.c index 1c86111..81a1d07 100644 --- a/core/scf_optimizer_basic_block.c +++ b/core/scf_optimizer_basic_block.c @@ -55,15 +55,18 @@ static int _bb_dag_update(scf_basic_block_t* bb, scf_vector_t* dag, scf_list_t* if (scf_type_is_assign_array_index(dn->type)) continue; + if (scf_type_is_assign_dereference(dn->type) || SCF_OP_DEREFERENCE == dn->type) + continue; if (scf_type_is_assign_pointer(dn->type)) continue; if (scf_type_is_assign(dn->type) - || SCF_OP_INC == dn->type || SCF_OP_DEC == dn->type - || SCF_OP_3AC_INC == dn->type || SCF_OP_3AC_DEC == dn->type - || SCF_OP_3AC_SETZ == dn->type || SCF_OP_3AC_SETNZ == dn->type - || SCF_OP_3AC_SETLT == dn->type || SCF_OP_3AC_SETLE == dn->type - || SCF_OP_3AC_SETGT == dn->type || SCF_OP_3AC_SETGE == dn->type) { + || SCF_OP_INC == dn->type || SCF_OP_DEC == dn->type + || SCF_OP_3AC_INC == dn->type || SCF_OP_3AC_DEC == dn->type + || SCF_OP_3AC_SETZ == dn->type || SCF_OP_3AC_SETNZ == dn->type + || SCF_OP_3AC_SETLT == dn->type || SCF_OP_3AC_SETLE == dn->type + || SCF_OP_3AC_SETGT == dn->type || SCF_OP_3AC_SETGE == dn->type + || SCF_OP_ADDRESS_OF == dn->type) { if (!dn->childs) { scf_list_del(&dn->list); @@ -84,24 +87,27 @@ static int _bb_dag_update(scf_basic_block_t* bb, scf_vector_t* dag, scf_list_t* return -1; } - if (scf_vector_find(bb->dn_saves, dn_func) - || scf_vector_find(bb->dn_resaves, dn_func)) - continue; + if (SCF_OP_ADDRESS_OF != dn->type) { - assert(dn_bb->parents && dn_bb->parents->size > 0); + if (scf_vector_find(bb->dn_saves, dn_func) + || scf_vector_find(bb->dn_resaves, dn_func)) + continue; - if (dn != dn_bb->parents->data[dn_bb->parents->size - 1]) - continue; + assert(dn_bb->parents && dn_bb->parents->size > 0); + + if (dn != dn_bb->parents->data[dn_bb->parents->size - 1]) + continue; - if (2 == dn->childs->size) { - dn_bb2 = dn->childs->data[1]; + if (2 == dn->childs->size) { + dn_bb2 = dn->childs->data[1]; - assert(0 == scf_vector_del(dn->childs, dn_bb2)); - assert(0 == scf_vector_del(dn_bb2->parents, dn)); + assert(0 == scf_vector_del(dn->childs, dn_bb2)); + assert(0 == scf_vector_del(dn_bb2->parents, dn)); - if (0 == dn_bb2->parents->size) { - scf_vector_free(dn_bb2->parents); - dn_bb2->parents = NULL; + if (0 == dn_bb2->parents->size) { + scf_vector_free(dn_bb2->parents); + dn_bb2->parents = NULL; + } } } @@ -355,7 +361,6 @@ static int _optimize_basic_block(scf_ast_t* ast, scf_function_t* f, scf_list_t* || bb->ret_flag || bb->end_flag || bb->call_flag - || bb->dereference_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_pointer_alias.c b/core/scf_optimizer_pointer_alias.c index d73035e..583cdb1 100644 --- a/core/scf_optimizer_pointer_alias.c +++ b/core/scf_optimizer_pointer_alias.c @@ -1,13 +1,15 @@ #include"scf_optimizer.h" #include"scf_pointer_alias.h" -static int _filter_3ac_by_pointer_alias(scf_3ac_operand_t* pointer, scf_list_t* prev, scf_basic_block_t* bb) +static int _filter_3ac_by_pointer_alias(scf_3ac_operand_t* pointer, scf_list_t* prev, scf_basic_block_t* bb, scf_list_t* bb_list_head) { - scf_3ac_code_t* c2; - scf_3ac_code_t* c3; - scf_list_t* l2; - scf_list_t* l3; - scf_list_t h; + scf_basic_block_t* bb2; + scf_basic_block_t* bb3; + scf_3ac_code_t* c2; + scf_3ac_code_t* c3; + scf_list_t* l2; + scf_list_t* l3; + scf_list_t h; scf_list_init(&h); @@ -17,31 +19,81 @@ static int _filter_3ac_by_pointer_alias(scf_3ac_operand_t* pointer, scf_list_t* return ret; } - for (l2 = scf_list_head(&h); l2 != scf_list_sentinel(&h); ) { + l3 = prev; + + for (l2 = scf_list_tail(&h); l2 != scf_list_sentinel(&h); ) { c2 = scf_list_data(l2, scf_3ac_code_t, list); - l2 = scf_list_next(l2); - for (l3 = prev; l3 != scf_list_sentinel(&bb->code_list_head); ) { + for ( ; l3 != scf_list_sentinel(&bb->code_list_head); ) { c3 = scf_list_data(l3, scf_3ac_code_t, list); - l3 = scf_list_prev(l3); if (scf_3ac_code_same(c2, c3)) { + l3 = scf_list_prev(l3); + l2 = scf_list_prev(l2); + scf_list_del(&c3->list); + scf_list_del(&c2->list); + scf_3ac_code_free(c3); + scf_3ac_code_free(c2); break; } + + l3 = scf_list_prev(l3); } - scf_list_del(&c2->list); - scf_3ac_code_free(c2); + if (l3 == scf_list_sentinel(&bb->code_list_head)) { + + if (scf_list_prev(&bb->list) == scf_list_sentinel(bb_list_head)) + break; + + bb2 = scf_list_data(scf_list_prev(&bb->list), scf_basic_block_t, list); + + if (!bb2->nexts || bb2->nexts->size != 1) + break; + + if (!bb->prevs || bb->prevs->size != 1) + break; + + if (bb2->nexts->data[0] != bb || bb->prevs->data[0] != bb2) + break; + + if (scf_list_empty(&bb->code_list_head)) { + + SCF_XCHG(bb2->nexts, bb->nexts); + + int i; + int j; + + for (i = 0; i < bb2->nexts->size; i++) { + bb3 = bb2->nexts->data[i]; + + for (j = 0; j < bb3->prevs->size; j++) { + + if (bb3->prevs->data[j] == bb) { + bb3->prevs->data[j] = bb2; + break; + } + } + } + + scf_list_del(&bb->list); + + scf_basic_block_free(bb); + bb = NULL; + } + + bb = bb2; + l3 = scf_list_tail(&bb->code_list_head); + } } return 0; } -static int _3ac_pointer_alias(scf_dag_node_t* alias, scf_3ac_code_t* c, scf_basic_block_t* bb) +static int _3ac_pointer_alias(scf_dag_node_t* alias, scf_3ac_code_t* c, scf_basic_block_t* bb, scf_list_t* bb_list_head) { scf_3ac_operand_t* pointer; @@ -58,7 +110,7 @@ static int _3ac_pointer_alias(scf_dag_node_t* alias, scf_3ac_code_t* c, scf_basi } #if 1 - ret = _filter_3ac_by_pointer_alias(pointer, scf_list_prev(&c->list), bb); + ret = _filter_3ac_by_pointer_alias(pointer, scf_list_prev(&c->list), bb, bb_list_head); if (ret < 0) return ret; #endif @@ -160,13 +212,16 @@ static int _alias_assign_dereference(scf_vector_t** paliases, scf_dag_node_t* dn status = aliases->data[0]; if (SCF_DN_ALIAS_VAR == status->alias_type) { - ret = _3ac_pointer_alias(status->alias, c, bb); + + ret = _3ac_pointer_alias(status->alias, c, bb, bb_list_head); + scf_vector_free(aliases); + aliases = NULL; + if (ret < 0) return ret; return scf_basic_block_inited_vars(bb, bb_list_head); } - return 0; } *paliases = aliases; @@ -196,7 +251,6 @@ static int __optimize_alias_dereference(scf_3ac_operand_t* pointer, scf_3ac_code return ret; if (aliases) { - flag = 1; if (1 == aliases->size) { ds = aliases->data[0]; @@ -217,7 +271,7 @@ static int __optimize_alias_dereference(scf_3ac_operand_t* pointer, scf_3ac_code l = scf_list_prev(&c->list); } - ret = _filter_3ac_by_pointer_alias(pointer, l, bb2); + ret = _filter_3ac_by_pointer_alias(pointer, l, bb2, bb_list_head); if (ret < 0) return ret; @@ -227,7 +281,9 @@ static int __optimize_alias_dereference(scf_3ac_operand_t* pointer, scf_3ac_code if (ret < 0) return ret; - flag = 0; + scf_vector_free(aliases); + aliases = NULL; + return 0; } } @@ -238,6 +294,8 @@ static int __optimize_alias_dereference(scf_3ac_operand_t* pointer, scf_3ac_code if (ret < 0) return ret; + + flag = 1; } return flag; @@ -301,13 +359,13 @@ static int __optimize_alias_bb(scf_list_t** pend, scf_list_t* start, scf_basic_b flag += ret; } else if (SCF_OP_DEREFERENCE == c->op->type) { - +#if 0 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); - +#endif } else { if (i > 0) break;