@@ -401,6 +401,49 @@ void build_rdf()
401401 free (args );
402402}
403403
404+ void users_add_tail (insn_t * i , var_t * var )
405+ {
406+ user_t * u = calloc (1 , sizeof (user_t ));
407+ u -> insn = i ;
408+ if (!var -> users_head )
409+ var -> users_head = u ;
410+ else
411+ var -> users_tail -> next = u ;
412+ u -> prev = var -> users_tail ;
413+ var -> users_tail = u ;
414+ }
415+
416+ void users_delete (user_t * u , var_t * var )
417+ {
418+ if (u -> prev )
419+ u -> prev -> next = u -> next ;
420+ else {
421+ var -> users_head = u -> next ;
422+ u -> next -> prev = NULL ;
423+ }
424+ if (u -> next )
425+ u -> next -> prev = u -> prev ;
426+ else {
427+ var -> users_tail = u -> prev ;
428+ u -> prev -> next = NULL ;
429+ }
430+ free (u );
431+ }
432+
433+ void build_users ()
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+ users_add_tail (i , i -> rs1 );
440+ if (i -> rs2 )
441+ users_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,80 @@ 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 ) {
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- }
1234+ user_t * rs1_delete_user = NULL ;
1235+ user_t * rs2_delete_user = NULL ;
1236+ for (user_t * user = base -> users_head ; user ; user = user -> next ) {
1237+ insn_t * i = user -> insn ;
12161238
1217- if (!def )
1218- return false;
1239+ /* Delete the use chain nodes found in the last loop */
1240+ if (rs1_delete_user ) {
1241+ users_delete (rs1_delete_user , rs1_delete_user -> insn -> rs1 );
1242+ rs1_delete_user = NULL ;
1243+ }
1244+ if (rs2_delete_user ) {
1245+ users_delete (rs2_delete_user , rs2_delete_user -> insn -> rs2 );
1246+ rs2_delete_user = NULL ;
1247+ }
1248+ if (i == prev )
1249+ continue ;
1250+ if (i -> opcode != OP_add )
1251+ continue ;
1252+ if (!i -> next )
1253+ continue ;
1254+ if (i -> next -> opcode != OP_read )
1255+ continue ;
1256+ if (i -> rs1 != base || i -> rs2 != idx )
1257+ continue ;
1258+ basic_block_t * i_bb = i -> belong_to ;
1259+ bool check_dom = 0 ;
1260+ /* Check if the instructions are under the same dominate tree */
1261+ for (;; i_bb = i_bb -> idom ) {
1262+ if (i_bb == bb ) {
1263+ check_dom = true;
1264+ break ;
1265+ }
1266+ if (i_bb == i_bb -> idom )
1267+ break ;
1268+ }
1269+ if (!check_dom )
1270+ continue ;
12191271
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 ;
1272+ i -> next -> opcode = OP_assign ;
1273+ i -> next -> rs1 = def ;
1274+ if (i -> prev ) {
1275+ i -> prev -> next = i -> next ;
1276+ i -> next -> prev = i -> prev ;
1277+ } else {
1278+ i -> belong_to -> insn_list .head = i -> next ;
1279+ i -> next -> prev = NULL ;
1280+ }
1281+ i -> next -> opcode = OP_assign ;
1282+ i -> next -> rs1 = def ;
1283+ /* Prepare information for deleting use chain nodes */
1284+ rs1_delete_user = user ;
1285+ for (rs2_delete_user = i -> rs2 -> users_head ;
1286+ rs2_delete_user -> insn != rs1_delete_user -> insn ;
1287+ rs2_delete_user = rs2_delete_user -> next )
1288+ ;
12261289 }
1227-
1228- insn -> opcode = OP_assign ;
1229- insn -> rs1 = def ;
12301290 return true;
12311291}
12321292
@@ -1466,6 +1526,8 @@ void optimize()
14661526 build_rdom ();
14671527 build_rdf ();
14681528
1529+ build_users ();
1530+
14691531 for (fn_t * fn = FUNC_LIST .head ; fn ; fn = fn -> next ) {
14701532 /* basic block level (control flow) optimizations */
14711533
0 commit comments