This is an archive of the discontinued LLVM Phabricator instance.

[InstCombine] Fold (A/-B)==(A/B) to (A/B)==0
Needs ReviewPublic

Authored by marcauberer on Aug 30 2023, 7:09 AM.

Details

Summary

Fixes #62382: https://github.com/llvm/llvm-project/issues/62382

This optimization applies under the precondition, that B is not equal to the minimum
value for the bitwidth of B, e.g. -128 for i8.

Alive2: https://alive2.llvm.org/ce/z/WIiHur
Baseline tests: https://reviews.llvm.org/D159204

Diff Detail

Event Timeline

marcauberer created this revision.Aug 30 2023, 7:09 AM
Herald added a project: Restricted Project. · View Herald TranscriptAug 30 2023, 7:09 AM
marcauberer requested review of this revision.Aug 30 2023, 7:09 AM
Herald added a project: Restricted Project. · View Herald TranscriptAug 30 2023, 7:09 AM
goldstein.w.n added inline comments.
llvm/lib/Analysis/ValueTracking.cpp
3153 ↗(On Diff #554717)

This at the very least should be a seperate patch and should probably fit into:
IsCondKnownTrue not be its own API.

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

This comment should include 'if B != INT_MIN'.

5234

Err B != INT_MAX or A != INT_MIN (if you update to also fallback to A check.

5240

m_Deferred -> m_Specific. You aren't rematching A/B in the same match statement.

5241

Can you split the isKnownNonEqual to a new patch and use either IsCondKnownTrue here or probably more direct in this case just use computeKnownBits.

5242

You can strengthen this as it also works if A != INT_MAX: https://alive2.llvm.org/ce/z/MFAjAs so if check for B fails you can tryout A.

marcauberer marked 3 inline comments as done.

Apply review feedback

marcauberer marked an inline comment as done.Aug 30 2023, 12:48 PM
marcauberer added inline comments.
llvm/lib/Analysis/ValueTracking.cpp
3153 ↗(On Diff #554717)

I cannot find IsCondKnownTrue. Where can I find it?

goldstein.w.n added inline comments.Aug 30 2023, 12:59 PM
llvm/lib/Analysis/ValueTracking.cpp
3153 ↗(On Diff #554717)

Crap I pasted the wrong thing. Mean: simplifyICmpInst

marcauberer added inline comments.Aug 30 2023, 2:41 PM
llvm/lib/Analysis/ValueTracking.cpp
3153 ↗(On Diff #554717)

I think I don't quite understand ... This newly added function is essentially the same as computeKnownBitsFromAssume or isKnownNonZeroFromAssume just for isKnownNonEqual. Why should this fit into simplifyICmpInst. Isn't this relevant overall for ValueTracking?
I agree regarding the split into a new patch.

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

How would I do that with computeKnownBits?

The following code does not seem to work, probably due to the fact that the assumption is not made for value A or B, but rather the icmp ne of A/B with MIN_INT:

// Check if A is known to be != INT_MIN
KnownBits KnownA = computeKnownBits(A, 0, &I);
if (KnownA.isConstant() && KnownA.getConstant() == MinInt)
  return new ICmpInst(Pred, Op1, Constant::getNullValue(A->getType()));
goldstein.w.n added inline comments.Sep 1 2023, 1:47 PM
llvm/lib/Analysis/ValueTracking.cpp
3153 ↗(On Diff #554717)

Sorry I misunderstood an aspect of you patch. Please split this part but you're right it belongs as it is.

Rebase onto ValueTracking change

marcauberer marked an inline comment as done.Sep 2 2023, 5:23 AM
marcauberer added inline comments.
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
5241

@goldstein.w.n ping? Or is this resolved with extracting the isKnownNonEqual part to a new patch? This is done now.

goldstein.w.n added inline comments.Sep 7 2023, 3:28 PM
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
5241

Ah sorry didn't see your earlier message.

You don't really need to/want to be testing isKnownNonEqual here. You want to be testing this particular fold.
which doesn't inherently rely on isKnownNonEqual, it just relies on A/B != INT_MIN.

The latter can sometimes be proven with knownbits, for example (a | 1) == INT_MAX is known always false.

Since the isKnownNonEqual patch will probably take longer to get in, I would suggest doing something like:
!computeKnownBits(A, ...).getSignedMinValue().isMinSignedValue()

Use computeKnownBits instead of isKnownNonEqual

marcauberer marked an inline comment as done.Sep 8 2023, 3:13 PM
marcauberer added inline comments.
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
5241

Done.
I had to adjust the tests a bit, because with the original precondition (A != MIN_INT) we are not able to compute any known bits. If we have A != NOT_MIN_INT, we are.

marcauberer marked an inline comment as done.

Rebase

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

NB: A missing todo is if B is contant and Op1 uses -B.
Can you either add TODO comment or implement that.

Add ToDo to cover more cases

marcauberer marked an inline comment as done.Sep 19 2023, 1:37 PM
marcauberer added inline comments.
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
5238

Added a ToDo.

goldstein.w.n added inline comments.Sep 19 2023, 6:31 PM
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
5239

This is a commutative pattern. Think should either put in a lambda so you can pass op0,op1 then op1,op0 or m_c_ICmp(Pred, Pattern0, Pattern1).

llvm/test/Transforms/InstCombine/icmp-sdiv-sdiv.ll
55

Can you flip the d1/d2 operands in a few of these tests?

goldstein.w.n added inline comments.Sep 19 2023, 6:37 PM
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
5239

Actually probably easier is something like:

if(match(Op0, S_Div(m_Value(A), m_Value(B))) && match(Op1, S_Div(m_Specific(A), m_Value(C))) {
D = nullptr;
if(match(B, m_Neg(m_Specific(C)) && Op0->hasOneUse()) {
D = B;
}
else if(match(C, m_Neg(m_Specific(B)) && Op1->hasOneUse()) {
D = C;
}
if(D) {
...
}
}