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?