Prevent Lhs load insns shared with the Rhs from being inadvertently removed by Rhs optimizers. Fixes issue #2947.
This commit is contained in:
@@ -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)
|
||||
/* Track loads for a code entry.
|
||||
** Return used registers.
|
||||
|
||||
@@ -180,6 +180,11 @@ void SetIfOperandSrcAffected (LoadInfo* LLI, CodeEntry* E);
|
||||
void SetIfOperandLoadUnremovable (LoadInfo* LI, unsigned Used);
|
||||
/* 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);
|
||||
/* Track loads for a code entry.
|
||||
** Return used registers.
|
||||
|
||||
@@ -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 */
|
||||
SetDontRemoveEntryFlags (&Data);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user