Hello, we found some optimizations (regarding Arithmetic optimization) that GCC may have missed. We would greatly appreicate if you can take a look and let us know what you think. Given the following code: https://godbolt.org/z/G9rWK7c3q int n1; void func1(int a){ if(a>1&&a<4) n1=(a+a+a+a)/(a+a); } Different from PR 111718, this missed optimization appears to be due to a missed pattern: (t*4)/(t*2) -> 2 # DEBUG BEGIN_STMT # RANGE [irange] int [8, 8][12, 12] NONZERO 0xc _3 = a_7(D) * 4; # RANGE [irange] int [4, 4][6, 6] NONZERO 0x6 _4 = a_7(D) * 2; # RANGE [irange] int [1, 3] NONZERO 0x3 _5 = _3 / _4; # .MEM_9 = VDEF <.MEM_8(D)> n1D.2761 = _5; Or a more general pattern: (t*m)/(t*n) -> m/n , where m and n are constants. Thank you very much for your time and effort! We look forward to hearing from you.
Confirmed. Same for int foo (int a, int b, int c) { return 2*c*(a*b) / (a*b); } note when we cannot remove the division like for c*a / d*a we have to watch out for -INT_MIN / -1, but I think the only way this would not invoke undefined behavior before the transform is when the factor is equal to -1 but then c*a cannot be -INT_MIN so it should be safe in general, not only when m and n are constants? Note we cannot re-associate for the transform. We only have /* Simplify (t * 2) / 2) -> t. */ (for div (trunc_div ceil_div floor_div round_div exact_div) (simplify (div (mult:c @0 @1) @1) (if (ANY_INTEGRAL_TYPE_P (type)) (if (TYPE_OVERFLOW_UNDEFINED (type)) @0 #if GIMPLE (with {value_range vr0, vr1;} (if (INTEGRAL_TYPE_P (type) && get_range_query (cfun)->range_of_expr (vr0, @0) && get_range_query (cfun)->range_of_expr (vr1, @1) && range_op_handler (MULT_EXPR).overflow_free_p (vr0, vr1)) @0)) #endif )))) but not the case with two multiplies.