Prevent Lhs load insns shared with the Rhs from being inadvertently removed by Rhs optimizers. Fixes issue #2947.

This commit is contained in:
Alex Volkov
2026-03-22 19:42:57 -04:00
parent af285ba9e5
commit d711b6d6fa
3 changed files with 73 additions and 0 deletions

View File

@@ -509,6 +509,68 @@ void SetIfOperandLoadUnremovable (LoadInfo* LI, unsigned Used)
static int IsRegInsnSameAsOtherAX (int InsnIndex, const LoadInfo* OtherLI)
/* Helper: Return true if the other side (Rhs or Lhs) refers to the same insn */
{
if (InsnIndex < 0) {
/* No, do not have an insn */
return 0;
}
/* Check if this insn matches any load/change on the other side */
return InsnIndex == OtherLI->A.LoadIndex ||
InsnIndex == OtherLI->A.ChgIndex ||
InsnIndex == OtherLI->X.LoadIndex ||
InsnIndex == OtherLI->X.ChgIndex;
}
static int IsRegInsnSameAsOtherY (int InsnIndex, const LoadInfo* OtherLI)
/* Helper: Return true if the other side (Rhs or Lhs) refers to the same insn */
{
if (InsnIndex < 0) {
/* No, do not have an insn */
return 0;
}
/* Check if this insn matches any load/change on the other side */
return InsnIndex == OtherLI->Y.LoadIndex ||
InsnIndex == OtherLI->Y.ChgIndex;
}
void SetUnremovableIfUsedByOther (LoadInfo* LI, const LoadInfo* OtherLI)
/* Check and flag operand loads unremovable if the other side (Rhs or Lhs)
** uses the same load insn (checked by index).
*/
{
/* Disallow removing the loads if they are shared between Lhs and Rhs.
** Note: For safety, we check the ChgIndex as well, which accounts for
** conditions where a label is encountered in the block.
*/
if (IsRegInsnSameAsOtherAX (LI->A.LoadIndex, OtherLI) ||
IsRegInsnSameAsOtherAX (LI->A.ChgIndex, OtherLI)) {
/* Parts of A load are used by other and cannot be removed */
LI->A.Flags |= LI_DONT_REMOVE;
}
if (IsRegInsnSameAsOtherAX (LI->X.LoadIndex, OtherLI) ||
IsRegInsnSameAsOtherAX (LI->X.ChgIndex, OtherLI)) {
/* Parts of X load are used by other and cannot be removed */
LI->X.Flags |= LI_DONT_REMOVE;
}
if (IsRegInsnSameAsOtherY (LI->Y.LoadIndex, OtherLI) ||
IsRegInsnSameAsOtherY (LI->Y.ChgIndex, OtherLI)) {
/* Parts of Y load are used by other and cannot be removed */
LI->Y.Flags |= LI_DONT_REMOVE;
}
}
unsigned int TrackLoads (LoadInfo* LI, CodeSeg* S, int I) unsigned int TrackLoads (LoadInfo* LI, CodeSeg* S, int I)
/* Track loads for a code entry. /* Track loads for a code entry.
** Return used registers. ** Return used registers.

View File

@@ -180,6 +180,11 @@ void SetIfOperandSrcAffected (LoadInfo* LLI, CodeEntry* E);
void SetIfOperandLoadUnremovable (LoadInfo* LI, unsigned Used); void SetIfOperandLoadUnremovable (LoadInfo* LI, unsigned Used);
/* Check and flag operand load that may be unremovable */ /* Check and flag operand load that may be unremovable */
void SetUnremovableIfUsedByOther (LoadInfo* LI, const LoadInfo* OtherLI);
/* Check and flag operand loads unremovable if the other side (Rhs or Lhs)
** uses the same load insn (checked by index).
*/
unsigned int TrackLoads (LoadInfo* LI, CodeSeg* S, int I); unsigned int TrackLoads (LoadInfo* LI, CodeSeg* S, int I);
/* Track loads for a code entry. /* Track loads for a code entry.
** Return used registers. ** Return used registers.

View File

@@ -2090,6 +2090,12 @@ unsigned OptStackOps (CodeSeg* S)
} }
} }
/* Lhs and Rhs may shared some of the load insns; or due to how
** the labels are processed, "change" insns may refer to the
** others' loads. In either case, it is unsafe to remove them.
*/
SetUnremovableIfUsedByOther (&Data.Lhs, &Data.Rhs);
/* Flag entries that can't be removed */ /* Flag entries that can't be removed */
SetDontRemoveEntryFlags (&Data); SetDontRemoveEntryFlags (&Data);