i965: Make try_rewrite_rhs_to_dst compare VGRF size to regs written.
authorKenneth Graunke <kenneth@whitecape.org>
Sun, 9 Dec 2012 23:44:03 +0000 (15:44 -0800)
committerKenneth Graunke <kenneth@whitecape.org>
Wed, 12 Dec 2012 22:44:37 +0000 (14:44 -0800)
try_rewrite_rhs_to_dst is a quick optimization to avoid generating new
temporaries (and MOVs from those temporaries to the dest) for every
expression tree we visit.  By generating better code in simple cases, we
reduce the burden on later optimization passes like register coalescing.

Previously, we compared inst->regs_written() to lhs->vector_elements
to make sure the instruction generating our value wrote the same number
of components as our destination register.

However, this fails in some cases.  One example is texturing (which
produces a vec4) into gl_FragData[i].  Technically, gl_FragData[i] is
also a vec4.  However, the destination VGRF actually has size 4n (where
n is the size of the array).

split_virtual_grfs() can't split VGRFs that are used by SEND messages
which require contiguous destination registers (like texturing), and
register allocation needs all VGRFs to have sizes between 1 and 4.

Amnesia: The Dark Descent hits this case: a texturing instruction
(4 components) gets rewritten to the gl_FragData output register
(which was 4*3 = 12 components), causing the register allocator to
hit the "we rely on split_virtual_grfs" assertion.

This makes it possible to play Amnesia.

Reviewed-by: Eric Anholt <eric@anholt.net>
src/mesa/drivers/dri/i965/brw_fs_visitor.cpp

index 56d43309f9d744e7a82a5686b9c101eae7433cb0..ccf905ebc62f6765ef76f1069626ec28a8927b56 100644 (file)
@@ -703,7 +703,7 @@ fs_visitor::try_rewrite_rhs_to_dst(ir_assignment *ir,
    /* If last_rhs_inst wrote a different number of components than our LHS,
     * we can't safely rewrite it.
     */
-   if (ir->lhs->type->vector_elements != modify->regs_written())
+   if (virtual_grf_sizes[dst.reg] != modify->regs_written())
       return false;
 
    /* Success!  Rewrite the instruction. */