@@ -1238,82 +1238,140 @@ void ssa_build(void)
12381238 unwind_phi ();
12391239}
12401240
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+
12411269/* Common Subexpression Elimination (CSE) */
1242- /* TODO: release detached insns node */
1270+ /* Enhanced to support general binary operations */
12431271bool cse (insn_t * insn , basic_block_t * bb )
12441272{
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;
12471282
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 ))
12521331 return false;
1253- if (prev -> rd != insn -> rs1 )
1332+
1333+ if (!insn -> rs1 || !insn -> rs2 || !insn -> rd )
12541334 return false;
12551335
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 )
12581338 return false;
12591339
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 */
12641344
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 )
12791346 continue ;
1280- if (i -> next -> opcode != OP_read )
1347+ if (! other -> rs1 || ! other -> rs2 || ! other -> rd )
12811348 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;
12911362 }
1292- if (i_bb == i_bb -> idom )
1293- break ;
12941363 }
1295- if (!check_dom )
1296- continue ;
12971364
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;
13061371 }
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- ;
13151372 }
1316- return true;
1373+
1374+ return false;
13171375}
13181376
13191377bool mark_const (insn_t * insn )
0 commit comments