Proof:
https://alive2.llvm.org/ce/z/4xharr
Solves PR47051
Differential D85593
[InstCombine] ~(~X + Y) -> X - Y xbolva00 on Aug 8 2020, 5:12 PM. Authored by
Details
Proof: Solves PR47051
Diff Detail Event Timeline
Comment Actions Please pre-commit the test file and upload diff with context.
Comment Actions I agree that this looks wrong for the example with undef substituted in...but that also means that almost every instcombine that doesn't specify hasOneUse() is wrong! Comment Actions @spatel The category of "undef-unsafe" transforms is relatively narrow; it's specifically transforms that use identities that don't work with possibly-undef inputs. For example, transforming x*2 -> x+x isn't legal because the bottom bit goes from zero to possibly-undef. Some people have referred to it as "increasing the number of uses", but really it's "using algebraic rules that don't work with undef". It doesn't have anything to do with the total number of uses of the value. Comment Actions To prove correctness of a transformation of expressions with constants and undefs, following these steps is sufficient: define i8 @src() { %a = add i8 255, undef // %a = {0, ... ,255} %nota = xor i8 %a, 255 // %nota = {0, ..., 255} call void @use(i8 %a) // use({0, ..., 255}) ret i8 %nota // return {0, ..., 255} } => define i8 @tgt(i8 %y) { %a = add i8 255, undef %s = sub i8 0, undef call void @use(i8 %a) // use({0, ..., 255}) ret i8 %s // return {0, ..., 255} } Since the sets given to @use() as well as ret are equal between the source and target, this transformation is correct. An example that converts mul x, 2 to add x, x: // Let's assume that x = undef = {0, ..., 255} y = mul x, 2 // y = {0, 2, 4, ..., 254} => y = add x, x // y = {0, 0+1, 1+0, 0+2, 1+1, ..., 255} = {0, ..., 255} Since the target's y contains {1, 3, 5, ...}, which did not appear at the source, this transformation is incorrect. Similarly, a transformation that converts x * (a + b) --> x * a + x * b is incorrect if x was undef. The statement 'each use of undef can see different values' is a simpler version of this. It is still effective however - bringing sets all the time isn't practical for reasoning, really (it should be very painful). +--- (my previous statements before editing) ---+
Comment Actions @aqjune Thank you! So my mistake here is that it's not valid to use "let undef = xxx" type reasoning to construct counter examples, one has to always consider a superposition of all possible values for undef at the same time. This LGTM :) |
Please can you add an additional vector test with at least one undef element in the -1 constant