El 01/05/18 a las 01:22, Jason Ekstrand escribió:
> On Mon, Apr 30, 2018 at 3:53 PM, Chema Casanova <jmcasan...@igalia.com
> <mailto:jmcasan...@igalia.com>> wrote:
> 
> 
> 
>     On 30/04/18 23:12, Jason Ekstrand wrote:
>     > On Mon, Apr 30, 2018 at 7:18 AM, Iago Toral Quiroga <ito...@igalia.com 
> <mailto:ito...@igalia.com>
>     > <mailto:ito...@igalia.com <mailto:ito...@igalia.com>>> wrote:
>     > 
>     >     From: Jose Maria Casanova Crespo <jmcasan...@igalia.com 
> <mailto:jmcasan...@igalia.com>
>     >     <mailto:jmcasan...@igalia.com <mailto:jmcasan...@igalia.com>>>
>     >
>     >     16-bit immediates need to replicate the 16-bit immediate value
>     >     in both words of the 32-bit value. This needs to be careful
>     >     to avoid sign-extension, which the previous implementation was
>     >     not handling properly.
>     >
>     >     For example, with the previous implementation, storing the value
>     >     -3 would generate imm.d = 0xfffffffd due to signed integer sign
>     >     extension, which is not correct. Instead, we should cast to
>     >     unsigned, which gives us the correct result: imm.ud = 0xfffdfffd.
>     >
>     >     We only had a couple of cases hitting this path in the driver
>     >     until now, one with value -1, which would work since all bits are
>     >     one in this case, and another with value -2 in brw_clip_tri(),
>     >     which would hit the aforementioned issue (this case only affects
>     >     gen4 although we are not aware of whether this was causing an
>     >     actual bug somewhere).
>     >     ---
>     >      src/intel/compiler/brw_reg.h | 2 +-
>     >      1 file changed, 1 insertion(+), 1 deletion(-)
>     >
>     >     diff --git a/src/intel/compiler/brw_reg.h
>     b/src/intel/compiler/brw_reg.h
>     >     index dff9b970b2..0084a78af6 100644
>     >     --- a/src/intel/compiler/brw_reg.h
>     >     +++ b/src/intel/compiler/brw_reg.h
>     >     @@ -705,7 +705,7 @@ static inline struct brw_reg
>     >      brw_imm_w(int16_t w)
>     >      {
>     >         struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_W);
>     >     -   imm.d = w | (w << 16);
>     >     +   imm.ud = (uint16_t)w | ((uint16_t)w << 16);
> 
>     > Uh... Is this cast right?  Doing a << 16 on a 16-bit data type should
>     > yield undefined results.  I think you want a (uint32_t) cast.
> 
>     In my test code it was working at least with GCC, I think it is because
>     at the end we have an integer promotion for any type with lower rank
>     than int.
> 
>     "Formally, the rule says (C11 6.3.1.1):
> 
>         If an int can represent all values of the original type (as
>     restricted by the width, for a bit-field), the value is converted to an
>     int; otherwise, it is converted to an unsigned int. These are called the
>     integer promotions."
> 
>     But I agree that is clearer if we just use (uint32_t).
>     I can change also the brw_imm_uw case that has the same issue.
> 
> 
> Yeah, best to make it clear. :-)

I was wrong, we can't just replace (uint16_t) cast by (uint32_t) because
the cast from signed short to uint32_t implies sign extension, because
it seems that sign extensions is done if source is signed and not in
destination type.

So for example, being w = -2  (0xfffe).

imm.ud = (uint32_t)w | (uint32_t)w << 16;

becomes: 0xfffffffe

So the alternatives I figure out with the correct result are.

imm.ud = (uint32_t) w & 0xffff | (uint32_t)w << 16;

Or:

uint16_t value = w;
imm.ud = (uint32_t)value | (uint32_t)value << 16;

Or something like:

imm.ud = (uint32_t)(uint16_t)w | ((uint32_t)(uint16_t)w << 16);

Any preference?

Chema
_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to