[all-commits] [llvm/llvm-project] 060de4: Reapply [InstCombine] Simplify and/or of icmp eq w...

Nikita Popov via All-commits all-commits at lists.llvm.org
Fri Nov 3 02:16:33 PDT 2023


  Branch: refs/heads/main
  Home:   https://github.com/llvm/llvm-project
  Commit: 060de415af335fdd82910f409e2be3b8457eaa43
      https://github.com/llvm/llvm-project/commit/060de415af335fdd82910f409e2be3b8457eaa43
  Author: Nikita Popov <npopov at redhat.com>
  Date:   2023-11-03 (Fri, 03 Nov 2023)

  Changed paths:
    M llvm/lib/Analysis/InstructionSimplify.cpp
    M llvm/test/CodeGen/PowerPC/pr45448.ll
    M llvm/test/Transforms/InstCombine/div-by-0-guard-before-smul_ov.ll
    M llvm/test/Transforms/InstCombine/div-by-0-guard-before-umul_ov.ll
    M llvm/test/Transforms/InstCombine/ispow2.ll
    M llvm/test/Transforms/InstSimplify/and-or-icmp-ctpop.ll
    M llvm/test/Transforms/InstSimplify/and-or-icmp-min-max.ll
    M llvm/test/Transforms/InstSimplify/and-or-implied-cond.ll
    M llvm/test/Transforms/InstSimplify/div-by-0-guard-before-smul_ov-not.ll
    M llvm/test/Transforms/InstSimplify/div-by-0-guard-before-smul_ov.ll
    M llvm/test/Transforms/InstSimplify/div-by-0-guard-before-umul_ov-not.ll
    M llvm/test/Transforms/InstSimplify/div-by-0-guard-before-umul_ov.ll
    M llvm/test/Transforms/InstSimplify/result-of-add-of-negative-is-non-zero-and-no-underflow.ll
    M llvm/test/Transforms/PGOProfile/chr.ll

  Log Message:
  -----------
  Reapply [InstCombine] Simplify and/or of icmp eq with op replacement (#70335)

Relative to the first attempt, this contains two changes:

First, we only handle the case where one side simplifies to true or
false, instead of calling simplification recursively. The previous
approach would return poison if one operand simplified to poison
(under the equality assumption), which is incorrect.

Second, we do not fold llvm.is.constant in simplifyWithOpReplaced().
We may be assuming that a value is constant, if the equality holds,
but it may not actually be constant. This is nominally just a QoI
issue, but the std::list implementation in libstdc++ relies on the
precise behavior in a way that causes miscompiles.

-----

and/or in logical (select) form benefit from generic simplifications via
simplifyWithOpReplaced(). However, the corresponding fold for plain
and/or currently does not exist.

Similar to selects, there are two general cases for this fold
(illustrated with `and`, but there are `or` conjugates).

The basic case is something like `(a == b) & c`, where the replacement
of a with b or b with a inside c allows it to fold to true or false.
Then the whole operation will fold to either false or `a == b`.

The second case is something like `(a != b) & c`, where the replacement
inside c allows it to fold to false. In that case, the operand can be
replaced with c, because in the case where a == b (and thus the icmp is
false), c itself will already be false.

As the test diffs show, this catches quite a lot of patterns in existing
test coverage. This also obsoletes quite a few existing special-case
and/or of icmp folds we have (e.g. simplifyAndOrOfICmpsWithLimitConst),
but I haven't removed anything as part of this patch in the interest of
risk mitigation.

Fixes #69050.
Fixes #69091.




More information about the All-commits mailing list