[InstCombine] Incorrect exact flag inferred for ashr with undef-derived shift count
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
The following function is transformed at `-O3` by replacing the second shift-count computation with the first one and adding `exact` to the final `ashr`.
Original IR:
```llvm
define i16 @shift_count_bitwidth_does_not_fit(i16 %x, i4 %n) {
%highbits = lshr i16 %x, 1
%sub1 = sub i4 0, %n
%z1 = zext i4 %sub1 to i16
%shl = shl i16 %highbits, %z1
%sub2 = sub i4 0, %n
%z2 = zext i4 %sub2 to i16
%ashr = ashr i16 %shl, %z2
ret i16 %ashr
}
```
Optimized IR:
```llvm
define i16 @shift_count_bitwidth_does_not_fit(i16 %x, i4 %n) local_unnamed_addr #0 {
%highbits = lshr i16 %x, 1
%sub1 = sub i4 0, %n
%z1 = zext i4 %sub1 to i16
%shl = shl i16 %highbits, %z1
%ashr = ashr exact i16 %shl, %z1
ret i16 %ashr
}
attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
```
The transformation appears to rely on the fact that the `shl` and `ashr` use the same SSA value as their shift count.
But `%n` is not `noundef`, and `%z1` is derived from `%n` without an intervening `freeze`
Alive2 also reports that it will transform more poisonous than source when `%x = 2` and `%n = undef`
https://alive2.llvm.org/ce/z/Lr_kDN
Contributor guide
Assessment
This issue has not been assessed yet.