[InstCombine] Add constant combines for `(urem/srem (mul X, Y), (mul X, Z))`
We can handle the following cases + some `nsw`/`nuw` flags:
`(srem (mul X, Y), (mul X, Z))`
[If `srem(Y, Z) == 0`]
-> 0
- https://alive2.llvm.org/ce/z/PW4XZ-
[If `srem(Y, Z) == Y`]
-> `(mul nuw nsw X, Y)`
- https://alive2.llvm.org/ce/z/DQe9Ek
-> `(mul nsw X, Y)`
- https://alive2.llvm.org/ce/z/Nr_MdH
[If `Y`/`Z` are constant]
-> `(mul/shl nuw nsw X, (srem Y, Z))`
- https://alive2.llvm.org/ce/z/ccTFj2
- https://alive2.llvm.org/ce/z/i_UQ5A
-> `(mul/shl nsw X, (srem Y, Z))`
- https://alive2.llvm.org/ce/z/mQKc63
- https://alive2.llvm.org/ce/z/uERkKH
`(urem (mul X, Y), (mul X, Z))`
[If `urem(Y, Z) == 0`]
-> 0
- https://alive2.llvm.org/ce/z/LL7UVR
[If `srem(Y, Z) == Y`]
-> `(mul nuw nsw X, Y)`
- https://alive2.llvm.org/ce/z/9Kgs_i
-> `(mul nuw X, Y)`
- https://alive2.llvm.org/ce/z/ow9i8u
[If `Y`/`Z` are constant]
-> `(mul nuw nsw X, (srem Y, Z))`
- https://alive2.llvm.org/ce/z/mNnQqJ
- https://alive2.llvm.org/ce/z/Bj_DR-
- https://alive2.llvm.org/ce/z/X6ZEtQ
-> `(mul nuw X, (srem Y, Z))`
- https://alive2.llvm.org/ce/z/SJYtUV
The rationale for doing this all in `InstCombine` rather than handling
the constant `mul` cases in `InstSimplify` is we often create a new
instruction because we are able to deduce more `nsw`/`nuw` flags than
the original instruction had.
Reviewed By: MattDevereau, sdesmalen
Differential Revision: https://reviews.llvm.org/D143014