[InstCombine] Unsound masked-xor fold duplicates an operand that may contain undef
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
InstCombine appears to perform an invalid transformation of a masked XOR expression involving `freeze` in following cases.
```llvm
define <2 x i4> @in_constant_varx_6_invmask(<2 x i4> %x, <2 x i4> %mask) {
%notmask = xor <2 x i4> %mask, splat (i4 -1)
%n0 = xor <2 x i4> %x, splat (i4 6)
%freeze.ins = freeze <2 x i4> %notmask
%n1 = and <2 x i4> %n0, %freeze.ins
%r = xor <2 x i4> %n1, splat (i4 6)
ret <2 x i4> %r
}
```
But the optimised expression introduces a second use of `%x`. The two uses may observe different values, thus making the target more undefined than the source if `%x` contains `undef`.
```llvm
define <2 x i4> @in_constant_varx_6_invmask(<2 x i4> %x, <2 x i4> %mask) local_unnamed_addr #0 {
%mask.fr = freeze <2 x i4> %mask
%n0 = xor <2 x i4> %x, splat (i4 6)
%1 = and <2 x i4> %mask.fr, %n0
%r = xor <2 x i4> %1, %x
ret <2 x i4> %r
}
attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
```
Reproduce: https://alive2.llvm.org/ce/z/Z8mus8
Contributor guide
Research direction
Start with the InstCombine masked-XOR transformation described in the issue and reproduce the failure using the provided LLVM IR and Alive2 link. Trace how the freeze and repeated operand uses are handled. Done means the optimization no longer makes `%x` observe different undef values than in the source expression, with the reproducer covered by a regression test.
Written by the indexing model from the issue text.
Assessment
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100