https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64006
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |NEW Last reconfirmed| |2014-11-21 CC| |jakub at gcc dot gnu.org Target Milestone|--- |5.0 Ever confirmed|0 |1 --- Comment #1 from Jakub Jelinek <jakub at gcc dot gnu.org> --- Reduced testcase: int v; long __attribute__ ((noinline)) test (long *x, int y) { int i; long s = 1; for (i = 0; i < y; i++) if (__builtin_mul_overflow (s, x[i], &s)) v++; return s; } int main () { long d[7] = { 975, 975, 975, 975, 975, 975, 975 }; long r = test (d, 7); if (sizeof (long) * __CHAR_BIT__ == 64 && v != 1) __builtin_abort (); else if (sizeof (long) * __CHAR_BIT__ == 32 && v != 4) __builtin_abort (); return 0; } The problem is in VRP, the IMAGPART_EXPR of the MUL_OVERFLOW result is processed with only some edges executable and others not, so the value ranges of the values are only temporary, not final. In that case, one of the arguments of MUL_OVERFLOW is assumed to be [1, 1] and the other argument is VARYING. A final [1, 1] * VARYING in the same types is never overflowing though, the result always fits into the type, so we set [0, 0] as the value range for the IMAGPART_EXPR. And for some reason we are not called again when the MUL_OVERFLOW arguments are VARYING * VARYING. So, is there some way how to tell VRP to simulate the IMAGPART_EXPR again? Or is there a way to see if the value ranges of the *_OVERFLOW arguments are just temporary simulation or final? Is the fact that IMAGPART_EXPR range might be narrower initially and change to larger one later on compatible with VRP at all? Though, how is that generally different from say simulating s = s + 4 inside a loop? There we initially assume (if s is 1 before the loop) range [5, 5] and later turn it into a wider range. Though, for the IMAGPART_EXPR in this case, the arguments of the MUL_OVERFLOW don't depend on the IMAGPART_EXPR value.