i965/vec4: Change types as needed to propagate source modifiers using current instruction
authorAlejandro Piñeiro <apinheiro@igalia.com>
Wed, 16 Sep 2015 08:26:55 +0000 (10:26 +0200)
committerAlejandro Piñeiro <apinheiro@igalia.com>
Fri, 18 Sep 2015 22:31:25 +0000 (00:31 +0200)
SEL and MOV instructions, as long as they don't have source modifiers, are
just copying bits around.  So those kind of instruction could be propagated
even if there are type mismatches. This is needed because NIR generates
integer SEL and MOV instructions whenever it doesn't know what else to
generate.

This commit adds support for copy propagation using current instruction
as reference.

Equivalent to commit 472ef9 but for vec4.

v2: include check for saturate, as Jason Ekstrand suggested
v3: check that the dst.type and the src type are the same, in order to
    solve (among others) the following deqp regression with v2:
    dEQP-GLES3.functional.shaders.operator.unary_operator.minus.lowp_uint_vertex

Reviewed-by: Jason Ekstrand <jason.ekstrand@intel.com>
src/mesa/drivers/dri/i965/brw_vec4_copy_propagation.cpp

index 5a15eb8976686a6b1b335c231100e3ed4417517f..1522eeabb1cb7a2b876e70f46b64a50c6cb5405e 100644 (file)
@@ -248,6 +248,18 @@ try_constant_propagate(const struct brw_device_info *devinfo,
    return false;
 }
 
+static bool
+can_change_source_types(vec4_instruction *inst)
+{
+   return inst->dst.type == inst->src[0].type &&
+      !inst->src[0].abs && !inst->src[0].negate && !inst->saturate &&
+      (inst->opcode == BRW_OPCODE_MOV ||
+       (inst->opcode == BRW_OPCODE_SEL &&
+        inst->dst.type == inst->src[1].type &&
+        inst->predicate != BRW_PREDICATE_NONE &&
+        !inst->src[1].abs && !inst->src[1].negate));
+}
+
 static bool
 try_copy_propagate(const struct brw_device_info *devinfo,
                    vec4_instruction *inst,
@@ -308,7 +320,9 @@ try_copy_propagate(const struct brw_device_info *devinfo,
         value.swizzle != BRW_SWIZZLE_XYZW) && !inst->can_do_source_mods(devinfo))
       return false;
 
-   if (has_source_modifiers && value.type != inst->src[arg].type)
+   if (has_source_modifiers &&
+       value.type != inst->src[arg].type &&
+       !can_change_source_types(inst))
       return false;
 
    if (has_source_modifiers &&
@@ -362,7 +376,19 @@ try_copy_propagate(const struct brw_device_info *devinfo,
       }
    }
 
-   value.type = inst->src[arg].type;
+   if (has_source_modifiers &&
+       value.type != inst->src[arg].type) {
+      /* We are propagating source modifiers from a MOV with a different
+       * type.  If we got here, then we can just change the source and
+       * destination types of the instruction and keep going.
+       */
+      assert(can_change_source_types(inst));
+      for (int i = 0; i < 3; i++) {
+         inst->src[i].type = value.type;
+      }
+      inst->dst.type = value.type;
+   } else
+      value.type = inst->src[arg].type;
    inst->src[arg] = value;
    return true;
 }