while (I < Count-1) {
/* Get the next entry */
- E = CollAt (&S->Entries, I);
+ E = GetCodeEntry (S, I);
/* Check if it's a branch, if it has a local target, and if the target
* is the next instruction.
*/
- if (E->AM == AM_BRA && E->JumpTo && E->JumpTo->Owner == CollAt (&S->Entries, I+1)) {
+ if (E->AM == AM_BRA && E->JumpTo && E->JumpTo->Owner == GetCodeEntry (S, I+1)) {
/* Delete the dead jump */
DelCodeEntry (S, I);
while (I < Count-1) {
/* Get this entry */
- CodeEntry* E = CollAt (&S->Entries, I);
+ CodeEntry* E = GetCodeEntry (S, I);
/* Check if it's an unconditional branch, and if the next entry has
* no labels attached
*/
- if ((E->OPC == OPC_JMP || E->OPC == OPC_BRA || E->OPC == OPC_RTS || E->OPC == OPC_RTI) &&
- !CodeEntryHasLabel (CollAt (&S->Entries, I+1))) {
+ if ((E->Info & OF_DEAD) != 0 && !CodeEntryHasLabel (GetCodeEntry (S, I+1))) {
/* Delete the next entry */
DelCodeEntry (S, I+1);
CodeLabel* NewLabel;
/* Get this entry */
- CodeEntry* E = CollAt (&S->Entries, I);
+ CodeEntry* E = GetCodeEntry (S, I);
/* Check if it's a branch, if it has a label attached, and if the
- * instruction at this label is also a branch.
+ * instruction at this label is also a branch, and (important) if
+ * both instructions are not identical.
*/
- if (E->AM == AM_BRA &&
- (OldLabel = E->JumpTo) != 0 &&
- OldLabel->Owner->AM == AM_BRA &&
- (NewLabel = OldLabel->Owner->JumpTo) != 0) {
+ if (E->AM == AM_BRA && /* It's a branch */
+ (OldLabel = E->JumpTo) != 0 && /* Label attached */
+ OldLabel->Owner->AM == AM_BRA && /* Jumps to a branch.. */
+ (NewLabel = OldLabel->Owner->JumpTo) != 0 && /* ..which has a label */
+ OldLabel->Owner != E) { /* And both are distinct */
/* Get the instruction that has the new label attached */
CodeEntry* N = OldLabel->Owner;
+/*****************************************************************************/
+/* Optimize jsr/rts */
+/*****************************************************************************/
+
+
+
+static void OptRTS (CodeSeg* S)
+/* Optimize subroutine calls followed by an RTS. The subroutine call will get
+ * replaced by a jump. Don't bother to delete the RTS if it does not have a
+ * label, the dead code elimination should take care of it.
+ */
+{
+ unsigned I;
+
+ /* Get the number of entries, bail out if we have less than 2 entries */
+ unsigned Count = CollCount (&S->Entries);
+ if (Count < 2) {
+ return;
+ }
+
+ /* Walk over all entries minus the last one */
+ I = 0;
+ while (I < Count-1) {
+
+ /* Get this entry */
+ CodeEntry* E = GetCodeEntry (S, I);
+
+ /* Check if it's a subroutine call and if the following insn is RTS */
+ if (E->OPC == OPC_JSR && GetCodeEntry(S,I+1)->OPC == OPC_RTS) {
+
+ /* Change the jsr to a jmp */
+ E->OPC = OPC_JMP;
+
+ /* Change the opcode info to that of the jump */
+ E->Info = GetOPCInfo (OPC_JMP);
+
+ /* Remember, we had changes */
+ ++OptChanges;
+
+ }
+
+ /* Next entry */
+ ++I;
+
+ }
+}
+
+
+
+/*****************************************************************************/
+/* Optimize jump targets */
+/*****************************************************************************/
+
+
+
+static void OptJumpTarget (CodeSeg* S)
+/* If the instruction preceeding an unconditional branch is the same as the
+ * instruction preceeding the jump target, the jump target may be moved
+ * one entry back. This is a size optimization, since the instruction before
+ * the branch gets removed.
+ */
+{
+ unsigned I;
+
+ /* Get the number of entries, bail out if we have not enough */
+ unsigned Count = CollCount (&S->Entries);
+ if (Count < 3) {
+ return;
+ }
+
+ /* Walk over all entries minus the first one */
+ I = 1;
+ while (I < Count) {
+
+ /* Get this entry and the entry before this one */
+ CodeEntry* E = GetCodeEntry (S, I);
+
+ /* Check if we have a jump or branch, and a matching label */
+ if ((E->Info & OF_UBRA) != 0 && E->JumpTo) {
+
+ /* Remember, we had changes */
+ ++OptChanges;
+
+ }
+
+ /* Next entry */
+ ++I;
+
+ }
+}
+
+
+
/*****************************************************************************/
/* Code */
/*****************************************************************************/
/* Table with optimizer steps - are called in this order */
static const OptFunc OptFuncs [] = {
- OptJumpCascades, /* Optimize jump cascades */
- OptDeadJumps, /* Remove dead jumps */
- OptDeadCode, /* Remove dead code */
+ OptJumpCascades, /* Optimize jump cascades */
+ OptDeadJumps, /* Remove dead jumps */
+ OptDeadCode, /* Remove dead code */
+ OptRTS, /* Change jsr/rts to jmp */
};
/* Repeat all steps until there are no more changes */
Flags = 1UL;
for (I = 0; I < sizeof(OptFuncs)/sizeof(OptFuncs[0]); ++I) {
if ((OptDisable & Flags) == 0) {
- OptFuncs[I] (S);
+ OptFuncs[I] (S);
} else if (Verbosity > 0 || Debug) {
- printf ("Optimizer pass %u skipped\n", I);
+ printf ("Optimizer pass %u skipped\n", I);
}
Flags <<= 1;
}