This is an archive of the discontinued LLVM Phabricator instance.

[InstCombine] icmp(X | OrC, C) --> icmp(X, 0)
ClosedPublic

Authored by junaire on Apr 5 2023, 1:52 AM.

Details

Summary

We can eliminate the or operation based on the predicate and the
relation between OrC and C.

sge: X | OrC s>= C --> X s>= 0 iff OrC s>= C s>= 0
sgt: X | OrC s> C --> X s>= 0 iff OrC s> C s>= 0
sle: X | OrC s<= C --> X s< 0 iff OrC s> C s>= 0
slt: X | OrC s< C --> X s< 0 iff OrC s>= C s>= 0

Alive2 links:
sge: https://alive2.llvm.org/ce/z/W-6FHE
sgt: https://alive2.llvm.org/ce/z/TKK2yJ
sle: https://alive2.llvm.org/ce/z/vURQGM
slt: https://alive2.llvm.org/ce/z/JAsVfw

Related issue: https://github.com/llvm/llvm-project/issues/61538

Signed-off-by: Jun Zhang <jun@junz.org>

Diff Detail

Event Timeline

junaire created this revision.Apr 5 2023, 1:52 AM
Herald added a project: Restricted Project. · View Herald TranscriptApr 5 2023, 1:52 AM
junaire requested review of this revision.Apr 5 2023, 1:52 AM
Herald added a project: Restricted Project. · View Herald TranscriptApr 5 2023, 1:52 AM
junaire updated this revision to Diff 511020.Apr 5 2023, 1:56 AM

Dummy update

junaire updated this revision to Diff 511024.Apr 5 2023, 2:18 AM

Simplify

junaire planned changes to this revision.Apr 5 2023, 3:07 AM

WIP

junaire retitled this revision from [InstCombine] Fold icmp(Positive1 * X * Y + Positive2) --> icmp(X * Y) to [InstCombine] Fold icmp(bin(X, Y) + Positive2) --> icmp(bin(X, Y)).Apr 5 2023, 4:26 AM
junaire edited the summary of this revision. (Show Details)
junaire edited the summary of this revision. (Show Details)Apr 5 2023, 4:29 AM
junaire retitled this revision from [InstCombine] Fold icmp(bin(X, Y) + Positive2) --> icmp(bin(X, Y)) to [InstCombine] Fold icmp(bin(X, Y) + Positive) --> icmp(bin(X, Y)).Apr 5 2023, 4:53 AM
junaire updated this revision to Diff 511054.Apr 5 2023, 4:58 AM

LHS s> RHS

junaire updated this revision to Diff 511056.Apr 5 2023, 5:10 AM

Update with vector tests

I think the title should be: 'icmp(bin(X, Y) | Positive)' (seems to be or, not add).

goldstein.w.n added inline comments.Apr 5 2023, 10:12 PM
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
1350

I don't think this matches the alive2 link you have. You only verify for RHS == 0, but here you seem to take any positive value.

Can you update the alive2 link (or the code). Also the alive2 link seems to have spurious nsw flags on the mul. Verifies w.o the nsw flags so nbd.

llvm/test/Transforms/InstCombine/icmp.ll
4827

Remove?

goldstein.w.n added inline comments.Apr 5 2023, 10:12 PM
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
1354

Can this just be return new ICmpInst(Pred, X, ConstantInt::getNullValue(X->getType())?

junaire retitled this revision from [InstCombine] Fold icmp(bin(X, Y) + Positive) --> icmp(bin(X, Y)) to [InstCombine] Fold icmp(bin(X, Y) | LHS, RHS) --> icmp(bin(X, Y)) iff LHS > RHS s>= 0.Apr 6 2023, 12:31 AM
junaire edited the summary of this revision. (Show Details)
junaire updated this revision to Diff 511304.Apr 6 2023, 12:58 AM

Move code to foldICmporConstant

junaire updated this revision to Diff 511309.Apr 6 2023, 1:06 AM

Update tests

goldstein.w.n added inline comments.Apr 7 2023, 10:00 AM
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
1959

I think the BinOp aspect of the transform is meaningless:
https://alive2.llvm.org/ce/z/cbWvv7

Also you're alive2 links still don't match the logic (you are only do C == 0).
You can create the constraints you need with @llvm.assume(i1)
I tried to implement here: https://alive2.llvm.org/ce/z/rmBJXx
but it doesn't verify.

junaire added inline comments.Apr 7 2023, 10:33 AM
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
1959

I agree we should remove the binop match, but the alive2 link you provided is not what the patch trying to transform. It should be https://alive2.llvm.org/ce/z/ybKpxy (in tgt we compare with 0, not RHS)

junaire added inline comments.Apr 7 2023, 10:35 AM
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
1959

Sorry, I think the binop match is necessary?

Hi @goldstein.w.n, please discard all my previous comments (sorry Phab doesn't allow me to delete inline comments :(

So I agree with you with m_BinOp is unnecessary and the transform is correct. Please take a look at https://alive2.llvm.org/ce/z/97gSUu
In fact, I guess we can add more generalized patterns based on the relation between LHS and RHS?

goldstein.w.n added inline comments.Apr 7 2023, 10:46 AM
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
1959

That wouldn't make sense, the binop includes things like or %x, 0 which is just %x.

It verifies for:
sge: https://alive2.llvm.org/ce/z/w35F7q
but not for
sle: https://alive2.llvm.org/ce/z/2ocRSw

Hi @goldstein.w.n, please discard all my previous comments (sorry Phab doesn't allow me to delete inline comments :(

So I agree with you with m_BinOp is unnecessary and the transform is correct. Please take a look at https://alive2.llvm.org/ce/z/97gSUu
In fact, I guess we can add more generalized patterns based on the relation between LHS and RHS?

Ah, so sle -> slt. I missed that.

Since this is a bit complicated can you do two things.

  1. make alive2 links for all cases (sgt, slt, sge, sle)
  2. Comment in the code the exact transformations that are taking place (in the switch would make sense).
junaire updated this revision to Diff 511838.Apr 7 2023, 7:49 PM

Add some comments

junaire retitled this revision from [InstCombine] Fold icmp(bin(X, Y) | LHS, RHS) --> icmp(bin(X, Y)) iff LHS > RHS s>= 0 to [InstCombine] icmp(X | LHS, RHS) --> icmp(X, 0) iff LHS > RHS s>= 0.Apr 7 2023, 7:50 PM
junaire edited the summary of this revision. (Show Details)
junaire updated this revision to Diff 511840.Apr 7 2023, 7:54 PM

Fix tiny nit

goldstein.w.n added inline comments.Apr 7 2023, 9:15 PM
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
1961

' X | RHS s<= C --> X s< C'
->
'
X | RHS s<= C --> X s< 0'

junaire updated this revision to Diff 511842.Apr 7 2023, 9:24 PM

Fix comments

junaire updated this revision to Diff 511951.Apr 8 2023, 8:06 PM

Add more tests

junaire updated this revision to Diff 511953.Apr 8 2023, 8:08 PM

I screw it up with arc, again :(

junaire retitled this revision from [InstCombine] icmp(X | LHS, RHS) --> icmp(X, 0) iff LHS > RHS s>= 0 to [InstCombine] icmp(X | LHS, RHS) --> icmp(X, 0).Apr 8 2023, 8:09 PM
junaire edited the summary of this revision. (Show Details)
goldstein.w.n added inline comments.Apr 9 2023, 3:34 PM
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
1959

nit: Can you make it:

if (C.isNonNegative() && match(Or, m_c_Or(m_Value(X), m_APInt(LHS))))

Otherwise LGTM.

LGTM.

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

nit: Your comments below use RHS but the variable is LHS. Can one of those be changed for consistencies sake?

1959

nit: Can you make it:

if (C.isNonNegative() && match(Or, m_c_Or(m_Value(X), m_APInt(LHS))))

Otherwise LGTM.

A few other nits as well.

1984

The sge/slt and the sgt/sle cases are indentical. Can you merge them i.e:

// X | RHS s<= C --> X s< 0 iff LHS s> C s>= 0
case ICmpInst::ICMP_SLE:
// X | RHS s> C --> X s>= 0 iff LHS s> C s>= 0
case ICmpInst::ICMP_SGT:
  if (LHS->sgt(C))
    return new ICmpInst(Pred, X,
                        ConstantInt::getNullValue(X->getType()));
  break;
// X | RHS s< C --> X s< 0 iff LHS s>= C s>= 0
case ICmpInst::ICMP_SLT:
// X | RHS s>= C --> X s>= 0 iff LHS s>= C s>= 0
case ICmpInst::ICMP_SGE:
  if (LHS->sge(C))
    return new ICmpInst(Pred, X,
                        ConstantInt::getNullValue(X->getType()));
  break;

Can you only use LHS and C in comments/code/summary. You use RHS to both reference LHS and C variable.

junaire updated this revision to Diff 512097.Apr 10 2023, 1:50 AM

Address comments, thx.

junaire updated this revision to Diff 512099.Apr 10 2023, 1:58 AM

use ICmpInst::getFlippedStrictnessPredicate

junaire retitled this revision from [InstCombine] icmp(X | LHS, RHS) --> icmp(X, 0) to [InstCombine] icmp(X | LHS, C) --> icmp(X, 0).Apr 10 2023, 2:03 AM
junaire edited the summary of this revision. (Show Details)
goldstein.w.n added inline comments.Apr 10 2023, 1:06 PM
llvm/test/Transforms/InstCombine/icmp.ll
4631–4632

Can you add negative tests where 1) C is negative. and 2) where C >= LHS.

junaire marked an inline comment as done.Apr 11 2023, 5:06 AM
junaire added inline comments.
llvm/test/Transforms/InstCombine/icmp.ll
4631–4632

Hi, I've added negative tests in D147597, do you have more comments? :)

junaire marked an inline comment as done.Apr 11 2023, 5:07 AM
junaire added inline comments.
llvm/test/Transforms/InstCombine/icmp.ll
4631–4632

Oops, I mean D147596

goldstein.w.n accepted this revision.Apr 11 2023, 10:52 AM

LGTM.

I'm not a maintainer so please wait a day or so before pushing
to give others a chance to look this over.

This revision is now accepted and ready to land.Apr 11 2023, 10:52 AM

Maybe we need two more tests here:

  1. Not one-use test .
  2. Vector test with poison constant.
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
1958

Do we really need c_or here? APInt should be always second operator.

nikic added inline comments.Apr 12 2023, 12:19 AM
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
1957

Why is a constant that occurs on the RHS called LHS?

llvm/test/Transforms/InstCombine/icmp.ll
4631–4632

What's the purpose of the mul instruction in all these tests? It doesn't seem related?

junaire added inline comments.Apr 12 2023, 1:52 AM
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
1957

Naming is hard. C here should really be the RHS but in foldICmpOrConstant it's called C so it's kinda confusing. Maybe rename it to RHS?

1958

Thanks, I'm uncertain if it's already been canonicalized when I first wrote this, will drop it.

llvm/test/Transforms/InstCombine/icmp.ll
4631–4632

Sorry, the patch has changed several times so I forgot to update the tests.

junaire updated this revision to Diff 512705.Apr 12 2023, 2:19 AM

Add m_OneUse & m_c_Or -> m_Or

junaire marked 11 inline comments as done.Apr 12 2023, 2:23 AM
junaire marked an inline comment as done.
junaire added inline comments.
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
1957

I'm still unsure about what should I call it, can you suggest one?

nikic added inline comments.Apr 12 2023, 2:28 AM
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
1957

C2, OrC, MaskC would all work.

nikic added inline comments.Apr 12 2023, 2:38 AM
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
1958

I don't think this one-use check is necessary, as we're only creating one insturction. I believe @bcl5980's point was just to add a multi-use test, not that it needs to be restricted to one-use.

junaire updated this revision to Diff 512725.Apr 12 2023, 2:39 AM

Address @nikic's comments, thx.

junaire retitled this revision from [InstCombine] icmp(X | LHS, C) --> icmp(X, 0) to [InstCombine] icmp(X | OrC, C) --> icmp(X, 0).Apr 12 2023, 2:41 AM
junaire edited the summary of this revision. (Show Details)
junaire updated this revision to Diff 512728.Apr 12 2023, 2:43 AM

Remove oneuse check

junaire marked 3 inline comments as done.Apr 12 2023, 2:44 AM

Do you have more comments to address? or can I land it? @nikic

bcl5980 added inline comments.Apr 12 2023, 9:45 PM
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
1958

Yeah, what I mean is only add a test for multi-use case. We needn't restrict one-use here.

nikic accepted this revision.Apr 13 2023, 12:27 AM
nikic added inline comments.
llvm/test/Transforms/InstCombine/icmp.ll
4955–4956

Not a negative test.

This revision was automatically updated to reflect the committed changes.

Thanks everyone!