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

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
582

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.

593–596

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.