From 03c4d20cddbeb9bbc0c7cde982a538d40160eab6 Mon Sep 17 00:00:00 2001
From: "yu.dongliang" <maja_creater@qq.com>
Date: Wed, 19 Oct 2022 17:45:25 +0800
Subject: [PATCH] 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.
---
 core/scf_3ac.c                     |   1 +
 core/scf_optimizer_basic_block.c   |  43 +++++++------
 core/scf_optimizer_pointer_alias.c | 100 +++++++++++++++++++++++------
 3 files changed, 104 insertions(+), 40 deletions(-)

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;
-- 
2.25.1