Considering: int f(int index, int stride) { const int i1 = index / stride; const int i2 = index % stride; const int index2 = i1*stride+i2; return index2; // expect: index2 = index } gcc 8.3 with "-O3" on x84_64 emits: f(int, int): mov eax, edi cdq idiv esi imul eax, esi add eax, edx ret By contrast, clang 7 with "-O3" emits f(int, int): mov eax, edi ret MSVC 2017 with "/O2" emits: int f(int,int) mov eax, ecx ret 0 Is there a way to persuade gcc to simplify this expression at compile time?
We do not have a (a / b) * b + (a % b) simplification rule. The following adds one: Index: gcc/match.pd =================================================================== --- gcc/match.pd (revision 269242) +++ gcc/match.pd (working copy) @@ -2729,6 +2729,13 @@ (define_operator_list COND_TERNARY (mult (convert1? (exact_div @0 @@1)) (convert2? @1)) (convert @0)) +/* Simplify (A / B) * B + (A % B) -> A. */ +(for div (trunc_div ceil_div floor_div round_div) + mod (trunc_mod ceil_mod floor_mod round_mod) + (simplify + (plus:c (mult:c (div @0 @1) @1) (mod @0 @1)) + @0)) + /* ((X /[ex] A) +- B) * A --> X +- A * B. */ (for op (plus minus) (simplify
(In reply to Richard Biener from comment #1) > We do not have a (a / b) * b + (a % b) simplification rule. Indeed. That's surprising since we do have for trunc_div /* X - (X / Y) * Y is the same as X % Y. */
Author: rguenth Date: Fri May 3 10:46:13 2019 New Revision: 270846 URL: https://gcc.gnu.org/viewcvs?rev=270846&root=gcc&view=rev Log: 2019-05-03 Richard Biener <rguenther@suse.de> PR middle-end/89518 * match.pd: Add pattern to optimize (A / B) * B + (A % B) to A. * gcc.dg/pr89518.c: New testcase. Added: trunk/gcc/testsuite/gcc.dg/pr89518.c Modified: trunk/gcc/ChangeLog trunk/gcc/match.pd trunk/gcc/testsuite/ChangeLog
Fixed.