llvm / llvm/llvm-project

[InstCombine] Incorrect exact flag inferred for ashr with undef-derived shift count

Open
#217,234 1 comment 0 reactions 1 assignee Claimed by @Chennesxu View on GitHub
llvm:instcombine miscompilation:undef
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.