aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Paul <[email protected]>2010-05-06 15:04:19 -0600
committerBrian Paul <[email protected]>2010-05-06 15:19:02 -0600
commit4b274f311c2c72e40e63c02e4a6f9f5ccc59f165 (patch)
tree572e0864e1a391cd600c46824f0338ce7849277a
parent895ee712ba1e9f1c1a0e54c6a5cebc52eea47a29 (diff)
tgsi: make SSE ADD instruction SOA-safe
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).
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_sse2.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/src/gallium/auxiliary/tgsi/tgsi_sse2.c b/src/gallium/auxiliary/tgsi/tgsi_sse2.c
index 0820a4137e7..01b4a960129 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_sse2.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_sse2.c
@@ -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)) {