summaryrefslogtreecommitdiffstats
path: root/configs
ModeNameSize
-rw-r--r--.gitignore17logstatsplain
-rw-r--r--aix771logstatsplain
-rw-r--r--aix-64778logstatsplain
-rw-r--r--aix-64-static557logstatsplain
-rw-r--r--aix-gcc602logstatsplain
-rw-r--r--aix-static523logstatsplain
-rw-r--r--autoconf.in4231logstatsplain
-rw-r--r--beos1743logstatsplain
-rw-r--r--bluegene-osmesa1085logstatsplain
-rw-r--r--bluegene-xlc-osmesa859logstatsplain
-rw-r--r--catamount-osmesa-pgi1082logstatsplain
-rw-r--r--config.mgw1152logstatsplain
-rw-r--r--darwin2140logstatsplain
-rw-r--r--darwin-fat-32bit163logstatsplain
-rw-r--r--darwin-fat-all196logstatsplain
-rw-r--r--darwin-x86ppc1303logstatsplain
-rw-r--r--default4157logstatsplain
-rw-r--r--freebsd793logstatsplain
-rw-r--r--freebsd-dri1630logstatsplain
-rw-r--r--freebsd-dri-amd64256logstatsplain
-rw-r--r--freebsd-dri-x86329logstatsplain
-rw-r--r--hpux10397logstatsplain
-rw-r--r--hpux10-gcc535logstatsplain
-rw-r--r--hpux10-static936logstatsplain
-rw-r--r--hpux11-32934logstatsplain
-rw-r--r--hpux11-32-static754logstatsplain
-rw-r--r--hpux11-32-static-nothreads643logstatsplain
-rw-r--r--hpux11-64990logstatsplain
-rw-r--r--hpux11-64-static793logstatsplain
-rw-r--r--hpux11-ia64918logstatsplain
-rw-r--r--hpux11-ia64-static799logstatsplain
-rw-r--r--hpux9446logstatsplain
-rw-r--r--hpux9-gcc401logstatsplain
-rw-r--r--irix6-64462logstatsplain
-rw-r--r--irix6-64-static615logstatsplain
-rw-r--r--irix6-n32471logstatsplain
-rw-r--r--irix6-n32-static604logstatsplain
-rw-r--r--irix6-o32433logstatsplain
-rw-r--r--irix6-o32-static569logstatsplain
-rw-r--r--linux934logstatsplain
-rw-r--r--linux-alpha758logstatsplain
-rw-r--r--linux-alpha-static992logstatsplain
-rw-r--r--linux-cell1374logstatsplain
-rw-r--r--linux-cell-debug153logstatsplain
-rw-r--r--linux-debug160logstatsplain
-rw-r--r--linux-directfb1185logstatsplain
-rw-r--r--linux-dri1772logstatsplain
-rw-r--r--linux-dri-debug414logstatsplain
-rw-r--r--linux-dri-ppc433logstatsplain
-rw-r--r--linux-dri-x86334logstatsplain
-rw-r--r--linux-dri-x86-64629logstatsplain
-rw-r--r--linux-dri-xcb2279logstatsplain
-rw-r--r--linux-egl1714logstatsplain
-rw-r--r--linux-fbdev615logstatsplain
-rw-r--r--linux-glide1062logstatsplain
-rw-r--r--linux-ia64-icc829logstatsplain
-rw-r--r--linux-ia64-icc-static893logstatsplain
-rw-r--r--linux-icc753logstatsplain
-rw-r--r--linux-icc-static891logstatsplain
-rw-r--r--linux-indirect1313logstatsplain
-rw-r--r--linux-llvm1009logstatsplain
-rw-r--r--linux-osmesa871logstatsplain
-rw-r--r--linux-osmesa-static1055logstatsplain
-rw-r--r--linux-osmesa16904logstatsplain
-rw-r--r--linux-osmesa16-static883logstatsplain
-rw-r--r--linux-osmesa32904logstatsplain
-rw-r--r--linux-ppc201logstatsplain
-rw-r--r--linux-ppc-static312logstatsplain
-rw-r--r--linux-profile160logstatsplain
-rw-r--r--linux-solo1642logstatsplain
-rw-r--r--linux-solo-ia64202logstatsplain
-rw-r--r--linux-solo-x86295logstatsplain
-rw-r--r--linux-sparc193logstatsplain
-rw-r--r--linux-sparc5132logstatsplain
-rw-r--r--linux-static643logstatsplain
-rw-r--r--linux-ultrasparc146logstatsplain
-rw-r--r--linux-x86278logstatsplain
-rw-r--r--linux-x86-32135logstatsplain
-rw-r--r--linux-x86-64282logstatsplain
-rw-r--r--linux-x86-64-debug170logstatsplain
-rw-r--r--linux-x86-64-profile199logstatsplain
-rw-r--r--linux-x86-64-static790logstatsplain
-rw-r--r--linux-x86-debug205logstatsplain
-rw-r--r--linux-x86-glide1194logstatsplain
-rw-r--r--linux-x86-profile191logstatsplain
-rw-r--r--linux-x86-static673logstatsplain
-rw-r--r--netbsd440logstatsplain
-rw-r--r--openbsd690logstatsplain
-rw-r--r--osf1561logstatsplain
-rw-r--r--osf1-static455logstatsplain
-rw-r--r--solaris-x86463logstatsplain
-rw-r--r--solaris-x86-gcc775logstatsplain
-rw-r--r--solaris-x86-gcc-static925logstatsplain
-rw-r--r--sunos4267logstatsplain
-rw-r--r--sunos4-gcc566logstatsplain
-rw-r--r--sunos4-static639logstatsplain
-rw-r--r--sunos5653logstatsplain
-rw-r--r--sunos5-64-gcc265logstatsplain
-rw-r--r--sunos5-gcc1063logstatsplain
-rw-r--r--sunos5-smp765logstatsplain
-rw-r--r--sunos5-v8706logstatsplain
-rw-r--r--sunos5-v8-static512logstatsplain
-rw-r--r--sunos5-v9762logstatsplain
-rw-r--r--sunos5-v9-cc-g++1189logstatsplain
-rw-r--r--sunos5-v9-static563logstatsplain
-rw-r--r--ultrix-gcc588logstatsplain
/* check dst reg */ if (inst->DstReg.File == PROGRAM_TEMPORARY) { const GLuint index = inst->DstReg.Index; ASSERT(index < REG_ALLOCATE_MAX_PROGRAM_TEMPS); if (inst->DstReg.RelAddr) { if (dbg) printf("abort remove dead code (indirect temp)\n"); goto done; } if (inst->CondUpdate) { /* If we're writing to this register and setting condition * codes we cannot remove the instruction. Prevent removal * by setting the 'read' flag. */ tempRead[index][0] = GL_TRUE; tempRead[index][1] = GL_TRUE; tempRead[index][2] = GL_TRUE; tempRead[index][3] = GL_TRUE; } } } /* find instructions that write to dead registers, flag for removal */ for (i = 0; i < prog->NumInstructions; i++) { struct prog_instruction *inst = prog->Instructions + i; const GLuint numDst = _mesa_num_inst_dst_regs(inst->Opcode); if (numDst != 0 && inst->DstReg.File == PROGRAM_TEMPORARY) { GLint chan, index = inst->DstReg.Index; for (chan = 0; chan < 4; chan++) { if (!tempRead[index][chan] && inst->DstReg.WriteMask & (1 << chan)) { if (dbg) { printf("Remove writemask on %u.%c\n", i, chan == 3 ? 'w' : 'x' + chan); } inst->DstReg.WriteMask &= ~(1 << chan); rem++; } } if (inst->DstReg.WriteMask == 0) { /* If we cleared all writes, the instruction can be removed. */ if (dbg) printf("Remove instruction %u: \n", i); removeInst[i] = GL_TRUE; } } } /* now remove the instructions which aren't needed */ rem = remove_instructions(prog, removeInst); if (dbg) { printf("Optimize: End dead code removal.\n"); printf(" %u channel writes removed\n", rem); printf(" %u instructions removed\n", rem); /*_mesa_print_program(prog);*/ } done: free(removeInst); return rem != 0; } enum inst_use { READ, WRITE, FLOW, END }; /** * Scan forward in program from 'start' for the next occurances of TEMP[index]. * We look if an instruction reads the component given by the masks and if they * are overwritten. * Return READ, WRITE, FLOW or END to indicate the next usage or an indicator * that we can't look further. */ static enum inst_use find_next_use(const struct gl_program *prog, GLuint start, GLuint index, GLuint mask) { GLuint i; for (i = start; i < prog->NumInstructions; i++) { const struct prog_instruction *inst = prog->Instructions + i; switch (inst->Opcode) { case OPCODE_BGNLOOP: case OPCODE_BGNSUB: case OPCODE_BRA: case OPCODE_CAL: case OPCODE_CONT: case OPCODE_IF: case OPCODE_ELSE: case OPCODE_ENDIF: case OPCODE_ENDLOOP: case OPCODE_ENDSUB: case OPCODE_RET: return FLOW; case OPCODE_END: return END; default: { const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode); GLuint j; for (j = 0; j < numSrc; j++) { if (inst->SrcReg[j].RelAddr || (inst->SrcReg[j].File == PROGRAM_TEMPORARY && inst->SrcReg[j].Index == index && (get_src_arg_mask(inst,j,NO_MASK) & mask))) return READ; } if (_mesa_num_inst_dst_regs(inst->Opcode) == 1 && inst->DstReg.File == PROGRAM_TEMPORARY && inst->DstReg.Index == index) { mask &= ~inst->DstReg.WriteMask; if (mask == 0) return WRITE; } } } } return END; } /** * Is the given instruction opcode a flow-control opcode? * XXX maybe move this into prog_instruction.[ch] */ static GLboolean _mesa_is_flow_control_opcode(enum prog_opcode opcode) { switch (opcode) { case OPCODE_BGNLOOP: case OPCODE_BGNSUB: case OPCODE_BRA: case OPCODE_CAL: case OPCODE_CONT: case OPCODE_IF: case OPCODE_ELSE: case OPCODE_END: case OPCODE_ENDIF: case OPCODE_ENDLOOP: case OPCODE_ENDSUB: case OPCODE_RET: return GL_TRUE; default: return GL_FALSE; } } /** * Test if the given instruction is a simple MOV (no conditional updating, * not relative addressing, no negation/abs, etc). */ static GLboolean can_downward_mov_be_modifed(const struct prog_instruction *mov) { return mov->Opcode == OPCODE_MOV && mov->CondUpdate == GL_FALSE && mov->SrcReg[0].RelAddr == 0 && mov->SrcReg[0].Negate == 0 && mov->SrcReg[0].Abs == 0 && mov->SrcReg[0].HasIndex2 == 0 && mov->SrcReg[0].RelAddr2 == 0 && mov->DstReg.RelAddr == 0 && mov->DstReg.CondMask == COND_TR && mov->SaturateMode == SATURATE_OFF; } static GLboolean can_upward_mov_be_modifed(const struct prog_instruction *mov) { return can_downward_mov_be_modifed(mov) && mov->DstReg.File == PROGRAM_TEMPORARY; } /** * Try to remove use of extraneous MOV instructions, to free them up for dead * code removal. */ static void _mesa_remove_extra_move_use(struct gl_program *prog) { GLuint i, j; if (dbg) { printf("Optimize: Begin remove extra move use\n"); _mesa_print_program(prog); } /* * Look for sequences such as this: * MOV tmpX, arg0; * ... * FOO tmpY, tmpX, arg1; * and convert into: * MOV tmpX, arg0; * ... * FOO tmpY, arg0, arg1; */ for (i = 0; i + 1 < prog->NumInstructions; i++) { const struct prog_instruction *mov = prog->Instructions + i; GLuint dst_mask, src_mask; if (can_upward_mov_be_modifed(mov) == GL_FALSE) continue; /* Scanning the code, we maintain the components which are still active in * these two masks */ dst_mask = mov->DstReg.WriteMask; src_mask = get_src_arg_mask(mov, 0, NO_MASK); /* Walk through remaining instructions until the or src reg gets * rewritten or we get into some flow-control, eliminating the use of * this MOV. */ for (j = i + 1; j < prog->NumInstructions; j++) { struct prog_instruction *inst2 = prog->Instructions + j; GLuint arg; if (_mesa_is_flow_control_opcode(inst2->Opcode)) break; /* First rewrite this instruction's args if appropriate. */ for (arg = 0; arg < _mesa_num_inst_src_regs(inst2->Opcode); arg++) { GLuint comp, read_mask; if (inst2->SrcReg[arg].File != mov->DstReg.File || inst2->SrcReg[arg].Index != mov->DstReg.Index || inst2->SrcReg[arg].RelAddr || inst2->SrcReg[arg].Abs) continue; read_mask = get_src_arg_mask(inst2, arg, NO_MASK); /* Adjust the swizzles of inst2 to point at MOV's source if ALL the * components read still come from the mov instructions */ if (is_swizzle_regular(inst2->SrcReg[arg].Swizzle) && (read_mask & dst_mask) == read_mask) { for (comp = 0; comp < 4; comp++) { const GLuint inst2_swz = GET_SWZ(inst2->SrcReg[arg].Swizzle, comp); const GLuint s = GET_SWZ(mov->SrcReg[0].Swizzle, inst2_swz); inst2->SrcReg[arg].Swizzle &= ~(7 << (3 * comp)); inst2->SrcReg[arg].Swizzle |= s << (3 * comp); inst2->SrcReg[arg].Negate ^= (((mov->SrcReg[0].Negate >> inst2_swz) & 0x1) << comp); } inst2->SrcReg[arg].File = mov->SrcReg[0].File; inst2->SrcReg[arg].Index = mov->SrcReg[0].Index; } } /* The source of MOV is written. This potentially deactivates some * components from the src and dst of the MOV instruction */ if (inst2->DstReg.File == mov->DstReg.File && (inst2->DstReg.RelAddr || inst2->DstReg.Index == mov->DstReg.Index)) { dst_mask &= ~inst2->DstReg.WriteMask; src_mask = get_src_arg_mask(mov, 0, dst_mask); } /* Idem when the destination of mov is written */ if (inst2->DstReg.File == mov->SrcReg[0].File && (inst2->DstReg.RelAddr || inst2->DstReg.Index == mov->SrcReg[0].Index)) { src_mask &= ~inst2->DstReg.WriteMask; dst_mask &= get_dst_mask_for_mov(mov, src_mask); } if (dst_mask == 0) break; } } if (dbg) { printf("Optimize: End remove extra move use.\n"); /*_mesa_print_program(prog);*/ } } /** * Complements dead_code_global. Try to remove code in block of code by * carefully monitoring the swizzles. Both functions should be merged into one * with a proper control flow graph */ static GLboolean _mesa_remove_dead_code_local(struct gl_program *prog) { GLboolean *removeInst; GLuint i, arg, rem = 0; removeInst = (GLboolean *) calloc(1, prog->NumInstructions * sizeof(GLboolean)); for (i = 0; i < prog->NumInstructions; i++) { const struct prog_instruction *inst = prog->Instructions + i; const GLuint index = inst->DstReg.Index; const GLuint mask = inst->DstReg.WriteMask; enum inst_use use; /* We must deactivate the pass as soon as some indirection is used */ if (inst->DstReg.RelAddr) goto done; for (arg = 0; arg < _mesa_num_inst_src_regs(inst->Opcode); arg++) if (inst->SrcReg[arg].RelAddr) goto done; if (_mesa_is_flow_control_opcode(inst->Opcode) || _mesa_num_inst_dst_regs(inst->Opcode) == 0 || inst->DstReg.File != PROGRAM_TEMPORARY || inst->DstReg.RelAddr) continue; use = find_next_use(prog, i+1, index, mask); if (use == WRITE || use == END) removeInst[i] = GL_TRUE; } rem = remove_instructions(prog, removeInst); done: free(removeInst); return rem != 0; } /** * Try to inject the destination of mov as the destination of inst and recompute * the swizzles operators for the sources of inst if required. Return GL_TRUE * of the substitution was possible, GL_FALSE otherwise */ static GLboolean _mesa_merge_mov_into_inst(struct prog_instruction *inst, const struct prog_instruction *mov) { /* Indirection table which associates destination and source components for * the mov instruction */ const GLuint mask = get_src_arg_mask(mov, 0, NO_MASK); /* Some components are not written by inst. We cannot remove the mov */ if (mask != (inst->DstReg.WriteMask & mask)) return GL_FALSE; /* Depending on the instruction, we may need to recompute the swizzles. * Also, some other instructions (like TEX) are not linear. We will only * consider completely active sources and destinations */ switch (inst->Opcode) { /* Carstesian instructions: we compute the swizzle */ case OPCODE_MOV: case OPCODE_MIN: case OPCODE_MAX: case OPCODE_ABS: case OPCODE_ADD: case OPCODE_MAD: case OPCODE_MUL: case OPCODE_SUB: { GLuint dst_to_src_comp[4] = {0,0,0,0}; GLuint dst_comp, arg; for (dst_comp = 0; dst_comp < 4; ++dst_comp) { if (mov->DstReg.WriteMask & (1 << dst_comp)) { const GLuint src_comp = GET_SWZ(mov->SrcReg[0].Swizzle, dst_comp); ASSERT(src_comp < 4); dst_to_src_comp[dst_comp] = src_comp; } } /* Patch each source of the instruction */ for (arg = 0; arg < _mesa_num_inst_src_regs(inst->Opcode); arg++) { const GLuint arg_swz = inst->SrcReg[arg].Swizzle; inst->SrcReg[arg].Swizzle = 0; /* Reset each active component of the swizzle */ for (dst_comp = 0; dst_comp < 4; ++dst_comp) { GLuint src_comp, arg_comp; if ((mov->DstReg.WriteMask & (1 << dst_comp)) == 0) continue; src_comp = dst_to_src_comp[dst_comp]; ASSERT(src_comp < 4); arg_comp = GET_SWZ(arg_swz, src_comp); ASSERT(arg_comp < 4); inst->SrcReg[arg].Swizzle |= arg_comp << (3*dst_comp); } } inst->DstReg = mov->DstReg; return GL_TRUE; } /* Dot products and scalar instructions: we only change the destination */ case OPCODE_RCP: case OPCODE_SIN: case OPCODE_COS: case OPCODE_RSQ: case OPCODE_POW: case OPCODE_EX2: case OPCODE_LOG: case OPCODE_DP2: case OPCODE_DP3: case OPCODE_DP4: inst->DstReg = mov->DstReg; return GL_TRUE; /* All other instructions require fully active components with no swizzle */ default: if (mov->SrcReg[0].Swizzle != SWIZZLE_XYZW || inst->DstReg.WriteMask != WRITEMASK_XYZW) return GL_FALSE; inst->DstReg = mov->DstReg; return GL_TRUE; } } /** * Try to remove extraneous MOV instructions from the given program. */ static GLboolean _mesa_remove_extra_moves(struct gl_program *prog) { GLboolean *removeInst; /* per-instruction removal flag */ GLuint i, rem = 0, nesting = 0; if (dbg) { printf("Optimize: Begin remove extra moves\n"); _mesa_print_program(prog); } removeInst = (GLboolean *) calloc(1, prog->NumInstructions * sizeof(GLboolean)); /* * Look for sequences such as this: * FOO tmpX, arg0, arg1; * MOV tmpY, tmpX; * and convert into: * FOO tmpY, arg0, arg1; */ for (i = 0; i < prog->NumInstructions; i++) { const struct prog_instruction *mov = prog->Instructions + i; switch (mov->Opcode) { case OPCODE_BGNLOOP: case OPCODE_BGNSUB: case OPCODE_IF: nesting++; break; case OPCODE_ENDLOOP: case OPCODE_ENDSUB: case OPCODE_ENDIF: nesting--; break; case OPCODE_MOV: if (i > 0 && can_downward_mov_be_modifed(mov) && mov->SrcReg[0].File == PROGRAM_TEMPORARY && nesting == 0) { /* see if this MOV can be removed */ const GLuint id = mov->SrcReg[0].Index; struct prog_instruction *prevInst; GLuint prevI; /* get pointer to previous instruction */ prevI = i - 1; while (prevI > 0 && removeInst[prevI]) prevI--; prevInst = prog->Instructions + prevI; if (prevInst->DstReg.File == PROGRAM_TEMPORARY && prevInst->DstReg.Index == id && prevInst->DstReg.RelAddr == 0 && prevInst->DstReg.CondSrc == 0 && prevInst->DstReg.CondMask == COND_TR) { const GLuint dst_mask = prevInst->DstReg.WriteMask; enum inst_use next_use = find_next_use(prog, i+1, id, dst_mask); if (next_use == WRITE || next_use == END) { /* OK, we can safely remove this MOV instruction. * Transform: * prevI: FOO tempIndex, x, y; * i: MOV z, tempIndex; * Into: * prevI: FOO z, x, y; */ if (_mesa_merge_mov_into_inst(prevInst, mov)) { removeInst[i] = GL_TRUE; if (dbg) { printf("Remove MOV at %u\n", i); printf("new prev inst %u: ", prevI); _mesa_print_instruction(prevInst); } } } } } break; default: ; /* nothing */ } } /* now remove the instructions which aren't needed */ rem = remove_instructions(prog, removeInst); free(removeInst); if (dbg) { printf("Optimize: End remove extra moves. %u instructions removed\n", rem); /*_mesa_print_program(prog);*/ } return rem != 0; } /** A live register interval */ struct interval { GLuint Reg; /** The temporary register index */ GLuint Start, End; /** Start/end instruction numbers */ }; /** A list of register intervals */ struct interval_list { GLuint Num; struct interval Intervals[REG_ALLOCATE_MAX_PROGRAM_TEMPS]; }; static void append_interval(struct interval_list *list, const struct interval *inv) { list->Intervals[list->Num++] = *inv; } /** Insert interval inv into list, sorted by interval end */ static void insert_interval_by_end(struct interval_list *list, const struct interval *inv) { /* XXX we could do a binary search insertion here since list is sorted */ GLint i = list->Num - 1; while (i >= 0 && list->Intervals[i].End > inv->End) { list->Intervals[i + 1] = list->Intervals[i]; i--; } list->Intervals[i + 1] = *inv; list->Num++; #ifdef DEBUG { GLuint i; for (i = 0; i + 1 < list->Num; i++) { ASSERT(list->Intervals[i].End <= list->Intervals[i + 1].End); } } #endif } /** Remove the given interval from the interval list */ static void remove_interval(struct interval_list *list, const struct interval *inv) { /* XXX we could binary search since list is sorted */ GLuint k; for (k = 0; k < list->Num; k++) { if (list->Intervals[k].Reg == inv->Reg) { /* found, remove it */ ASSERT(list->Intervals[k].Start == inv->Start); ASSERT(list->Intervals[k].End == inv->End); while (k < list->Num - 1) { list->Intervals[k] = list->Intervals[k + 1]; k++; } list->Num--; return; } } } /** called by qsort() */ static int compare_start(const void *a, const void *b) { const struct interval *ia = (const struct interval *) a; const struct interval *ib = (const struct interval *) b; if (ia->Start < ib->Start) return -1; else if (ia->Start > ib->Start) return +1; else return 0; } /** sort the interval list according to interval starts */ static void sort_interval_list_by_start(struct interval_list *list) { qsort(list->Intervals, list->Num, sizeof(struct interval), compare_start); #ifdef DEBUG { GLuint i; for (i = 0; i + 1 < list->Num; i++) { ASSERT(list->Intervals[i].Start <= list->Intervals[i + 1].Start); } } #endif } struct loop_info { GLuint Start, End; /**< Start, end instructions of loop */ }; /** * Update the intermediate interval info for register 'index' and * instruction 'ic'. */ static void update_interval(GLint intBegin[], GLint intEnd[], struct loop_info *loopStack, GLuint loopStackDepth, GLuint index, GLuint ic) { int i; /* If the register is used in a loop, extend its lifetime through the end * of the outermost loop that doesn't contain its definition. */ for (i = 0; i < loopStackDepth; i++) { if (intBegin[index] < loopStack[i].Start) { ic = loopStack[i].End; break; } } ASSERT(index < REG_ALLOCATE_MAX_PROGRAM_TEMPS); if (intBegin[index] == -1) { ASSERT(intEnd[index] == -1); intBegin[index] = intEnd[index] = ic; } else { intEnd[index] = ic; } } /** * Find first/last instruction that references each temporary register. */ GLboolean _mesa_find_temp_intervals(const struct prog_instruction *instructions, GLuint numInstructions, GLint intBegin[REG_ALLOCATE_MAX_PROGRAM_TEMPS], GLint intEnd[REG_ALLOCATE_MAX_PROGRAM_TEMPS]) { struct loop_info loopStack[MAX_LOOP_NESTING]; GLuint loopStackDepth = 0; GLuint i; for (i = 0; i < REG_ALLOCATE_MAX_PROGRAM_TEMPS; i++){ intBegin[i] = intEnd[i] = -1; } /* Scan instructions looking for temporary registers */ for (i = 0; i < numInstructions; i++) { const struct prog_instruction *inst = instructions + i; if (inst->Opcode == OPCODE_BGNLOOP) { loopStack[loopStackDepth].Start = i; loopStack[loopStackDepth].End = inst->BranchTarget; loopStackDepth++; } else if (inst->Opcode == OPCODE_ENDLOOP) { loopStackDepth--; } else if (inst->Opcode == OPCODE_CAL) { return GL_FALSE; } else { const GLuint numSrc = 3;/*_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; if (inst->SrcReg[j].RelAddr) return GL_FALSE; update_interval(intBegin, intEnd, loopStack, loopStackDepth, index, i); } } if (inst->DstReg.File == PROGRAM_TEMPORARY) { const GLuint index = inst->DstReg.Index; if (inst->DstReg.RelAddr) return GL_FALSE; update_interval(intBegin, intEnd, loopStack, loopStackDepth, index, i); } } } return GL_TRUE; } /** * Find the live intervals for each temporary register in the program. * For register R, the interval [A,B] indicates that R is referenced * from instruction A through instruction B. * Special consideration is needed for loops and subroutines. * \return GL_TRUE if success, GL_FALSE if we cannot proceed for some reason */ static GLboolean find_live_intervals(struct gl_program *prog, struct interval_list *liveIntervals) { GLint intBegin[REG_ALLOCATE_MAX_PROGRAM_TEMPS]; GLint intEnd[REG_ALLOCATE_MAX_PROGRAM_TEMPS]; GLuint i; /* * Note: we'll return GL_FALSE below if we find relative indexing * into the TEMP register file. We can't handle that yet. * We also give up on subroutines for now. */ if (dbg) { printf("Optimize: Begin find intervals\n"); } /* build intermediate arrays */ if (!_mesa_find_temp_intervals(prog->Instructions, prog->NumInstructions, intBegin, intEnd)) return GL_FALSE; /* Build live intervals list from intermediate arrays */ liveIntervals->Num = 0; for (i = 0; i < REG_ALLOCATE_MAX_PROGRAM_TEMPS; i++) { if (intBegin[i] >= 0) { struct interval inv; inv.Reg = i; inv.Start = intBegin[i];