Fix UB-introducing rewrite in FindIntrinsics #8539
Open
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
FindIntrinsics was rewriting
i8(rounding_shift_left(i16(foo_i8), 11))
to
rounding_shift_left(foo_i8, 11)
I.e. it decided it could do the shift in the narrower type. However this isn't correct, because 11 is a valid shift for a 16-bit int, but not for an 8-bit int. The former is zero, the latter gets turned into a poison value because we lower it to llvm's shl. This was discovered by a random failure in test/correctness/lossless_cast.cpp in another PR for seed 826708018.
This PR fixes this case by adding a compile-time check that the shift is in-range. For the examples in test/correctness/intrinsics.cpp the shift amount ends up in a let, so making this work on those cases required handling a TODO: tracking the constant integer bounds of variables in scope in FindIntrinsics and therefore also in lossless_cast.