[Mesa-dev] [PATCH] svga: fix register collision issue in emit_conditional()
Brian Paul
brianp at vmware.com
Tue Jul 3 14:54:10 PDT 2012
If the 'dst' register is the same as the 'pass' register we'll generate
invalid code. Use a temporary register in that case.
---
src/gallium/drivers/svga/svga_tgsi_insn.c | 32 +++++++++++++++++++++++++++-
1 files changed, 30 insertions(+), 2 deletions(-)
diff --git a/src/gallium/drivers/svga/svga_tgsi_insn.c b/src/gallium/drivers/svga/svga_tgsi_insn.c
index c3a74c4..4cf5cf4 100644
--- a/src/gallium/drivers/svga/svga_tgsi_insn.c
+++ b/src/gallium/drivers/svga/svga_tgsi_insn.c
@@ -1245,6 +1245,20 @@ static boolean emit_kilp(struct svga_shader_emitter *emit,
return submit_op0( emit, inst, temp );
}
+
+/**
+ * Test if r1 and r2 are the same register.
+ */
+static boolean
+same_register(struct src_register r1, struct src_register r2)
+{
+ return (r1.base.num == r2.base.num &&
+ r1.base.type_upper == r2.base.type_upper &&
+ r1.base.type_lower == r2.base.type_lower);
+}
+
+
+
/* Implement conditionals by initializing destination reg to 'fail',
* then set predicate reg with UFOP_SETP, then move 'pass' to dest
* based on predicate reg.
@@ -1264,6 +1278,7 @@ emit_conditional(struct svga_shader_emitter *emit,
{
SVGA3dShaderDestToken pred_reg = dst_register( SVGA3DREG_PREDICATE, 0 );
SVGA3dShaderInstToken setp_token, mov_token;
+ struct src_register pass2;
setp_token = inst_token( SVGA3DOP_SETP );
switch (compare_func) {
@@ -1295,6 +1310,19 @@ emit_conditional(struct svga_shader_emitter *emit,
break;
}
+ if (same_register(src(dst), pass)) {
+ /* We'll get bad results if the dst and pass registers are the same
+ * so use a temp register containing pass.
+ */
+ SVGA3dShaderDestToken temp = get_temp(emit);
+ if (!submit_op1(emit, inst_token(SVGA3DOP_MOV), temp, pass))
+ return FALSE;
+ pass2 = src(temp);
+ }
+ else {
+ pass2 = pass;
+ }
+
/* SETP src0, COMPOP, src1 */
if (!submit_op2( emit, setp_token, pred_reg,
src0, src1 ))
@@ -1307,14 +1335,14 @@ emit_conditional(struct svga_shader_emitter *emit,
fail ))
return FALSE;
- /* MOV dst, pass (predicated)
+ /* MOV dst, pass2 (predicated)
*
* Note that the predicate reg (and possible modifiers) is passed
* as the first source argument.
*/
mov_token.predicated = 1;
if (!submit_op2( emit, mov_token, dst,
- src( pred_reg ), pass ))
+ src( pred_reg ), pass2 ))
return FALSE;
return TRUE;
--
1.7.7.3
More information about the mesa-dev
mailing list