autoconf: Optimization and Wraparound

1 
1 13.2.3 Optimizations That Break Wraparound Arithmetic
1 -----------------------------------------------------
1 
1 Compilers sometimes generate code that is incompatible with wraparound
1 integer arithmetic.  A simple example is an algebraic simplification: a
1 compiler might translate `(i * 2000) / 1000' to `i * 2' because it
1 assumes that `i * 2000' does not overflow.  The translation is not
1 equivalent to the original when overflow occurs: e.g., in the typical
1 case of 32-bit signed two's complement wraparound `int', if `i' has
1 type `int' and value `1073742', the original expression returns
1 -2147483 but the optimized version returns the mathematically correct
1 value 2147484.
1 
1    More subtly, loop induction optimizations often exploit the undefined
1 behavior of signed overflow.  Consider the following contrived function
1 `sumc':
1 
1      int
1      sumc (int lo, int hi)
1      {
1        int sum = 0;
1        int i;
1        for (i = lo; i <= hi; i++)
1          sum ^= i * 53;
1        return sum;
1      }
1 
1 To avoid multiplying by 53 each time through the loop, an optimizing
1 compiler might internally transform `sumc' to the equivalent of the
1 following:
1 
1      int
1      transformed_sumc (int lo, int hi)
1      {
1        int sum = 0;
1        int hic = hi * 53;
1        int ic;
1        for (ic = lo * 53; ic <= hic; ic += 53)
1          sum ^= ic;
1        return sum;
1      }
1 
1 This transformation is allowed by the C standard, but it is invalid for
1 wraparound arithmetic when `INT_MAX / 53 < hi', because then the
1 overflow in computing expressions like `hi * 53' can cause the
1 expression `i <= hi' to yield a different value from the transformed
1 expression `ic <= hic'.
1 
1    For this reason, compilers that use loop induction and similar
1 techniques often do not support reliable wraparound arithmetic when a
1 loop induction variable like `ic' is involved.  Since loop induction
1 variables are generated by the compiler, and are not visible in the
1 source code, it is not always trivial to say whether the problem
1 affects your code.
1 
1    Hardly any code actually depends on wraparound arithmetic in cases
1 like these, so in practice these loop induction optimizations are almost
1 always useful.  However, edge cases in this area can cause problems.
1 For example:
1 
1      int j;
1      for (j = 1; 0 < j; j *= 2)
1        test (j);
1 
1 Here, the loop attempts to iterate through all powers of 2 that `int'
1 can represent, but the C standard allows a compiler to optimize away
1 the comparison and generate an infinite loop, under the argument that
1 behavior is undefined on overflow.  As of this writing this
1 optimization is not done by any production version of GCC with `-O2',
1 but it might be performed by other compilers, or by more aggressive GCC
1 optimization options, and the GCC developers have not decided whether
1 it will continue to work with GCC and `-O2'.
1