i965/fs: Use the source type when looking for UD negations in copy prop
authorJason Ekstrand <jason.ekstrand@intel.com>
Fri, 3 Apr 2015 19:15:48 +0000 (12:15 -0700)
committerJason Ekstrand <jason.ekstrand@intel.com>
Fri, 17 Apr 2015 18:01:33 +0000 (11:01 -0700)
There can be problems with floats and conditional modifiers when
copy-propagating a negated UD source.  The problem arises when a source
modifier is applied to a UD value.  In this case, a 33-bit representation
is internally used.  If you do the following:

   1: mov foo:UD 7U
   2: mov bar:UD -foo:UD
   3: mov out:F bar:UD

the out register will have the value (float)(unt32_t)-7 which is some very
large floating-point number.  However, if we allow copy-propagation of the
second mov, we get

   1: mov foo:UD 7U
   3: mov out:f -bar:UD

and, since the negation is computed in 33-bits, we get a value of -7.0f
which is clearly not the same.  This is a similar problem if the
instruction has a conditional modifier where the 33-bit value is used in
the comparison and not the 32-bit version.

Previously, we checked the source to be copied for the negate and then
checked the source being propagated to for the type.  This isn't quite what
we want because we are really just looking for negated UD sources.  A check
later in the file ensures that both ends of the propagate have the right
type so it works.  However, if we relax the restriction that both ends of
the propagation have the same type, it ends up causing us to bail early in
cases we don't want.

Signed-off-by: Jason Ekstrand <jason.ekstrand@intel.com>
Reviewed-by: Anuj Phogat <anuj.phogat@gmail.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
src/mesa/drivers/dri/i965/brw_fs_copy_propagation.cpp

index 764741d369ef9a82c96aa668f24febd9562e0baa..e8d092cbc00d2f41b40719e25d452963813b2763 100644 (file)
@@ -307,7 +307,7 @@ fs_visitor::try_copy_propagate(fs_inst *inst, int arg, acp_entry *entry)
     * instead. See also resolve_ud_negate() and comment in
     * fs_generator::generate_code.
     */
-   if (inst->src[arg].type == BRW_REGISTER_TYPE_UD &&
+   if (entry->src.type == BRW_REGISTER_TYPE_UD &&
        entry->src.negate)
       return false;