Commit Graph

85130 Commits

Author SHA1 Message Date
Francisco Jerez f33a8f8fcf i965/vec4: Don't spill non-GRF-aligned register regions.
A better fix would be to do something along the lines of the FS
back-end spilling code and emit a scratch read before any instruction
that overwrites the register to spill partially due to a non-zero
sub-register offset.  In the meantime mark registers used with a
non-zero sub-register offset as no-spill to prevent the spilling code
from miscompiling the program.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:59 -07:00
Francisco Jerez 8531f943d9 i965/vec4: Fix copy propagation for non-register-aligned regions.
This prevents it from trying to propagate a copy through a
register-misaligned region.  MOV instructions with a misaligned
destination shouldn't be treated as a direct GRF copy, because they
only define the destination GRFs partially.  Also fix the interference
check implemented with is_channel_updated() to consider overlapping
regions with different register offset to interfere, since the
writemask check implemented in the function is only valid under the
assumption that the source and destination regions are aligned
component by component.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:59 -07:00
Francisco Jerez 0e657b7b55 i965/vec4: Compare full register offsets in cmod propagation.
Cmod propagation would misoptimize the program if the destination
offset of the generating instruction wasn't exactly the same as the
source region offset of the copy instruction.  In preparation for
adding support for sub-GRF offsets to the VEC4 IR.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:58 -07:00
Francisco Jerez 8bed1adfc1 i965/vec4: Assign correct destination offset to rewritten instruction in register coalesce.
Because the pass already checks that the destination offset of each
'scan_inst' that needs to be rewritten matches 'inst->src[0].offset'
exactly, the final offset of the rewritten instruction is just the
original destination offset of the copy.  This is in preparation for
adding support for sub-GRF offsets to the VEC4 IR.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:58 -07:00
Francisco Jerez 3a74e437fd i965/vec4: Don't coalesce registers with overlapping writes not matching the MOV source.
In preparation for adding support for sub-GRF offsets to the VEC4 IR.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:58 -07:00
Francisco Jerez 1bb5074474 i965/vec4: Compare full register offsets in opt_register_coalesce nop move check.
In preparation for adding support for sub-GRF offsets to the VEC4 IR.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:58 -07:00
Francisco Jerez 3be0d6d040 i965/vec4: Check that the write offsets match when setting dependency controls.
For simplicity just assume that two writes to the same GRF with
different sub-GRF offsets will potentially interfere and break the
dependency control chain.  This is in preparation for adding sub-GRF
offset support to the VEC4 IR.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:58 -07:00
Francisco Jerez b52fefc4d5 i965/vec4: Change opt_vector_float to keep track of the last offset seen in bytes.
This simplifies things slightly and makes the pass more correct in
presence of sub-GRF offsets.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:58 -07:00
Francisco Jerez 230615e228 i965/vec4: Simplify src/dst_reg to brw_reg conversion by using byte_offset().
This should also have the side effect of fixing convert_to_hw_regs()
to handle sub-GRF register offsets.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:58 -07:00
Francisco Jerez eb746a80e5 i965/ir: Update several stale comments.
Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:58 -07:00
Francisco Jerez 47784e2346 i965/ir: Don't print ARF subnr values twice.
Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:58 -07:00
Francisco Jerez 5d65d51e78 i965/vec4: Print src/dst_reg::offset field consistently for all register files.
C.f. 'i965/fs: Print fs_reg::offset field consistently for all
register files.'.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:57 -07:00
Francisco Jerez ec259f5307 i965/fs: Print fs_reg::offset field consistently for all register files.
The offset printing code in fs_visitor::dump_instruction() was doing
things differently for sources and destinations and for each register
file -- In some cases it would be added to the base register number
fs_reg::nr, in other cases it would follow the base register separated
with a plus sign, in other cases (uniforms) it would do both (!).  The
sub-register offset was also being printed or not rather
inconsistently.  Fix it.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:57 -07:00
Francisco Jerez 950af5ed40 i965/fs: Misc simplification.
Get rid of some leftover redundant arithmetic introduced during the
conversion to byte offsets and sizes that can be simplified easily.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:57 -07:00
Francisco Jerez 80e1d670b4 i965/fs: Get rid of fs_inst::set_smear().
component() was generally a better alternative because of several
issues set_smear() had:

 - It wouldn't take the original stride and offset of the register
   into account, which means that set_smear() on the result of
   e.g. another set_smear() call or an offset() call would give a
   bogus region as result.

 - It was an inherently destructive operation.  See the
   'nir_intrinsic_shader_clock' hunk below for how this could lead to
   subtle bugs in cases where set_smear() was called multiple times on
   the same register like 'r.set_smear(0), r.set_smear(1)' with the
   expectation that each call would return a separate value instead of
   a reference to the same subsequently mutated object.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:57 -07:00
Francisco Jerez 8e58e4412f i965/fs: Use region_contained_in() in compute-to-mrf coalescing pass.
Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:57 -07:00
Francisco Jerez f2d2156ba2 i965/fs: Move region_contained_in to the IR header and fix for non-VGRF files.
Also changed the argument names since 'src' and 'dst' don't make that
much sense outside of the context of copy propagation.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:57 -07:00
Francisco Jerez 645261c4b2 i965/fs: Change region_contained_in() to use byte units.
This makes the function less annoying to use and more accurate -- We
shouldn't propagate a copy into a register region that wasn't fully
contained in the destination of the copy (IOW, a source region that
wasn't fully defined by the copy) just because the number of registers
written and read by each instruction happened to get rounded up to the
same GRF multiple.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:57 -07:00
Francisco Jerez 1c67e27247 i965/fs: Simplify copy propagation LOAD_PAYLOAD ACP setup.
By keeping track of 'offset' in byte units.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:57 -07:00
Francisco Jerez 2d7d4a7910 i965/fs: Simplify a bunch of fs_inst::size_written calculations by using component_size().
Using component_size() is easier and generally more correct because it
takes into account the register type and stride for you.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:56 -07:00
Francisco Jerez 0bc46cc961 i965/fs: Simplify result_live calculation in dead_code_eliminate().
No need to unroll the first iteration of the loop manually.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:56 -07:00
Francisco Jerez 62aaef6c83 i965/fs: Simplify and fix buggy stride/offset calculations using subscript().
These were bashing the 'offset' and 'stride' values of several
registers without taking the previous value into account, which
probably didn't matter in practice for optimize_frontfacing_ternary()
because the 'tmp' register already had a known region, but it would
have given the wrong region as result in the other cases in
lower_integer_multiplication().  subscript(..., i) is a more
straightforward way to take the i-th field of a given type from each
channel of a register which should give the right answer as result
regardless of the original 'offset' and 'stride' parameters of the
register region.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:56 -07:00
Francisco Jerez 3b7b908787 i965/fs: Simplify get_fpu_lowered_simd_width() by using inequalities instead of rounding.
Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:56 -07:00
Francisco Jerez ee930c0435 i965/fs: Simplify byte_offset().
In the most common case this can now be implemented as a simple
addition because the offset is already encoded as a single scalar
value in bytes.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:56 -07:00
Francisco Jerez bae3a41171 i965/fs: Fix signedness of the return value of fs_inst::size_read().
Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:56 -07:00
Francisco Jerez a384503c15 i965/fs: Switch mask_relative_to() used in compute-to-mrf to byte units.
This makes the helper function less annoying to use and somewhat more
accurate.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:56 -07:00
Francisco Jerez 401fc228fd i965/fs: Fix bogus sub-MRF offset calculation in compute-to-mrf.
The 'scan_inst->dst.offset % REG_SIZE' term in the final
'scan_inst->dst.offset' calculation is obviously bogus.  The offset
from the start of the copy destination register 'inst->dst' where the
destination of the generating instruction 'scan_inst' would be written
to (before compute-to-mrf runs) is just the offset of 'scan_inst->dst'
relative to the source of the copy instruction (AKA rel_offset in the
code below).

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:56 -07:00
Francisco Jerez cd0134072a i965/fs: Take into account copy register offset during compute-to-mrf.
This was dropping 'inst->dst.offset' on the floor.  Nothing in the
code above seems to guarantee that it's zero and in that case the
offset of the register being coalesced into wouldn't be taken into
account while rewriting the generating instruction.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:56 -07:00
Francisco Jerez fcd9d1badc i965/vec4: Drop backend_reg::in_range() in favor of regions_overlap().
This makes sure that overlap checks are done correctly throughout the
back-end when the '*this' register starts before the register/size
pair provided as argument, and is actually less annoying to use than
in_range() at this point since regions_overlap() takes its size
arguments in bytes.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:55 -07:00
Francisco Jerez 56bcb2230f i965/vec4: Port regions_overlap() to the vec4 IR.
This is copy-pasted almost line by line from the FS back-end.  The
only reason it cannot be implemented in terms of backend_reg is that
the backend_reg::nr field doesn't have the same meaning for uniforms
on both back-ends.  It could be easily deduplicated by using a
template function.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:55 -07:00
Francisco Jerez c057278c06 i965/fs: Stop using fs_reg::in_range() in favor of regions_overlap().
Its only use left in the FS back-end should be using regions_overlap()
instead to avoid getting a false negative result in cases where source
and destination overlap but the former starts before the latter in the
VGRF file.

v2: Put back lost components factor (Iago).

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:55 -07:00
Francisco Jerez b42c13a5b8 i965/fs: Drop fs_inst::overwrites_reg() in favor of regions_overlap().
fs_inst::overwrites_reg is rather easy to misuse because it cannot
tell how large the register region starting at 'reg' is, so in cases
where the destination region starts after 'reg' it may give a
misleading result.  regions_overlap() is somewhat more verbose to use
but handles arbitrary overlap correctly so it should generally be used
instead.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:55 -07:00
Francisco Jerez 32d67923b2 i965/fs: Fix LOAD_PAYLOAD handling in register coalesce is_nop_mov().
is_nop_mov() was broken for LOAD_PAYLOAD instructions in two ways: On
the one hand the original destination register offset wasn't being
taken into account which would give incorrect results if it was
already non-zero, and on the other hand all source registers were
being treated as if they had a size of 32B, which is almost never the
case in SIMD16 programs for non-header sources.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:55 -07:00
Francisco Jerez 5cc6425d70 i965/fs: Fix can_propagate_from() source/destination overlap check.
The previous overlap condition only made sure that the VGRF numbers or
GRF-aligned offsets were different without taking the amount of data
written and read by the instruction into consideration.  Use the
regions_overlap() helper instead.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:55 -07:00
Francisco Jerez 9ae77d7020 i965/fs: Compare full register offsets in cmod propagation pass.
This could potentially have misoptimized a program in cases where
inst->src[0] had a non-zero sub-GRF offset.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:55 -07:00
Francisco Jerez 3a4ea7cf80 i965/fs: Don't consider LOAD_PAYLOAD with stride > 1 source to behave like a raw copy.
Noticed the problem by inspection while typing in the previous commit.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:55 -07:00
Francisco Jerez 1164aa1a1b i965/fs: Don't consider LOAD_PAYLOAD with sub-GRF offset to behave like a raw copy.
This was likely the original intention, and at least register coalesce
relies on it.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:55 -07:00
Francisco Jerez a5bbe4c127 i965/vec4: Take into account misalignment in regs_written() and regs_read().
Unlike the FS counterpart of this commit this was likely not (yet) a
bug, but let's fix it already in preparation for implementing support
for sub-GRF offsets in the VEC4 back-end.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:54 -07:00
Francisco Jerez 717d8efd58 i965/fs: Take into account misalignment in regs_written() and regs_read().
There was a workaround for this in fs_inst::size_read() for the
SHADER_OPCODE_MOV_INDIRECT instruction and FIXED_GRF register file
*only*.  We should take this possibility into account for the sources
and destinations of all instructions on all optimization passes that
need to quantize dataflow in 32B increments by adding the amount of
misalignment to the size read or written from the regs_read() and
regs_written() helpers respectively.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:54 -07:00
Francisco Jerez e540045df5 i965/fs: Take into account trailing padding in regs_written() and regs_read().
This fixes regs_written() and regs_read() to return a more accurate
value when the padding left between components due to a stride value
greater than one causes the region bounds given by size_written or
size_read to overflow into the next register.  This could become a
problem in optimization passes that keep track of dataflow using
fixed-size arrays with register granularity, because the overflow
register (not actually accessed by the region) may not have been
allocated at all which could lead to undefined memory access.

An alternative to this would be to subtract the trailing padding
already during the calculation of fs_inst::size_read and
::size_written, but that would break code that currently assumes that
::size_read and _written are whole multiples of the component size,
and would be hard to maintain looking forward because size_written is
assigned from a bunch of different places.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:54 -07:00
Francisco Jerez 937373eb25 i965/fs: Handle fixed HW GRF subnr in reg_offset().
This will be useful later on when we start using reg_offset() on fixed
hardware registers.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:54 -07:00
Francisco Jerez 1a4b7fdd88 i965/fs: Handle arbitrary offsets in brw_reg_from_fs_reg for MRF/VGRF registers.
This restriction seemed rather artificial...  Removing it actually
simplifies things slightly.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:54 -07:00
Francisco Jerez d6b60934aa i965/fs: Return more accurate read size for LINTERP from fs_inst::size_read.
The LINTERP virtual instruction only reads three scalar components
from the first 16B of the second source, we can now teach size_read()
about it since its return value is represented with byte granularity.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:54 -07:00
Francisco Jerez 31a40202b8 i965/fs: Return more accurate read size from fs_inst::size_read for IMM and UNIFORM files.
Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:54 -07:00
Francisco Jerez 728dd30c0a i965/vec4: Replace vec4_instruction::regs_read with ::size_read using byte units.
The previous regs_read value can be recovered by rewriting each
reference of regs_read() like 'x = i.regs_read(j)' to 'x =
DIV_ROUND_UP(i.size_read(j), reg_unit)'.

For the same reason as in the previous patches, this doesn't attempt
to be particularly clever about simplifying the result in the interest
of keeping the rather lengthy patch as obvious as possible.  I'll come
back later to clean up any ugliness introduced here.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:54 -07:00
Francisco Jerez e1a918ba7b i965/fs: Replace fs_inst::regs_read with ::size_read using byte units.
The previous regs_read value can be recovered by rewriting each
reference of regs_read() like 'x = i.regs_read(j)' to 'x =
DIV_ROUND_UP(i.size_read(j), reg_unit)'.

For the same reason as in the previous patches, this doesn't attempt
to be particularly clever about simplifying the result in the interest
of keeping the rather lengthy patch as obvious as possible.  I'll come
back later to clean up any ugliness introduced here.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:53 -07:00
Francisco Jerez 27cb6b081e i965/ir: Drop backend_instruction::regs_written field.
Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:53 -07:00
Francisco Jerez 69fdf13c21 i965/vec4: Replace vec4_instruction::regs_written with ::size_written field in bytes.
The previous regs_written field can be recovered by rewriting each
rvalue reference of regs_written like 'x = i.regs_written' to 'x =
DIV_ROUND_UP(i.size_written, reg_unit)', and each lvalue reference
like 'i.regs_written = x' to 'i.size_written = x * reg_unit'.

For the same reason as in the previous patches, this doesn't attempt
to be particularly clever about simplifying the result in the interest
of keeping the rather lengthy patch as obvious as possible.  I'll come
back later to clean up any ugliness introduced here.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:53 -07:00
Francisco Jerez 69570bbad8 i965/fs: Replace fs_inst::regs_written with ::size_written field in bytes.
The previous regs_written field can be recovered by rewriting each
rvalue reference of regs_written like 'x = i.regs_written' to 'x =
DIV_ROUND_UP(i.size_written, reg_unit)', and each lvalue reference
like 'i.regs_written = x' to 'i.size_written = x * reg_unit'.

For the same reason as in the previous patches, this doesn't attempt
to be particularly clever about simplifying the result in the interest
of keeping the rather lengthy patch as obvious as possible.  I'll come
back later to clean up any ugliness introduced here.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:53 -07:00
Francisco Jerez d28cfa35fe i965/vec4: Add wrapper functions for vec4_instruction::regs_read and ::regs_written.
This is in preparation for dropping vec4_instruction::regs_read and
::regs_written in favor of more accurate alternatives expressed in
byte units.  The main reason these wrappers are useful is that a
number of optimization passes implement dataflow analysis with
register granularity, so these helpers will come in handy once we've
switched register offsets and sizes to the byte representation.  The
wrapper functions will also make sure that GRF misalignment (currently
neglected by most of the back-end) is taken into account correctly in
the calculation of regs_read and regs_written.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
2016-09-14 14:50:53 -07:00