Sanjay Patel via llvm-dev
2017-Jul-13 21:12 UTC
[llvm-dev] failing to optimize boolean ops on cmps
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>
Daniel Berlin via llvm-dev
2017-Jul-13 23:10 UTC
[llvm-dev] failing to optimize boolean ops on cmps
On Thu, Jul 13, 2017 at 2:12 PM, Sanjay Patel <spatel at rotateright.com> wrote:> 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: > >I would rather see this added to instsimplify than instcombine. If you do that, GVN/et all will get this already. This probably does require a special matcher though: We have: if (m_c_And(m_Cmp(Pred, m_Value(), m_Value()), m_Cmp(Pred, m_Value(), m_Value())) and you really want: if (m_c_And(m_Cmp(Pred, m_Value(), m_Value()), m_Cmp(m_Opposite(Pred), m_Value(), m_Value())) -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20170713/c715aa5d/attachment.html>
Sanjay Patel via llvm-dev
2017-Jul-13 23:37 UTC
[llvm-dev] failing to optimize boolean ops on cmps
This can't be an instsimplify though? The values we want in these cases do not exist already: %res = or i8 %b, %a %res = or i1 %cmp, %c On Thu, Jul 13, 2017 at 5:10 PM, Daniel Berlin <dberlin at dberlin.org> wrote:> > > On Thu, Jul 13, 2017 at 2:12 PM, Sanjay Patel <spatel at rotateright.com> > wrote: > >> 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: >> >> > I would rather see this added to instsimplify than instcombine. > If you do that, GVN/et all will get this already. > > This probably does require a special matcher though: > > > We have: > if (m_c_And(m_Cmp(Pred, m_Value(), m_Value()), > m_Cmp(Pred, m_Value(), m_Value())) > > and you really want: > if (m_c_And(m_Cmp(Pred, m_Value(), m_Value()), > m_Cmp(m_Opposite(Pred), m_Value(), m_Value())) > > > >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20170713/6108341b/attachment.html>