nv50: make address reg allocation a little less hacky
authorChristoph Bumiller <e0425955@student.tuwien.ac.at>
Sun, 20 Dec 2009 12:40:14 +0000 (13:40 +0100)
committerChristoph Bumiller <e0425955@student.tuwien.ac.at>
Sun, 20 Dec 2009 13:15:51 +0000 (14:15 +0100)
Before I tried to distinguish int +0 and -0, and regs
relative to $a1 would have been considered reserved
for TGSI.
This would probably never occur, let it be fixed even so.

src/gallium/drivers/nv50/nv50_program.c

index 9ad0677978ed4855b8b5c8dec3c75f7393b7a019..04b345bcf3710755b932dfea3c378d30897caf76 100644 (file)
@@ -131,6 +131,7 @@ struct nv50_pc {
        int immd_nr;
        struct nv50_reg **addr;
        int addr_nr;
+       uint8_t addr_alloc; /* set bit indicates used for TGSI_FILE_ADDRESS */
 
        struct nv50_reg *temp_temp[16];
        unsigned temp_temp_nr;
@@ -200,8 +201,7 @@ terminate_mbb(struct nv50_pc *pc)
 
        /* remove records of temporary address register values */
        for (i = 0; i < NV50_SU_MAX_ADDR; ++i)
-               if (pc->r_addr[i].index < 0)
-                       pc->r_addr[i].rhw = -1;
+               pc->r_addr[i].rhw = -1;
 }
 
 static void
@@ -546,21 +546,24 @@ emit_add_addr_imm(struct nv50_pc *pc, struct nv50_reg *dst,
 static struct nv50_reg *
 alloc_addr(struct nv50_pc *pc, struct nv50_reg *ref)
 {
-       int i;
        struct nv50_reg *a_tgsi = NULL, *a = NULL;
+       int i;
+       uint8_t avail = ~pc->addr_alloc;
 
        if (!ref) {
-               /* allocate for TGSI address reg */
-               for (i = 0; i < NV50_SU_MAX_ADDR; ++i) {
-                       if (pc->r_addr[i].index >= 0)
-                               continue;
-                       if (pc->r_addr[i].rhw >= 0 &&
-                           pc->r_addr[i].acc == pc->insn_cur)
-                               continue;
+               /* allocate for TGSI_FILE_ADDRESS */
+               while (avail) {
+                       i = ffs(avail) - 1;
 
-                       pc->r_addr[i].rhw = -1;
-                       pc->r_addr[i].index = i;
-                       return &pc->r_addr[i];
+                       if (pc->r_addr[i].rhw < 0 ||
+                           pc->r_addr[i].acc != pc->insn_cur) {
+                               pc->addr_alloc |= (1 << i);
+
+                               pc->r_addr[i].rhw = -1;
+                               pc->r_addr[i].index = i;
+                               return &pc->r_addr[i];
+                       }
+                       avail &= ~(1 << i);
                }
                assert(0);
                return NULL;
@@ -568,15 +571,16 @@ alloc_addr(struct nv50_pc *pc, struct nv50_reg *ref)
 
        /* Allocate and set an address reg so we can access 'ref'.
         *
-        * If and r_addr has index < 0, it is not reserved for TGSI,
-        * and index will be the negative of the TGSI addr index the
-        * value in rhw is relative to, or -256 if rhw is an offset
-        * from 0. If rhw < 0, the reg has not been initialized.
+        * If and r_addr->index will be -1 or the hw index the value
+        * value in rhw is relative to. If rhw < 0, the reg has not
+        * been initialized or is in use for TGSI_FILE_ADDRESS.
         */
-       for (i = NV50_SU_MAX_ADDR - 1; i >= 0; --i) {
-               if (pc->r_addr[i].index >= 0) /* occupied for TGSI */
-                       continue;
-               if (pc->r_addr[i].rhw < 0) { /* unused */
+       while (avail) { /* only consider regs that are not TGSI */
+               i = ffs(avail) - 1;
+               avail &= ~(1 << i);
+
+               if ((!a || a->rhw >= 0) && pc->r_addr[i].rhw < 0) {
+                       /* prefer an usused reg with low hw index */
                        a = &pc->r_addr[i];
                        continue;
                }
@@ -586,8 +590,8 @@ alloc_addr(struct nv50_pc *pc, struct nv50_reg *ref)
                if (ref->hw - pc->r_addr[i].rhw >= 128)
                        continue;
 
-               if ((ref->acc >= 0 && pc->r_addr[i].index == -256) ||
-                   (ref->acc < 0 && -pc->r_addr[i].index == ref->index)) {
+               if ((ref->acc >= 0 && pc->r_addr[i].index < 0) ||
+                   (ref->acc < 0 && pc->r_addr[i].index == ref->index)) {
                        pc->r_addr[i].acc = pc->insn_cur;
                        return &pc->r_addr[i];
                }
@@ -601,7 +605,7 @@ alloc_addr(struct nv50_pc *pc, struct nv50_reg *ref)
 
        a->rhw = ref->hw & ~0x7f;
        a->acc = pc->insn_cur;
-       a->index = a_tgsi ? -ref->index : -256;
+       a->index = a_tgsi ? ref->index : -1;
        return a;
 }