New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Instcombine does not work after 'and'/'or' were replaced with 'select' #51419
Comments
I'm not sure if this is the entire problem, but we don't have a poison-safe DeMorgan fold for 'not' with 'not' op: https://alive2.llvm.org/ce/z/RXpR3M ; ~(~x | y) --> x & ~y define i1 @tgt(i1 %x, i1 %y) { |
Can you see if there are still problems after this patch: |
The patch changes the block, but does not optimize it. After you patch I got: lor.lhs.false: ; preds = %for.body6 |
Thanks. So at least one more missing bool logic fold: ; (x || y) && (x || !y) --> x https://alive2.llvm.org/ce/z/XZ5_2a This one should be in instsimplify... |
I just discovered (but haven't read it all yet): cc'ing Juneyoung. I am assuming we just want to add some more logic folds for 'select' to get the same optimizations as with 'and'/'or'/'xor', but let me know if you see a more general solution. |
Adding this pattern seems like the easiest and fastest solution to me. Another solution that I can think of is to attach noundef to everywhere, but it will certainly take some time. |
Ok - I'll work on it. Interestingly, we also don't have the corresponding bitwise logic fold in -instsimplify: define i1 @bitwise_logic(i1 %x, i1 %y) { This is only caught inside -instcombine via SimplifyUsingDistributiveLaws(). |
Added the bitwise logic fold: Then needed to add some infrastructure: And then the select fold: So the IR in the attached file now becomes: !(x & y) || z Is there still more that we can do? |
Nope, the resulting expression ('!(x & y) || z') is obviously the simplest form. I could reproduce the output using the latest LLVM as well. |
Resolving - if we are still missing logical and/or (select) folds, please file bugs. Thanks! |
It is resolved! Thank you. |
Extended Description
The code bellow is being optimized by instcombine if we put and/or instead of 'select':
lor.lhs.false: ; preds = %for.body6
%or.cond87.not = xor i1 %or.cond, true
;%or.cond88 = or i1 %or.cond87.not, %cmp16
%or.cond88 = select i1 %or.cond87.not, i1 true, i1 %cmp16
%or.cond88.not = xor i1 %or.cond88, true
;%or.cond89 = and i1 %or.cond88.not, %cmp28
%or.cond89 = select i1 %or.cond88.not, i1 %cmp28, i1 false
%or.cond89.not = xor i1 %or.cond89, true
;%or.cond92 = or i1 %or.cond88, %cmp28
%or.cond92 = select i1 %or.cond88, i1 true, i1 %cmp28
;%or.cond93 = and i1 %or.cond89.not, %or.cond92
%or.cond93 = select i1 %or.cond89.not, i1 %or.cond92, i1 false
There are also some changes were done in visitSelectInst()
if (match(TrueVal, m_One()) && impliesPoison(FalseVal, CondVal)) {
// Change: A = select B, true, C --> A = or B, C
return BinaryOperator::CreateOr(CondVal, FalseVal);
}
IsSafeToConvert() was replaced with impliesPoison()
The text was updated successfully, but these errors were encountered: