]> git.sur5r.net Git - cc65/blobdiff - src/cc65/expr.c
Add fast path for char postdec
[cc65] / src / cc65 / expr.c
index 64fc17e3f2833018b1c1b9d12a340bb0f956986b..e5c1a17b91b5b0cef39448c040eb98cbf58e295e 100644 (file)
@@ -1534,25 +1534,34 @@ static void PostInc (ExprDesc* Expr)
     /* Get the data type */
     Flags = TypeOf (Expr->Type);
 
-    /* Push the address if needed */
-    PushAddr (Expr);
+    /* Fast path: char */
+    if ((Flags & CF_CHAR) == CF_CHAR && ED_GetLoc(Expr) & (E_LOC_GLOBAL | E_LOC_STATIC)) {
 
-    /* Fetch the value and save it (since it's the result of the expression) */
-    LoadExpr (CF_NONE, Expr);
-    g_save (Flags | CF_FORCECHAR);
+        LoadExpr (CF_NONE, Expr);
+        AddCodeLine ("inc %s", ED_GetLabelName(Expr, 0));
 
-    /* If we have a pointer expression, increment by the size of the type */
-    if (IsTypePtr (Expr->Type)) {
-        g_inc (Flags | CF_CONST | CF_FORCECHAR, CheckedSizeOf (Expr->Type + 1));
     } else {
-        g_inc (Flags | CF_CONST | CF_FORCECHAR, 1);
-    }
 
-    /* Store the result back */
-    Store (Expr, 0);
+        /* Push the address if needed */
+        PushAddr (Expr);
 
-    /* Restore the original value in the primary register */
-    g_restore (Flags | CF_FORCECHAR);
+        /* Fetch the value and save it (since it's the result of the expression) */
+        LoadExpr (CF_NONE, Expr);
+        g_save (Flags | CF_FORCECHAR);
+
+        /* If we have a pointer expression, increment by the size of the type */
+        if (IsTypePtr (Expr->Type)) {
+            g_inc (Flags | CF_CONST | CF_FORCECHAR, CheckedSizeOf (Expr->Type + 1));
+        } else {
+            g_inc (Flags | CF_CONST | CF_FORCECHAR, 1);
+        }
+
+        /* Store the result back */
+        Store (Expr, 0);
+
+        /* Restore the original value in the primary register */
+        g_restore (Flags | CF_FORCECHAR);
+    }
 
     /* The result is always an expression, no reference */
     ED_MakeRValExpr (Expr);
@@ -1581,25 +1590,34 @@ static void PostDec (ExprDesc* Expr)
     /* Get the data type */
     Flags = TypeOf (Expr->Type);
 
-    /* Push the address if needed */
-    PushAddr (Expr);
+    /* Fast path: char */
+    if ((Flags & CF_CHAR) == CF_CHAR && ED_GetLoc(Expr) & (E_LOC_GLOBAL | E_LOC_STATIC)) {
 
-    /* Fetch the value and save it (since it's the result of the expression) */
-    LoadExpr (CF_NONE, Expr);
-    g_save (Flags | CF_FORCECHAR);
+        LoadExpr (CF_NONE, Expr);
+        AddCodeLine ("dec %s", ED_GetLabelName(Expr, 0));
 
-    /* If we have a pointer expression, increment by the size of the type */
-    if (IsTypePtr (Expr->Type)) {
-        g_dec (Flags | CF_CONST | CF_FORCECHAR, CheckedSizeOf (Expr->Type + 1));
     } else {
-        g_dec (Flags | CF_CONST | CF_FORCECHAR, 1);
-    }
 
-    /* Store the result back */
-    Store (Expr, 0);
+        /* Push the address if needed */
+        PushAddr (Expr);
 
-    /* Restore the original value in the primary register */
-    g_restore (Flags | CF_FORCECHAR);
+        /* Fetch the value and save it (since it's the result of the expression) */
+        LoadExpr (CF_NONE, Expr);
+        g_save (Flags | CF_FORCECHAR);
+
+        /* If we have a pointer expression, increment by the size of the type */
+        if (IsTypePtr (Expr->Type)) {
+            g_dec (Flags | CF_CONST | CF_FORCECHAR, CheckedSizeOf (Expr->Type + 1));
+        } else {
+            g_dec (Flags | CF_CONST | CF_FORCECHAR, 1);
+        }
+
+        /* Store the result back */
+        Store (Expr, 0);
+
+        /* Restore the original value in the primary register */
+        g_restore (Flags | CF_FORCECHAR);
+    }
 
     /* The result is always an expression, no reference */
     ED_MakeRValExpr (Expr);
@@ -2105,8 +2123,8 @@ static void hie_compare (const GenDesc* Ops,    /* List of generators */
                 */
                 Type* left  = Indirect (Expr->Type);
                 Type* right = Indirect (Expr2.Type);
-                if (TypeCmp (left, right) < TC_EQUAL && left->C != T_VOID && right->C != T_VOID) {
-                    /* Incomatible pointers */
+                if (TypeCmp (left, right) < TC_QUAL_DIFF && left->C != T_VOID && right->C != T_VOID) {
+                    /* Incompatible pointers */
                     Error ("Incompatible types");
                 }
             } else if (!ED_IsNullPtr (&Expr2)) {
@@ -2390,7 +2408,6 @@ static void parseadd (ExprDesc* Expr)
     Type* lhst;                 /* Type of left hand side */
     Type* rhst;                 /* Type of right hand side */
 
-
     /* Skip the PLUS token */
     NextToken ();
 
@@ -2573,7 +2590,7 @@ static void parseadd (ExprDesc* Expr)
                 flags = CF_PTR;
             } else if (IsClassInt (lhst) && IsClassPtr (rhst)) {
                 /* Left is int, right is pointer, must scale lhs */
-                g_tosint (TypeOf (rhst));       /* Make sure, TOS is int */
+                g_tosint (TypeOf (lhst));       /* Make sure TOS is int */
                 g_swap (CF_INT);                /* Swap TOS and primary */
                 g_scale (CF_INT, CheckedPSizeOf (rhst));
                 /* Operate on pointers, result type is a pointer */
@@ -2607,7 +2624,6 @@ static void parseadd (ExprDesc* Expr)
 
     /* Condition codes not set */
     ED_MarkAsUntested (Expr);
-
 }