i965/fs: Lower math into Gen4-5 send-like instructions in lower_logical_sends.
authorFrancisco Jerez <currojerez@riseup.net>
Wed, 18 May 2016 06:54:25 +0000 (23:54 -0700)
committerFrancisco Jerez <currojerez@riseup.net>
Sat, 28 May 2016 06:19:21 +0000 (23:19 -0700)
The benefit is we will be able to use the SIMD lowering pass to unroll
math instructions of unsupported width and then remove some cruft from
the generator.

Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
src/mesa/drivers/dri/i965/brw_fs.cpp
src/mesa/drivers/dri/i965/brw_fs_builder.h

index d7ae90a8f046cce15e7a3d91e7b8e5c3dca424f6..822d863ab1c69befcc4b4c60c56fe2e9cec8d4f1 100644 (file)
@@ -4434,6 +4434,36 @@ lower_varying_pull_constant_logical_send(const fs_builder &bld, fs_inst *inst)
    }
 }
 
+static void
+lower_math_logical_send(const fs_builder &bld, fs_inst *inst)
+{
+   assert(bld.shader->devinfo->gen < 6);
+
+   inst->base_mrf = 2;
+   inst->mlen = inst->sources * inst->exec_size / 8;
+
+   if (inst->sources > 1) {
+      /* From the Ironlake PRM, Volume 4, Part 1, Section 6.1.13
+       * "Message Payload":
+       *
+       * "Operand0[7].  For the INT DIV functions, this operand is the
+       *  denominator."
+       *  ...
+       * "Operand1[7].  For the INT DIV functions, this operand is the
+       *  numerator."
+       */
+      const bool is_int_div = inst->opcode != SHADER_OPCODE_POW;
+      const fs_reg src0 = is_int_div ? inst->src[1] : inst->src[0];
+      const fs_reg src1 = is_int_div ? inst->src[0] : inst->src[1];
+
+      inst->resize_sources(1);
+      inst->src[0] = src0;
+
+      assert(inst->exec_size == 8);
+      bld.MOV(fs_reg(MRF, inst->base_mrf + 1, src1.type), src1);
+   }
+}
+
 bool
 fs_visitor::lower_logical_sends()
 {
@@ -4543,6 +4573,31 @@ fs_visitor::lower_logical_sends()
          lower_varying_pull_constant_logical_send(ibld, inst);
          break;
 
+      case SHADER_OPCODE_RCP:
+      case SHADER_OPCODE_RSQ:
+      case SHADER_OPCODE_SQRT:
+      case SHADER_OPCODE_EXP2:
+      case SHADER_OPCODE_LOG2:
+      case SHADER_OPCODE_SIN:
+      case SHADER_OPCODE_COS:
+      case SHADER_OPCODE_POW:
+      case SHADER_OPCODE_INT_QUOTIENT:
+      case SHADER_OPCODE_INT_REMAINDER:
+         /* The math opcodes are overloaded for the send-like and
+          * expression-like instructions which seems kind of icky.  Gen6+ has
+          * a native (but rather quirky) MATH instruction so we don't need to
+          * do anything here.  On Gen4-5 we'll have to lower the Gen6-like
+          * logical instructions (which we can easily recognize because they
+          * have mlen = 0) into send-like virtual instructions.
+          */
+         if (devinfo->gen < 6 && inst->mlen == 0) {
+            lower_math_logical_send(ibld, inst);
+            break;
+
+         } else {
+            continue;
+         }
+
       default:
          continue;
       }
index 2087e585b06bb3d8b76f7d82fc667f96caa3dbb3..b50dda421ae062521286cb4cc1ac7ee9db279541 100644 (file)
@@ -281,9 +281,8 @@ namespace brw {
          case SHADER_OPCODE_LOG2:
          case SHADER_OPCODE_SIN:
          case SHADER_OPCODE_COS:
-            return fix_math_instruction(
-               emit(instruction(opcode, dispatch_width(), dst,
-                                fix_math_operand(src0))));
+            return emit(instruction(opcode, dispatch_width(), dst,
+                                    fix_math_operand(src0)));
 
          default:
             return emit(instruction(opcode, dispatch_width(), dst, src0));
@@ -301,10 +300,9 @@ namespace brw {
          case SHADER_OPCODE_POW:
          case SHADER_OPCODE_INT_QUOTIENT:
          case SHADER_OPCODE_INT_REMAINDER:
-            return fix_math_instruction(
-               emit(instruction(opcode, dispatch_width(), dst,
-                                fix_math_operand(src0),
-                                fix_math_operand(src1))));
+            return emit(instruction(opcode, dispatch_width(), dst,
+                                    fix_math_operand(src0),
+                                    fix_math_operand(src1)));
 
          default:
             return emit(instruction(opcode, dispatch_width(), dst, src0, src1));
@@ -640,41 +638,6 @@ namespace brw {
          }
       }
 
-      /**
-       * Workaround other weirdness of the math instruction.
-       */
-      instruction *
-      fix_math_instruction(instruction *inst) const
-      {
-         if (shader->devinfo->gen < 6) {
-            inst->base_mrf = 2;
-            inst->mlen = inst->sources * dispatch_width() / 8;
-
-            if (inst->sources > 1) {
-               /* From the Ironlake PRM, Volume 4, Part 1, Section 6.1.13
-                * "Message Payload":
-                *
-                * "Operand0[7].  For the INT DIV functions, this operand is the
-                *  denominator."
-                *  ...
-                * "Operand1[7].  For the INT DIV functions, this operand is the
-                *  numerator."
-                */
-               const bool is_int_div = inst->opcode != SHADER_OPCODE_POW;
-               const fs_reg src0 = is_int_div ? inst->src[1] : inst->src[0];
-               const fs_reg src1 = is_int_div ? inst->src[0] : inst->src[1];
-
-               inst->resize_sources(1);
-               inst->src[0] = src0;
-
-               at(block, inst).MOV(fs_reg(MRF, inst->base_mrf + 1, src1.type),
-                                   src1);
-            }
-         }
-
-         return inst;
-      }
-
       bblock_t *block;
       exec_node *cursor;