i915: Remove most of the code under gen >= 4 checks.
[mesa.git] / src / mesa / drivers / dri / i965 / brw_vec4_copy_propagation.cpp
index c46735abfab85a5edbcd7466be40bd446372b3b6..64f6ccc98f7bcf453b5e2a3f8238dcdd6d997109 100644 (file)
@@ -95,13 +95,21 @@ try_constant_propagation(vec4_instruction *inst, int arg, src_reg *values[4])
       inst->src[arg] = value;
       return true;
 
+   case BRW_OPCODE_MACH:
    case BRW_OPCODE_MUL:
    case BRW_OPCODE_ADD:
       if (arg == 1) {
         inst->src[arg] = value;
         return true;
       } else if (arg == 0 && inst->src[1].file != IMM) {
-        /* Fit this constant in by commuting the operands */
+        /* Fit this constant in by commuting the operands.  Exception: we
+         * can't do this for 32-bit integer MUL/MACH because it's asymmetric.
+         */
+        if ((inst->opcode == BRW_OPCODE_MUL ||
+              inst->opcode == BRW_OPCODE_MACH) &&
+            (inst->src[1].type == BRW_REGISTER_TYPE_D ||
+             inst->src[1].type == BRW_REGISTER_TYPE_UD))
+           break;
         inst->src[0] = inst->src[1];
         inst->src[1] = value;
         return true;
@@ -153,9 +161,10 @@ try_constant_propagation(vec4_instruction *inst, int arg, src_reg *values[4])
    return false;
 }
 
-static bool
-try_copy_propagation(struct intel_context *intel,
-                    vec4_instruction *inst, int arg, src_reg *values[4])
+bool
+vec4_visitor::try_copy_propagation(struct intel_context *intel,
+                                   vec4_instruction *inst, int arg,
+                                   src_reg *values[4])
 {
    /* For constant propagation, we only handle the same constant
     * across all 4 channels.  Some day, we should handle the 8-bit
@@ -196,19 +205,39 @@ try_copy_propagation(struct intel_context *intel,
       value.abs = true;
    }
    if (inst->src[arg].negate)
-      value.negate = true;
+      value.negate = !value.negate;
+
+   bool has_source_modifiers = (value.negate || value.abs ||
+                                value.swizzle != BRW_SWIZZLE_XYZW ||
+                                value.file == UNIFORM);
 
-   /* FINISHME: We can't copy-propagate things that aren't normal
-    * vec8s into gen6 math instructions, because of the weird src
-    * handling for those instructions.  Just ignore them for now.
+   /* gen6 math and gen7+ SENDs from GRFs ignore source modifiers on
+    * instructions.
     */
-   if (intel->gen >= 6 && inst->is_math())
+   if (has_source_modifiers && !can_do_source_mods(inst))
+      return false;
+
+   bool is_3src_inst = (inst->opcode == BRW_OPCODE_LRP ||
+                        inst->opcode == BRW_OPCODE_MAD ||
+                        inst->opcode == BRW_OPCODE_BFE ||
+                        inst->opcode == BRW_OPCODE_BFI2);
+   if (is_3src_inst && value.file == UNIFORM)
+      return false;
+
+   /* We can't copy-propagate a UD negation into a condmod
+    * instruction, because the condmod ends up looking at the 33-bit
+    * signed accumulator value instead of the 32-bit value we wanted
+    */
+   if (inst->conditional_mod &&
+       value.negate &&
+       value.type == BRW_REGISTER_TYPE_UD)
       return false;
 
    /* Don't report progress if this is a noop. */
    if (value.equals(&inst->src[arg]))
       return false;
 
+   value.type = inst->src[arg].type;
    inst->src[arg] = value;
    return true;
 }
@@ -241,9 +270,6 @@ vec4_visitor::opt_copy_propagation()
        * optimizing out access to the copy result
        */
       for (int i = 2; i >= 0; i--) {
-        int reg = (virtual_grf_reg_map[inst->src[i].reg] +
-                   inst->src[i].reg_offset);
-
         /* Copied values end up in GRFs, and we don't track reladdr
          * accesses.
          */
@@ -251,6 +277,9 @@ vec4_visitor::opt_copy_propagation()
             inst->src[i].reladdr)
            continue;
 
+        int reg = (virtual_grf_reg_map[inst->src[i].reg] +
+                   inst->src[i].reg_offset);
+
         /* Find the regs that each swizzle component came from.
          */
         src_reg *values[4];
@@ -282,33 +311,30 @@ vec4_visitor::opt_copy_propagation()
       }
 
       /* Track available source registers. */
-      if (is_direct_copy(inst)) {
-        int reg = virtual_grf_reg_map[inst->dst.reg] + inst->dst.reg_offset;
+      if (inst->dst.file == GRF) {
+        const int reg =
+           virtual_grf_reg_map[inst->dst.reg] + inst->dst.reg_offset;
+
+        /* Update our destination's current channel values.  For a direct copy,
+         * the value is the newly propagated source.  Otherwise, we don't know
+         * the new value, so clear it.
+         */
+        bool direct_copy = is_direct_copy(inst);
         for (int i = 0; i < 4; i++) {
            if (inst->dst.writemask & (1 << i)) {
-              cur_value[reg][i] = &inst->src[0];
+              cur_value[reg][i] = direct_copy ? &inst->src[0] : NULL;
            }
         }
-        continue;
-      }
 
-      /* For any updated channels, clear tracking of them as a source
-       * or destination.
-       */
-      if (inst->dst.file == GRF) {
+        /* Clear the records for any registers whose current value came from
+         * our destination's updated channels, as the two are no longer equal.
+         */
         if (inst->dst.reladdr)
            memset(cur_value, 0, sizeof(cur_value));
         else {
-           int reg = virtual_grf_reg_map[inst->dst.reg] + inst->dst.reg_offset;
-
-           for (int i = 0; i < 4; i++) {
-              if (inst->dst.writemask & (1 << i))
-                 cur_value[reg][i] = NULL;
-           }
-
            for (int i = 0; i < virtual_grf_reg_count; i++) {
               for (int j = 0; j < 4; j++) {
-                 if (inst->dst.writemask & (1 << i) &&
+                 if (inst->dst.writemask & (1 << j) &&
                      cur_value[i][j] &&
                      cur_value[i][j]->file == GRF &&
                      cur_value[i][j]->reg == inst->dst.reg &&