@@ -1238,82 +1238,140 @@ void ssa_build(void)
1238
1238
unwind_phi ();
1239
1239
}
1240
1240
1241
+ /* Check if operation can be subject to CSE */
1242
+ bool is_cse_candidate (insn_t * insn )
1243
+ {
1244
+ switch (insn -> opcode ) {
1245
+ case OP_add :
1246
+ case OP_sub :
1247
+ case OP_mul :
1248
+ case OP_div :
1249
+ case OP_mod :
1250
+ case OP_lshift :
1251
+ case OP_rshift :
1252
+ case OP_bit_and :
1253
+ case OP_bit_or :
1254
+ case OP_bit_xor :
1255
+ case OP_log_and :
1256
+ case OP_log_or :
1257
+ case OP_eq :
1258
+ case OP_neq :
1259
+ case OP_lt :
1260
+ case OP_leq :
1261
+ case OP_gt :
1262
+ case OP_geq :
1263
+ return true;
1264
+ default :
1265
+ return false;
1266
+ }
1267
+ }
1268
+
1241
1269
/* Common Subexpression Elimination (CSE) */
1242
- /* TODO: release detached insns node */
1270
+ /* Enhanced to support general binary operations */
1243
1271
bool cse (insn_t * insn , basic_block_t * bb )
1244
1272
{
1245
- if (insn -> opcode != OP_read )
1246
- return false;
1273
+ /* Handle array access pattern: add + read */
1274
+ if (insn -> opcode == OP_read ) {
1275
+ insn_t * prev = insn -> prev ;
1276
+ if (!prev )
1277
+ return false;
1278
+ if (prev -> opcode != OP_add )
1279
+ return false;
1280
+ if (prev -> rd != insn -> rs1 )
1281
+ return false;
1247
1282
1248
- insn_t * prev = insn -> prev ;
1249
- if (!prev )
1250
- return false;
1251
- if (prev -> opcode != OP_add )
1283
+ var_t * def = insn -> rd , * base = prev -> rs1 , * idx = prev -> rs2 ;
1284
+ if (base -> is_global || idx -> is_global )
1285
+ return false;
1286
+
1287
+ /* Look for identical add+read patterns */
1288
+ for (use_chain_t * user = base -> users_head ; user ; user = user -> next ) {
1289
+ insn_t * i = user -> insn ;
1290
+ if (i == prev )
1291
+ continue ;
1292
+ if (i -> opcode != OP_add )
1293
+ continue ;
1294
+ if (!i -> next )
1295
+ continue ;
1296
+ if (i -> next -> opcode != OP_read )
1297
+ continue ;
1298
+ if (i -> rs1 != base || i -> rs2 != idx )
1299
+ continue ;
1300
+
1301
+ /* Check dominance */
1302
+ basic_block_t * i_bb = i -> belong_to ;
1303
+ bool check_dom = false;
1304
+ for (;; i_bb = i_bb -> idom ) {
1305
+ if (i_bb == bb ) {
1306
+ check_dom = true;
1307
+ break ;
1308
+ }
1309
+ if (i_bb == i_bb -> idom )
1310
+ break ;
1311
+ }
1312
+ if (!check_dom )
1313
+ continue ;
1314
+
1315
+ /* Replace with assignment */
1316
+ i -> next -> opcode = OP_assign ;
1317
+ i -> next -> rs1 = def ;
1318
+ if (i -> prev ) {
1319
+ i -> prev -> next = i -> next ;
1320
+ i -> next -> prev = i -> prev ;
1321
+ } else {
1322
+ i -> belong_to -> insn_list .head = i -> next ;
1323
+ i -> next -> prev = NULL ;
1324
+ }
1325
+ }
1326
+ return true;
1327
+ }
1328
+
1329
+ /* Handle general binary operations */
1330
+ if (!is_cse_candidate (insn ))
1252
1331
return false;
1253
- if (prev -> rd != insn -> rs1 )
1332
+
1333
+ if (!insn -> rs1 || !insn -> rs2 || !insn -> rd )
1254
1334
return false;
1255
1335
1256
- var_t * def = insn -> rd , * base = prev -> rs1 , * idx = prev -> rs2 ;
1257
- if (base -> is_global || idx -> is_global )
1336
+ /* Don't CSE operations with global variables */
1337
+ if (insn -> rs1 -> is_global || insn -> rs2 -> is_global )
1258
1338
return false;
1259
1339
1260
- use_chain_t * rs1_delete_user = NULL ;
1261
- use_chain_t * rs2_delete_user = NULL ;
1262
- for ( use_chain_t * user = base -> users_head ; user ; user = user -> next ) {
1263
- insn_t * i = user -> insn ;
1340
+ /* Look for identical binary operations */
1341
+ for ( insn_t * other = bb -> insn_list . head ; other ; other = other -> next ) {
1342
+ if ( other == insn )
1343
+ break ; /* Only consider earlier instructions */
1264
1344
1265
- /* Delete the use chain nodes found in the last loop */
1266
- if (rs1_delete_user ) {
1267
- use_chain_delete (rs1_delete_user , rs1_delete_user -> insn -> rs1 );
1268
- rs1_delete_user = NULL ;
1269
- }
1270
- if (rs2_delete_user ) {
1271
- use_chain_delete (rs2_delete_user , rs2_delete_user -> insn -> rs2 );
1272
- rs2_delete_user = NULL ;
1273
- }
1274
- if (i == prev )
1275
- continue ;
1276
- if (i -> opcode != OP_add )
1277
- continue ;
1278
- if (!i -> next )
1345
+ if (other -> opcode != insn -> opcode )
1279
1346
continue ;
1280
- if (i -> next -> opcode != OP_read )
1347
+ if (! other -> rs1 || ! other -> rs2 || ! other -> rd )
1281
1348
continue ;
1282
- if (i -> rs1 != base || i -> rs2 != idx )
1283
- continue ;
1284
- basic_block_t * i_bb = i -> belong_to ;
1285
- bool check_dom = 0 ;
1286
- /* Check if the instructions are under the same dominate tree */
1287
- for (;; i_bb = i_bb -> idom ) {
1288
- if (i_bb == bb ) {
1289
- check_dom = true;
1290
- break ;
1349
+
1350
+ /* Check if operands match */
1351
+ bool operands_match = false;
1352
+ if (other -> rs1 == insn -> rs1 && other -> rs2 == insn -> rs2 ) {
1353
+ operands_match = true;
1354
+ } else if (insn -> opcode == OP_add || insn -> opcode == OP_mul ||
1355
+ insn -> opcode == OP_bit_and || insn -> opcode == OP_bit_or ||
1356
+ insn -> opcode == OP_bit_xor || insn -> opcode == OP_log_and ||
1357
+ insn -> opcode == OP_log_or || insn -> opcode == OP_eq ||
1358
+ insn -> opcode == OP_neq ) {
1359
+ /* Commutative operations */
1360
+ if (other -> rs1 == insn -> rs2 && other -> rs2 == insn -> rs1 ) {
1361
+ operands_match = true;
1291
1362
}
1292
- if (i_bb == i_bb -> idom )
1293
- break ;
1294
1363
}
1295
- if (!check_dom )
1296
- continue ;
1297
1364
1298
- i -> next -> opcode = OP_assign ;
1299
- i -> next -> rs1 = def ;
1300
- if (i -> prev ) {
1301
- i -> prev -> next = i -> next ;
1302
- i -> next -> prev = i -> prev ;
1303
- } else {
1304
- i -> belong_to -> insn_list .head = i -> next ;
1305
- i -> next -> prev = NULL ;
1365
+ if (operands_match ) {
1366
+ /* Replace current instruction with assignment */
1367
+ insn -> opcode = OP_assign ;
1368
+ insn -> rs1 = other -> rd ;
1369
+ insn -> rs2 = NULL ;
1370
+ return true;
1306
1371
}
1307
- i -> next -> opcode = OP_assign ;
1308
- i -> next -> rs1 = def ;
1309
- /* Prepare information for deleting use chain nodes */
1310
- rs1_delete_user = user ;
1311
- for (rs2_delete_user = i -> rs2 -> users_head ;
1312
- rs2_delete_user -> insn != rs1_delete_user -> insn ;
1313
- rs2_delete_user = rs2_delete_user -> next )
1314
- ;
1315
1372
}
1316
- return true;
1373
+
1374
+ return false;
1317
1375
}
1318
1376
1319
1377
bool mark_const (insn_t * insn )
0 commit comments