svga: fix register collision issue in emit_conditional()
authorBrian Paul <brianp@vmware.com>
Tue, 3 Jul 2012 21:51:22 +0000 (15:51 -0600)
committerBrian Paul <brianp@vmware.com>
Thu, 5 Jul 2012 14:03:19 +0000 (08:03 -0600)
If the 'dst' register is the same as the 'pass' register we'll generate
invalid code.  Use a temporary register in that case.

Reviewed-by: José Fonseca <jfonseca@vmware.com>
src/gallium/drivers/svga/svga_tgsi_insn.c

index 64dfa55753948bc66f4ad377ad9627885e11d778..42df4195fcca1492a840217c5b48d7bbac0b42ac 100644 (file)
@@ -1285,6 +1285,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.
@@ -1335,6 +1349,16 @@ 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;
+      pass = src(temp);
+   }
+
    /* SETP src0, COMPOP, src1 */
    if (!submit_op2( emit, setp_token, pred_reg,
                     src0, src1 ))