This is an archive of the discontinued LLVM Phabricator instance.

[ConstantRange] Remove costly udivrem from ConstantRange::truncate
ClosedPublic

Authored by craig.topper on Apr 29 2017, 12:07 PM.

Details

Summary

Truncate currently uses a udivrem call which is going to be slow particularly for larger than 64-bit widths.

As far as I can tell all we were trying to do was modulo LowerDiv by (MaxValue+1) and make sure whatever value was effectively subtracted from LowerDiv was also subtracted from UpperDiv.

This patch recognizes that MaxValue+1 is a power of 2 so we can just use a bitwise AND to accomplish a modulo operation or isolate the upper bits.

Diff Detail

Repository
rL LLVM

Event Timeline

craig.topper created this revision.Apr 29 2017, 12:07 PM

Refine this even more to remove another temporary APInt. Now we count bits to replace the compares with MaxValue.

craig.topper added inline comments.Apr 29 2017, 7:16 PM
lib/IR/ConstantRange.cpp
579 ↗(On Diff #97202)

Note this countTrailingOnes check isn't strictly necessary. If Upper is equal to MaxValue(DstTy), Union will be FullSet. We could continue on and trust unionWith to return FullSet.

592 ↗(On Diff #97202)

Note the original code used uge, but I believe ugt was sufficient. Thus I've only implemented the equivalent of ugt with the getActiveBits check here.

spatel edited edge metadata.Jun 4 2017, 9:52 AM

Do we have (or can you add) unit tests to make sure this is behaving as expected?

We had some unittests. I added a missing EXPECT for one of them in r304693. And added a few more tests in r304694.

spatel accepted this revision.Jun 5 2017, 1:17 PM

LGTM.

This revision is now accepted and ready to land.Jun 5 2017, 1:17 PM
This revision was automatically updated to reflect the committed changes.