`vec::convert` is underspecified
Opened this issue · 1 comments
Table 142 of the SYCL 2020 specification defines vec::convert
as follows:
Converts this SYCL
vec
to a SYCLvec
of a different element type specified byConvertT
using the rounding mode specified byRoundingMode
. The new SYCLvec
type must have the same number of elements as this SYCLvec
. The different rounding modes are described in Table 144.
Which raises a number of questions:
There are no restrictions about using different rounding modes even for integer to integer conversions. What is the meaning of them in that case? Note that there are cases when source value is not representable in destination type, like narrowing conversion, signed to unsigned conversion for negative values. Should rounding modes affect the result in those cases?
How "converts" is defined, exactly? Does it follow C++ standard or some other rules? If it follows C++, then which one?
The latest C++ spec draft defines integer conversions in conv.integral.3 as:
the result is the unique value of the destination type that is congruent to the source integer modulo
2^N
, whereN
is the width of the destination type.
However, if you take a look at C++17 draft (document N4713) 7.8 Integer conversions, you will find the following:
If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source integer (modulo
2^n
wheren
is the number of bits used to represent the unsigned type). [ Note: In a two’s complement representation, this conversion is conceptual and there is no change in the bit pattern (if there is no truncation). — end note ]
If the destination type is signed, the value is unchanged if it can be represented in the destination type; otherwise, the value is implementation-defined
SYCL-CTS is using C-style cast to compute reference value for integer conversions: tests/common/common_vec.h:132
, which means that reference selected in CTS is technically implementation-defined if it is compiled with C++17-based toolchain and it is well-defined it it is compiled with C++20-based toolchain, which doesn't sound right.
Note: signed-to-unsigned (and vice-versa) conversions defined in SPIR-V do not follow C++20 rules: they clamp input value to a nearest representable value in the destination type instead of doing modulo arithmetic, see OpSatConvertSToU
for example.
SYCL WG call:
- Original specification was based on OpenCL, but should be considered in light of C++17
- @nliber will take a look at this