commit 7ab9fc73707be46375668e557b5a5c1a373096ad
Author: chr <chr@LAPTOP.(none)>
Date:   Sun May 3 21:03:35 2009 +0200

    Remove some memory leaks: free allocated temp in all opcode cases
    of tx_insn; free nv50_regs for immds in LIT and those allocated in
    tgsi_src.
    Make LRP use 2 instructions (SUB,MAD) instead of 3 (NEG,MAD,MAD).

diff --git a/src/gallium/drivers/nv50/nv50_program.c b/src/gallium/drivers/nv50/nv50_program.c
index 2d15868..1a94327 100644
--- a/src/gallium/drivers/nv50/nv50_program.c
+++ b/src/gallium/drivers/nv50/nv50_program.c
@@ -28,6 +28,7 @@
 #include "pipe/p_shader_tokens.h"
 #include "tgsi/tgsi_parse.h"
 #include "tgsi/tgsi_util.h"
+#include "tgsi/tgsi_dump.h"
 
 #include "nv50_context.h"
 
@@ -795,12 +796,6 @@ emit_lit(struct nv50_pc *pc, struct nv50_reg **dst, unsigned mask,
 	struct nv50_reg *pos128 = alloc_immd(pc,  127.999999);
 	struct nv50_reg *tmp[4];
 
-	if (mask & (1 << 0))
-		emit_mov(pc, dst[0], one);
-
-	if (mask & (1 << 3))
-		emit_mov(pc, dst[3], one);
-
 	if (mask & (3 << 1)) {
 		if (mask & (1 << 1))
 			tmp[0] = dst[1];
@@ -823,6 +818,18 @@ emit_lit(struct nv50_pc *pc, struct nv50_reg **dst, unsigned mask,
 		emit_mov(pc, dst[2], zero);
 		set_pred(pc, 3, 0, pc->p->exec_tail);
 	}
+
+	/* do this last, in case src[i,j] == dst[0,3] */
+	if (mask & (1 << 0))
+		emit_mov(pc, dst[0], one);
+
+	if (mask & (1 << 3))
+		emit_mov(pc, dst[3], one);
+	
+	FREE(pos128);
+	FREE(neg128);
+	FREE(zero);
+	FREE(one);
 }
 
 static void
@@ -885,8 +892,9 @@ tgsi_src(struct nv50_pc *pc, int chan, const struct tgsi_full_src_register *src)
 {
 	struct nv50_reg *r = NULL;
 	struct nv50_reg *temp;
-	unsigned c;
+	unsigned sgn, c;
 
+	sgn = tgsi_util_get_full_src_register_sign_mode(src, chan);
 	c = tgsi_util_get_full_src_register_extswizzle(src, chan);
 	switch (c) {
 	case TGSI_EXTSWIZZLE_X:
@@ -915,16 +923,18 @@ tgsi_src(struct nv50_pc *pc, int chan, const struct tgsi_full_src_register *src)
 		break;
 	case TGSI_EXTSWIZZLE_ZERO:
 		r = alloc_immd(pc, 0.0);
-		break;
+		return r;
 	case TGSI_EXTSWIZZLE_ONE:
-		r = alloc_immd(pc, 1.0);
-		break;
+		if (sgn == TGSI_UTIL_SIGN_TOGGLE || sgn == TGSI_UTIL_SIGN_SET)
+			return alloc_immd(pc, -1.0);
+		else
+			return alloc_immd(pc, 1.0);
 	default:
 		assert(0);
 		break;
 	}
 
-	switch (tgsi_util_get_full_src_register_sign_mode(src, chan)) {
+	switch (sgn) {
 	case TGSI_UTIL_SIGN_KEEP:
 		break;
 	case TGSI_UTIL_SIGN_CLEAR:
@@ -955,7 +965,7 @@ static boolean
 nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok)
 {
 	const struct tgsi_full_instruction *inst = &tok->FullInstruction;
-	struct nv50_reg *rdst[4], *dst[4], *src[3][4], *temp;
+	struct nv50_reg *rdst[4], *dst[4], *src[3][4], *temp = NULL;
 	unsigned mask, sat, unit;
 	int i, c;
 
@@ -1021,7 +1031,6 @@ nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok)
 				continue;
 			emit_mov(pc, dst[c], temp);
 		}
-		free_temp(pc, temp);
 		break;
 	case TGSI_OPCODE_DP4:
 		temp = alloc_temp(pc, NULL);
@@ -1034,7 +1043,6 @@ nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok)
 				continue;
 			emit_mov(pc, dst[c], temp);
 		}
-		free_temp(pc, temp);
 		break;
 	case TGSI_OPCODE_DPH:
 		temp = alloc_temp(pc, NULL);
@@ -1047,7 +1055,6 @@ nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok)
 				continue;
 			emit_mov(pc, dst[c], temp);
 		}
-		free_temp(pc, temp);
 		break;
 	case TGSI_OPCODE_DST:
 	{
@@ -1072,7 +1079,6 @@ nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok)
 				continue;
 			emit_mov(pc, dst[c], temp);
 		}
-		free_temp(pc, temp);
 		break;
 	case TGSI_OPCODE_FLR:
 		for (c = 0; c < 4; c++) {
@@ -1089,7 +1095,6 @@ nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok)
 			emit_flr(pc, temp, src[0][c]);
 			emit_sub(pc, dst[c], src[0][c], temp);
 		}
-		free_temp(pc, temp);
 		break;
 	case TGSI_OPCODE_KIL:
 		emit_kil(pc, src[0][0]);
@@ -1110,15 +1115,12 @@ nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok)
 		}
 		break;
 	case TGSI_OPCODE_LRP:
+		temp = alloc_temp(pc, NULL);
 		for (c = 0; c < 4; c++) {
 			if (!(mask & (1 << c)))
 				continue;
-			/*XXX: we can do better than this */
-			temp = alloc_temp(pc, NULL);
-			emit_neg(pc, temp, src[0][c]);
-			emit_mad(pc, temp, temp, src[2][c], src[2][c]);
-			emit_mad(pc, dst[c], src[0][c], src[1][c], temp);
-			free_temp(pc, temp);
+			emit_sub(pc, temp, src[1][c], src[2][c]);
+			emit_mad(pc, dst[c], temp, src[0][c], src[2][c]);
 		}
 		break;
 	case TGSI_OPCODE_MAD:
@@ -1164,7 +1166,6 @@ nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok)
 				continue;
 			emit_mov(pc, dst[c], temp);
 		}
-		free_temp(pc, temp);
 		break;
 	case TGSI_OPCODE_RCP:
 		for (c = 0; c < 4; c++) {
@@ -1259,7 +1260,6 @@ nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok)
 			emit_mul(pc, temp, src[0][1], src[1][0]);
 			emit_msb(pc, dst[2], src[0][0], src[1][1], temp);
 		}
-		free_temp(pc, temp);
 		break;
 	case TGSI_OPCODE_END:
 		break;
@@ -1268,6 +1268,9 @@ nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok)
 		return FALSE;
 	}
 
+	if (temp)
+		free_temp(pc, temp);
+
 	if (sat) {
 		for (c = 0; c < 4; c++) {
 			struct nv50_program_exec *e;
@@ -1288,6 +1291,19 @@ nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok)
 		}
 	}
 
+	for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
+		for (c = 0; c < 4; c++) {
+			if (!src[i][c])
+				continue;
+			if (src[i][c]->index == -1 && src[i][c]->type == P_IMMD)
+				FREE(src[i][c]);
+
+			/* Might also release temporaries not used anymore in this loop,
+			 * therefore no temp_immd and temp_immd_nr like for temp_temp.
+			 */
+		}
+	}
+
 	kill_temp_temp(pc);
 	return TRUE;
 }
