x86 does not have an SSE instruction to convert from unsigned int32 to floating point. What would be the most efficient instruction sequence for achieving this?
EDIT:
To clarify, i want to do the vector sequence of the following scalar operation:
unsigned int x = ...
float res = (float)x;
EDIT2: Here is a naive algorithm for doing a scalar conversion.
unsigned int x = ...
float bias = 0.f;
if (x > 0x7fffffff) {
bias = (float)0x80000000;
x -= 0x80000000;
}
res = signed_convert(x) + bias;
Your naive scalar algorithm doesn’t deliver a correctly-rounded conversion — it will suffer from double rounding on certain inputs. As an example: if
xis0x88000081, then the correctly-rounded result of conversion to float is2281701632.0f, but your scalar algorithm will return2281701376.0finstead.Off the top of my head, you can do a correct conversion as follows (as I said, this is off the top of my head, so it’s likely possible to save an instruction somewhere):
where the constants have the following values:
What this does is separately convert the high- and low-halves of each lane to floating-point, then add these converted values together. Because each half is only 16 bits wide, the conversion to float does not incur any rounding. Rounding only occurs when the two halves are added; because addition is a correctly-rounded operation, the entire conversion is correctly rounded.
By contrast, your naive implementation first converts the low 31 bits to float, which incurs a rounding, then conditionally adds 2^31 to that result, which may cause a second rounding. Any time you have two separate rounding points in a conversion, unless you are exceedingly careful about how they occur, you should not expect the result to be correctly rounded.