This is an archive of the discontinued LLVM Phabricator instance.

[IRCE] Smarter detection of empty ranges using SCEV
ClosedPublic

Authored by mkazantsev on Oct 19 2017, 1:35 AM.

Details

Summary

For a SCEV range, this patch replaces the naive emptiness check for SCEV ranges
which looks like Begin == End with a SCEV check. The range is guaranteed to be
empty of Begin >= End. We should filter such ranges out and do not try to perform
IRCE for them.

For example, we can get such range when intersecting range [A, B) and [C, D)
where A < B < C < D. The resulting range is [max(A, C), min(B, D)) = [C, B).
This range is empty, but its Begin does not match with End.

Making IRCE for an empty range is basically safe, but unprofitable because we
never actually get into the main loop where the range checks are supposed to
be eliminated. This patch uses SCEV mechanisms to treat loops with proved
Begin >= End as empty.

Diff Detail

Repository
rL LLVM

Event Timeline

mkazantsev created this revision.Oct 19 2017, 1:35 AM
anna added inline comments.Oct 19 2017, 7:48 AM
lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp
185 ↗(On Diff #119555)

SCEV's isKnownPredicate is actually really good in most cases to identify the empty range (BEGIN >= END).
However, there's a stronger version of isKnownPredicate in DependenceInfo::isKnownPredicate.

Specifically, it first checks SCEV's version of isKnownPredicate and if it fails, it does a further analysis using the Delta between Begin and End and checking the Delta based on the predicate passed in.

I'm wondering if SCEV's form maybe weaker and hence we may fire the assert added about empty ranges at line 1756?

test/Transforms/IRCE/empty_ranges.ll
9 ↗(On Diff #119555)

So, in this case, from now on, only the first range check is removed, i.e. we will not remove range checks where the safe iteration space intersected with the "true" iteration space is empty. By true iteration space, I mean, the set where the guard is always true.

mkazantsev added inline comments.Oct 19 2017, 9:19 PM
lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp
185 ↗(On Diff #119555)

Assert on 1756 should never fire. If you look into IntersectRange, we check range on isEmpty() and return None if it is true. We make check before return and check in assert with the same isEmpty(), so we just cannot end up with one returning true and another returning false.

Thanks for pointing me out of DependenceInfo::isKnownPredicate, I will see if I can use it here.

test/Transforms/IRCE/empty_ranges.ll
9 ↗(On Diff #119555)

That was the intension. Checks in pre- and postloop are not eliminated, and if the safe iteration space is empty, we will never get to the mainloop (where something was removed). Removing at least something from the main loop which remains reachable may be good by itself. For example, if there was a load between range checks 1 and 2, we can now correctly hoist it out of the main loop because it becomes guaranteed to execute now.

mkazantsev added inline comments.Oct 19 2017, 10:17 PM
lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp
185 ↗(On Diff #119555)

I don't really like this idea after looking into its code. The reasons are:

  1. To use it, we need to factor this method out of dependency analysis ( e.g. into an utility function which takes ScalarEvolution as a parameter);
  2. It does not currently support unsigned comparisons failing with llvm_unreachable("unexpected predicate in isKnownPredicate");, and we do need them;
  3. If what it does with Delta is really profitable for symbolics, I don't see why it shouldn't be moved to ScalarEvolution::isKnownPredicate. This code doesn't need anything but ScalarEvolution.

So I would rather leave it as it is and consider this extra stuff from DependenceInfo::isKnownPredicate for factoring into SCEV in case if it is proved to make any sense.

mkazantsev added inline comments.Oct 19 2017, 11:16 PM
test/Transforms/IRCE/empty_ranges.ll
9 ↗(On Diff #119555)

For example, if the 2nd range check wasn't leaving the loop, the transform would also be profitable.

anna accepted this revision.Oct 23 2017, 9:31 AM

LGTM.

lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp
185 ↗(On Diff #119555)

agreed. I was just curious about how the further Delta checks helps here (if any), and it looks like it won't help us?

This revision is now accepted and ready to land.Oct 23 2017, 9:31 AM
mkazantsev added inline comments.Oct 23 2017, 9:10 PM
lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp
185 ↗(On Diff #119555)

In theory, they can help if we iterate from symbilic to symbolic; in practice, I think in most such cases we won't be able to prove anything if we don't have a known range for them, and if we know the range, we can prove isKnownPredicate basing on it.

This revision was automatically updated to reflect the committed changes.