From da52cffcfca12375a1a93506d34d4c4ad5f1d3d2 Mon Sep 17 00:00:00 2001 From: Fabian Bieler Date: Tue, 22 Mar 2011 12:27:30 +0100 Subject: [PATCH] mesa: Extend register live intervals to the beginning of loops if they are referenced outside of the loop --- src/mesa/program/prog_optimize.c | 49 ++++++++++++++++++++++++++++++++----- 1 files changed, 42 insertions(+), 7 deletions(-) diff --git a/src/mesa/program/prog_optimize.c b/src/mesa/program/prog_optimize.c index 96971f2..b819b00 100644 --- a/src/mesa/program/prog_optimize.c +++ b/src/mesa/program/prog_optimize.c @@ -932,9 +932,10 @@ 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) + GLuint index, GLuint ic, GLuint regsInLoop[], + GLuint *numRegsInLoop) { int i; @@ -952,9 +953,22 @@ update_interval(GLint intBegin[], GLint intEnd[], if (intBegin[index] == -1) { ASSERT(intEnd[index] == -1); intBegin[index] = intEnd[index] = ic; + ASSERT(intLoopStart[index] == -1); + if (loopStackDepth) { + regsInLoop[*numRegsInLoop] = index; + (*numRegsInLoop)++; + } } 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]; + } } } @@ -971,9 +985,16 @@ _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]; + /* Temporary registers inside current top level loop */ + GLuint regsInLoop[REG_ALLOCATE_MAX_PROGRAM_TEMPS]; + GLuint numRegsInLoop = 0; 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 +1006,19 @@ _mesa_find_temp_intervals(const struct prog_instruction *instructions, loopStackDepth++; } else if (inst->Opcode == OPCODE_ENDLOOP) { + GLuint j; loopStackDepth--; + for (j = 0; j < numRegsInLoop; j++) { + GLuint index = regsInLoop[j]; + ASSERT(intBegin[index] != -1); + if (intBegin[index] > loopStack[loopStackDepth].Start && + intBegin[index] < loopStack[loopStackDepth].End) { + intLoopStart[index] = loopStack[loopStackDepth].Start; + } + } + if (loopStackDepth == 0) { + numRegsInLoop = 0; + } } else if (inst->Opcode == OPCODE_CAL) { return GL_FALSE; @@ -998,16 +1031,18 @@ _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, regsInLoop, + &numRegsInLoop); } } 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, regsInLoop, + &numRegsInLoop); } } } -- 1.7.4.1