This is an archive of the discontinued LLVM Phabricator instance.

Teach ScalarEvolution to exploit min and max expressions.
ClosedPublic

Authored by sanjoy on Dec 11 2014, 8:28 PM.

Details

Summary

Teach ScalarEvolution to exploit min and max expressions when proving isKnownPredicate.

The motivation for this change is to optimize away checks in loops like this:

limit = min(t, len)
for (i = 0 to limit)
  if (i >= len || i < 0) throw_array_of_of_bounds();
  a[i] = ...

Diff Detail

Repository
rL LLVM

Event Timeline

sanjoy updated this revision to Diff 17212.Dec 11 2014, 8:28 PM
sanjoy retitled this revision from to Teach ScalarEvolution to exploit min and max expressions..
sanjoy updated this object.
sanjoy edited the test plan for this revision. (Show Details)
sanjoy added reviewers: atrick, reames, nlewycky, hfinkel.
sanjoy added a subscriber: Unknown Object (MLST).
majnemer added inline comments.
lib/Analysis/ScalarEvolution.cpp
6982 ↗(On Diff #17212)

Might be more concise as:

for (const SCEV *Operand : MaxExpr)
  const SCEV *Difference = SE.getMinusSCEV(Candidate, Operand);
7004–7006 ↗(On Diff #17212)
7015–7016 ↗(On Diff #17212)

I thought case labels should be at the same indentation level as the switch.

sanjoy updated this revision to Diff 17219.Dec 11 2014, 10:51 PM
sanjoy added a reviewer: majnemer.

Address David's review + minor nits I noticed. No functional change.

atrick edited edge metadata.Dec 12 2014, 12:33 AM

Overall really nice work. Thanks to David for reviewing. See my comments inline.

lib/Analysis/ScalarEvolution.cpp
6952 ↗(On Diff #17219)

insert a comma: "computes ~A, assign"

6954 ↗(On Diff #17219)

Not a big deal, but why not return NotOf and nullptr for a mismatch?

Did you implement the pattern matching to avoid the overhead of just comparing the result of getNotExpr if you can bail-out of the match early?

6983 ↗(On Diff #17219)

Can you explain why the subtraction is necessary. What unique expressions have zero difference?

Are you assuming that MaybeExpr and Candidate have the same bitwidth? What happens if they don't?

7034 ↗(On Diff #17219)

Out of curiosity, do you need the unreachable? There shouldn't be a warning for a covered switch, should be a warning otherwise.

sanjoy added inline comments.Dec 12 2014, 1:20 AM
lib/Analysis/ScalarEvolution.cpp
6954 ↗(On Diff #17219)

Not a big deal, but why not return NotOf and nullptr for a mismatch?

Will do, that seems obviously better.

Did you implement the pattern matching to avoid the overhead of just comparing the result of getNotExpr if you can bail-out of the match early?

Yes. I have to admit though that I don't have a good intuition on what kinds of operations in ScalarEvolution are fast enough that they're not worth optimizing like this.

6983 ↗(On Diff #17219)

Can you explain why the subtraction is necessary. What unique expressions have zero difference?

I was initially thinking of things like %a OP %b vs. %b OP %a but depending on how scev canonicalizes these it may not actually be an issue. I'll change it to use pointer equality for now -- that seems to pass the test with this patch.

Are you assuming that MaybeExpr and Candidate have the same bitwidth? What happens if they don't?

I don't think that should be an issue once I change this to use pointer equality. That said, is isImpliedCondOperands(P, A, B, C, D) ever called with either A Pred B or C Pred D not well-typed?

7034 ↗(On Diff #17219)

Without the llvm_unreachable I don't see a warning with clang, but wasn't sure if one of the buildbots might.

sanjoy updated this revision to Diff 17220.Dec 12 2014, 1:22 AM
sanjoy edited edge metadata.

Address review comments by Andy

atrick accepted this revision.Dec 12 2014, 9:14 AM
atrick edited edge metadata.

LGTM

This revision is now accepted and ready to land.Dec 12 2014, 9:14 AM
This revision was automatically updated to reflect the committed changes.