From f100711c3ea5867acd43dee43425f130a07b2685 Mon Sep 17 00:00:00 2001 From: Fabian Bieler Date: Mon, 28 Mar 2011 19:45:34 +0200 Subject: [PATCH 1/2] mesa: Extend register live intervals to the beginning of loops if they are referenced outside of the loop --- src/mesa/program/prog_optimize.c | 36 ++++++++++++++++++++++++++++++------ 1 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/mesa/program/prog_optimize.c b/src/mesa/program/prog_optimize.c index 96971f2..9f3edab 100644 --- a/src/mesa/program/prog_optimize.c +++ b/src/mesa/program/prog_optimize.c @@ -932,7 +932,7 @@ struct loop_info * instruction 'ic'. */ static void -update_interval(GLint intBegin[], GLint intEnd[], +update_interval(GLint intBegin[], GLint intEnd[], GLint intLoopStart[], struct loop_info *loopStack, GLuint loopStackDepth, GLuint index, GLuint ic) { @@ -952,9 +952,19 @@ update_interval(GLint intBegin[], GLint intEnd[], if (intBegin[index] == -1) { ASSERT(intEnd[index] == -1); intBegin[index] = intEnd[index] = ic; + ASSERT(intLoopStart[index] == -1); } else { intEnd[index] = ic; + /* If a register is assigned to in a loop and referenced outside of the + * loop, add the entire loop to the live interval so that instructions + * before the assignement don't overwrite it on subsequent iterations. + */ + if (intLoopStart[index] != -1) { + ASSERT(intLoopStart[index] <= intBegin[index]); + intBegin[index] = intLoopStart[index]; + intLoopStart[index] = -1; + } } } @@ -971,9 +981,13 @@ _mesa_find_temp_intervals(const struct prog_instruction *instructions, struct loop_info loopStack[MAX_LOOP_NESTING]; GLuint loopStackDepth = 0; GLuint i; + /* If a register was first used in a (nested) loop this variable holds the + * start of the loop that contains said usage and was closed most recently + */ + GLint intLoopStart[REG_ALLOCATE_MAX_PROGRAM_TEMPS]; for (i = 0; i < REG_ALLOCATE_MAX_PROGRAM_TEMPS; i++){ - intBegin[i] = intEnd[i] = -1; + intBegin[i] = intEnd[i] = intLoopStart[i] = -1; } /* Scan instructions looking for temporary registers */ @@ -985,7 +999,17 @@ _mesa_find_temp_intervals(const struct prog_instruction *instructions, loopStackDepth++; } else if (inst->Opcode == OPCODE_ENDLOOP) { + GLuint j; loopStackDepth--; + for (j = 0; j < REG_ALLOCATE_MAX_PROGRAM_TEMPS; j++) { + GLuint index = j; + if (intBegin[index] == -1) + continue; + if (intBegin[index] > loopStack[loopStackDepth].Start && + intBegin[index] < loopStack[loopStackDepth].End) { + intLoopStart[index] = loopStack[loopStackDepth].Start; + } + } } else if (inst->Opcode == OPCODE_CAL) { return GL_FALSE; @@ -998,16 +1022,16 @@ _mesa_find_temp_intervals(const struct prog_instruction *instructions, const GLuint index = inst->SrcReg[j].Index; if (inst->SrcReg[j].RelAddr) return GL_FALSE; - update_interval(intBegin, intEnd, loopStack, loopStackDepth, - index, i); + update_interval(intBegin, intEnd, intLoopStart, 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); + update_interval(intBegin, intEnd, intLoopStart, loopStack, + loopStackDepth, index, i); } } } -- 1.7.4.1