]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Complete reg-alloc output storage, and misc other stuff to make it
authorJulian Seward <jseward@acm.org>
Fri, 2 Jul 2004 07:09:23 +0000 (07:09 +0000)
committerJulian Seward <jseward@acm.org>
Fri, 2 Jul 2004 07:09:23 +0000 (07:09 +0000)
compile and link.

git-svn-id: svn://svn.valgrind.org/vex/trunk@32

VEX/Makefile
VEX/host_regs.c
VEX/include/host_regs.h
VEX/reg_alloc.c

index 0e6cbea328e391f2a334e481a094375d1eb88184..2acaaf307dca14d0e39498057cc4d6a748aef06b 100644 (file)
@@ -5,7 +5,7 @@ INCLUDES = include/arena.h                              \
 
 ##OBJS = basictypes.o ir_defs.o arena.o linker.o dispatch.o
 OBJS = basictypes.o ir_defs.o host_regs.o \
-       x86h_defs.o isel_x86.o test_main.o
+       x86h_defs.o isel_x86.o reg_alloc.o test_main.o
 
 CC_OPTS = -g -Wall -Iinclude
 
@@ -25,6 +25,8 @@ x86h_defs.o: x86h_defs.c $(INCLUDES)
        gcc $(CC_OPTS) -c x86h_defs.c
 isel_x86.o: isel_x86.c $(INCLUDES)
        gcc $(CC_OPTS) -c isel_x86.c
+reg_alloc.o: reg_alloc.c $(INCLUDES)
+       gcc $(CC_OPTS) -c reg_alloc.c
 arena.o: arena.c $(INCLUDES)
        gcc $(CC_OPTS) -c arena.c
 linker.o: linker.c $(INCLUDES)
index 8a9530e86beb7d3af51d663e2dd61d9ea06e40be..e400cfc457fd89247cf3e4e1b9fd34475734f0ba 100644 (file)
@@ -40,6 +40,17 @@ UInt hregNumber ( HReg r )
    return ((UInt)r) & 0x00FFFFFF;
 }
 
+void ppHRegClass ( FILE* f, HRegClass hrc )
+{
+   switch (hrc) {
+      case HRcInt:       fprintf(f, "HRcInt32"); break;
+      case HRcInt64:     fprintf(f, "HRcInt64"); break;
+      case HRcFloat:     fprintf(f, "HRcFloat"); break;
+      case HRcVector:    fprintf(f, "HRcVector64"); break;
+      case HRcVector128: fprintf(f, "HRcVector128"); break;
+      default: panic("ppHRegClass");
+   }
+}
 
 /* Generic printing for registers. */
 void ppHReg ( FILE* f, HReg r ) 
index 7e49bfab0e22e12218786b170d767229e55c5eb3..fda6b8f0c0ae7f49273470e8fb3ecd69afabf2ac 100644 (file)
@@ -45,7 +45,12 @@ typedef UInt HReg;
 
 /* When extending this, do not use any value > 14 or < 0. */
 typedef
-   enum { HRcInt=4, HRcFloat=5, HRcVector=6 }
+enum { HRcInt=4,       /* 32-bit int */
+       HRcInt64=5,     /* 64-bit int */
+       HRcFloat=6,     /* 64-bit float */
+       HRcVector=7,    /* 64-bit SIMD */
+       HRcVector128=8  /* 128-bit SIMD */
+   }
    HRegClass;
 
 extern void ppHRegClass ( FILE*, HRegClass );
index 0d6e0528261286db290dc60a6521cc5a460d35ac..eca8c34f7ca067f36152d44e71c31abbf7c384b3 100644 (file)
@@ -73,27 +73,43 @@ typedef
 
 
 
+/* Does this instruction mention a particular reg? */
+static Bool instrMentionsReg ( 
+   void (*getRegUsage) (HInstr*, HRegUsage*),
+   HInstr* instr, 
+   HReg r 
+)
+{
+   Int       i;
+   HRegUsage reg_usage;
+   (*getRegUsage)(instr, &reg_usage);
+   for (i = 0; i < reg_usage.n_used; i++)
+      if (reg_usage.hreg[i] == r)
+         return True;
+   return False;
+}
+
+
 /* A target-independent register allocator for Valgrind.  Requires
-   various functions which to deal abstractly with instructions and
-   registers (of which it cannot have any target-specific knowledge).  
+   various functions which it uses to deal abstractly with
+   instructions and registers, since it cannot have any
+   target-specific knowledge.
 
-   Returns a new list of instructions, which (depending on
-   the behaviour of mapRegs) may be in-place modifications of
-   the original instructions.
+   Returns a new list of instructions, which, as a result of the
+   behaviour of mapRegs, will be in-place modifications of the
+   original instructions.
 
    Requires that the incoming code has been generated using
    vreg numbers 0, 1 .. n_vregs-1.  Appearance of a vreg outside
    that range is a checked run-time error.
-*/
-extern void emitInstr ( HInstr* );
-extern Bool instrMentionsVReg ( HInstr*, HReg );
-
 
+   Takes a NULL-terminated array of pointers to unallocated insns.
+   Returns a NULL-terminated array of pointers to allocated insns.
+*/
 HInstr** doRegisterAllocation (
 
-   /* Incoming virtual-registerised code */ 
+   /* Incoming virtual-registerised code, NULL terminated */ 
    HInstr** instrs,
-   Int      n_instrs,
    Int      n_vregs,
 
    /* An array listing all the real registers the allocator may use,
@@ -117,26 +133,62 @@ HInstr** doRegisterAllocation (
    HInstr* (*genReload) ( HReg, Int )
 )
 {
-   Int ii, j, k, m;
-
-   Int furthest, furthest_k;
+   /* Iterators and temporaries. */
+   Int       ii, j, k, m, furthest, furthest_k;
+   HReg      rreg, vreg;
+   HRegUsage reg_usage;
 
+   /* Info on vregs and rregs.  Computed once and remains
+      unchanged. */
    VRegInfo* vreg_info;
-   HRegUsage reg_usage;
    RRegInfo* rreg_info;
+   Int       rreg_info_size;
+   Int       rreg_info_used;
+
+   /* Used when constructing vreg_info (for allocating stack
+      slots). */
+   Int ss_busy_until_before[N_SPILL64S];
+
+   /* Used when constructing rreg_info. */
    Int* rreg_live_after;
    Int* rreg_dead_before;
-   Int rreg_info_size;
-   Int rreg_info_used;
+
+   /* Running state of the core allocation algorithm. */
    RRegState* state;
-   Int n_state;
+   Int        n_state;
+
+   /* The vreg -> rreg map constructed and then applied to each
+      instr. */
    HRegRemap remap;
 
-   HReg rreg, vreg;
-   Int ss_busy_until_before[N_SPILL64S];
+   /* The output array of instructions. */
+   HInstr** instrs_out;
+   Int      instrs_out_size;
+   Int      instrs_out_used;
+
+   /* Number of incoming instructions. */
+   Int n_instrs;
+
 
 #  define INVALID_INSTRNO (-2)
 
+   /* --------- Stage 0: set up output array. --------- */
+   n_instrs = 0;
+   while (instrs[n_instrs] != NULL)
+      n_instrs ++;
+
+   instrs_out_size = 2 * n_instrs;
+   instrs_out_used = 0;
+   instrs_out      = malloc(instrs_out_size * sizeof(HInstr*));
+
+#  define EMIT_INSTR(_instr)                                         \
+      do {                                                           \
+         if (instrs_out_used >= instrs_out_used)                     \
+            panic("doRegisterAllocation: instrs_out is too small");  \
+         instrs_out[instrs_out_used] = (_instr);                     \
+         instrs_out_used++;                                          \
+      } while (0)
+
 
    /* --------- Stage 1: compute vreg live ranges. --------- */
 
@@ -227,8 +279,10 @@ HInstr** doRegisterAllocation (
       /* for each reg mentioned in the insn ... */
       for (j = 0; j < reg_usage.n_used; j++) {
 
+        /* Dummy initialisations of flush_la and flush_db to avoid
+          possible bogus uninit-var warnings from gcc. */
+         Int  flush_la = INVALID_INSTRNO, flush_db = INVALID_INSTRNO;
          Bool flush;
-         Int flush_la, flush_db;
 
          rreg = reg_usage.hreg[j];
 
@@ -313,7 +367,7 @@ HInstr** doRegisterAllocation (
       put as few values as possible in spill slows, but nevertheless
       need to have a spill slot available for all vregs, just in case.
    */
-   //   max_ss_no = -1;
+   /* max_ss_no = -1; */
 
    for (j = 0; j < N_SPILL64S; j++)
       ss_busy_until_before[j] = 0;
@@ -335,8 +389,8 @@ HInstr** doRegisterAllocation (
       }
       ss_busy_until_before[k] = vreg_info[j].dead_before;
       vreg_info[j].spill_offset = k * 8;
-      //      if (j > max_ss_no)
-      //   max_ss_no = j;
+      /* if (j > max_ss_no) */
+      /*    max_ss_no = j; */
    }
 
 
@@ -473,8 +527,8 @@ HInstr** doRegisterAllocation (
                /* Yes, there is an associated vreg.  Spill it. */
                m = hregNumber(state[k].vreg);
                assert(m >= 0 && m < n_vregs);
-               emitInstr((*genSpill)( vreg_info[m].spill_offset, 
-                                      state[k].rreg ));
+               EMIT_INSTR( (*genSpill)( vreg_info[m].spill_offset, 
+                                        state[k].rreg ) );
                state[k].disp = Free;
                state[k].vreg = INVALID_HREG;
             }
@@ -537,17 +591,18 @@ HInstr** doRegisterAllocation (
             candidates, due to holding a vreg mentioned by this
             instruction.  Or being of the wrong class. */
          for (k = 0; k < n_state; k++) {
-           state[k].is_spill_cand = False;
-           if (state[k].disp != Bound)
-             continue;
-           if (hregClass(state[k].rreg) != hregClass(vreg))
-             continue;
-           state[k].is_spill_cand = True;
-           for (m = 0; m < reg_usage.n_used; m++)
-             if (state[k].vreg == reg_usage.hreg[m]) {
-               state[k].is_spill_cand = False;
-               break;
-             }
+            state[k].is_spill_cand = False;
+            if (state[k].disp != Bound)
+               continue;
+            if (hregClass(state[k].rreg) != hregClass(vreg))
+               continue;
+            state[k].is_spill_cand = True;
+            for (m = 0; m < reg_usage.n_used; m++) {
+               if (state[k].vreg == reg_usage.hreg[m]) {
+                  state[k].is_spill_cand = False;
+                  break;
+               }
+            }
          }
 
          /* We can choose any rreg satisfying state[r].is_spill_cand
@@ -563,7 +618,8 @@ HInstr** doRegisterAllocation (
                continue;
             assert(state[k].disp == Bound);
             for (m = ii+1; m < n_instrs; m++)
-               if (instrMentionsVReg(instrs[m], state[k].vreg))
+               if (instrMentionsReg(getRegUsage, 
+                                    instrs[m], state[k].vreg))
                   break;
             if (m > furthest) {
                furthest = m;
@@ -594,8 +650,8 @@ HInstr** doRegisterAllocation (
          assert(vreg_info[m].dead_before > ii);
 
          /* So here's the spill store. */
-         emitInstr((*genSpill)( vreg_info[m].spill_offset, 
-                                state[furthest_k].rreg ));
+         EMIT_INSTR( (*genSpill)( vreg_info[m].spill_offset, 
+                                  state[furthest_k].rreg ) );
 
          /* Update the state to reflect the new assignment for this
             rreg. */
@@ -606,8 +662,8 @@ HInstr** doRegisterAllocation (
          if (reg_usage.mode[j] != HRmWrite) {
             m = hregNumber(vreg);
             assert(m >= 0 && m < n_vregs);
-            emitInstr((*genReload)( vreg_info[m].spill_offset,
-                                    state[furthest_k].rreg ));
+            EMIT_INSTR( (*genReload)( vreg_info[m].spill_offset,
+                                      state[furthest_k].rreg ) );
          }
 
          /* So after much twisting and turning, we have vreg mapped to
@@ -629,16 +685,20 @@ HInstr** doRegisterAllocation (
 
       /* NOTE, DESTRUCTIVELY MODIFIES instrs[ii]. */
       (*mapRegs)( &remap, instrs[ii] );
-      emitInstr( instrs[ii] );
+      EMIT_INSTR( instrs[ii] );
 
    } /* iterate over insns */
 
+   EMIT_INSTR(NULL);
+
    free(state);
    free(rreg_info);
    if (vreg_info) free(vreg_info);
 
-#  undef INVALID_INSTRNO
+   return instrs_out;
 
+#  undef INVALID_INSTRNO
+#  undef EMIT_INSTR
 }