At the moment, we only do biv (basic induction variable) widening when we can argue that overflow cuases undefined behaviour, as in: int f (int start, int end, int x, int y) { short i; for (i = start; i < end; i++) x <<= y; return x; } However, for -ftrapv, we get the wrong result (it doesn't trap in case of overflow), and for -fwrapv, no biv widening is done. Likewise, if the biv is unsigned, as in: int f (int start, int end, int x, int y) { unsigned short i; for (i = start; i < end; i++) x <<= y; return x; } we fail to do any biv widening. Using suitable loop transformations, biv widening can be done safely without a change in observable program behaviour. If a cheap vector addition is available that adds units as wide as the original biv size, proper updates of a narrow unsigned biv can be obtained by making sure the biv is properly zero-extended at the loop entry, and using the vector addition to do the increment. If no cheap vector addition is available, or if defined operation on a narrow signed biv is required, biv widening can be done safely by transforming the loop into two nested loops, where end value of the inner loop is calculated so that if the biv should overflow, the value of the biv during the last iteration will be the value prior to the overflow. The outer loop can then, if required, trap, calculate the new biv value to archive wrap-around semantics, and continue looping.
Created attachment 12668 [details] 3.4.3 patch For illustration, this patch implements this optimization in a 3.4.3 based compiler. Because the 4.x series uses a completely different infrastructure, we must re-implement this from scratch.