]> git.sur5r.net Git - cc65/commitdiff
Some branch improvements.
authoruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sat, 15 Aug 2009 15:58:21 +0000 (15:58 +0000)
committeruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sat, 15 Aug 2009 15:58:21 +0000 (15:58 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@4019 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/cc65/codeopt.c
src/cc65/coptind.c
src/cc65/coptind.h

index 95f6f2f304a0b222b735acea1f209072833e3c88..254f30e23a26c95b9fc04734a8b6c832b3d6bfe3 100644 (file)
@@ -1014,7 +1014,8 @@ static OptFunc DOptDeadJumps      = { OptDeadJumps,    "OptDeadJumps",    100, 0,
 static OptFunc DOptDecouple     = { OptDecouple,     "OptDecouple",     100, 0, 0, 0, 0, 0 };
 static OptFunc DOptDupLoads     = { OptDupLoads,     "OptDupLoads",       0, 0, 0, 0, 0, 0 };
 static OptFunc DOptJumpCascades        = { OptJumpCascades, "OptJumpCascades", 100, 0, 0, 0, 0, 0 };
-static OptFunc DOptJumpTarget          = { OptJumpTarget,   "OptJumpTarget",   100, 0, 0, 0, 0, 0 };
+static OptFunc DOptJumpTarget1  = { OptJumpTarget1,  "OptJumpTarget1",  100, 0, 0, 0, 0, 0 };
+static OptFunc DOptJumpTarget2  = { OptJumpTarget2,  "OptJumpTarget2",  100, 0, 0, 0, 0, 0 };
 static OptFunc DOptLoad1        = { OptLoad1,        "OptLoad1",        100, 0, 0, 0, 0, 0 };
 static OptFunc DOptRTS                 = { OptRTS,          "OptRTS",          100, 0, 0, 0, 0, 0 };
 static OptFunc DOptRTSJumps1    = { OptRTSJumps1,    "OptRTSJumps1",           100, 0, 0, 0, 0, 0 };
@@ -1093,7 +1094,8 @@ static OptFunc* OptFuncs[] = {
     &DOptDecouple,
     &DOptDupLoads,
     &DOptJumpCascades,
-    &DOptJumpTarget,
+    &DOptJumpTarget1,
+    &DOptJumpTarget2,
     &DOptLoad1,
     &DOptNegA1,
     &DOptNegA2,
@@ -1453,7 +1455,8 @@ static unsigned RunOptGroup3 (CodeSeg* S)
                C += RunOptFunc (S, &DOptDeadJumps, 1);
                C += RunOptFunc (S, &DOptRTS, 1);
                C += RunOptFunc (S, &DOptDeadCode, 1);
-               C += RunOptFunc (S, &DOptJumpTarget, 1);
+               C += RunOptFunc (S, &DOptJumpTarget1, 1);
+               C += RunOptFunc (S, &DOptJumpTarget2, 1);
                C += RunOptFunc (S, &DOptCondBranches, 1);
                C += RunOptFunc (S, &DOptRTSJumps1, 1);
                C += RunOptFunc (S, &DOptBoolTrans, 1);
@@ -1549,7 +1552,7 @@ static unsigned RunOptGroup6 (CodeSeg* S)
          * may have opened new oportunities.
          */
         Changes += RunOptFunc (S, &DOptUnusedLoads, 1);
-        Changes += RunOptFunc (S, &DOptJumpTarget, 5);
+        Changes += RunOptFunc (S, &DOptJumpTarget1, 5);
         Changes += RunOptFunc (S, &DOptStore5, 1);
     }
 
@@ -1560,7 +1563,7 @@ static unsigned RunOptGroup6 (CodeSeg* S)
          * may have opened new oportunities.
          */
         Changes += RunOptFunc (S, &DOptUnusedLoads, 1);
-        Changes += RunOptFunc (S, &DOptJumpTarget, 5);
+        Changes += RunOptFunc (S, &DOptJumpTarget1, 5);
         Changes += RunOptFunc (S, &DOptStore5, 1);
     }
 
index c1bbf1ea66b9abf060ac3c0cbf5510650d2bbb88..2ca307e370c817cdd6d1be686286e77dbbc1bd25 100644 (file)
@@ -544,7 +544,7 @@ unsigned OptRTS (CodeSeg* S)
 
 
 
-unsigned OptJumpTarget (CodeSeg* S)
+unsigned OptJumpTarget1 (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
@@ -623,6 +623,83 @@ NextEntry:
 
 
 
+unsigned OptJumpTarget2 (CodeSeg* S)
+/* If a bcs jumps to a sec insn or a bcc jumps to clc, skip this insn, since
+ * it's job is already done.
+ */
+{
+    unsigned Changes = 0;
+
+    /* Walk over the entries */
+    unsigned I = 0;
+    while (I < CS_GetEntryCount (S)) {
+
+        /* OP that may be skipped */
+        opc_t OPC;
+
+        /* Jump target insn, old and new */
+        CodeEntry* T;
+        CodeEntry* N;
+                           
+        /* New jump label */
+        CodeLabel* L;
+
+       /* Get next entry */
+               CodeEntry* E = CS_GetEntry (S, I);
+
+        /* Check if this is a bcc insn */
+        if (E->OPC == OP65_BCC || E->OPC == OP65_JCC) {
+            OPC = OP65_CLC;
+        } else if (E->OPC == OP65_BCS || E->OPC == OP65_JCS) {
+            OPC = OP65_SEC;
+        } else {
+            /* Not what we're looking for */
+            goto NextEntry;
+        }
+
+        /* Must have a jump target */
+        if (E->JumpTo == 0) {
+            goto NextEntry;
+        }
+
+        /* Get the owner insn of the jump target and check if it's the one, we
+         * will skip if present.
+         */
+        T = E->JumpTo->Owner;
+        if (T->OPC != OPC) {
+            goto NextEntry;
+        }
+
+        /* Get the entry following the branch target */
+        N = CS_GetNextEntry (S, CS_GetEntryIndex (S, T));
+        if (N == 0) {
+            /* There is no such entry */
+            goto NextEntry;
+        }
+
+        /* Get the label for the instruction following the jump target.
+         * This routine will create a new label if the instruction does
+         * not already have one.
+         */
+        L = CS_GenLabel (S, N);
+
+        /* Change the jump target to point to this new label */
+        CS_MoveLabelRef (S, E, L);
+
+        /* Remember that we had changes */
+        ++Changes;
+
+NextEntry:
+        /* Next entry */
+        ++I;
+    }
+
+    /* Return the number of changes made */
+    return Changes;
+}
+
+
+
 /*****************************************************************************/
 /*                      Optimize conditional branches                       */
 /*****************************************************************************/
@@ -1481,7 +1558,7 @@ unsigned OptTransfers4 (CodeSeg* S)
                     (LoadEntry->AM == AM65_ABS          ||
                      LoadEntry->AM == AM65_ZP           ||
                      LoadEntry->AM == AM65_IMM)                                 &&
-                    !MemAccess (S, Load+1, Xfer-1, LoadEntry->Arg)) { 
+                    !MemAccess (S, Load+1, Xfer-1, LoadEntry->Arg)) {
 
                     /* Generate the replacement load insn */
                     CodeEntry* X = 0;
index ca799bcd65963a44095bed546cecbe34c794daa2..2c7aa903411d92bdce651b43b4f8bb68b0edad46 100644 (file)
@@ -77,13 +77,18 @@ unsigned OptRTS (CodeSeg* S);
  * label, the dead code elimination should take care of it.
  */
 
-unsigned OptJumpTarget (CodeSeg* S);
+unsigned OptJumpTarget1 (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 OptJumpTarget2 (CodeSeg* S);
+/* If a bcs jumps to a sec insn or a bcc jumps to clc, skip this insn, since
+ * it's job is already done.
+ */
+
 unsigned OptCondBranches (CodeSeg* S);
 /* If an immidiate load of a register is followed by a conditional jump that
  * is never taken because the load of the register sets the flags in such a