@@ -401,6 +401,49 @@ void build_rdf()
401401 free (args );
402402}
403403
404+ void use_chain_add_tail (insn_t * i , var_t * var )
405+ {
406+ uc_node_t * n = calloc (1 , sizeof (uc_node_t ));
407+ n -> insn = i ;
408+ if (!var -> use_chain_head )
409+ var -> use_chain_head = n ;
410+ else
411+ var -> use_chain_tail -> next = n ;
412+ n -> prev = var -> use_chain_tail ;
413+ var -> use_chain_tail = n ;
414+ }
415+
416+ void use_chain_delete (uc_node_t * node , var_t * var )
417+ {
418+ if (node -> prev )
419+ node -> prev -> next = node -> next ;
420+ else {
421+ var -> use_chain_head = node -> next ;
422+ node -> next -> prev = NULL ;
423+ }
424+ if (node -> next )
425+ node -> next -> prev = node -> prev ;
426+ else {
427+ var -> use_chain_tail = node -> prev ;
428+ node -> prev -> next = NULL ;
429+ }
430+ free (node );
431+ }
432+
433+ void build_use_chain ()
434+ {
435+ for (fn_t * fn = FUNC_LIST .head ; fn ; fn = fn -> next ) {
436+ for (basic_block_t * bb = fn -> bbs ; bb ; bb = bb -> rpo_next ) {
437+ for (insn_t * i = bb -> insn_list .head ; i ; i = i -> next ) {
438+ if (i -> rs1 )
439+ use_chain_add_tail (i , i -> rs1 );
440+ if (i -> rs2 )
441+ use_chain_add_tail (i , i -> rs2 );
442+ }
443+ }
444+ }
445+ }
446+
404447bool var_check_killed (var_t * var , basic_block_t * bb )
405448{
406449 for (int i = 0 ; i < bb -> live_kill_idx ; i ++ ) {
@@ -1170,63 +1213,82 @@ void ssa_build(int dump_ir)
11701213}
11711214
11721215/* Common Subexpression Elimination (CSE) */
1173- /* TODO: simplify with def-use chain */
11741216/* TODO: release detached insns node */
11751217bool cse (insn_t * insn , basic_block_t * bb )
11761218{
11771219 if (insn -> opcode != OP_read )
11781220 return false;
11791221
11801222 insn_t * prev = insn -> prev ;
1181-
11821223 if (!prev )
11831224 return false;
11841225 if (prev -> opcode != OP_add )
11851226 return false;
11861227 if (prev -> rd != insn -> rs1 )
11871228 return false;
11881229
1189- var_t * def = NULL , * base = prev -> rs1 , * idx = prev -> rs2 ;
1230+ var_t * def = insn -> rd , * base = prev -> rs1 , * idx = prev -> rs2 ;
11901231 if (base -> is_global || idx -> is_global )
11911232 return false;
11921233
1193- insn_t * i = prev ;
1194- for (basic_block_t * b = bb ;; b = b -> idom ) {
1234+ uc_node_t * rs1_delete_node = NULL ;
1235+ uc_node_t * rs2_delete_node = NULL ;
1236+ for (uc_node_t * node = base -> use_chain_head ; node ; node = node -> next ) {
1237+ insn_t * i = node -> insn ;
1238+
1239+ /* Delete the use chain nodes found in the last loop */
1240+ if (rs1_delete_node ) {
1241+ use_chain_delete (rs1_delete_node , rs1_delete_node -> insn -> rs1 );
1242+ rs1_delete_node = NULL ;
1243+ }
1244+ if (rs2_delete_node ) {
1245+ use_chain_delete (rs2_delete_node , rs2_delete_node -> insn -> rs2 );
1246+ rs2_delete_node = NULL ;
1247+ }
11951248 if (!i )
1196- i = b -> insn_list .tail ;
1197-
1198- for (; i ; i = i -> prev ) {
1199- if (i == prev )
1200- continue ;
1201- if (i -> opcode != OP_add )
1202- continue ;
1203- if (!i -> next )
1204- continue ;
1205- if (i -> next -> opcode != OP_read )
1206- continue ;
1207- if (i -> rs1 != base || i -> rs2 != idx )
1208- continue ;
1209- def = i -> next -> rd ;
1249+ continue ;
1250+ if (i == prev )
1251+ continue ;
1252+ if (i -> opcode != OP_add )
1253+ continue ;
1254+ if (!i -> next )
1255+ continue ;
1256+ if (i -> next -> opcode != OP_read )
1257+ continue ;
1258+ if (i -> rs1 != base || i -> rs2 != idx )
1259+ continue ;
1260+ basic_block_t * i_bb = i -> belong_to ;
1261+ bool check_dom = 0 ;
1262+ /* Check if the instructions are under the same dominate tree */
1263+ for (;; i_bb = i_bb -> idom ) {
1264+ if (i_bb == bb ) {
1265+ check_dom = true;
1266+ break ;
1267+ }
1268+ if (i_bb == i_bb -> idom )
1269+ break ;
12101270 }
1211- if (def )
1212- break ;
1213- if (b -> idom == b )
1214- break ;
1215- }
1216-
1217- if (!def )
1218- return false;
1271+ if (!check_dom )
1272+ continue ;
12191273
1220- if (prev -> prev ) {
1221- insn -> prev = prev -> prev ;
1222- prev -> prev -> next = insn ;
1223- } else {
1224- bb -> insn_list .head = insn ;
1225- insn -> prev = NULL ;
1274+ i -> next -> opcode = OP_assign ;
1275+ i -> next -> rs1 = def ;
1276+ if (i -> prev ) {
1277+ i -> prev -> next = i -> next ;
1278+ i -> next -> prev = i -> prev ;
1279+ } else {
1280+ i -> belong_to -> insn_list .head = i -> next ;
1281+ i -> next -> prev = NULL ;
1282+ }
1283+ i -> next -> opcode = OP_assign ;
1284+ i -> next -> rs1 = def ;
1285+ /* Prepare information for deleting use chain nodes */
1286+ rs1_delete_node = node ;
1287+ for (rs2_delete_node = i -> rs2 -> use_chain_head ;
1288+ rs2_delete_node -> insn != rs1_delete_node -> insn ;
1289+ rs2_delete_node = rs2_delete_node -> next )
1290+ ;
12261291 }
1227-
1228- insn -> opcode = OP_assign ;
1229- insn -> rs1 = def ;
12301292 return true;
12311293}
12321294
@@ -1466,6 +1528,8 @@ void optimize()
14661528 build_rdom ();
14671529 build_rdf ();
14681530
1531+ build_use_chain ();
1532+
14691533 for (fn_t * fn = FUNC_LIST .head ; fn ; fn = fn -> next ) {
14701534 /* basic block level (control flow) optimizations */
14711535
0 commit comments