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