]> git.sur5r.net Git - cc65/blobdiff - src/cc65/codeopt.c
Working on the backend
[cc65] / src / cc65 / codeopt.c
index 72d425d830775edadd42c0cb598447d65a1e77c6..24193418748bf9eda60bd4a5756faa0d87bd754b 100644 (file)
@@ -80,12 +80,12 @@ static void OptDeadJumps (CodeSeg* S)
     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);
@@ -131,13 +131,12 @@ static void OptDeadCode (CodeSeg* S)
     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);
@@ -189,15 +188,17 @@ static void OptJumpCascades (CodeSeg* S)
        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;
@@ -230,6 +231,99 @@ static void OptJumpCascades (CodeSeg* S)
 
 
 
+/*****************************************************************************/
+/*                            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                                    */
 /*****************************************************************************/
@@ -243,9 +337,10 @@ void RunOpt (CodeSeg* S)
 
     /* 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 */
@@ -261,9 +356,9 @@ void RunOpt (CodeSeg* S)
        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;
        }