[llvm] [InstCombine] Support division of numbers that can be converted to a shift (PR #88220)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Apr 10 09:57:30 PDT 2024
================
@@ -1638,6 +1638,30 @@ define i32 @sdiv_mul_sub_nsw(i32 %x, i32 %y) {
ret i32 %d
}
+ define i32 @mul_by_150_udiv_by_100 (i32 %0) {
----------------
AtariDreams wrote:
Hard to do in Alive 2 so I'll do a formal proof:
Note that because this transformation only works when it has no unsigned wrap, and with signed integers, requires both no unsigned wrap and no signed wrap.
Let's start with variable m
Let m be defined as (X * C1)/C2;
Divsibility: m divides n if there is a number q such that m*q=n
Multiplication Overflow: an overflow is when two integers multiply and result in an integer greater than the max value. Because overflow loses information, it is important that does not happen. When it does, this is referred to as a wrap.
If m*q=n does not overflow, then n/q will return m. n/q is an exact division because the remainder is 0.
Now, to prove that if a number x * m does not overflow, neither does the result of x * m less than x.
Definition of multiplication:
For any two positive integers a and b
multiplication =
answer=0;
For (I = 0; I < B; I++)
{
answer += I;
}
Because I is positive, answer can only increase.
Therefore, if x * m does not overflow, neither does it for all integers between m and 0.
it is proven that a * m*n/b*n = a * m/b in mathematics.
Because the same whole number is returned
Because these are integers, computer division will always return a whole number.
Therefore, reducing a multiplication and division by the same common factor preserves the results as long as the original expression does not overflow.
https://github.com/llvm/llvm-project/pull/88220
More information about the llvm-commits
mailing list