@@ -1220,78 +1220,146 @@ void ssa_build(void)
12201220/* TODO: release detached insns node */
12211221bool cse (insn_t * insn , basic_block_t * bb )
12221222{
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;
12251232
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;
12331236
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 ;
12371260
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 ;
12421274
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+ ;
12511292 }
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;
12691320 }
1270- if (i_bb == i_bb -> idom )
1271- break ;
12721321 }
1273- if (! check_dom )
1274- continue ;
1322+ return false;
1323+ }
12751324
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+ }
12841358 }
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;
12931360 }
1294- return true;
1361+
1362+ return false;
12951363}
12961364
12971365bool mark_const (insn_t * insn )
0 commit comments