intel/fs: Add a lowering pass for linear interpolation.
authorRafael Antognolli <rafael.antognolli@intel.com>
Tue, 23 Oct 2018 16:03:32 +0000 (09:03 -0700)
committerRafael Antognolli <rafael.antognolli@intel.com>
Mon, 22 Apr 2019 23:54:00 +0000 (16:54 -0700)
On gen11, instead of using a PLN instruction, we convert
FS_OPCODE_LINTERP to 2 or 4 multiply adds. That is done in the
fs_generator code.

This patch adds a lowering pass that does the same thing at the
fs_visitor. It also drops the usage of NF types, since we don't need the
extra precision and it lets us skip the accumulator. With all that, some
optimizations will still be run on the generated code, and we should get
better scheduling.

v2: Update comment about saturation and conditional mod (Matt)

Reviewed-by: Matt Turner <mattst88@gmail.com>
src/intel/compiler/brw_fs.cpp
src/intel/compiler/brw_fs.h

index 8d72eb8837df5a5321fefa378ccf689b58c742fe..22eefd4ef490c39d9c810549e5efe6e203a91b88 100644 (file)
@@ -3876,6 +3876,47 @@ fs_visitor::lower_load_payload()
    return progress;
 }
 
+bool
+fs_visitor::lower_linterp()
+{
+   bool progress = false;
+
+   if (devinfo->gen < 11)
+      return false;
+
+   foreach_block_and_inst_safe(block, fs_inst, inst, cfg) {
+      const fs_builder ibld(this, block, inst);
+
+      if (inst->opcode != FS_OPCODE_LINTERP)
+         continue;
+
+      fs_reg dwP = component(inst->src[1], 0);
+      fs_reg dwQ = component(inst->src[1], 1);
+      fs_reg dwR = component(inst->src[1], 3);
+      for (unsigned i = 0; i < DIV_ROUND_UP(dispatch_width, 8); i++) {
+         const fs_builder hbld(ibld.half(i));
+         fs_reg dst = half(inst->dst, i);
+         fs_reg delta_xy = offset(inst->src[0], ibld, i);
+         hbld.MAD(dst, dwR, half(delta_xy, 0), dwP);
+         fs_inst *mad = hbld.MAD(dst, dst, half(delta_xy, 1), dwQ);
+
+         /* Propagate conditional mod and saturate from the original
+          * instruction to the second MAD instruction.
+          */
+         set_saturate(inst->saturate, mad);
+         set_condmod(inst->conditional_mod, mad);
+      }
+
+      inst->remove(block);
+      progress = true;
+   }
+
+   if (progress)
+      invalidate_live_intervals();
+
+   return progress;
+}
+
 bool
 fs_visitor::lower_integer_multiplication()
 {
@@ -7070,6 +7111,11 @@ fs_visitor::optimize()
       OPT(compact_virtual_grfs);
    } while (progress);
 
+   if (OPT(lower_linterp)) {
+      OPT(opt_copy_propagation);
+      OPT(dead_code_eliminate);
+   }
+
    /* Do this after cmod propagation has had every possible opportunity to
     * propagate results into SEL instructions.
     */
index e8af99e17058cadd1f33fab6083802208b567292..f05a9e0625ac055114ae50fa9d7d1ebbe5e9d209 100644 (file)
@@ -167,6 +167,7 @@ public:
    bool lower_pack();
    bool lower_regioning();
    bool lower_logical_sends();
+   bool lower_linterp();
    bool lower_integer_multiplication();
    bool lower_minmax();
    bool lower_simd_width();