RAA subsystem: use shift instead of divide
authorH. Peter Anvin <hpa@zytor.com>
Tue, 22 Jan 2008 00:33:00 +0000 (16:33 -0800)
committerH. Peter Anvin <hpa@zytor.com>
Tue, 22 Jan 2008 00:33:00 +0000 (16:33 -0800)
Make the RAA size always a power of two, so we can use shifts instead
of multiple, expensive divides.

nasmlib.c
nasmlib.h

index fca9d06..4fc9fc5 100644 (file)
--- a/nasmlib.c
+++ b/nasmlib.c
@@ -445,7 +445,7 @@ void standard_extension(char *inname, char *outname, char *extension,
 #define LEAFSIZ (sizeof(RAA)-sizeof(RAA_UNION)+sizeof(RAA_LEAF))
 #define BRANCHSIZ (sizeof(RAA)-sizeof(RAA_UNION)+sizeof(RAA_BRANCH))
 
-#define LAYERSIZ(r) ( (r)->layers==0 ? RAA_BLKSIZE : RAA_LAYERSIZE )
+#define LAYERSHIFT(r) ( (r)->layers==0 ? RAA_BLKSHIFT : RAA_LAYERSHIFT )
 
 static struct RAA *real_raa_init(int layers)
 {
@@ -454,15 +454,13 @@ static struct RAA *real_raa_init(int layers)
 
     if (layers == 0) {
         r = nasm_zalloc(LEAFSIZ);
-        r->stepsize = 1L;
+        r->shift = 0;
     } else {
         r = nasm_malloc(BRANCHSIZ);
         r->layers = layers;
         for (i = 0; i < RAA_LAYERSIZE; i++)
             r->u.b.data[i] = NULL;
-        r->stepsize = RAA_BLKSIZE;
-        while (--layers)
-            r->stepsize *= RAA_LAYERSIZE;
+        r->shift = (RAA_BLKSHIFT-RAA_LAYERSHIFT) + layers*RAA_LAYERSHIFT;
     }
     return r;
 }
@@ -485,13 +483,12 @@ void raa_free(struct RAA *r)
 
 int64_t raa_read(struct RAA *r, int32_t posn)
 {
-    if (posn >= r->stepsize * LAYERSIZ(r))
+    if ((uint32_t)posn >= (UINT32_C(1) << (r->shift + LAYERSHIFT(r))))
         return 0;               /* Return 0 for undefined entries */
     while (r->layers > 0) {
-        ldiv_t l;
-        l = ldiv(posn, r->stepsize);
-        r = r->u.b.data[l.quot];
-        posn = l.rem;
+       int32_t l = posn >> r->shift;
+       posn &= (UINT32_C(1) << r->shift)-1;
+        r = r->u.b.data[l];
         if (!r)
             return 0;           /* Return 0 for undefined entries */
     }
@@ -505,7 +502,7 @@ struct RAA *raa_write(struct RAA *r, int32_t posn, int64_t value)
     if (posn < 0)
         nasm_malloc_error(ERR_PANIC, "negative position in raa_write");
 
-    while (r->stepsize * LAYERSIZ(r) <= posn) {
+    while ((UINT32_C(1) << (r->shift+LAYERSHIFT(r))) <= (uint32_t)posn) {
         /*
          * Must add a layer.
          */
@@ -516,7 +513,7 @@ struct RAA *raa_write(struct RAA *r, int32_t posn, int64_t value)
         for (i = 0; i < RAA_LAYERSIZE; i++)
             s->u.b.data[i] = NULL;
         s->layers = r->layers + 1;
-        s->stepsize = LAYERSIZ(r) * r->stepsize;
+        s->shift = LAYERSHIFT(r) + r->shift;
         s->u.b.data[0] = r;
         r = s;
     }
@@ -524,14 +521,13 @@ struct RAA *raa_write(struct RAA *r, int32_t posn, int64_t value)
     result = r;
 
     while (r->layers > 0) {
-        ldiv_t l;
         struct RAA **s;
-        l = ldiv(posn, r->stepsize);
-        s = &r->u.b.data[l.quot];
+       int32_t l = posn >> r->shift;
+       posn &= (UINT32_C(1) << r->shift)-1;
+        s = &r->u.b.data[l];
         if (!*s)
             *s = real_raa_init(r->layers - 1);
         r = *s;
-        posn = l.rem;
     }
 
     r->u.l.data[posn] = value;
index 00fd35e..6300312 100644 (file)
--- a/nasmlib.h
+++ b/nasmlib.h
@@ -266,13 +266,15 @@ void fwriteint64_t(uint64_t data, FILE * fp);
 void fwriteaddr(uint64_t data, int size, FILE * fp);
 
 /*
- * Routines to manage a dynamic random access array of int32_ts which
+ * Routines to manage a dynamic random access array of int64_ts which
  * may grow in size to be more than the largest single malloc'able
  * chunk.
  */
 
-#define RAA_BLKSIZE    32768   /* this many longs allocated at once */
-#define RAA_LAYERSIZE  32768   /* this many _pointers_ allocated */
+#define RAA_BLKSHIFT   15      /* 2**this many longs allocated at once */
+#define RAA_BLKSIZE    (1 << RAA_BLKSHIFT)
+#define RAA_LAYERSHIFT 15      /* 2**this many _pointers_ allocated */
+#define RAA_LAYERSIZE  (1 << RAA_LAYERSHIFT)
 
 typedef struct RAA RAA;
 typedef union RAA_UNION RAA_UNION;
@@ -288,14 +290,16 @@ struct RAA {
      * structures.
      */
     int layers;
+
     /*
      * Number of real data items spanned by one position in the
-     * `data' array at this level. This number is 1, trivially, for
+     * `data' array at this level. This number is 0 trivially, for
      * a leaf (level 0): for a level 1 branch it should be
-     * RAA_BLKSIZE, and for a level 2 branch it's
-     * RAA_LAYERSIZE*RAA_BLKSIZE.
+     * RAA_BLKSHIFT, and for a level 2 branch it's
+     * RAA_LAYERSHIFT+RAA_BLKSHIFT.
      */
-    int32_t stepsize;
+    int shift;
+
     union RAA_UNION {
         struct RAA_LEAF {
             int64_t data[RAA_BLKSIZE];