4 ms·
> Most Linux distributions consist of packages of vast amounts of unmaintained or mostly unmaintained C code Well, that's exactly the kind of code I'd expect t
by brigade 8y ago
> Most Linux distributions consist of packages of vast amounts of unmaintained or mostly unmaintained C code
Well, that's exactly the kind of code I'd expect to simply break when the compiler becomes able to prove new optimizations based on undefined behavior.
When that happened to me, I decided there was no way I was trawling through our massive legacy codebase to fix undefined behavior that ubsan can't catch. Resulted in -fwrapv -fno-strict-aliasing being added, and any speed loss was noise under 0.5%
Then in our modern codebase, I did my absolute best to ensure we built it no undefined behaviour, including contortions to avoid undefined left shifts... and we still got screwed over by a new version of clang.
For all the worry about "for (int i = 0; i < array->length; i++)" specifically, how often is that actually measurable whole-program? It's one additional sign extension in a tight loop, plus a store/load in a complex loop, which a modern CPU would completely hide 99.9% of the time.
- pcwalton 8y ago> It's one additional sign extension in a tight loop, plus a store/load in a complex loop, which a modern CPU would completely hide 99.9% of the time. Not true. It's a store/load in the tight, simple loops that are the problem. Sometimes making your loop too big will cause you to fall out of the uop cache on x86, which is a significant performance hit. Modern CPUs don't hide this inefficiency, which is why compiler developers implemented the optimizations in the first place. (LLVM and GCC benchmarking infrastructure is excellent; they test this stuff continuously and don't land changes that don't demonstrate benefits.)
- brigade 8y agoMy suspicion is that loops that need even a dozen registers are in general either not tight enough on modern CPUs that a spill is measurable (maybe they were that tight 10-15 years ago), or were optimized after 64-bit was common. Or maybe I'm just disappointed from all the times I've eliminated spills and other extraneous µops in small tight loops with no measurable gain even in microbenchmarks. I kinda wish that benchmarking infrastructure was reflected in my experience; I've spent entirely too much time fixing performance regressions in various inner loops caused by newer compilers. Though to be fair, only once has that regression exceeded 2x. To give some context: if a loop is large enough that it's on the verge of falling out of the µop cache, I'd consider that a massive loop. And from my experience any code that complex I definitely wouldn't trust newer compiler versions to not randomly add a dozen or two instructions. Anyway... exactly how much does -fwrapv impact LLVM or GCC's benchmarking testsuite?