@@ -1225,78 +1225,146 @@ void ssa_build(void)
1225
1225
/* TODO: release detached insns node */
1226
1226
bool cse (insn_t * insn , basic_block_t * bb )
1227
1227
{
1228
- if (insn -> opcode != OP_read )
1229
- return false;
1228
+ /* Handle memory reads */
1229
+ if (insn -> opcode == OP_read ) {
1230
+ insn_t * prev = insn -> prev ;
1231
+ if (!prev )
1232
+ return false;
1233
+ if (prev -> opcode != OP_add )
1234
+ return false;
1235
+ if (prev -> rd != insn -> rs1 )
1236
+ return false;
1230
1237
1231
- insn_t * prev = insn -> prev ;
1232
- if (!prev )
1233
- return false;
1234
- if (prev -> opcode != OP_add )
1235
- return false;
1236
- if (prev -> rd != insn -> rs1 )
1237
- return false;
1238
+ var_t * def = insn -> rd , * base = prev -> rs1 , * idx = prev -> rs2 ;
1239
+ if (base -> is_global || idx -> is_global )
1240
+ return false;
1238
1241
1239
- var_t * def = insn -> rd , * base = prev -> rs1 , * idx = prev -> rs2 ;
1240
- if (base -> is_global || idx -> is_global )
1241
- return false;
1242
+ use_chain_t * rs1_delete_user = NULL , * rs2_delete_user = NULL ;
1243
+ for (use_chain_t * user = base -> users_head ; user ; user = user -> next ) {
1244
+ insn_t * i = user -> insn ;
1245
+
1246
+ /* Delete the use chain nodes found in the last loop */
1247
+ if (rs1_delete_user ) {
1248
+ use_chain_delete (rs1_delete_user , rs1_delete_user -> insn -> rs1 );
1249
+ rs1_delete_user = NULL ;
1250
+ }
1251
+ if (rs2_delete_user ) {
1252
+ use_chain_delete (rs2_delete_user , rs2_delete_user -> insn -> rs2 );
1253
+ rs2_delete_user = NULL ;
1254
+ }
1255
+ if (i == prev )
1256
+ continue ;
1257
+ if (i -> opcode != OP_add )
1258
+ continue ;
1259
+ if (!i -> next )
1260
+ continue ;
1261
+ if (i -> next -> opcode != OP_read )
1262
+ continue ;
1263
+ if (i -> rs1 != base || i -> rs2 != idx )
1264
+ continue ;
1242
1265
1243
- use_chain_t * rs1_delete_user = NULL ;
1244
- use_chain_t * rs2_delete_user = NULL ;
1245
- for (use_chain_t * user = base -> users_head ; user ; user = user -> next ) {
1246
- insn_t * i = user -> insn ;
1266
+ basic_block_t * i_bb = i -> belong_to ;
1267
+ bool check_dom = 0 ;
1268
+ /* Check if the instructions are under the same dominate tree */
1269
+ for (;; i_bb = i_bb -> idom ) {
1270
+ if (i_bb == bb ) {
1271
+ check_dom = true;
1272
+ break ;
1273
+ }
1274
+ if (i_bb == i_bb -> idom )
1275
+ break ;
1276
+ }
1277
+ if (!check_dom )
1278
+ continue ;
1247
1279
1248
- /* Delete the use chain nodes found in the last loop */
1249
- if (rs1_delete_user ) {
1250
- use_chain_delete (rs1_delete_user , rs1_delete_user -> insn -> rs1 );
1251
- rs1_delete_user = NULL ;
1252
- }
1253
- if (rs2_delete_user ) {
1254
- use_chain_delete (rs2_delete_user , rs2_delete_user -> insn -> rs2 );
1255
- rs2_delete_user = NULL ;
1280
+ i -> next -> opcode = OP_assign ;
1281
+ i -> next -> rs1 = def ;
1282
+ if (i -> prev ) {
1283
+ i -> prev -> next = i -> next ;
1284
+ i -> next -> prev = i -> prev ;
1285
+ } else {
1286
+ i -> belong_to -> insn_list .head = i -> next ;
1287
+ i -> next -> prev = NULL ;
1288
+ }
1289
+ i -> next -> opcode = OP_assign ;
1290
+ i -> next -> rs1 = def ;
1291
+ /* Prepare information for deleting use chain nodes */
1292
+ rs1_delete_user = user ;
1293
+ for (rs2_delete_user = i -> rs2 -> users_head ;
1294
+ rs2_delete_user -> insn != rs1_delete_user -> insn ;
1295
+ rs2_delete_user = rs2_delete_user -> next )
1296
+ ;
1256
1297
}
1257
- if (i == prev )
1258
- continue ;
1259
- if (i -> opcode != OP_add )
1260
- continue ;
1261
- if (!i -> next )
1262
- continue ;
1263
- if (i -> next -> opcode != OP_read )
1264
- continue ;
1265
- if (i -> rs1 != base || i -> rs2 != idx )
1266
- continue ;
1267
- basic_block_t * i_bb = i -> belong_to ;
1268
- bool check_dom = 0 ;
1269
- /* Check if the instructions are under the same dominate tree */
1270
- for (;; i_bb = i_bb -> idom ) {
1271
- if (i_bb == bb ) {
1272
- check_dom = true;
1273
- break ;
1298
+ return true;
1299
+ }
1300
+
1301
+ /* Handle non-commutative binary operations (OP_sub, OP_div) */
1302
+ if (insn -> opcode == OP_sub || insn -> opcode == OP_div ) {
1303
+ if (!insn -> rs1 || !insn -> rs2 || !insn -> rd )
1304
+ return false;
1305
+
1306
+ /* Don't CSE operations with global variables (safety) */
1307
+ if (insn -> rs1 -> is_global || insn -> rs2 -> is_global )
1308
+ return false;
1309
+
1310
+ /* Look for identical expressions in the same basic block */
1311
+ for (insn_t * candidate = bb -> insn_list .head ;
1312
+ candidate && candidate != insn ; candidate = candidate -> next ) {
1313
+ if (candidate -> opcode != insn -> opcode || !candidate -> rd )
1314
+ continue ;
1315
+
1316
+ if (!candidate -> rs1 || !candidate -> rs2 )
1317
+ continue ;
1318
+
1319
+ /* Check for exact match only (no commutativity for sub/div) */
1320
+ if (candidate -> rs1 == insn -> rs1 && candidate -> rs2 == insn -> rs2 ) {
1321
+ insn -> opcode = OP_assign ;
1322
+ insn -> rs1 = candidate -> rd ;
1323
+ insn -> rs2 = NULL ;
1324
+ return true;
1274
1325
}
1275
- if (i_bb == i_bb -> idom )
1276
- break ;
1277
1326
}
1278
- if (! check_dom )
1279
- continue ;
1327
+ return false;
1328
+ }
1280
1329
1281
- i -> next -> opcode = OP_assign ;
1282
- i -> next -> rs1 = def ;
1283
- if (i -> prev ) {
1284
- i -> prev -> next = i -> next ;
1285
- i -> next -> prev = i -> prev ;
1286
- } else {
1287
- i -> belong_to -> insn_list .head = i -> next ;
1288
- i -> next -> prev = NULL ;
1330
+ /* Handle commutative binary operations (OP_add, OP_mul) */
1331
+ if (insn -> opcode == OP_add || insn -> opcode == OP_mul ) {
1332
+ if (!insn -> rs1 || !insn -> rs2 || !insn -> rd )
1333
+ return false;
1334
+
1335
+ /* Don't CSE operations with global variables (safety) */
1336
+ if (insn -> rs1 -> is_global || insn -> rs2 -> is_global )
1337
+ return false;
1338
+
1339
+ /* Look for identical expressions in the same basic block */
1340
+ for (insn_t * candidate = bb -> insn_list .head ;
1341
+ candidate && candidate != insn ; candidate = candidate -> next ) {
1342
+ if (candidate -> opcode != insn -> opcode || !candidate -> rd )
1343
+ continue ;
1344
+
1345
+ if (!candidate -> rs1 || !candidate -> rs2 )
1346
+ continue ;
1347
+
1348
+ /* Check for exact match: a op b */
1349
+ if (candidate -> rs1 == insn -> rs1 && candidate -> rs2 == insn -> rs2 ) {
1350
+ insn -> opcode = OP_assign ;
1351
+ insn -> rs1 = candidate -> rd ;
1352
+ insn -> rs2 = NULL ;
1353
+ return true;
1354
+ }
1355
+
1356
+ /* Check for commutative match: b op a = a op b */
1357
+ if (candidate -> rs1 == insn -> rs2 && candidate -> rs2 == insn -> rs1 ) {
1358
+ insn -> opcode = OP_assign ;
1359
+ insn -> rs1 = candidate -> rd ;
1360
+ insn -> rs2 = NULL ;
1361
+ return true;
1362
+ }
1289
1363
}
1290
- i -> next -> opcode = OP_assign ;
1291
- i -> next -> rs1 = def ;
1292
- /* Prepare information for deleting use chain nodes */
1293
- rs1_delete_user = user ;
1294
- for (rs2_delete_user = i -> rs2 -> users_head ;
1295
- rs2_delete_user -> insn != rs1_delete_user -> insn ;
1296
- rs2_delete_user = rs2_delete_user -> next )
1297
- ;
1364
+ return false;
1298
1365
}
1299
- return true;
1366
+
1367
+ return false;
1300
1368
}
1301
1369
1302
1370
bool mark_const (insn_t * insn )
0 commit comments