@@ -401,6 +401,54 @@ void build_rdf()
401
401
free (args );
402
402
}
403
403
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
+
404
452
bool var_check_killed (var_t * var , basic_block_t * bb )
405
453
{
406
454
for (int i = 0 ; i < bb -> live_kill_idx ; i ++ ) {
@@ -1170,63 +1218,80 @@ void ssa_build(int dump_ir)
1170
1218
}
1171
1219
1172
1220
/* Common Subexpression Elimination (CSE) */
1173
- /* TODO: simplify with def-use chain */
1174
1221
/* TODO: release detached insns node */
1175
1222
bool cse (insn_t * insn , basic_block_t * bb )
1176
1223
{
1177
1224
if (insn -> opcode != OP_read )
1178
1225
return false;
1179
1226
1180
1227
insn_t * prev = insn -> prev ;
1181
-
1182
1228
if (!prev )
1183
1229
return false;
1184
1230
if (prev -> opcode != OP_add )
1185
1231
return false;
1186
1232
if (prev -> rd != insn -> rs1 )
1187
1233
return false;
1188
1234
1189
- var_t * def = NULL , * base = prev -> rs1 , * idx = prev -> rs2 ;
1235
+ var_t * def = insn -> rd , * base = prev -> rs1 , * idx = prev -> rs2 ;
1190
1236
if (base -> is_global || idx -> is_global )
1191
1237
return false;
1192
1238
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 ;
1216
1243
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 ;
1219
1276
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
+ ;
1226
1294
}
1227
-
1228
- insn -> opcode = OP_assign ;
1229
- insn -> rs1 = def ;
1230
1295
return true;
1231
1296
}
1232
1297
@@ -1466,6 +1531,8 @@ void optimize()
1466
1531
build_rdom ();
1467
1532
build_rdf ();
1468
1533
1534
+ use_chain_build ();
1535
+
1469
1536
for (fn_t * fn = FUNC_LIST .head ; fn ; fn = fn -> next ) {
1470
1537
/* basic block level (control flow) optimizations */
1471
1538
0 commit comments