[PATCH] D85593: [InstCombine] ~(~X + Y) -> X - Y

Juneyoung Lee via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 10 23:11:38 PDT 2020


aqjune added a comment.

To prove correctness of a transformation of expressions with constants and undefs, following these steps is sufficient:
(1) Replace an undef with a set of all possible values. For example, i8 undef is {0, 1, 2, ..., 255}.
(2) Evaluate each operation by pairwisely picking elements from operands' sets.
(3) If the final result is in a subset relation, the transformation is correct.

  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.

Checking whether the number of uses is increased globally is a quick way to check whether the optimization is incorrect. It has to introduce new uses that was guaranteed not to be undef before.

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.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D85593/new/

https://reviews.llvm.org/D85593



More information about the llvm-commits mailing list