expand-large-fp-convert cannot handle vector types.
If overly large vector element types survive into
isel, they will likely be scalarized there, but since
isel cannot handle scalar integer types of that size,
it will assert.
Handle vector types in expand-large-fp-convert by
scalarizing them and then expanding the scalar type
operation. For large vectors, this results in a
*massive* code expansion, but it's better than
asserting.
The IR for a double-to-i129 conversion looks like this in one of the
blocks in compiler-rt:
%cmp5.i = icmp ult i16 %3, -129, !dbg !24
But in ExpandLargeFpConvert, it looks like:
%13 = icmp ult i129 %12, 4294967167, !dbg !19
ExpandLargeFpConvert is wrong; the value should have been
signed before negating, but instead we get a very large
unsigned value. Another value in the same pass also has this
issue.
When deciding whether to perform rounding on the significand,
the generated IR was using (width - leading zeros - 1) rather
than (width - leading zeros). This is different from how the
routine in compiler-rt does it:
int sd = srcBits - clzSrcT(a);
int e = sd - 1;
if (sd > dstMantDig) {
This bug means that the following code, when built on -O0:
#include <stdio.h>
_BitInt(233) v_1037 = 0;
int main(void)
{
v_1037 = 18014398509481982wb;
double d = v_1037;
printf("d = %f\n", d);
return 0;
}
prints "d = 9007199254740992.000000", which is incorrect.
The correct result is "d = 18014398509481982.000000".