i965: Add src/dst interference for certain instructions with hazards.
authorKenneth Graunke <kenneth@whitecape.org>
Fri, 20 Nov 2015 00:00:18 +0000 (16:00 -0800)
committerKenneth Graunke <kenneth@whitecape.org>
Mon, 30 Nov 2015 08:34:07 +0000 (00:34 -0800)
commit83dedb6354d0e9b04e8ccad77e86bdb7bad44bdd
treea7334a4f185711e186ca84dfc14308b900d7cd2f
parent1ac1581f3889d5f7e6e231c05651f44fbd80f0b6
i965: Add src/dst interference for certain instructions with hazards.

When working on tessellation shaders, I created some vec4 virtual
opcodes for creating message headers through a sequence like:

   mov(8) g7<1>UD      0x00000000UD    { align1 WE_all 1Q compacted };
   mov(1) g7.5<1>UD    0x00000100UD    { align1 WE_all };
   mov(1) g7<1>UD      g0<0,1,0>UD     { align1 WE_all compacted };
   mov(1) g7.3<1>UD    g8<0,1,0>UD     { align1 WE_all };

This is done in the generator since the vec4 backend can't handle align1
regioning.  From the visitor's point of view, this is a single opcode:

   hs_set_output_urb_offsets vgrf7.0:UD, 1U, vgrf8.xxxx:UD

Normally, there's no hazard between sources and destinations - an
instruction (naturally) reads its sources, then writes the result to the
destination.  However, when the virtual instruction generates multiple
hardware instructions, we can get into trouble.

In the above example, if the register allocator assigned vgrf7 and vgrf8
to the same hardware register, then we'd clobber the source with 0 in
the first instruction, and read back the wrong value in the last one.

It occured to me that this is exactly the same problem we have with
SIMD16 instructions that use W/UW or B/UB types with 0 stride.  The
hardware implicitly decodes them as two SIMD8 instructions, and with
the overlapping regions, the first would clobber the second.

Previously, we handled that by incrementing the live range end IP by 1,
which works, but is excessive: the next instruction doesn't actually
care about that.  It might also be the end of control flow.  This might
keep values alive too long.  What we really want is to say "my source
and destinations interfere".

This patch creates new infrastructure for doing just that, and teaches
the register allocator to add interference when there's a hazard.  For
my vec4 case, we can determine this by switching on opcodes.  For the
SIMD16 case, we just move the existing code there.

I audited our existing virtual opcodes that generate multiple
instructions; I believe FS_OPCODE_PACK_HALF_2x16_SPLIT needs this
treatment as well, but no others.

v2: Rebased by mattst88.

Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Matt Turner <mattst88@gmail.com>
src/mesa/drivers/dri/i965/brw_fs.cpp
src/mesa/drivers/dri/i965/brw_fs_live_variables.cpp
src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp
src/mesa/drivers/dri/i965/brw_ir_fs.h
src/mesa/drivers/dri/i965/brw_ir_vec4.h
src/mesa/drivers/dri/i965/brw_vec4.cpp
src/mesa/drivers/dri/i965/brw_vec4_reg_allocate.cpp