This patch is an expansion to http://reviews.llvm.org/D12090.
In D12090, the ExprValueMap was added to reuse existing value during SCEV expansion. However, const folding and sext/zext distribution can make the reuse difficult. I found a common case where the reuse opportunity was missed like this:
Loop lowerbound is intconst 2. Loop upperbound is a complex expr.
%lowerbound = 2
%smax = select ...
%complexexpr = add nsw %i32 %smax, -1
%upperbound = sext i32 %complexexpr i64
When we build SCEV for upperbound, %complexexpr is mapped to SCEV S1: (-1 + X smax Y) <nsw>
%upperbound is mapped to SCEV S2 = sext(S1) = sext((-1 + X smax Y) <nsw>) = (-1 + sext(X smax Y)) <nsw> (sext distribution for SCEV applied here)
Both S1 and S2 will have reuse value entries in ExprValueMap.
Then when we compute loop iteration number based on upperbound SCEV S2 and lowerbound 2: it is S2 - 2 + 1 = -2 + sext(X smax Y) (const folding applied here). Note we only have S1 and S2 in ExprValueMap so we don't have reuse entry for -2 + sext(X smax Y) or sext(X smax Y) so we have to expand "-2 + sext(X smax Y)" literally. When X and Y are also complex expression, it will produce a lot of redundent code.
The patch is proposing to save {Value, Offset} pair instead of just Value in ExprValueMap, and if a SCEV can be splitted into a stripped SCEV part plus an int offset, the mapping "stripped SCEV -> {Value, Offset}" will be added into ExprValueMap, so we won't worry missing reuse opportunity because of const folding.
For %upperbound which is mapped to SCEV S2 = (-1 + sext(X smax Y)), in addition to save mapping "S2 -> %upperbound" into ExprValueMap (Represented as S2 -> {%upperbound, 0}), it will split S2 into two parts: "stripped SCEV S3" + "offset -1". Here S3 is "sext(X smax Y)". Mapping "S3 -> {%upperbound, -1}" will also be saved into ExprValueMap.
Then when scev expander did code expansion for loop iteration number: -2 + sext(X smax Y), it will find out SCEV S3: sext(X smax Y) is in ExprValueMap (The entry: S3 -> {%upperbound, -1}), so it knows to reuse %upperbound - (-1) to represent sext(X smax Y), instead of expanding S3 literally.
I think this first part of the explanation can be made easier to
follow if we write in a more explicit way:
The second part is fine, but please make it a obvious that it
semantically maps S to {expand(S + Offset), Offset}, that is, if
S is mapped to {V, Offset} then expand(S) is V - Offset.