This is an archive of the discontinued LLVM Phabricator instance.

[InstCombine] Generalise ((x1 ^ y1) | (x2 ^ y2)) == 0 transform
ClosedPublic

Authored by kitaisreal on Jul 2 2023, 10:10 AM.

Details

Summary

Generalise ((x1 ^ y1) | (x2 ^ y2)) == 0 transform to more than two pairs of variables https://github.com/llvm/llvm-project/issues/57831.
Depends D154384.

Diff Detail

Event Timeline

kitaisreal created this revision.Jul 2 2023, 10:10 AM
kitaisreal requested review of this revision.Jul 2 2023, 10:10 AM
goldstein.w.n added inline comments.
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
2110

Shouldn't we also be able to chase OrOp1 (if it doesn't match Xor).

Figure it should be something along the lines of:

if(match(Op0, Xor) && match(Op1, Xor)) {
 // Base Case
}
else if(match(Op0, Xor)) {
 // Chase Op1
}
else if(match(Op1, Xor)) {
 // Chase Op1
}
else {
 break;
}
2110

Err third condition should be "Chase Op0"

kitaisreal marked 2 inline comments as done.Jul 2 2023, 11:36 AM
kitaisreal added inline comments.
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
2110

Agree. Updated.

goldstein.w.n added inline comments.Jul 2 2023, 12:12 PM
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
2093

AFAICT this condition never comes into play. You check the loop condition before reseting OrOperator every time. I'd say either make this a while(1) or make this BO && B0->getOpcode() == Instruction::Or

2116

There could we a case where we have:

(or (or (xor A, B), (xor C, D)), (or (xor E, F), (xor G, H))).
Not sure if it worth handling this case, but maybe switch this to a worklist algo so you can arbitrarily add Or ops.

goldstein.w.n added inline comments.Jul 2 2023, 12:13 PM
llvm/test/Transforms/InstCombine/icmp-or.ll
415

Can you 1) split the tests to a seperate patch (so we can see the diff this patch generates).

  1. Can you add a few negative tests (maybe where cmp is not against 0, one of the xors has multiuse, where its or->or (invalid), etc...).
goldstein.w.n added inline comments.Jul 2 2023, 12:14 PM
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
2088

Maybe add as a todo, but this also works for sub (or implement in a follow up patch!)

kitaisreal updated this revision to Diff 537767.Jul 6 2023, 9:22 AM

Make implementation more general. Updated tests.

kitaisreal marked an inline comment as done.Jul 6 2023, 9:23 AM
kitaisreal added inline comments.
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
2088

I can implement this in follow up patch.

2116

Updated implementation to support such case.

goldstein.w.n added inline comments.Jul 6 2023, 11:15 AM
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
2088

Thanks :)
Can you add TODO for it in the meantime.

2102

Prefer not name these Or* as you expect to match them for Xor. Can you just make these Lhs/Rhs.

2111

The match(Op, Xor) { emplace(XorOps) } else { WorkList.Add(Op) } could be a lambda for LHS/RHS.

2118

At first I thought this should be !CmpValues.empty() so you can match something like:

(or (or (xor A, B), (xor C, D)), (and E, F)) but realize we will visit the inner or and handle it there. Can you add a comment here (or above where you set Match to false) that such a case will inherently be handled so its okay to fail on any non-or/xor.

llvm/test/Transforms/InstCombine/icmp-or.ll
415

This is still outstanding.

nikic added inline comments.Jul 6 2023, 11:51 AM
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
2091

Unnecessary llvm:: prefix here and elsewhere.

2095

Why does this one need to be handled separately?

2102

These are the Lhs/Rhs of an Or though. Lhs/Rhs of the Xor are matched below.

Not sure why this isn't doing match(CurrentValue, m_Or(m_Value(OrLhs), m_Value(OrRhs)) though.

kitaisreal updated this revision to Diff 538059.Jul 7 2023, 3:31 AM
kitaisreal marked an inline comment as done.

Updated implementation

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
2088

Added TODO.

2091

Updated.

2095

To properly support lifetime of allocated operators we must allocate them using Builder, and Builder methods return Value *.
But this function expects to return BinaryOperator * instead of Value *, so last one handled separately.

2102

Updated implementation to use match.

2111

Updated.

2118

It seems that more easier approach is to clear CmpValues if we fail to match.

llvm/test/Transforms/InstCombine/icmp-or.ll
415

I moved tests into separate patch https://reviews.llvm.org/D154384. Should we merge it first so we can see the difference after this patch is applied ?

kitaisreal edited the summary of this revision. (Show Details)
kitaisreal retitled this revision from [InstCombine] Generalise ((x1 ^ y1) | (x2 ^ y2)) == 0 transform to more than two pairs of variables to [InstCombine] Generalise ((x1 ^ y1) | (x2 ^ y2)) == 0 transform.

Updated tests.

General note, can you actually mark "done" the comments you have addressed rather than just replying to them?

goldstein.w.n added inline comments.Jul 12 2023, 3:14 PM
llvm/test/Transforms/InstCombine/icmp-or.ll
415

Do the following.

Rebase this patch ontop of the test change (so instead of this patch adding a bunch of tests, we should see diffs generated).

Then use the "Edit Related Revisions" option on phabricator and set this commit as the child of the test commit.

Added changes on top of the tests.

kitaisreal marked 3 inline comments as done.Jul 13 2023, 2:54 AM
This revision is now accepted and ready to land.Jul 13 2023, 5:11 PM
goldstein.w.n added inline comments.Jul 13 2023, 5:12 PM
llvm/test/Transforms/InstCombine/icmp-or.ll
488–489

Can you postfix all the negative tests with '_fail'?

nikic added inline comments.Jul 14 2023, 12:26 AM
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
2095

You can do something like return replaceInstUsesWith(Or, LhsCmp) to convert the Value into Instruction for the return value.

2111

As this is now a pretty complex fold, I'd suggest moving it into a separate function. That would allow you to use early return nullptr here.

kitaisreal marked 3 inline comments as done.

Updated implementation.

nikic accepted this revision.Jul 14 2023, 3:28 AM

LG

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
1980

nit: Omit braces for single-line if.

kitaisreal marked an inline comment as done.Jul 14 2023, 6:54 AM

I do not have commit access. Can you please land this one for me Maksim Kita <kitaetoya@gmail.com> ?

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
1980

I plan to continue this optimization for 'sub' in my next patch, so I will fix nitpick in next patch.

kitaisreal marked an inline comment as done.Jul 14 2023, 6:55 AM

I do not have commit access. Can you please land this one for me Maksim Kita <kitaetoya@gmail.com> ?

Will do later today.