]> git.sur5r.net Git - cc65/commitdiff
Another optimization step
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sat, 23 Nov 2002 12:05:23 +0000 (12:05 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sat, 23 Nov 2002 12:05:23 +0000 (12:05 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@1603 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/cc65/codegen.c
src/cc65/codegen.h
src/cc65/codeopt.c
src/cc65/typecast.c

index 40dcd46ab3a48b63f8e390835d233d0fb7727d0c..c4a50b139551d301bad60b8ce223ead0a9cab8d7 100644 (file)
@@ -450,7 +450,7 @@ void g_leave (void)
 {
     /* How many bytes of locals do we have to drop? */
     int k = -oursp;
-                                  
+
     /* If we didn't have a variable argument list, don't call leave */
     if (funcargs >= 0) {
 
@@ -1131,18 +1131,81 @@ void g_tosint (unsigned flags)
 
 
 
-void g_reglong (unsigned flags)
+void g_regint (unsigned Flags)
+/* Make sure, the value in the primary register an int. Convert if necessary */
+{
+    unsigned L;
+
+    switch (Flags & CF_TYPE) {
+
+       case CF_CHAR:
+            if (Flags & CF_FORCECHAR) {
+                /* Conversion is from char */
+                if (Flags & CF_UNSIGNED) {
+                    AddCodeLine ("ldx #$00");
+                } else {
+                    L = GetLocalLabel();
+                    AddCodeLine ("ldx #$00");
+                    AddCodeLine ("cmp #$80");
+                    AddCodeLine ("bcc %s", LocalLabelName (L));
+                    AddCodeLine ("dex");
+                    g_defcodelabel (L);
+                }
+            }
+            /* FALLTHROUGH */
+
+       case CF_INT:
+       case CF_LONG:
+           break;
+
+       default:
+           typeerror (Flags);
+    }
+}
+
+
+
+void g_reglong (unsigned Flags)
 /* Make sure, the value in the primary register a long. Convert if necessary */
 {
-    switch (flags & CF_TYPE) {
+    unsigned L;
+
+    switch (Flags & CF_TYPE) {
 
        case CF_CHAR:
+            if (Flags & CF_FORCECHAR) {
+                /* Conversion is from char */
+                if (Flags & CF_UNSIGNED) {
+                    if (CodeSizeFactor >= 200) {
+                        AddCodeLine ("ldx #$00");
+                        AddCodeLine ("stx sreg");
+                        AddCodeLine ("stx sreg+1");
+                    } else {
+                        AddCodeLine ("jsr aulong");
+                    }
+                } else {
+                    if (CodeSizeFactor >= 366) {
+                        L = GetLocalLabel();
+                        AddCodeLine ("ldx #$00");
+                        AddCodeLine ("cmp #$80");
+                        AddCodeLine ("bcc %s", LocalLabelName (L));
+                        AddCodeLine ("dex");
+                        g_defcodelabel (L);
+                        AddCodeLine ("stx sreg");
+                        AddCodeLine ("stx sreg+1");
+                    } else {
+                        AddCodeLine ("jsr along");
+                    }
+                }
+            }
+            /* FALLTHROUGH */
+
        case CF_INT:
-           if (flags & CF_UNSIGNED) {
+           if (Flags & CF_UNSIGNED) {
                if (CodeSizeFactor >= 200) {
                    ldyconst (0);
                    AddCodeLine ("sty sreg");
-                   AddCodeLine ("sty sreg+1");
+                   AddCodeLine ("sty sreg+1");
                } else {
                    AddCodeLine ("jsr axulong");
                }
@@ -1155,7 +1218,7 @@ void g_reglong (unsigned flags)
            break;
 
        default:
-           typeerror (flags);
+           typeerror (Flags);
     }
 }
 
@@ -1223,9 +1286,14 @@ unsigned g_typecast (unsigned lhs, unsigned rhs)
     rtype = rhs & CF_TYPE;
 
     /* Check if a conversion is needed */
-    if (ltype == CF_LONG && rtype != CF_LONG && (rhs & CF_CONST) == 0) {
-       /* We must promote the primary register to long */
-       g_reglong (rhs);
+    if ((rhs & CF_CONST) == 0) {
+        if (ltype == CF_LONG && rtype != CF_LONG) {
+            /* We must promote the primary register to long */
+            g_reglong (rhs);
+        } else if (ltype == CF_INT && rtype != CF_INT) {
+            /* We must promote the primary register to int */
+            g_regint (rhs);
+        }
     }
 
     /* Do not need any other action. If the left type is int, and the primary
index 37f5febb7616d69a3d3ad0ce60c8b6f81e5ca6e3..68e15b1897c0baebe83650c31affa0f901b56cb2 100644 (file)
@@ -186,7 +186,10 @@ void g_toslong (unsigned flags);
 void g_tosint (unsigned flags);
 /* Make sure, the value on TOS is an int. Convert if necessary */
 
-void g_reglong (unsigned flags);
+void g_regint (unsigned Flags);
+/* Make sure, the value in the primary register an int. Convert if necessary */
+
+void g_reglong (unsigned Flags);
 /* Make sure, the value in the primary register a long. Convert if necessary */
 
 unsigned g_typeadjust (unsigned lhs, unsigned rhs);
index 01bba7b42369fb00c289939e418c1c3df31de2c9..f9fcd9428f4484928031c9099fd522b4becd24fe 100644 (file)
@@ -333,6 +333,70 @@ static unsigned OptShift3 (CodeSeg* S)
 
 
 
+/*****************************************************************************/
+/*                              Optimize loads                               */
+/*****************************************************************************/
+
+
+
+static unsigned OptLoad1 (CodeSeg* S)
+/* Search for a call to ldaxysp where X is not used later and replace it by
+ * a load of just the A register.
+ */
+{
+    unsigned I;
+    unsigned Changes = 0;
+
+    /* Generate register info */
+    CS_GenRegInfo (S);
+
+    /* Walk over the entries */
+    I = 0;
+    while (I < CS_GetEntryCount (S)) {
+
+       CodeEntry* E;
+
+       /* Get next entry */
+               E = CS_GetEntry (S, I);
+
+       /* Check for the sequence */
+               if (CE_IsCallTo (E, "ldaxysp")          &&
+            RegValIsKnown (E->RI->In.RegY)      &&
+            !RegXUsed (S, I+1)) {
+
+            CodeEntry* X;
+
+            /* Reload the Y register */
+            const char* Arg = MakeHexArg (E->RI->In.RegY - 1);
+            X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, E->LI);
+            CS_InsertEntry (S, X, I+1);
+
+            /* Load from stack */
+            X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "sp", 0, E->LI);
+            CS_InsertEntry (S, X, I+2);
+
+            /* Now remove the call to the subroutine */
+           CS_DelEntry (S, I);
+
+           /* Remember, we had changes */
+            ++Changes;
+
+       }
+
+       /* Next entry */
+       ++I;
+
+    }
+
+    /* Free the register info */
+    CS_FreeRegInfo (S);
+
+    /* Return the number of changes made */
+    return Changes;
+}
+
+
+
 /*****************************************************************************/
 /*                    Optimize stores through pointers                      */
 /*****************************************************************************/
@@ -1355,6 +1419,7 @@ static OptFunc DOptDecouple     = { OptDecouple,     "OptDecouple",     100, 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 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 };
 static OptFunc DOptRTSJumps2    = { OptRTSJumps2,    "OptRTSJumps2",           100, 0, 0, 0, 0, 0 };
@@ -1415,6 +1480,7 @@ static OptFunc* OptFuncs[] = {
     &DOptDupLoads,
     &DOptJumpCascades,
     &DOptJumpTarget,
+    &DOptLoad1,
     &DOptNegA1,
     &DOptNegA2,
     &DOptNegAX1,
@@ -1629,7 +1695,7 @@ static void WriteOptStats (const char* Name)
                 O->Name,
                 O->TotalRuns,
                 O->LastRuns,
-                O->TotalChanges,
+                O->TotalChanges,
                 O->LastChanges);
     }
 
@@ -1759,6 +1825,7 @@ static unsigned RunOptGroup3 (CodeSeg* S)
                C += RunOptFunc (S, &DOptCmp6, 1);
                C += RunOptFunc (S, &DOptCmp7, 1);
                C += RunOptFunc (S, &DOptTest1, 1);
+        C += RunOptFunc (S, &DOptLoad1, 1);
                C += RunOptFunc (S, &DOptUnusedLoads, 1);
                C += RunOptFunc (S, &DOptUnusedStores, 1);
                C += RunOptFunc (S, &DOptDupLoads, 1);
index bd9641761c10e81d099340a2ba825fcd4771fd1c..406680a7732c91df0f28c9023aee2d585eda6f53 100644 (file)
@@ -172,8 +172,8 @@ int TypeCast (ExprDesc* lval)
                     /* Load the value into the primary */
                     exprhs (CF_NONE, k, lval);
 
-                    /* Emit typecast code. ### CHARS */
-                    g_typecast (TypeOf (OldType), TypeOf (NewType));
+                    /* Emit typecast code. */
+                    g_typecast (TypeOf (OldType), TypeOf (NewType) | CF_FORCECHAR);
 
                     /* Value is now in primary */
                     lval->Flags = E_MEXPR;
@@ -190,7 +190,7 @@ int TypeCast (ExprDesc* lval)
             exprhs (CF_NONE, k, lval);
 
             /* Emit typecast code */
-            g_typecast (TypeOf (OldType), TypeOf (NewType));
+            g_typecast (TypeOf (OldType), TypeOf (NewType) | CF_FORCECHAR);
 
             /* Value is now in primary */
             lval->Flags = E_MEXPR;