| Issue |
181118
|
| Summary |
[InstCombine] Dropping `freeze` under range-to-poison semantics makes the result more poisonous
|
| Labels |
new issue
|
| Assignees |
|
| Reporter |
ariskeirio
|
## Description
I found InstCombine optimization will drop `freeze` while rewriting some operations and adding flags. Under LLVM IR semantics where `range(i32 a, b)` violations are converted to poison, removing `freeze` is not refinement: it can make the target more poisonous than the source.
This pattern seems to occur in multiple instances in my workload. I’m reporting the following as one concrete example. It is related to dropping `freeze` in the presence of `range` constraints.
**Source IR**
```llvm
define <2 x i16> @src(<2 x i16> noundef %x, <2 x i16> noundef range(i16 1, 110) %w) {
%cmp = icmp ule <2 x i16> %x, %w
%sub = add nuw <2 x i16> %w, splat (i16 -1)
%r = select <2 x i1> %cmp, <2 x i16> %x, <2 x i16> %sub
%1 = freeze <2 x i16> %r
ret <2 x i16> %1
}
```
**Target IR**
```llvm
define <2 x i16> @tgt(<2 x i16> noundef %x, <2 x i16> noundef range(i16 1, 110) %w) {
%cmp.not = icmp ugt <2 x i16> %x, %w
%r = select <2 x i1> %cmp.not, <2 x i16> splat (i16 -1), <2 x i16> %x
ret <2 x i16> %r
}
```
LLVM specifies that `range` violations are converted to poison. With that semantics, `freeze` is observable: if `%r` becomes poison, `freeze` can produce a concrete value while removing `freeze` returns poison.
Alive2 translation validation reports the target is more poisonous than the source.
```llvm
define <2 x i16> @src(<2 x i16> noundef %x, <2 x i16> noundef %w) {
init:
%#range_0_%w = !range <2 x i16> noundef %w, i16 1, i16 110, welldefined
br label %#0
#0:
%cmp = icmp ule <2 x i16> noundef %x, %#range_0_%w
%sub = add nuw <2 x i16> %#range_0_%w, { 65535, 65535 }
%r = select <2 x i1> %cmp, <2 x i16> noundef %x, <2 x i16> %sub
%#1 = freeze <2 x i16> %r
ret <2 x i16> %#1
}
=>
define <2 x i16> @src(<2 x i16> noundef %x, <2 x i16> noundef %w) {
init:
%#range_0_%w = !range <2 x i16> noundef %w, i16 1, i16 110, welldefined
br label %#0
#0:
%cmp.not = icmp ugt <2 x i16> noundef %x, %#range_0_%w
%r = select <2 x i1> %cmp.not, <2 x i16> { 65535, 65535 }, <2 x i16> noundef %x
ret <2 x i16> %r
}
Transformation doesn't verify!
ERROR: Target is more poisonous than source
Example:
<2 x i16> noundef %x = < #x0003 (3), #x0003 (3) >
<2 x i16> noundef %w = < #x0000 (0), #x0000 (0) >
Source:
<2 x i16> %#range_0_%w = < poison, poison >
>> Jump to %#0
<2 x i1> %cmp = < poison, poison >
<2 x i16> %sub = < poison, poison >
<2 x i16> %r = < poison, poison >
<2 x i16> %#1 = < #x0003 (3), #x0003 (3) >
Target:
<2 x i16> %#range_0_%w = < poison, poison >
>> Jump to %#0
<2 x i1> %cmp.not = < poison, poison >
<2 x i16> %r = < poison, poison >
Source value: < #x0003 (3), #x0003 (3) >
Target value: < poison, poison >
```
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs