X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fprogram%2Fprog_optimize.c;h=7efdcadc1220edd84a9b91ad2a5348883281f11d;hb=HEAD;hp=3340ce0498b7967ae00087c862e25632be06c23f;hpb=6bd5f43f212962a054a41290b0f8e350dae2f40d;p=mesa.git diff --git a/src/mesa/program/prog_optimize.c b/src/mesa/program/prog_optimize.c index 3340ce0498b..7efdcadc122 100644 --- a/src/mesa/program/prog_optimize.c +++ b/src/mesa/program/prog_optimize.c @@ -1,6 +1,5 @@ /* * Mesa 3-D graphics library - * Version: 7.5 * * Copyright (C) 2009 VMware, Inc. All Rights Reserved. * @@ -58,55 +57,46 @@ get_src_arg_mask(const struct prog_instruction *inst, GLuint read_mask, channel_mask; GLuint comp; - ASSERT(arg < _mesa_num_inst_src_regs(inst->Opcode)); + assert(arg < _mesa_num_inst_src_regs(inst->Opcode)); /* Form the dst register, find the written channels */ - if (inst->CondUpdate) { + switch (inst->Opcode) { + case OPCODE_MOV: + case OPCODE_MIN: + case OPCODE_MAX: + case OPCODE_ABS: + case OPCODE_ADD: + case OPCODE_MAD: + case OPCODE_MUL: + case OPCODE_SUB: + case OPCODE_CMP: + case OPCODE_FLR: + case OPCODE_FRC: + case OPCODE_LRP: + case OPCODE_SGE: + case OPCODE_SLT: + case OPCODE_SSG: + channel_mask = inst->DstReg.WriteMask & dst_mask; + break; + case OPCODE_RCP: + case OPCODE_SIN: + case OPCODE_COS: + case OPCODE_RSQ: + case OPCODE_POW: + case OPCODE_EX2: + case OPCODE_LOG: + channel_mask = WRITEMASK_X; + break; + case OPCODE_DP2: + channel_mask = WRITEMASK_XY; + break; + case OPCODE_DP3: + case OPCODE_XPD: + channel_mask = WRITEMASK_XYZ; + break; + default: channel_mask = WRITEMASK_XYZW; - } - else { - switch (inst->Opcode) { - case OPCODE_MOV: - case OPCODE_MIN: - case OPCODE_MAX: - case OPCODE_ABS: - case OPCODE_ADD: - case OPCODE_MAD: - case OPCODE_MUL: - case OPCODE_SUB: - case OPCODE_CMP: - case OPCODE_FLR: - case OPCODE_FRC: - case OPCODE_LRP: - case OPCODE_SEQ: - case OPCODE_SGE: - case OPCODE_SGT: - case OPCODE_SLE: - case OPCODE_SLT: - case OPCODE_SNE: - case OPCODE_SSG: - channel_mask = inst->DstReg.WriteMask & dst_mask; - break; - case OPCODE_RCP: - case OPCODE_SIN: - case OPCODE_COS: - case OPCODE_RSQ: - case OPCODE_POW: - case OPCODE_EX2: - case OPCODE_LOG: - channel_mask = WRITEMASK_X; - break; - case OPCODE_DP2: - channel_mask = WRITEMASK_XY; - break; - case OPCODE_DP3: - case OPCODE_XPD: - channel_mask = WRITEMASK_XYZ; - break; - default: - channel_mask = WRITEMASK_XYZW; - break; - } + break; } /* Now, given the src swizzle and the written channels, find which @@ -115,7 +105,6 @@ get_src_arg_mask(const struct prog_instruction *inst, read_mask = 0x0; for (comp = 0; comp < 4; ++comp) { const GLuint coord = GET_SWZ(inst->SrcReg[arg].Swizzle, comp); - ASSERT(coord < 4); if (channel_mask & (1 << comp) && coord <= SWIZZLE_W) read_mask |= 1 << coord; } @@ -135,7 +124,7 @@ get_dst_mask_for_mov(const struct prog_instruction *mov, GLuint src_mask) GLuint comp; GLuint updated_mask = 0x0; - ASSERT(mov->Opcode == OPCODE_MOV); + assert(mov->Opcode == OPCODE_MOV); for (comp = 0; comp < 4; ++comp) { GLuint src_comp; @@ -170,13 +159,14 @@ is_swizzle_regular(GLuint swz) * \return number of instructions removed */ static GLuint -remove_instructions(struct gl_program *prog, const GLboolean *removeFlags) +remove_instructions(struct gl_program *prog, const GLboolean *removeFlags, + void *mem_ctx) { GLint i, removeEnd = 0, removeCount = 0; GLuint totalRemoved = 0; /* go backward */ - for (i = prog->NumInstructions - 1; i >= 0; i--) { + for (i = prog->arb.NumInstructions - 1; i >= 0; i--) { if (removeFlags[i]) { totalRemoved++; if (removeCount == 0) { @@ -195,7 +185,7 @@ remove_instructions(struct gl_program *prog, const GLboolean *removeFlags) */ if (removeCount > 0) { GLint removeStart = removeEnd - removeCount + 1; - _mesa_delete_instructions(prog, removeStart, removeCount); + _mesa_delete_instructions(prog, removeStart, removeCount, mem_ctx); removeStart = removeCount = 0; /* reset removal info */ } } @@ -203,7 +193,7 @@ remove_instructions(struct gl_program *prog, const GLboolean *removeFlags) /* Finish removing if the first instruction was to be removed. */ if (removeCount > 0) { GLint removeStart = removeEnd - removeCount + 1; - _mesa_delete_instructions(prog, removeStart, removeCount); + _mesa_delete_instructions(prog, removeStart, removeCount, mem_ctx); } return totalRemoved; } @@ -220,20 +210,20 @@ replace_regs(struct gl_program *prog, gl_register_file file, const GLint map[]) { GLuint i; - for (i = 0; i < prog->NumInstructions; i++) { - struct prog_instruction *inst = prog->Instructions + i; + for (i = 0; i < prog->arb.NumInstructions; i++) { + struct prog_instruction *inst = prog->arb.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 == file) { GLuint index = inst->SrcReg[j].Index; - ASSERT(map[index] >= 0); + assert(map[index] >= 0); inst->SrcReg[j].Index = map[index]; } } if (inst->DstReg.File == file) { const GLuint index = inst->DstReg.Index; - ASSERT(map[index] >= 0); + assert(map[index] >= 0); inst->DstReg.Index = map[index]; } } @@ -247,7 +237,7 @@ replace_regs(struct gl_program *prog, gl_register_file file, const GLint map[]) * write to such registers. Be careful with condition code setters. */ static GLboolean -_mesa_remove_dead_code_global(struct gl_program *prog) +_mesa_remove_dead_code_global(struct gl_program *prog, void *mem_ctx) { GLboolean tempRead[REG_ALLOCATE_MAX_PROGRAM_TEMPS][4]; GLboolean *removeInst; /* per-instruction removal flag */ @@ -260,12 +250,12 @@ _mesa_remove_dead_code_global(struct gl_program *prog) /*_mesa_print_program(prog);*/ } - removeInst = (GLboolean *) - calloc(1, prog->NumInstructions * sizeof(GLboolean)); + removeInst = + calloc(prog->arb.NumInstructions, sizeof(GLboolean)); /* Determine which temps are read and written */ - for (i = 0; i < prog->NumInstructions; i++) { - const struct prog_instruction *inst = prog->Instructions + i; + for (i = 0; i < prog->arb.NumInstructions; i++) { + const struct prog_instruction *inst = prog->arb.Instructions + i; const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode); GLuint j; @@ -274,7 +264,7 @@ _mesa_remove_dead_code_global(struct gl_program *prog) if (inst->SrcReg[j].File == PROGRAM_TEMPORARY) { const GLuint index = inst->SrcReg[j].Index; GLuint read_mask; - ASSERT(index < REG_ALLOCATE_MAX_PROGRAM_TEMPS); + assert(index < REG_ALLOCATE_MAX_PROGRAM_TEMPS); read_mask = get_src_arg_mask(inst, j, NO_MASK); if (inst->SrcReg[j].RelAddr) { @@ -285,42 +275,30 @@ _mesa_remove_dead_code_global(struct gl_program *prog) for (comp = 0; comp < 4; comp++) { const GLuint swz = GET_SWZ(inst->SrcReg[j].Swizzle, comp); - ASSERT(swz < 4); - if ((read_mask & (1 << swz)) == 0) - continue; - if (swz <= SWIZZLE_W) + if (swz <= SWIZZLE_W) { + if ((read_mask & (1 << swz)) == 0) + continue; tempRead[index][swz] = GL_TRUE; + } } } } /* check dst reg */ if (inst->DstReg.File == PROGRAM_TEMPORARY) { - const GLuint index = inst->DstReg.Index; - ASSERT(index < REG_ALLOCATE_MAX_PROGRAM_TEMPS); + assert(inst->DstReg.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; + for (i = 0; i < prog->arb.NumInstructions; i++) { + struct prog_instruction *inst = prog->arb.Instructions + i; const GLuint numDst = _mesa_num_inst_dst_regs(inst->Opcode); if (numDst != 0 && inst->DstReg.File == PROGRAM_TEMPORARY) { @@ -348,7 +326,7 @@ _mesa_remove_dead_code_global(struct gl_program *prog) } /* now remove the instructions which aren't needed */ - rem = remove_instructions(prog, removeInst); + rem = remove_instructions(prog, removeInst, mem_ctx); if (dbg) { printf("Optimize: End dead code removal.\n"); @@ -387,12 +365,11 @@ find_next_use(const struct gl_program *prog, { GLuint i; - for (i = start; i < prog->NumInstructions; i++) { - const struct prog_instruction *inst = prog->Instructions + i; + for (i = start; i < prog->arb.NumInstructions; i++) { + const struct prog_instruction *inst = prog->arb.Instructions + i; switch (inst->Opcode) { case OPCODE_BGNLOOP: case OPCODE_BGNSUB: - case OPCODE_BRA: case OPCODE_CAL: case OPCODE_CONT: case OPCODE_IF: @@ -411,7 +388,7 @@ find_next_use(const struct gl_program *prog, for (j = 0; j < numSrc; j++) { if (inst->SrcReg[j].RelAddr || (inst->SrcReg[j].File == PROGRAM_TEMPORARY && - inst->SrcReg[j].Index == index && + inst->SrcReg[j].Index == (GLint)index && (get_src_arg_mask(inst,j,NO_MASK) & mask))) return READ; } @@ -439,7 +416,6 @@ _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: @@ -465,14 +441,9 @@ 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->DstReg.RelAddr == 0; } @@ -482,7 +453,7 @@ can_upward_mov_be_modifed(const struct prog_instruction *mov) return can_downward_mov_be_modifed(mov) && mov->DstReg.File == PROGRAM_TEMPORARY && - mov->SaturateMode == SATURATE_OFF; + !mov->Saturate; } @@ -511,8 +482,8 @@ _mesa_remove_extra_move_use(struct gl_program *prog) * FOO tmpY, arg0, arg1; */ - for (i = 0; i + 1 < prog->NumInstructions; i++) { - const struct prog_instruction *mov = prog->Instructions + i; + for (i = 0; i + 1 < prog->arb.NumInstructions; i++) { + const struct prog_instruction *mov = prog->arb.Instructions + i; GLuint dst_mask, src_mask; if (can_upward_mov_be_modifed(mov) == GL_FALSE) continue; @@ -527,8 +498,8 @@ _mesa_remove_extra_move_use(struct gl_program *prog) * 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; + for (j = i + 1; j < prog->arb.NumInstructions; j++) { + struct prog_instruction *inst2 = prog->arb.Instructions + j; GLuint arg; if (_mesa_is_flow_control_opcode(inst2->Opcode)) @@ -540,8 +511,7 @@ _mesa_remove_extra_move_use(struct gl_program *prog) if (inst2->SrcReg[arg].File != mov->DstReg.File || inst2->SrcReg[arg].Index != mov->DstReg.Index || - inst2->SrcReg[arg].RelAddr || - inst2->SrcReg[arg].Abs) + inst2->SrcReg[arg].RelAddr) continue; read_mask = get_src_arg_mask(inst2, arg, NO_MASK); @@ -599,16 +569,16 @@ _mesa_remove_extra_move_use(struct gl_program *prog) * with a proper control flow graph */ static GLboolean -_mesa_remove_dead_code_local(struct gl_program *prog) +_mesa_remove_dead_code_local(struct gl_program *prog, void *mem_ctx) { GLboolean *removeInst; GLuint i, arg, rem = 0; - removeInst = (GLboolean *) - calloc(1, prog->NumInstructions * sizeof(GLboolean)); + removeInst = + calloc(prog->arb.NumInstructions, sizeof(GLboolean)); - for (i = 0; i < prog->NumInstructions; i++) { - const struct prog_instruction *inst = prog->Instructions + i; + for (i = 0; i < prog->arb.NumInstructions; i++) { + const struct prog_instruction *inst = prog->arb.Instructions + i; const GLuint index = inst->DstReg.Index; const GLuint mask = inst->DstReg.WriteMask; enum inst_use use; @@ -631,7 +601,7 @@ _mesa_remove_dead_code_local(struct gl_program *prog) removeInst[i] = GL_TRUE; } - rem = remove_instructions(prog, removeInst); + rem = remove_instructions(prog, removeInst, mem_ctx); done: free(removeInst); @@ -657,7 +627,7 @@ _mesa_merge_mov_into_inst(struct prog_instruction *inst, if (mask != (inst->DstReg.WriteMask & mask)) return GL_FALSE; - inst->SaturateMode |= mov->SaturateMode; + inst->Saturate |= mov->Saturate; /* Depending on the instruction, we may need to recompute the swizzles. * Also, some other instructions (like TEX) are not linear. We will only @@ -680,7 +650,7 @@ _mesa_merge_mov_into_inst(struct prog_instruction *inst, 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); + assert(src_comp < 4); dst_to_src_comp[dst_comp] = src_comp; } } @@ -696,9 +666,9 @@ _mesa_merge_mov_into_inst(struct prog_instruction *inst, if ((mov->DstReg.WriteMask & (1 << dst_comp)) == 0) continue; src_comp = dst_to_src_comp[dst_comp]; - ASSERT(src_comp < 4); + assert(src_comp < 4); arg_comp = GET_SWZ(arg_swz, src_comp); - ASSERT(arg_comp < 4); + assert(arg_comp < 4); inst->SrcReg[arg].Swizzle |= arg_comp << (3*dst_comp); } } @@ -735,7 +705,7 @@ _mesa_merge_mov_into_inst(struct prog_instruction *inst, * Try to remove extraneous MOV instructions from the given program. */ static GLboolean -_mesa_remove_extra_moves(struct gl_program *prog) +_mesa_remove_extra_moves(struct gl_program *prog, void *mem_ctx) { GLboolean *removeInst; /* per-instruction removal flag */ GLuint i, rem = 0, nesting = 0; @@ -745,8 +715,8 @@ _mesa_remove_extra_moves(struct gl_program *prog) _mesa_print_program(prog); } - removeInst = (GLboolean *) - calloc(1, prog->NumInstructions * sizeof(GLboolean)); + removeInst = + calloc(prog->arb.NumInstructions, sizeof(GLboolean)); /* * Look for sequences such as this: @@ -756,8 +726,8 @@ _mesa_remove_extra_moves(struct gl_program *prog) * FOO tmpY, arg0, arg1; */ - for (i = 0; i < prog->NumInstructions; i++) { - const struct prog_instruction *mov = prog->Instructions + i; + for (i = 0; i < prog->arb.NumInstructions; i++) { + const struct prog_instruction *mov = prog->arb.Instructions + i; switch (mov->Opcode) { case OPCODE_BGNLOOP: @@ -786,13 +756,11 @@ _mesa_remove_extra_moves(struct gl_program *prog) prevI = i - 1; while (prevI > 0 && removeInst[prevI]) prevI--; - prevInst = prog->Instructions + prevI; + prevInst = prog->arb.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) { + prevInst->DstReg.RelAddr == 0) { const GLuint dst_mask = prevInst->DstReg.WriteMask; enum inst_use next_use = find_next_use(prog, i+1, id, dst_mask); @@ -823,7 +791,7 @@ _mesa_remove_extra_moves(struct gl_program *prog) } /* now remove the instructions which aren't needed */ - rem = remove_instructions(prog, removeInst); + rem = remove_instructions(prog, removeInst, mem_ctx); free(removeInst); @@ -876,7 +844,7 @@ insert_interval_by_end(struct interval_list *list, const struct interval *inv) { GLuint i; for (i = 0; i + 1 < list->Num; i++) { - ASSERT(list->Intervals[i].End <= list->Intervals[i + 1].End); + assert(list->Intervals[i].End <= list->Intervals[i + 1].End); } } #endif @@ -892,8 +860,8 @@ remove_interval(struct interval_list *list, const struct interval *inv) 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); + 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++; @@ -929,7 +897,7 @@ sort_interval_list_by_start(struct interval_list *list) { GLuint i; for (i = 0; i + 1 < list->Num; i++) { - ASSERT(list->Intervals[i].Start <= list->Intervals[i + 1].Start); + assert(list->Intervals[i].Start <= list->Intervals[i + 1].Start); } } #endif @@ -949,7 +917,7 @@ update_interval(GLint intBegin[], GLint intEnd[], struct loop_info *loopStack, GLuint loopStackDepth, GLuint index, GLuint ic) { - int i; + unsigned i; GLuint begin = ic; GLuint end = ic; @@ -971,9 +939,9 @@ update_interval(GLint intBegin[], GLint intEnd[], begin = loopStack[0].Start; } - ASSERT(index < REG_ALLOCATE_MAX_PROGRAM_TEMPS); + assert(index < REG_ALLOCATE_MAX_PROGRAM_TEMPS); if (intBegin[index] == -1) { - ASSERT(intEnd[index] == -1); + assert(intEnd[index] == -1); intBegin[index] = begin; intEnd[index] = end; } @@ -1066,7 +1034,8 @@ find_live_intervals(struct gl_program *prog, } /* build intermediate arrays */ - if (!_mesa_find_temp_intervals(prog->Instructions, prog->NumInstructions, + if (!_mesa_find_temp_intervals(prog->arb.Instructions, + prog->arb.NumInstructions, intBegin, intEnd)) return GL_FALSE; @@ -1181,7 +1150,7 @@ _mesa_reallocate_registers(struct gl_program *prog) else { /* Interval 'inv' has expired */ const GLint regNew = registerMap[inv->Reg]; - ASSERT(regNew >= 0); + assert(regNew >= 0); if (dbg) printf(" expire interval for reg %u\n", inv->Reg); @@ -1193,7 +1162,7 @@ _mesa_reallocate_registers(struct gl_program *prog) /* return register regNew to the free pool */ if (dbg) printf(" free reg %d\n", regNew); - ASSERT(usedRegs[regNew] == GL_TRUE); + assert(usedRegs[regNew] == GL_TRUE); usedRegs[regNew] = GL_FALSE; } } @@ -1226,7 +1195,7 @@ _mesa_reallocate_registers(struct gl_program *prog) */ replace_regs(prog, PROGRAM_TEMPORARY, registerMap); - prog->NumTemporaries = maxTemp + 1; + prog->arb.NumTemporaries = maxTemp + 1; } if (dbg) { @@ -1241,7 +1210,7 @@ _mesa_reallocate_registers(struct gl_program *prog) #if 0 static void print_it(struct gl_context *ctx, struct gl_program *program, const char *txt) { - fprintf(stderr, "%s (%u inst):\n", txt, program->NumInstructions); + fprintf(stderr, "%s (%u inst):\n", txt, program->arb.NumInstructions); _mesa_print_program(program); _mesa_print_program_parameters(ctx, program); fprintf(stderr, "\n\n"); @@ -1289,8 +1258,8 @@ _mesa_simplify_cmp(struct gl_program * program) outputWrites[i] = 0; } - for (i = 0; i < program->NumInstructions; i++) { - struct prog_instruction *inst = program->Instructions + i; + for (i = 0; i < program->arb.NumInstructions; i++) { + struct prog_instruction *inst = program->arb.Instructions + i; GLuint prevWriteMask; /* Give up if we encounter relative addressing or flow control. */ @@ -1343,7 +1312,7 @@ _mesa_simplify_cmp(struct gl_program * program) * instructions, temp regs, etc. */ void -_mesa_optimize_program(struct gl_context *ctx, struct gl_program *program) +_mesa_optimize_program(struct gl_program *program, void *mem_ctx) { GLboolean any_change; @@ -1352,12 +1321,14 @@ _mesa_optimize_program(struct gl_context *ctx, struct gl_program *program) do { any_change = GL_FALSE; _mesa_remove_extra_move_use(program); - if (_mesa_remove_dead_code_global(program)) + if (_mesa_remove_dead_code_global(program, mem_ctx)) any_change = GL_TRUE; - if (_mesa_remove_extra_moves(program)) + if (_mesa_remove_extra_moves(program, mem_ctx)) any_change = GL_TRUE; - if (_mesa_remove_dead_code_local(program)) + if (_mesa_remove_dead_code_local(program, mem_ctx)) any_change = GL_TRUE; + + any_change = _mesa_constant_fold(program) || any_change; _mesa_reallocate_registers(program); } while (any_change); }