This is an archive of the discontinued LLVM Phabricator instance.

[InstCombine] Transform (A > 0) | (A < 0) -> zext (A != 0) fold
ClosedPublic

Authored by XChy on Jun 29 2023, 11:13 AM.

Details

Summary

[InstCombine] Transform (A > 0) | (A < 0) -> zext (A != 0) fold

This extends foldCastedBitwiseLogic to handle the similar cases.

Actually, for (A > B) | (A < B), when B != 0, it can be optimized to zext( A != B ) by foldAndOrOfICmpsUsingRanges.
However, when B = 0, transformZExtICmp will transform zext(A < 0) to i32 into A >> 31,
which cannot be optimized by foldAndOrOfICmpsUsingRanges.

Because I'm new to LLVM and has no concise knowledge about how LLVM decides the order of optimization,
I choose to extend foldCastedBitwiseLogic to fold ( A >> (X - 1) ) | ((A > 0) zext to iX) -> (A != 0) zext to iX.

And the equivalent fold follows:

A >> (X - 1) ) | ((A > 0) zext to iX
 -> A < 0 | A > 0
 -> (A != 0) zext to iX

It's proved by alive-tv

Related issue:
(a > b) | (a < b) is not simplified only for the case b=0

Diff Detail

Event Timeline

XChy created this revision.Jun 29 2023, 11:13 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 29 2023, 11:13 AM
XChy requested review of this revision.Jun 29 2023, 11:13 AM
goldstein.w.n added a subscriber: goldstein.w.n.EditedJun 29 2023, 11:40 AM

Thank you for the patch and welcome!

We actually seem to handle this as long as its (zext (or slt, sgt)): https://alive2.llvm.org/ce/z/Fpyw7G
Its only if we have (or (zext slt), (zext sgt)) that we fail.

I think the best approach we actually be to fold:(bitwise_logic (zext A), (zext B)) -> (zext (bitwise_logic A, B)). That will cover this case any may help other cases.

Edit: Ah I see, we already do that (https://alive2.llvm.org/ce/z/nXUetC), we just mess up the pattern here.

Thank you for the patch and welcome!

We actually seem to handle this as long as its (zext (or slt, sgt)): https://alive2.llvm.org/ce/z/Fpyw7G
Its only if we have (or (zext slt), (zext sgt)) that we fail.

I think the best approach we actually be to fold:(bitwise_logic (zext A), (zext B)) -> (zext (bitwise_logic A, B)). That will cover this case any may help other cases.

Edit: Ah I see, we already do that (https://alive2.llvm.org/ce/z/nXUetC), we just mess up the pattern here.

It might also be easier to just update the fold for (or slt, sgt) to look through zext.

llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
1720

Style pred -> Pred.

1722

m_ConstantInt(B) -> m_APInt(B) (and make B a const APInt *).

1723

m_SpecificInt(0) -> m_Zero().

1725

Instead of duplicating the matching logic for both orders, can you create a lambda that tries the match on maybe Lhs and Rhs then just call it with (Op0, Op1) and (Op1, Op0).
Another approach is to match match(&I, m_c_ICmp(<your logic for one of the cases here>)). (note the m_c prefix means commutative i.e try swapping the arg positions).

1726

A->getType()->getScalarBitWidth

1728

A->getType()->isIntegerTy() is unneeded, this is ICmp (IntegerCmp)... I think.

1729

Style cmp variable should be Cmp.

1731

Builder.getInt(APInt::getZero(A->getType()->getIntegerBitWidth())) -> Constant::getNullValue(A->getType())

llvm/test/Transforms/InstCombine/and-or-icmps.ll
2595

Can you add:

  1. A vector test.
  2. A few negative tests (maybe ashr instead of lshr, slt instead of sgt, incorrect shift amt).
XChy updated this revision to Diff 536183.EditedJun 30 2023, 5:02 AM

Thanks for your review and advice!
I have updated my patch and added support for vector.
I would appreciate it if you could review it and offer some advice.

XChy updated this revision to Diff 536190.Jun 30 2023, 5:15 AM
XChy marked 9 inline comments as done.

[Format the code to pass the patch test]

XChy updated this revision to Diff 536192.Jun 30 2023, 5:23 AM
This comment was removed by XChy.
XChy updated this revision to Diff 536208.Jun 30 2023, 6:25 AM
XChy updated this revision to Diff 536215.Jun 30 2023, 6:45 AM
XChy set the repository for this revision to rG LLVM Github Monorepo.
XChy updated this revision to Diff 536233.Jun 30 2023, 7:18 AM

[Rebase commits to pass the patch test]

XChy updated this revision to Diff 536252.Jun 30 2023, 7:52 AM
XChy set the repository for this revision to rG LLVM Github Monorepo.
goldstein.w.n added inline comments.Jun 30 2023, 8:44 AM
llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
1724

Since you only use the constant as a splat just match B as an m_APInt(B). And make B a const APInt *.

1737

The Pred == ICmpInst::ICMP_SGT should probably be at the top when you check that logicop is Or.

XChy updated this revision to Diff 536292.Jun 30 2023, 9:36 AM
XChy marked an inline comment as done.
goldstein.w.n added inline comments.Jun 30 2023, 9:56 AM
llvm/test/Transforms/InstCombine/and-or-icmps.ll
2684

Can you split the tests to a seperate patch?

Basically
Commit 1: Tests
Commit 2: Impl (Update tests so we can see the changes the impl causes)

Then you set the relationship between the patches using the "Edit Related Revisions" Options on Phabricator.

XChy updated this revision to Diff 536476.Jun 30 2023, 4:25 PM
XChy set the repository for this revision to rG LLVM Github Monorepo.
XChy marked an inline comment as done.
XChy added inline comments.
llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
1724

Good advice, you remind me of m_APInt can match splated vector.

1737

Thanks for advice, but maybe Pred's value is decided by MatchOrZextIcmp function, so Pred == xxx must be after MatchOrZextIcmp.

llvm/test/Transforms/InstCombine/and-or-icmps.ll
2684

OK, thanks for instruction, I will get them done next morning.

Other than a few nits, looks basically good.

llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
1723

nit: ZextIcmp -> ZExtICmp.

llvm/test/Transforms/InstCombine/and-or-icmps.ll
2641–2642

nit, can you replace <test>_neg<N> -> <test>_fail<N> (neg can also be 0-X).

2678–2679

you already test incorrect shift amount, maybe keep this one with correct shift amount but change the icmp to sgt X, 1 (or any non-zero).

XChy updated this revision to Diff 536511.Jun 30 2023, 9:24 PM
XChy marked an inline comment as done.
XChy updated this revision to Diff 536512.Jun 30 2023, 9:26 PM
XChy marked 2 inline comments as done.
XChy set the repository for this revision to rG LLVM Github Monorepo.
nikic added inline comments.Jul 1 2023, 12:30 AM
llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
1733

You can include this check directly in the match above using m_SpecificInt(X - 1).

XChy added inline comments.Jul 1 2023, 5:22 AM
llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
1733

The type of A is determined during the match, but X = A->getType()->getScalarSizeInBits() must be passed to the m_SpecificInt before matching. Actually, X keep zero before the match.

Or do you mean something like:

auto MatchOrZExtICmp = [&](Value *Op0, Value *Op1) -> bool {
    const Value *X;
    return match(Op0, m_LShr(m_Value(A), m_Value(X))) &&
           match(X, m_SpecificInt(A->getType()->getScalarSizeInBits() - 1)) &&
           match(Op1, m_ZExt(m_ICmp(Pred, m_Specific(A), m_Zero())));
  };

I'm not sure how to solve this problem. Could you help me with it?

goldstein.w.n added inline comments.Jul 1 2023, 9:23 AM
llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
1733

A has the same type as Op0 and Op1

XChy updated this revision to Diff 536562.Jul 1 2023, 6:59 PM
XChy marked 2 inline comments as done.
goldstein.w.n accepted this revision.Jul 2 2023, 11:53 AM

LGTM.

Do you have commit access?
If not can you give me your email/name so I can commit for you.

This revision is now accepted and ready to land.Jul 2 2023, 11:53 AM
XChy marked an inline comment as done.Jul 2 2023, 6:56 PM

LGTM.

Do you have commit access?
If not can you give me your email/name so I can commit for you.

No, I have not commit access.
I would appreciate it if you could commit it.
My email is xxs_chy@outlook.com.
My name is XChy.

XChy marked an inline comment as done.Jul 5 2023, 9:52 PM
This revision was landed with ongoing or failed builds.Jul 6 2023, 12:03 AM
This revision was automatically updated to reflect the committed changes.
XChy edited the summary of this revision. (Show Details)Jul 9 2023, 5:29 PM