mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-06 11:00:11 +01:00
panfrost/midgard: Implement integer downsize ops
Oh, dear. No turning back now. We begin implementing non-32-bit types, using downsizing integer type conversions as the initial instructions. We implement them naively as type-converting moves; substantially more efficient operation is possible by copypropping the type conversion modifier, but this optimization is not implemented here. Size converting modifiers on Midgard allow an instruction to write to a destination 1/2 the size, or to read from a source 1/2 the size. If we need an extreme conversion (32-bit to 8-bit, for instance), multiple type converting ops are chained together, which here is handled via an algebraic pass. Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
This commit is contained in:
parent
dc69d3bf8f
commit
4df80cab40
2 changed files with 62 additions and 3 deletions
|
|
@ -703,6 +703,29 @@ nir_is_fzero_constant(nir_src src)
|
|||
return true;
|
||||
}
|
||||
|
||||
/* Analyze the sizes of inputs/outputs to determine which reg mode to run an
|
||||
* ALU instruction in. Right now, we just consider the size of the first
|
||||
* argument. This will fail for upconverting, for instance (TODO) */
|
||||
|
||||
static midgard_reg_mode
|
||||
reg_mode_for_nir(nir_alu_instr *instr)
|
||||
{
|
||||
unsigned src_bitsize = nir_src_bit_size(instr->src[0].src);
|
||||
|
||||
switch (src_bitsize) {
|
||||
case 8:
|
||||
return midgard_reg_mode_8;
|
||||
case 16:
|
||||
return midgard_reg_mode_16;
|
||||
case 32:
|
||||
return midgard_reg_mode_32;
|
||||
case 64:
|
||||
return midgard_reg_mode_64;
|
||||
default:
|
||||
unreachable("Invalid bit size");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
emit_alu(compiler_context *ctx, nir_alu_instr *instr)
|
||||
{
|
||||
|
|
@ -728,6 +751,12 @@ emit_alu(compiler_context *ctx, nir_alu_instr *instr)
|
|||
|
||||
unsigned broadcast_swizzle = 0;
|
||||
|
||||
/* Do we need a destination override? Used for inline
|
||||
* type conversion */
|
||||
|
||||
midgard_dest_override dest_override =
|
||||
midgard_dest_override_none;
|
||||
|
||||
switch (instr->op) {
|
||||
ALU_CASE(fadd, fadd);
|
||||
ALU_CASE(fmul, fmul);
|
||||
|
|
@ -824,6 +853,20 @@ emit_alu(compiler_context *ctx, nir_alu_instr *instr)
|
|||
ALU_CASE(fneg, fmov);
|
||||
ALU_CASE(fsat, fmov);
|
||||
|
||||
/* For size conversion, we use a move. Ideally though we would squash
|
||||
* these ops together; maybe that has to happen after in NIR as part of
|
||||
* propagation...? An earlier algebraic pass ensured we step down by
|
||||
* only / exactly one size */
|
||||
|
||||
case nir_op_u2u8:
|
||||
case nir_op_u2u16:
|
||||
case nir_op_i2i8:
|
||||
case nir_op_i2i16: {
|
||||
op = midgard_alu_op_imov;
|
||||
dest_override = midgard_dest_override_lower;
|
||||
break;
|
||||
}
|
||||
|
||||
/* For greater-or-equal, we lower to less-or-equal and flip the
|
||||
* arguments */
|
||||
|
||||
|
|
@ -958,8 +1001,8 @@ emit_alu(compiler_context *ctx, nir_alu_instr *instr)
|
|||
|
||||
midgard_vector_alu alu = {
|
||||
.op = op,
|
||||
.reg_mode = midgard_reg_mode_32,
|
||||
.dest_override = midgard_dest_override_none,
|
||||
.reg_mode = reg_mode_for_nir(instr),
|
||||
.dest_override = dest_override,
|
||||
.outmod = outmod,
|
||||
|
||||
/* Writemask only valid for non-SSA NIR */
|
||||
|
|
@ -2066,6 +2109,10 @@ mir_nontrivial_outmod(midgard_instruction *ins)
|
|||
bool is_int = midgard_is_integer_op(ins->alu.op);
|
||||
unsigned mod = ins->alu.outmod;
|
||||
|
||||
/* Type conversion is a sort of outmod */
|
||||
if (ins->alu.dest_override != midgard_dest_override_none)
|
||||
return true;
|
||||
|
||||
if (is_int)
|
||||
return mod != midgard_outmod_int_wrap;
|
||||
else
|
||||
|
|
|
|||
|
|
@ -44,6 +44,18 @@ algebraic_late = [
|
|||
(('b32csel', a, 0, 'b@32'), ('iand', ('inot', a), b)),
|
||||
]
|
||||
|
||||
|
||||
# Midgard is able to type convert down by only one "step" per instruction; if
|
||||
# NIR wants more than one step, we need to break up into multiple instructions
|
||||
|
||||
converts = [
|
||||
(('i2i8', 'a@32'), ('i2i8', ('i2i16', a))),
|
||||
(('u2u8', 'a@32'), ('u2u8', ('u2u16', a))),
|
||||
|
||||
(('i2i32', 'a@8'), ('i2i32', ('i2i16', a))),
|
||||
(('u2u32', 'a@8'), ('u2u32', ('u2u16', a)))
|
||||
]
|
||||
|
||||
# Midgard scales fsin/fcos arguments by pi.
|
||||
# Pass must be run only once, after the main loop
|
||||
|
||||
|
|
@ -66,7 +78,7 @@ def run():
|
|||
print('#include "midgard_nir.h"')
|
||||
|
||||
print(nir_algebraic.AlgebraicPass("midgard_nir_lower_algebraic_late",
|
||||
algebraic_late).render())
|
||||
algebraic_late + converts).render())
|
||||
|
||||
print(nir_algebraic.AlgebraicPass("midgard_nir_scale_trig",
|
||||
scale_trig).render())
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue