panfrost/midgard: Lower source modifiers for ints
authorAlyssa Rosenzweig <alyssa@rosenzweig.io>
Mon, 25 Mar 2019 02:49:04 +0000 (02:49 +0000)
committerAlyssa Rosenzweig <alyssa@rosenzweig.io>
Tue, 26 Mar 2019 23:35:36 +0000 (23:35 +0000)
On Midgard, float ops support standard source modifiers (abs/neg) and
destination modifiers (sat/pos/round). Integer ops do not support these,
however. To cope, we use native NIR source modifiers for floats, but
lower them away to iabs/ineg for integers, implementing those ops
simultaneously to avoid regressions.

Fixes the integer tests in
dEQP-GLES2.functional.shaders.operator.unary_operator.minus.*

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
src/gallium/drivers/panfrost/midgard/helpers.h
src/gallium/drivers/panfrost/midgard/midgard_compile.c
src/gallium/drivers/panfrost/midgard/midgard_nir.h
src/gallium/drivers/panfrost/midgard/midgard_nir_algebraic.py

index c90d7530ecbf7f85253341e419facb77cdbee1ff..01c88ed0fcf4837363567f59787916cce9dd3c1f 100644 (file)
@@ -142,6 +142,7 @@ midgard_is_integer_op(int op)
         //case midgard_alu_op_f2i:
         //case midgard_alu_op_f2u:
         case midgard_alu_op_ieq:
+        case midgard_alu_op_iabs:
         case midgard_alu_op_ine:
         case midgard_alu_op_ilt:
         case midgard_alu_op_ile:
@@ -209,6 +210,7 @@ static unsigned alu_opcode_props[256] = {
 
         /* Incredibly, iadd can run on vmul, etc */
         [midgard_alu_op_iadd]           = UNITS_MOST,
+        [midgard_alu_op_iabs]           = UNITS_MOST,
         [midgard_alu_op_isub]           = UNITS_MOST,
         [midgard_alu_op_imul]           = UNITS_MOST,
         [midgard_alu_op_imov]           = UNITS_MOST | QUIRK_FLIPPED_R24,
index 5147e85fa2633b1c9913e14d6f31cabc8b88f93a..dac5eeb2c1bb613e2c94b453056ca8bc6d233af5 100644 (file)
@@ -748,9 +748,13 @@ optimise_nir(nir_shader *nir)
         } while (progress);
 
         NIR_PASS(progress, nir, nir_opt_algebraic_late);
+        NIR_PASS(progress, nir, midgard_nir_lower_algebraic_late);
 
-        /* Lower mods */
-        NIR_PASS(progress, nir, nir_lower_to_source_mods, nir_lower_all_source_mods);
+        /* Lower mods for float ops only. Integer ops don't support modifiers
+         * (saturate doesn't make sense on integers, neg/abs require dedicated
+         * instructions) */
+
+        NIR_PASS(progress, nir, nir_lower_to_source_mods, nir_lower_float_source_mods);
         NIR_PASS(progress, nir, nir_copy_prop);
         NIR_PASS(progress, nir, nir_opt_dce);
 
@@ -975,6 +979,7 @@ emit_alu(compiler_context *ctx, nir_alu_instr *instr)
                 ALU_CASE(iadd, iadd);
                 ALU_CASE(isub, isub);
                 ALU_CASE(imul, imul);
+                ALU_CASE(iabs, iabs);
 
                 /* XXX: Use fmov, not imov, since imov was causing major
                  * issues with texture precision? XXX research */
index b7a2298050274a077532b1bb634349c3367cf9a3..6b4833b32b2d4d76085e4eb17eaed45cf7576e13 100644 (file)
@@ -2,4 +2,5 @@
 #include "nir.h"
 
 bool midgard_nir_lower_algebraic(nir_shader *shader);
+bool midgard_nir_lower_algebraic_late(nir_shader *shader);
 bool midgard_nir_scale_trig(nir_shader *shader);
index 07ea427359b6548b47f4321352f303173fa0d007..05a49d18d9e9994242cb4d7252c3b5abfc615ac4 100644 (file)
@@ -39,6 +39,15 @@ algebraic = [
     (('fsign', a), ('bcsel', ('fge', a, 0), 1.0, -1.0)),
 ]
 
+algebraic_late = [
+    # ineg must be lowered late, but only for integers; floats will try to
+    # have modifiers attached... hence why this has to be here rather than
+    # a more standard lower_negate approach
+
+    (('ineg', a), ('isub', 0, a)),
+]
+
+
 # Midgard scales fsin/fcos arguments by pi.
 # Pass must be run only once, after the main loop
 
@@ -62,6 +71,9 @@ def run():
     print(nir_algebraic.AlgebraicPass("midgard_nir_lower_algebraic",
                                       algebraic).render())
 
+    print(nir_algebraic.AlgebraicPass("midgard_nir_lower_algebraic_late",
+                                      algebraic_late).render())
+
     print(nir_algebraic.AlgebraicPass("midgard_nir_scale_trig",
                                       scale_trig).render())