vc4: Optimize fmul(x, 0) and fmul(x, 1).
authorEric Anholt <eric@anholt.net>
Thu, 9 Oct 2014 13:02:00 +0000 (15:02 +0200)
committerEric Anholt <eric@anholt.net>
Thu, 9 Oct 2014 19:47:06 +0000 (21:47 +0200)
This was being generated frequently by matrix multiplies of 2 and
3-channel vertex attributes (which have the 0 or 1 loaded in the shader).

src/gallium/drivers/vc4/vc4_opt_algebraic.c

index 8c6fcef5936328831a6d699c72950e3e4ca5d1b5..435814e6912502abab5b5f67a23aa6725dbf4f34 100644 (file)
@@ -33,6 +33,7 @@
  */
 
 #include "vc4_qir.h"
+#include "util/u_math.h"
 
 static bool debug;
 
@@ -77,6 +78,16 @@ is_zero(struct vc4_compile *c, struct qinst **defs, struct qreg reg)
                 c->uniform_data[reg.index] == 0);
 }
 
+static bool
+is_1f(struct vc4_compile *c, struct qinst **defs, struct qreg reg)
+{
+        reg = follow_movs(defs, reg);
+
+        return (reg.file == QFILE_UNIF &&
+                c->uniform_contents[reg.index] == QUNIFORM_CONSTANT &&
+                c->uniform_data[reg.index] == fui(1.0));
+}
+
 static void
 replace_with_mov(struct vc4_compile *c, struct qinst *inst, struct qreg arg)
 {
@@ -87,6 +98,30 @@ replace_with_mov(struct vc4_compile *c, struct qinst *inst, struct qreg arg)
         dump_to(c, inst);
 }
 
+static bool
+fmul_replace_zero(struct vc4_compile *c,
+                  struct qinst **defs,
+                  struct qinst *inst,
+                  int arg)
+{
+        if (!is_zero(c, defs, inst->src[arg]))
+                return false;
+        replace_with_mov(c, inst, inst->src[arg]);
+        return true;
+}
+
+static bool
+fmul_replace_one(struct vc4_compile *c,
+                 struct qinst **defs,
+                 struct qinst *inst,
+                 int arg)
+{
+        if (!is_1f(c, defs, inst->src[arg]))
+                return false;
+        replace_with_mov(c, inst, inst->src[1 - arg]);
+        return true;
+}
+
 bool
 qir_opt_algebraic(struct vc4_compile *c)
 {
@@ -177,6 +212,16 @@ qir_opt_algebraic(struct vc4_compile *c)
                         }
                         break;
 
+                case QOP_FMUL:
+                        if (fmul_replace_zero(c, defs, inst, 0) ||
+                            fmul_replace_zero(c, defs, inst, 1) ||
+                            fmul_replace_one(c, defs, inst, 0) ||
+                            fmul_replace_one(c, defs, inst, 1)) {
+                                progress = true;
+                                break;
+                        }
+                        break;
+
                 default:
                         break;
                 }