[Mesa-dev] [PATCH 07/42] panfrost/midgard: Implement integer downsize ops
Alyssa Rosenzweig
alyssa.rosenzweig at collabora.com
Mon Jul 8 14:08:20 UTC 2019
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 at collabora.com>
---
.../panfrost/midgard/midgard_compile.c | 51 ++++++++++++++++++-
.../panfrost/midgard/midgard_nir_algebraic.py | 14 ++++-
2 files changed, 62 insertions(+), 3 deletions(-)
diff --git a/src/gallium/drivers/panfrost/midgard/midgard_compile.c b/src/gallium/drivers/panfrost/midgard/midgard_compile.c
index 39b8d9c1005..32cc55c52ee 100644
--- a/src/gallium/drivers/panfrost/midgard/midgard_compile.c
+++ b/src/gallium/drivers/panfrost/midgard/midgard_compile.c
@@ -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 */
@@ -2077,6 +2120,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
diff --git a/src/gallium/drivers/panfrost/midgard/midgard_nir_algebraic.py b/src/gallium/drivers/panfrost/midgard/midgard_nir_algebraic.py
index df0caa26640..b05c193e507 100644
--- a/src/gallium/drivers/panfrost/midgard/midgard_nir_algebraic.py
+++ b/src/gallium/drivers/panfrost/midgard/midgard_nir_algebraic.py
@@ -44,6 +44,18 @@ algebraic_late = [
(('b32csel', a, 0, 'b at 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 at 32'), ('i2i8', ('i2i16', a))),
+ (('u2u8', 'a at 32'), ('u2u8', ('u2u16', a))),
+
+ (('i2i32', 'a at 8'), ('i2i32', ('i2i16', a))),
+ (('u2u32', 'a at 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())
--
2.20.1
More information about the mesa-dev
mailing list