summaryrefslogtreecommitdiff
path: root/src/mesa
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2010-07-07 21:28:28 -0700
committerEric Anholt <eric@anholt.net>2010-07-07 21:33:38 -0700
commit25cda5039df0da6c2c65f1cac1bfc750c0c16e82 (patch)
tree4609b1052281cd5c8955ed28c3e3629d8fcfe465 /src/mesa
parentf632a330eccb26c28a3b94216c55994e94988751 (diff)
mesa: Extend register lifetimes to the end of the largest loop required.
Previously, a register defined at main scope and used in a loop in a loop could end up getting marked as needed only from the definition outside of the loops to the end of the inner loop, and we would cleverly slot in something else in its register in the end of the outer loop. Fixes glsl-vs-loop-nested and glsl-fs-loop-nested on glsl2. This doesn't happen much on master because the original compiler does its own register allocation, so we find little we can do with linear scan register (re)allocation.
Diffstat (limited to 'src/mesa')
-rw-r--r--src/mesa/shader/prog_optimize.c40
1 files changed, 23 insertions, 17 deletions
diff --git a/src/mesa/shader/prog_optimize.c b/src/mesa/shader/prog_optimize.c
index 2941a17da3..bd120b8643 100644
--- a/src/mesa/shader/prog_optimize.c
+++ b/src/mesa/shader/prog_optimize.c
@@ -728,14 +728,32 @@ sort_interval_list_by_start(struct interval_list *list)
#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[], GLuint index, GLuint ic)
+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 < MAX_PROGRAM_TEMPS);
if (intBegin[index] == -1) {
ASSERT(intEnd[index] == -1);
@@ -756,10 +774,6 @@ _mesa_find_temp_intervals(const struct prog_instruction *instructions,
GLint intBegin[MAX_PROGRAM_TEMPS],
GLint intEnd[MAX_PROGRAM_TEMPS])
{
- struct loop_info
- {
- GLuint Start, End; /**< Start, end instructions of loop */
- };
struct loop_info loopStack[MAX_LOOP_NESTING];
GLuint loopStackDepth = 0;
GLuint i;
@@ -790,24 +804,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, index, i);
- if (loopStackDepth > 0) {
- /* extend temp register's interval to end of loop */
- GLuint loopEnd = loopStack[loopStackDepth - 1].End;
- update_interval(intBegin, intEnd, index, loopEnd);
- }
+ 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, index, i);
- if (loopStackDepth > 0) {
- /* extend temp register's interval to end of loop */
- GLuint loopEnd = loopStack[loopStackDepth - 1].End;
- update_interval(intBegin, intEnd, index, loopEnd);
- }
+ update_interval(intBegin, intEnd, loopStack, loopStackDepth,
+ index, i);
}
}
}