tgsi: make SSE ADD instruction SOA-safe
authorBrian Paul <brianp@vmware.com>
Thu, 6 May 2010 21:04:19 +0000 (15:04 -0600)
committerBrian Paul <brianp@vmware.com>
Thu, 6 May 2010 21:19:02 +0000 (15:19 -0600)
To properly execute an instruction such as "ADD tmp, tmp.wzyx, foo;"
with SOA we (sometimes) need to put the results into temporaries before
writing the results to the destination register.

This patch fixes the ADD instruction but this needs to be done for
many more instructions.

Helps to fix piglit fp-long-alu test (fd.o bug 27989).

src/gallium/auxiliary/tgsi/tgsi_sse2.c

index 0820a4137e7d73f282cc20df4e10baf6d653c00d..01b4a960129c1ff83c9eed3b1e79da745b5fb286 100644 (file)
@@ -1938,11 +1938,17 @@ emit_instruction(
       break;
 
    case TGSI_OPCODE_ADD:
+      /* do all fetches and adds, storing results in temp regs */
       FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
-         FETCH( func, *inst, 0, 0, chan_index );
-         FETCH( func, *inst, 1, 1, chan_index );
-         emit_add( func, 0, 1 );
-         STORE( func, *inst, 0, 0, chan_index );
+         int r = chan_index + 1;
+         FETCH( func, *inst, 0, 0, chan_index ); /* load xmm[0] */
+         FETCH( func, *inst, r, 1, chan_index ); /* load xmm[r] */
+         emit_add( func, r, 0 );   /* xmm[r] = xmm[r] + xmm[0] */
+      }
+      /* do all stores of the temp regs */
+      FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
+         int r = chan_index + 1;
+         STORE( func, *inst, r, 0, chan_index ); /* store xmm[r] */
       }
       break;
 
@@ -2825,8 +2831,10 @@ static void
 check_soa_dependencies(const struct tgsi_full_instruction *inst)
 {
    switch (inst->Instruction.Opcode) {
+   case TGSI_OPCODE_ADD:
+   case TGSI_OPCODE_MOV:
    case TGSI_OPCODE_XPD:
-      /* OK */
+      /* OK - these opcodes correctly handle SOA dependencies */
       break;
    default:
       if (tgsi_check_soa_dependencies(inst)) {