From c2eb9d3a0a0dfe42255e0b68c5064213053ac293 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Sun, 9 Dec 2012 15:44:03 -0800 Subject: [PATCH] i965: Make try_rewrite_rhs_to_dst compare VGRF size to regs written. 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 --- src/mesa/drivers/dri/i965/brw_fs_visitor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp index 56d43309f9d..ccf905ebc62 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp @@ -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. */ -- 2.30.2