[llvm-dev] failing to optimize boolean ops on cmps

Sanjay Patel via llvm-dev llvm-dev at lists.llvm.org
Thu Jul 13 14:12:21 PDT 2017


We have several optimizations in InstCombine for bitwise logic ops
(and/or/xor) that fail to handle compare patterns with the equivalent
bitwise logic. Example:

define i8 @or_and_not(i8 %a, i8 %b) {
  %nota = xor i8 %a, -1
  %and = and i8 %nota, %b
  %res = or i8 %and, %a
  ret i8 %res
}

define i1 @or_and_cmp_not(i32 %a, i32 %b, i1 %c) {
  %cmp = icmp sgt i32 %a, %b
  %cmp_inv = icmp sle i32 %a, %b ; this is 'not' of %cmp
  %and = and i1 %c, %cmp_inv
  %res = or i1 %cmp, %and
  ret i1 %res
}

$ ./opt -instcombine hidden_not.ll -S

define i8 @or_and_not(i8 %a, i8 %b) {
  %res = or i8 %b, %a
  ret i8 %res
}

define i1 @or_and_cmp_not(i32 %a, i32 %b, i1 %c) {
  %cmp = icmp sgt i32 %a, %b
  %cmp_inv = icmp sle i32 %a, %b
  %and = and i1 %cmp_inv, %c
  %res = or i1 %cmp, %and
  ret i1 %res
}

---------------------------------------------------------------------

Would adding to the existing InstCombine logic folds to handle this kind of
pattern be a welcome enhancement? I don't know if it's possible to make the
matchers handle this case without adding a new matcher. Eg:

  // ((~A & B) | A) -> (A | B)
  if (match(Op0, m_c_And(m_Not(m_Specific(Op1)), m_Value(A))))
    return BinaryOperator::CreateOr(A, Op1);

Is there a way to make "m_Not(m_Specific())" match an inverted compare?

This optimization hole can manifest in strange ways:
https://godbolt.org/g/gjpAVo

We got it right for C++, but C managed to fall through the cracks!
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20170713/d96f9cef/attachment.html>


More information about the llvm-dev mailing list