コード例 #1
0
ファイル: prog_optimize.c プロジェクト: ChillyWillyGuru/RSXGL
/**
 * This function implements "Linear Scan Register Allocation" to reduce
 * the number of temporary registers used by the program.
 *
 * We compute the "live interval" for all temporary registers then
 * examine the overlap of the intervals to allocate new registers.
 * Basically, if two intervals do not overlap, they can use the same register.
 */
static void
_mesa_reallocate_registers(struct gl_program *prog)
{
   struct interval_list liveIntervals;
   GLint registerMap[REG_ALLOCATE_MAX_PROGRAM_TEMPS];
   GLboolean usedRegs[REG_ALLOCATE_MAX_PROGRAM_TEMPS];
   GLuint i;
   GLint maxTemp = -1;

   if (dbg) {
      printf("Optimize: Begin live-interval register reallocation\n");
      _mesa_print_program(prog);
   }

   for (i = 0; i < REG_ALLOCATE_MAX_PROGRAM_TEMPS; i++){
      registerMap[i] = -1;
      usedRegs[i] = GL_FALSE;
   }

   if (!find_live_intervals(prog, &liveIntervals)) {
      if (dbg)
         printf("Aborting register reallocation\n");
      return;
   }

   {
      struct interval_list activeIntervals;
      activeIntervals.Num = 0;

      /* loop over live intervals, allocating a new register for each */
      for (i = 0; i < liveIntervals.Num; i++) {
         const struct interval *live = liveIntervals.Intervals + i;

         if (dbg)
            printf("Consider register %u\n", live->Reg);

         /* Expire old intervals.  Intervals which have ended with respect
          * to the live interval can have their remapped registers freed.
          */
         {
            GLint j;
            for (j = 0; j < (GLint) activeIntervals.Num; j++) {
               const struct interval *inv = activeIntervals.Intervals + j;
               if (inv->End >= live->Start) {
                  /* Stop now.  Since the activeInterval list is sorted
                   * we know we don't have to go further.
                   */
                  break;
               }
               else {
                  /* Interval 'inv' has expired */
                  const GLint regNew = registerMap[inv->Reg];
                  ASSERT(regNew >= 0);

                  if (dbg)
                     printf("  expire interval for reg %u\n", inv->Reg);

                  /* remove interval j from active list */
                  remove_interval(&activeIntervals, inv);
                  j--;  /* counter-act j++ in for-loop above */

                  /* return register regNew to the free pool */
                  if (dbg)
                     printf("  free reg %d\n", regNew);
                  ASSERT(usedRegs[regNew] == GL_TRUE);
                  usedRegs[regNew] = GL_FALSE;
               }
            }
         }

         /* find a free register for this live interval */
         {
            const GLint k = alloc_register(usedRegs);
            if (k < 0) {
               /* out of registers, give up */
               return;
            }
            registerMap[live->Reg] = k;
            maxTemp = MAX2(maxTemp, k);
            if (dbg)
               printf("  remap register %u -> %d\n", live->Reg, k);
         }

         /* Insert this live interval into the active list which is sorted
          * by increasing end points.
          */
         insert_interval_by_end(&activeIntervals, live);
      }
   }

   if (maxTemp + 1 < (GLint) liveIntervals.Num) {
      /* OK, we've reduced the number of registers needed.
       * Scan the program and replace all the old temporary register
       * indexes with the new indexes.
       */
      replace_regs(prog, PROGRAM_TEMPORARY, registerMap);

      prog->NumTemporaries = maxTemp + 1;
   }

   if (dbg) {
      printf("Optimize: End live-interval register reallocation\n");
      printf("Num temp regs before: %u  after: %u\n",
                   liveIntervals.Num, maxTemp + 1);
      _mesa_print_program(prog);
   }
}
コード例 #2
0
ファイル: prog_optimize.c プロジェクト: aljen/haiku-opengl
/**
 * Consolidate temporary registers to use low numbers.  For example, if the
 * shader only uses temps 4, 5, 8, replace them with 0, 1, 2.
 */
static void
_mesa_consolidate_registers(struct gl_program *prog)
{
   GLboolean tempUsed[MAX_PROGRAM_TEMPS];
   GLint tempMap[MAX_PROGRAM_TEMPS];
   GLuint tempMax = 0, i;

   if (dbg) {
      _mesa_printf("Optimize: Begin register consolidation\n");
   }

   memset(tempUsed, 0, sizeof(tempUsed));

   for (i = 0; i < MAX_PROGRAM_TEMPS; i++) {
      tempMap[i] = -1;
   }

   /* set tempUsed[i] if temporary [i] is referenced */
   for (i = 0; i < prog->NumInstructions; i++) {
      const struct prog_instruction *inst = prog->Instructions + i;
      const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode);
      GLuint j;
      for (j = 0; j < numSrc; j++) {
         if (inst->SrcReg[j].File == PROGRAM_TEMPORARY) {
            const GLuint index = inst->SrcReg[j].Index;
            ASSERT(index < MAX_PROGRAM_TEMPS);
            tempUsed[index] = GL_TRUE;
            tempMax = MAX2(tempMax, index);
            break;
         }
      }
      if (inst->DstReg.File == PROGRAM_TEMPORARY) {
         const GLuint index = inst->DstReg.Index;
         ASSERT(index < MAX_PROGRAM_TEMPS);
         tempUsed[index] = GL_TRUE;
         tempMax = MAX2(tempMax, index);
      }
   }

   /* allocate a new index for each temp that's used */
   {
      GLuint freeTemp = 0;
      for (i = 0; i <= tempMax; i++) {
         if (tempUsed[i]) {
            tempMap[i] = freeTemp++;
            /*_mesa_printf("replace %u with %u\n", i, tempMap[i]);*/
         }
      }
      if (freeTemp == tempMax + 1) {
         /* no consolidation possible */
         return;
      }         
      if (dbg) {
         _mesa_printf("Replace regs 0..%u with 0..%u\n", tempMax, freeTemp-1);
      }
   }

   replace_regs(prog, PROGRAM_TEMPORARY, tempMap);

   if (dbg) {
      _mesa_printf("Optimize: End register consolidation\n");
   }
}