@@ -436,9 +436,9 @@ static unsigned Opt_toseqax_tosneax (StackOpData* D, const char* BoolTransformer
436436 X = NewCodeEntry (OP65_CMP , LoadA -> AM , LoadA -> Arg , 0 , D -> OpEntry -> LI );
437437 InsertEntry (D , X , D -> IP ++ );
438438
439- /* Rhs load entries must be removed */
440- D -> Rhs .X .Flags |= LI_REMOVE ;
441- D -> Rhs .A .Flags |= LI_REMOVE ;
439+ /* Rhs load entries must be removed because Lhs must be in effect */
440+ D -> Rhs .X .Flags |= ( LI_REMOVE | LI_MUST_REMOVE ) ;
441+ D -> Rhs .A .Flags |= ( LI_REMOVE | LI_MUST_REMOVE ) ;
442442
443443 } else if (RhsIsRemovable (D )) {
444444
@@ -454,6 +454,10 @@ static unsigned Opt_toseqax_tosneax (StackOpData* D, const char* BoolTransformer
454454 /* Add operand for high byte */
455455 AddOpHigh (D , OP65_CMP , & D -> Rhs , 0 );
456456
457+ /* Rhs load entries must be removed because Lhs must be in effect */
458+ D -> Rhs .X .Flags |= LI_MUST_REMOVE ;
459+ D -> Rhs .A .Flags |= LI_MUST_REMOVE ;
460+
457461 } else {
458462
459463 /* Implement the op via a temp ZP location */
@@ -1018,9 +1022,9 @@ static unsigned Opt_tosgeax (StackOpData* D)
10181022 X = NewCodeEntry (OP65_ROL , AM65_ACC , "a" , 0 , D -> OpEntry -> LI );
10191023 InsertEntry (D , X , D -> IP ++ );
10201024
1021- /* Rhs load entries must be removed */
1022- D -> Rhs .X .Flags |= LI_REMOVE ;
1023- D -> Rhs .A .Flags |= LI_REMOVE ;
1025+ /* Rhs load entries must be removed because Lhs must be in effect */
1026+ D -> Rhs .X .Flags |= LI_MUST_REMOVE ;
1027+ D -> Rhs .A .Flags |= LI_MUST_REMOVE ;
10241028
10251029 /* Remove the push and the call to the tosgeax function */
10261030 RemoveRemainders (D );
@@ -1075,9 +1079,9 @@ static unsigned Opt_tosltax (StackOpData* D)
10751079 X = NewCodeEntry (OP65_ROL , AM65_ACC , "a" , 0 , D -> OpEntry -> LI );
10761080 InsertEntry (D , X , D -> IP ++ );
10771081
1078- /* Rhs load entries must be removed */
1079- D -> Rhs .X .Flags |= LI_REMOVE ;
1080- D -> Rhs .A .Flags |= LI_REMOVE ;
1082+ /* Rhs load entries must be removed because Lhs must be in effect */
1083+ D -> Rhs .X .Flags |= LI_MUST_REMOVE ;
1084+ D -> Rhs .A .Flags |= LI_MUST_REMOVE ;
10811085
10821086 /* Remove the push and the call to the tosltax function */
10831087 RemoveRemainders (D );
@@ -1158,9 +1162,9 @@ static unsigned Opt_tossubax (StackOpData* D)
11581162 /* Add code for high operand */
11591163 AddOpHigh (D , OP65_SBC , & D -> Rhs , 1 );
11601164
1161- /* Rhs load entries must be removed */
1162- D -> Rhs .X .Flags |= LI_REMOVE ;
1163- D -> Rhs .A .Flags |= LI_REMOVE ;
1165+ /* Rhs load entries must be removed because Lhs must be in effect */
1166+ D -> Rhs .X .Flags |= LI_MUST_REMOVE ;
1167+ D -> Rhs .A .Flags |= LI_MUST_REMOVE ;
11641168
11651169 /* Remove the push and the call to the tossubax function */
11661170 RemoveRemainders (D );
@@ -1200,9 +1204,9 @@ static unsigned Opt_tosugeax (StackOpData* D)
12001204 X = NewCodeEntry (OP65_ROL , AM65_ACC , "a" , 0 , D -> OpEntry -> LI );
12011205 InsertEntry (D , X , D -> IP ++ );
12021206
1203- /* Rhs load entries must be removed */
1204- D -> Rhs .X .Flags |= LI_REMOVE ;
1205- D -> Rhs .A .Flags |= LI_REMOVE ;
1207+ /* Rhs load entries must be removed because Lhs must be in effect */
1208+ D -> Rhs .X .Flags |= LI_MUST_REMOVE ;
1209+ D -> Rhs .A .Flags |= LI_MUST_REMOVE ;
12061210
12071211 /* Remove the push and the call to the tosugeax function */
12081212 RemoveRemainders (D );
@@ -1246,9 +1250,9 @@ static unsigned Opt_tosugtax (StackOpData* D)
12461250 X = NewCodeEntry (OP65_JSR , AM65_ABS , "boolugt" , 0 , D -> OpEntry -> LI );
12471251 InsertEntry (D , X , D -> IP ++ );
12481252
1249- /* Rhs load entries must be removed */
1250- D -> Rhs .X .Flags |= LI_REMOVE ;
1251- D -> Rhs .A .Flags |= LI_REMOVE ;
1253+ /* Rhs load entries must be removed because Lhs must be in effect */
1254+ D -> Rhs .X .Flags |= LI_MUST_REMOVE ;
1255+ D -> Rhs .A .Flags |= LI_MUST_REMOVE ;
12521256
12531257 /* Remove the push and the call to the operator function */
12541258 RemoveRemainders (D );
@@ -1292,9 +1296,9 @@ static unsigned Opt_tosuleax (StackOpData* D)
12921296 X = NewCodeEntry (OP65_JSR , AM65_ABS , "boolule" , 0 , D -> OpEntry -> LI );
12931297 InsertEntry (D , X , D -> IP ++ );
12941298
1295- /* Rhs load entries must be removed */
1296- D -> Rhs .X .Flags |= LI_REMOVE ;
1297- D -> Rhs .A .Flags |= LI_REMOVE ;
1299+ /* Rhs load entries must be removed because Lhs must be in effect */
1300+ D -> Rhs .X .Flags |= LI_MUST_REMOVE ;
1301+ D -> Rhs .A .Flags |= LI_MUST_REMOVE ;
12981302
12991303 /* Remove the push and the call to the operator function */
13001304 RemoveRemainders (D );
@@ -1326,9 +1330,9 @@ static unsigned Opt_tosultax (StackOpData* D)
13261330 X = NewCodeEntry (OP65_JSR , AM65_ABS , "boolult" , 0 , D -> OpEntry -> LI );
13271331 InsertEntry (D , X , D -> IP ++ );
13281332
1329- /* Rhs load entries must be removed */
1330- D -> Rhs .X .Flags |= LI_REMOVE ;
1331- D -> Rhs .A .Flags |= LI_REMOVE ;
1333+ /* Rhs load entries must be removed because Lhs must be in effect */
1334+ D -> Rhs .X .Flags |= LI_MUST_REMOVE ;
1335+ D -> Rhs .A .Flags |= LI_MUST_REMOVE ;
13321336
13331337 /* Remove the push and the call to the operator function */
13341338 RemoveRemainders (D );
@@ -1396,8 +1400,8 @@ static unsigned Opt_a_tosbitwise (StackOpData* D, opc_t OPC)
13961400 X = NewCodeEntry (OPC , D -> Rhs .A .LoadEntry -> AM , D -> Rhs .A .LoadEntry -> Arg , 0 , D -> OpEntry -> LI );
13971401 InsertEntry (D , X , D -> IP ++ );
13981402
1399- /* Rhs load entries must be removed */
1400- D -> Rhs .A .Flags |= LI_REMOVE ;
1403+ /* Rhs A load must be removed because Lhs must be in effect */
1404+ D -> Rhs .A .Flags |= ( LI_REMOVE | LI_MUST_REMOVE ) ;
14011405
14021406 } else if (RegIsDirectNonStackLoaded (& D -> Lhs .A )) {
14031407
@@ -1419,12 +1423,10 @@ static unsigned Opt_a_tosbitwise (StackOpData* D, opc_t OPC)
14191423 InsertEntry (D , X , D -> IP ++ );
14201424 }
14211425
1422- /* ### Bug to come: there are dangerous Rhs X removal attempts here.
1423- ** Runtime function calls can be "loads", and must be treated as a
1424- ** single A/X unit, so removal of X load alone is not valid.
1425- ** This can be solved with an additional "removable Rhs" test, or
1426- ** by simply not forcing the LI_REMOVE flag and letting other optimizers
1427- ** remove any unnecessary loads.
1426+ /* Note: Eager Rhs X removals here can sometimes produce slightly worse
1427+ ** code after all other optimizers have run. This may need a general
1428+ ** study of which is better: eager removal, or letting other optimizers
1429+ ** take care of unneeded loads.
14281430 */
14291431 /* Do high-byte operation only when its result is used */
14301432 if ((GetRegInfo (D -> Code , D -> IP , REG_X ) & REG_X ) != 0 ) {
@@ -1433,10 +1435,12 @@ static unsigned Opt_a_tosbitwise (StackOpData* D, opc_t OPC)
14331435 /* Since this is a "same X" EOR, the result is always 0. */
14341436 X = NewCodeEntry (OP65_LDX , AM65_IMM , MakeHexArg (0 ), 0 , D -> Rhs .X .ChgEntry -> LI );
14351437 InsertEntry (D , X , D -> IP ++ );
1438+
1439+ /* Rhs X load may be removed (but this is not a demand) */
14361440 D -> Rhs .X .Flags |= LI_REMOVE ;
14371441 }
14381442 } else {
1439- /* Rhs load entries may be removed */
1443+ /* Rhs X load may be removed (but this is not a demand) */
14401444 D -> Rhs .X .Flags |= LI_REMOVE ;
14411445 }
14421446
@@ -1464,7 +1468,7 @@ static unsigned Opt_a_toscmpbool (StackOpData* D, const char* BoolTransformer)
14641468
14651469 /* Rhs low-byte load must be removed and hi-byte load may be removed */
14661470 D -> Rhs .X .Flags |= LI_REMOVE ;
1467- D -> Rhs .A .Flags |= LI_REMOVE ;
1471+ D -> Rhs .A .Flags |= LI_MUST_REMOVE ;
14681472
14691473 } else if (RegIsDirectLoaded (& D -> Lhs .A )) {
14701474 /* If the lhs is direct (but not stack relative), encode compares with lhs,
@@ -1604,7 +1608,9 @@ static unsigned Opt_a_tosicmp (StackOpData* D)
16041608 InsertEntry (D , X , D -> IP ++ );
16051609 }
16061610
1607- /* RHS may be removed */
1611+ /* RHS may be removed, but it is not a demand because Lhs was
1612+ ** reloaded at Op and is in effect.
1613+ */
16081614 D -> Rhs .A .Flags |= LI_REMOVE ;
16091615 D -> Rhs .X .Flags |= LI_REMOVE ;
16101616 }
@@ -1703,9 +1709,11 @@ static unsigned Opt_a_tossub (StackOpData* D)
17031709 InsertEntry (D , X , D -> IP ++ );
17041710 }
17051711
1706- /* Rhs load entries must be removed */
1712+ /* Rhs low-byte load must be removed (because Lhs must be in effect)
1713+ ** and hi-byte load may be removed.
1714+ */
17071715 D -> Rhs .X .Flags |= LI_REMOVE ;
1708- D -> Rhs .A .Flags |= LI_REMOVE ;
1716+ D -> Rhs .A .Flags |= LI_MUST_REMOVE ;
17091717
17101718 /* Remove the push and the call to the tossubax function */
17111719 RemoveRemainders (D );
0 commit comments