Lots of loop stuff also depends on non-overflowing signed integers. If integers can shrink on addition then you cannot safely do a lot of unrolling or fancier stuff based on affine loop transformations.
That is most definitely not true. All modern hardware is 2's complement arithmetic, and the corresponding signed integer arithmetic operation will silently overflow without complaint.
> Lots of loop stuff also depends on non-overflowing signed integers. If integers can shrink on addition then you cannot safely do a lot of unrolling or fancier stuff based on affine loop transformations.
Not really. Only certain particular patterns force weirdness on loops were overflow well-defined, and these aren't the most common pattern (a basic for (int i = 0; i < N; i++) loop doesn't need overflow to be undefined to have loop optimizations kick in). Even if you hit a case where it can be annoying (such as the poor man's multidimensional array access, because C lacks such niceties), you can multiversion the loop to fall back to an unoptimized loop in cases where overflow would have kicked in and otherwise use the optimized loop.
Where I've seen the most issues with signed versus unsigned is when LLVM decides to take a loop with a signed 32-bit index, promote the index variable to 64-bit (using zero-extension for all the related values), and then retain a signed 32-bit comparison for the loop bound. The unsigned version of the code had fewer problems. So much for signed overflow being good for optimizations.
But not the same width. Does it overflow at 32bits or 64? If you define it as one or the other, that requires a runtime check.
Last time I looked at the speedup you got from loop optimization it at most a few percent for a very simple loop. For a loop that has some meat it'd be noise.
Wow, no. Most loop optimizations make loops significantly faster, even an order of magnitude is not uncommon. Write a few loops and compare the code generated by any compiler with O0 vs O3.