This is an archive of the discontinued LLVM Phabricator instance.

[InstCombine] Fold "x ?% y ==/!= 0" to "x & (y-1) ==/!= 0" iff y is power-of-two
ClosedPublic

Authored by lebedev.ri on Jul 21 2019, 2:18 AM.

Details

Summary

I have stumbled into this by accident while preparing to extend backend x s% C ==/!= 0 handling.

While we did happen to handle this fold in most of the cases,
the folding is indirect - we fold x u% y to x & (y-1) (iff y is power-of-two),
or first turn x s% -y to x u% y; that does handle most of the cases.
But we can't turn x s% INT_MIN to x u% -INT_MIN,
and thus we end up being stuck with (x s% INT_MIN) == 0.

There is no such restriction for the more general fold:
https://rise4fun.com/Alive/IIeS

To be noted, the fold does not enforce that y is a constant,
so it may indeed increase instruction count.
This is consistent with what x u% y->x & (y-1) already does.
I think it makes sense, it's at most one (simple) extra instruction,
while remainder is really much more un-simple (and likely very costly).

Diff Detail

Event Timeline

lebedev.ri created this revision.Jul 21 2019, 2:18 AM

NFC, fix comment and function name.

xbolva00 added inline comments.Jul 22 2019, 1:42 PM
llvm/include/llvm/IR/PatternMatch.h
1006

Maybe separate patch + test for IRem?

Not sure if needed, since this fold “tests” it actually..

RKSimon added inline comments.Jul 29 2019, 7:37 AM
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
1335

Do we need a ICmpInst::isEquality(Pred) test?

lebedev.ri marked 2 inline comments as done.Jul 29 2019, 7:43 AM
lebedev.ri added inline comments.
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
1335

This is valid both for equality and all unsigned predicates: https://rise4fun.com/Alive/wp0N
But not signed ones: https://rise4fun.com/Alive/I67

Regardless, see beginning of the function:

// This fold is only valid for equality predicates.
if (!I.isEquality())
  return nullptr;
RKSimon added inline comments.Jul 29 2019, 9:35 AM
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
1335

Cheers - I missed that - maybe add a TODO that other unsigned predicates could be supported?

lebedev.ri marked 3 inline comments as done.Jul 29 2019, 9:41 AM
lebedev.ri added inline comments.
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
1335
lebedev.ri marked 2 inline comments as done.Jul 29 2019, 1:56 PM
lebedev.ri added inline comments.
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
1335

Err, to rephrase: we don't really care about non-equality predicates here,
because the unsigned comparisons with zero will either be constant-folded,
or the predicate will be changed to an equality before we get here.

RKSimon accepted this revision.Jul 30 2019, 7:12 AM

LGTM - thanks for the explanation.

This revision is now accepted and ready to land.Jul 30 2019, 7:12 AM

Thank you for the review!

This revision was automatically updated to reflect the committed changes.