This is an attempt to fix up the mess of code left over in:
https://godbolt.org/z/ZRUqCX
Where, when compiling this code (optionally having the loop do something):
unsigned test(unsigned A)
{
while(A >= 32) {
A -= 32;
};
return A;
}We end up with this remainder code from IndVarSimplify calculating the exit value of A:
define i32 @test(i32 %A) {
entry:
%l0 = icmp ult i32 %A, 31
%l1 = select i1 %l0, i32 %A, i32 31
%umax = xor i32 %l1, -1
%l2 = add i32 %umax, %A
%l3 = add i32 %l2, 32
%l4 = and i32 %l3, -32
%l5 = sub i32 %A, %l4
ret i32 %l5
}This:
(A - (-32 & (32 + A + ~min(A, 31))))
can be simplified to just (https://rise4fun.com/Alive/ARG).
A & 31
This looks like an instcombine problem to me, so here I've put in two new folds. One (here) takes us from:
A + ~min(A, 31) or A + ~select(P, A, B)
to
A < 31 ? -1 : A-32 select(P, -1, A+~B)
https://rise4fun.com/Alive/LvO. But can potentially break appart the min/max in the process. In this case we happen to fold back with the 32+ into another min/max, but that might not be the case in general.
The second part has been moved over to D53033. Together they get us down to A&31.
m_Value(A) will *always* match.
I wonder if would it make sense to swap them around?