On MIPS, shift operation on signed types give unpredictable results. Therefore we use unsigned value while shifting and after shifting is done we convert it back to signed value.
Diff Detail
- Repository
- rL LLVM
Event Timeline
Please elaborate what's going on here (i.e. what is the value that we fail to sign-extend)? This code looks far too complex to me, and I'd strongly suggest to make it platform-independent.
Please elaborate what's going on here (i.e. what is the value that we fail to sign-extend)?
The value that we fail to sign extend is of SIntMax(Val). We are getting uncertain results on bit shifting of signed types. Therefore we need to use unsigned types when applying bit shifting. Since return type of getSIntValue() function is SIntMax, we can type cast the return value after bit shifting to SIntMax.
This code looks far too complex to me, and I'd strongly suggest to make it platform-independent.
I have tried to simplify the code and make it platform independent. I will update this patch with the simplified code
Could you confirm the type of SIntMax and the value of ExtraBits when it gives incorrect results? 'X << N >> N' is a common idiom for sign-extension so it's surprising that it's not working for you.
The type of SIntMax is __int128. The value of ExtraBits is 64 when getType().getIntegerBitWidth() returns 64 and it is 96 when getType().getIntegerBitWidth() returns 32.
I haven't identified the guilty instruction(s) yet but it looks like a CodeGen bug with 128-bit shifts. At the moment '(x << 64) == x' and '(x << 32) == (x << 96)' neither of which should be true.
What Daniel says. Looks like you should fix the MIPS CodeGen instead. As a workaround, you can try to hack ubsan_value.h to treat __int128 as unavailable on MIPS.