mesa: add/update comments in _mesa_copy_buffer_subdata()
[mesa.git] / src / mesa / drivers / dri / i965 / brw_vec4_copy_propagation.cpp
index 4b33df1f105b4f25e987b78fa0874735606cb0ca..4d27c53ddf390f8cbdb48bc1991b1eb2f0044f5a 100644 (file)
@@ -101,7 +101,13 @@ try_constant_propagation(vec4_instruction *inst, int arg, src_reg *values[4])
         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 because it's asymmetric.
+         */
+        if (inst->opcode == BRW_OPCODE_MUL &&
+            (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;
@@ -187,6 +193,7 @@ try_copy_propagation(struct intel_context *intel,
    value.swizzle = BRW_SWIZZLE4(s[0], s[1], s[2], s[3]);
 
    if (value.file != UNIFORM &&
+       value.file != GRF &&
        value.file != ATTR)
       return false;
 
@@ -195,7 +202,7 @@ try_copy_propagation(struct intel_context *intel,
       value.abs = true;
    }
    if (inst->src[arg].negate)
-      value.negate = true;
+      value.negate = !value.negate;
 
    /* FINISHME: We can't copy-propagate things that aren't normal
     * vec8s into gen6 math instructions, because of the weird src
@@ -204,6 +211,19 @@ try_copy_propagation(struct intel_context *intel,
    if (intel->gen >= 6 && inst->is_math())
       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;
+
    inst->src[arg] = value;
    return true;
 }
@@ -236,9 +256,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.
          */
@@ -246,6 +263,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];
@@ -277,31 +297,37 @@ 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.
-       *
-       * FINISHME: Sources aren't handled, which will need to be done
-       * for copy propagation.
-       */
-      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 << j) &&
+                     cur_value[i][j] &&
+                     cur_value[i][j]->file == GRF &&
+                     cur_value[i][j]->reg == inst->dst.reg &&
+                     cur_value[i][j]->reg_offset == inst->dst.reg_offset) {
+                    cur_value[i][j] = NULL;
+                 }
+              }
            }
         }
       }