This replaces several rewriting rules in ScalarEvolution::applyLoopGuards that are applied to min/max expressions with the equivalent ones but applied to its arguments.
So currently given we have a loop guard min(a, b) >= c, the min expression gets rewritten as max(c, min(a, b)).
With such approach, we're unable to apply the rewrite if min operands are zext for example (min(zext(a), zext(b))), however it's equivalent to the expression zext(min(a, b)) for which we can apply the rewrite.
We can rewrite the min operands instead with these expressions:
- a --> max(c, a) and
- b --> max(c, b)
and this would allow us to apply the loop guard in this and similar cases: min(zext(a), zext(b)) would get rewritten as min(zext(max(c, a)), zext(max(c, b))) instead of just being skipped.
The table of replaced rules (omitting predicates signedness for simplicity):
Old rule | New rules |
min(a, b) >= c --> max(c, min(a, b)) | a --> max(a, c) and b --> max(b, c) |
min(a, b) > c --> max(c + 1, min(a, b)) | a --> max(a, c + 1) and b --> max(b, c + 1) |
max(a, b) <= c --> min(c, max(a, b)) | a --> min(a, c) and b --> min(b, c) |
max(a, b) < c --> min(c - 1, max(a, b)) | a --> min(a, c - 1) and b --> min(b, c - 1) |
This is not correct (c + 1 may overflow). Why didn't you just keep it as
?