[patch] Improvement to implicit scalar-vector conversions

Pekka Jääskeläinen pekka.jaaskelainen at tut.fi
Wed Apr 2 01:58:32 PDT 2014


Hi,

Should we try to comply to the OpenCL C specified behavior here or is
there some other relevant standard to look at in this case?

This piece from the OpenCL 1.2 specs is relevant here:

"6.2.6 Usual Arithmetic Conversions

Many operators that expect operands of arithmetic type cause conversions and
yield result types in a similar way. The purpose is to determine a common real
type for the operands and result. For the specified operands, each operand is
converted, without change of type domain, to a type
whose corresponding real type is the common real type.

**For this purpose, all
vector types shall be considered to have higher conversion ranks than scalars.**

Unless explicitly stated otherwise, the common real type is also the
corresponding real type of the result, whose type domain is the
type domain of the operands if they are the same, and complex otherwise. This
pattern is called the usual arithmetic conversions.

**If the operands are of
more than one vector type, then an error shall occur. Implicit conversions
between vector types are not permitted, per section 6.2.1.**

**Otherwise, if there is only a single vector type, and all other operands are
scalar types, the scalar types are converted to the type of the vector
element, then widened into a new vector containing the same number of elements
as the vector, by duplication of the scalar value across the width of
the new vector.**

An error shall occur if any scalar operand has greater rank
than the type of the vector element. For this purpose, the rank order defined
as follows:

1. The rank of a floating-point type is greater than the rank of another
floating-point type, if the first floating-point type can exactly represent 
all numeric values in the second floating-point type. (For this purpose, the 
encoding of the floating-point value is used, rather than the subset of the 
encoding usable by the device.)

2. The rank of any floating-point type is greater than the rank of any integer
type.

3. The rank of an integer type is greater than the rank of an integer type
with less precision.

4. The rank of an unsigned integer type is greater than the rank of a signed
integer type with the same precision.35

5. The rank of the bool type is less than the rank of any other type.

6. The rank of an enumerated type shall equal the rank of the compatible
integer type.

7. For all types, T1, T2 and T3, if T1 has greater rank than T2, and T2 has
greater rank than

T3, then T1 has greater rank than T3.

Otherwise, if all operands are scalar, the usual arithmetic conversions apply,
per section 6.3.1.8 of the C99 standard.
NOTE: Both the standard orderings in sections 6.3.1.8 and 6.3.1.1 of C99 were
examined and rejected. Had we used integer conversion rank here, int4 + 0U 
would have been legal and had int4 return type. Had we used standard C99 usual 
arithmetic conversion rules for scalars, then the standard integer promotion 
would have been performed on vector integer element types and
short8 + char would either have return type of int8 or be illegal."


If I understood it correctly, your patch goes towards the OpenCL C specified
behavior. It LGTM.

BR,
Pekka

On 03/27/2014 02:34 AM, Stephen Canon wrote:
> ExtVectors currently support basic operations with scalar data (which is
> interpreted as an implicit splat).  However, this support has some serious
> issues.  Most critically, at present the type of the result depends on
> operand order:
>
> typedef float __attribute__((ext_vector_type(2))) float2;
>
> float2 x; double y = 2.0 + x; // reinterprets y as double, scalar
> double-precision add. float2 z = x + 2.0; // reinterprets x as float2, does
> packed single-precision add.
>
> Both behaviors are pretty busted; the odds are overwhelming that the
> programmer's intention was to add two to both lanes of x.  What’s worse, +,
> which is a commutative operator for any reasonable FP type, doesn’t even
> return the same type when the operand order is flipped.
>
> This patch makes it so that “real scalar OP vector” is interpreted as
> “convert the scalar to vector element type and splat, then perform OP”,
> regardless of operand order or conversion rank of the scalar and vector
> type (i.e. the type of the vector elements always “wins”, even if the rank
> of the scalar type is greater).  This is somewhat different from the
> arithmetic promotions for scalar types, but it is by far the most sensible
> behavior; it is what most vector programmers want to get.
>
> This also improves the state of affairs for integer scalars in ExtVector
> expressions.  When operating on vectors with elements smaller than int, it
> has until now been necessary to sprinkle in lots of casts:
>
> typedef unsigned char __attribute__((__ext_vector_type__(16))) uchar16;
> uchar16 baz(uchar16 x) { return x + (unsigned char)2; }
>
> The extra cast adds little to nothing, and makes simple expressions overly
> verbose.  With this patch, the following works just fine:
>
> uchar16 baz(uchar16 x) { return x + 2; }
>
> I also improved the state of warnings for implicit scalar->vector casts to
> make it easier to identify suspicious conversions:
>
> short4 bar( ) { return 65536; }
>
> previously this produced no error or warning.  Now, with -Wconversion we
> get:
>
> foo.c:9:12: warning: implicit conversion from 'int' to 'short4' changes
> value from 65536 to 0 [-Wconstant-conversion]
>
> Thanks in advance for your feedback! – Steve
>
>
>
> _______________________________________________ cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>






More information about the cfe-commits mailing list