@@ -401,6 +401,54 @@ void build_rdf()
401401 free (args );
402402}
403403
404+ void use_chain_add_tail (insn_t * i , var_t * var )
405+ {
406+ use_chain_t * u = calloc (1 , sizeof (use_chain_t ));
407+ if (!u ) {
408+ printf ("calloc failed\n" );
409+ abort ();
410+ }
411+
412+ u -> insn = i ;
413+ if (!var -> users_head )
414+ var -> users_head = u ;
415+ else
416+ var -> users_tail -> next = u ;
417+ u -> prev = var -> users_tail ;
418+ var -> users_tail = u ;
419+ }
420+
421+ void use_chain_delete (use_chain_t * u , var_t * var )
422+ {
423+ if (u -> prev )
424+ u -> prev -> next = u -> next ;
425+ else {
426+ var -> users_head = u -> next ;
427+ u -> next -> prev = NULL ;
428+ }
429+ if (u -> next )
430+ u -> next -> prev = u -> prev ;
431+ else {
432+ var -> users_tail = u -> prev ;
433+ u -> prev -> next = NULL ;
434+ }
435+ free (u );
436+ }
437+
438+ void use_chain_build ()
439+ {
440+ for (fn_t * fn = FUNC_LIST .head ; fn ; fn = fn -> next ) {
441+ for (basic_block_t * bb = fn -> bbs ; bb ; bb = bb -> rpo_next ) {
442+ for (insn_t * i = bb -> insn_list .head ; i ; i = i -> next ) {
443+ if (i -> rs1 )
444+ use_chain_add_tail (i , i -> rs1 );
445+ if (i -> rs2 )
446+ use_chain_add_tail (i , i -> rs2 );
447+ }
448+ }
449+ }
450+ }
451+
404452bool var_check_killed (var_t * var , basic_block_t * bb )
405453{
406454 for (int i = 0 ; i < bb -> live_kill_idx ; i ++ ) {
@@ -1170,63 +1218,80 @@ void ssa_build(int dump_ir)
11701218}
11711219
11721220/* Common Subexpression Elimination (CSE) */
1173- /* TODO: simplify with def-use chain */
11741221/* TODO: release detached insns node */
11751222bool cse (insn_t * insn , basic_block_t * bb )
11761223{
11771224 if (insn -> opcode != OP_read )
11781225 return false;
11791226
11801227 insn_t * prev = insn -> prev ;
1181-
11821228 if (!prev )
11831229 return false;
11841230 if (prev -> opcode != OP_add )
11851231 return false;
11861232 if (prev -> rd != insn -> rs1 )
11871233 return false;
11881234
1189- var_t * def = NULL , * base = prev -> rs1 , * idx = prev -> rs2 ;
1235+ var_t * def = insn -> rd , * base = prev -> rs1 , * idx = prev -> rs2 ;
11901236 if (base -> is_global || idx -> is_global )
11911237 return false;
11921238
1193- insn_t * i = prev ;
1194- for (basic_block_t * b = bb ;; b = b -> idom ) {
1195- 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 ;
1210- }
1211- if (def )
1212- break ;
1213- if (b -> idom == b )
1214- break ;
1215- }
1239+ use_chain_t * rs1_delete_user = NULL ;
1240+ use_chain_t * rs2_delete_user = NULL ;
1241+ for (use_chain_t * user = base -> users_head ; user ; user = user -> next ) {
1242+ insn_t * i = user -> insn ;
12161243
1217- if (!def )
1218- return false;
1244+ /* Delete the use chain nodes found in the last loop */
1245+ if (rs1_delete_user ) {
1246+ use_chain_delete (rs1_delete_user , rs1_delete_user -> insn -> rs1 );
1247+ rs1_delete_user = NULL ;
1248+ }
1249+ if (rs2_delete_user ) {
1250+ use_chain_delete (rs2_delete_user , rs2_delete_user -> insn -> rs2 );
1251+ rs2_delete_user = NULL ;
1252+ }
1253+ if (i == prev )
1254+ continue ;
1255+ if (i -> opcode != OP_add )
1256+ continue ;
1257+ if (!i -> next )
1258+ continue ;
1259+ if (i -> next -> opcode != OP_read )
1260+ continue ;
1261+ if (i -> rs1 != base || i -> rs2 != idx )
1262+ continue ;
1263+ basic_block_t * i_bb = i -> belong_to ;
1264+ bool check_dom = 0 ;
1265+ /* Check if the instructions are under the same dominate tree */
1266+ for (;; i_bb = i_bb -> idom ) {
1267+ if (i_bb == bb ) {
1268+ check_dom = true;
1269+ break ;
1270+ }
1271+ if (i_bb == i_bb -> idom )
1272+ break ;
1273+ }
1274+ if (!check_dom )
1275+ continue ;
12191276
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 ;
1277+ i -> next -> opcode = OP_assign ;
1278+ i -> next -> rs1 = def ;
1279+ if (i -> prev ) {
1280+ i -> prev -> next = i -> next ;
1281+ i -> next -> prev = i -> prev ;
1282+ } else {
1283+ i -> belong_to -> insn_list .head = i -> next ;
1284+ i -> next -> prev = NULL ;
1285+ }
1286+ i -> next -> opcode = OP_assign ;
1287+ i -> next -> rs1 = def ;
1288+ /* Prepare information for deleting use chain nodes */
1289+ rs1_delete_user = user ;
1290+ for (rs2_delete_user = i -> rs2 -> users_head ;
1291+ rs2_delete_user -> insn != rs1_delete_user -> insn ;
1292+ rs2_delete_user = rs2_delete_user -> next )
1293+ ;
12261294 }
1227-
1228- insn -> opcode = OP_assign ;
1229- insn -> rs1 = def ;
12301295 return true;
12311296}
12321297
@@ -1466,6 +1531,8 @@ void optimize()
14661531 build_rdom ();
14671532 build_rdf ();
14681533
1534+ use_chain_build ();
1535+
14691536 for (fn_t * fn = FUNC_LIST .head ; fn ; fn = fn -> next ) {
14701537 /* basic block level (control flow) optimizations */
14711538
0 commit comments