Groups | Search | Server Info | Login | Register
Groups > comp.compilers > #3683
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Newsgroups | comp.compilers |
| Subject | Re: Undefined behaviour in C23 |
| Date | 2025-08-22 18:42 +0200 |
| Organization | Compilers Central |
| Message-ID | <25-08-009@comp.compilers> (permalink) |
| References | <25-08-002@comp.compilers> <25-08-004@comp.compilers> |
On 21/08/2025 07:44, anton@mips.complang.tuwien.ac.at wrote: > Martin Ward <mwardgkc@gmail.com> writes: > [actually, John Levine writes:] >> [When a language is 50 years old and there is a mountain of legacy code that >> they really don't want to break, it accumulates a lot of cruft. > > But there is a very vocal group of people who argue that programs that > exercise undefined behaviour are already broken (and they often use > stronger words that that) and that compilers are allowed to (and > should) compile them to code that behaves differently than earlier > compilers that the new compiler supposedly is just a new version of. Yes. It is good that compilers often support ways to get the "old" behaviour if the user wants. But new compiler versions should not be held back by the limitations of old compilers - that would stifle progress. Imagine if car manufacturers had to limit the speeds of new cars to 10 miles per hour, because some drivers a century ago assumed that they could safely put their foot flat on the accelerator without hitting the horse and cart in front of them. And also remember that broken code is not necessarily useless code. For programs of reasonable size, very few are completely bug-free. And yet we still manage to use them if they are good enough, despite being imperfect. > > So according to this argument, when something that the legacy code > does is declared as undefined behaviour, this breaks this program. > > And the practice is that the people in C compiler maintenance reject > bug reports as RESOLVED INVALID when the code exercises undefined > behaviour, even when the code works as intended in earlier versions of > the compiler and when the breakage could be easily fixed (e.g., for > <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66804> and > <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65709> by using movdqu > instead of movdqa). > I don't see any problem with these being marked as "resolved invalid". There is definitely a challenge in writing C code that is maximally efficient on a wide variety of compilers - old and new, powerfully optimising and weakly optimising, and for different target architectures. C code can't always be written in an ideal and fully portable way. This can be handled by using abstractions, compiler detection and conditional compilation for things like block copies - use unaligned non-conforming large moves if you know it is safe on a particular implementation, and fall back to safe but possibly slow memcpy() (or memmove()) in general. That kind of solution, of course, has its own disadvantages in development time, code complexity, testing, etc. The C programming world is not perfect. But the solution is certainly /not/ to say that people everyone correct C code and compiling with high optimisations should get slower results because someone else previously wrote code that made unwarranted and unchecked assumptions about particular compilers and particular target processors. > But they not always do so: The SATD function from the SPEC benchmark > 464.h264ref exercises undefined behaviour, and a pre-release version > of gcc-4.8 generated code that did not behave as intended. The > release version of gcc-4.8 compiled 464.h264ref as intended (but later > a similar case that was not in a SPEC program > <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66875> was rejected as > RESOLVED INVALID). So the gcc developers made an exception for a particularly important, useful and common case? Again that doesn't sound unreasonable to me. Sometimes there are trade-offs - some code is more important than other code. The C compiler development world is not perfect either. > When I brought this up, the reactions reached from > flat-out denial that it ever happened (despite it being widely > publicized <https://lwn.net/Articles/544123/>) through a claim that > the "optimization" turned out to have no benefit (and yet the similar > case mentioned above still was "optimized" in a later gcc version) to > a statement along the lines that 464.h264ref is a relevant benchmark. > Maybe this particular case was handled badly, or at least the communications involved were bad. It was over a decade ago, in a pre-release candidate compiler. (Pre-release candidates are used precisely to check if changes cause trouble with real-world code.) How long are you going to hold a grudge about this? > The last reaction seems to be the most plausible to me. The people > working on the optimizers tend to evaluate their performance on a > number of benchmarks, i.e., "relevant benchmarks", and of course these > benchmarks must be compiled as intended, so that's what happens. My > guess is that "relevant benchmarks" are industry standard benchmarks > like SPEC, but also programs coming from paying customers. > For gcc, a typical benchmark is the Linux kernel and a wide selection of open source programs - people do full rebuilds of whole Linux distributions as part of testing before full compiler releases. SPEC is a special case, because these programs are used on a wide variety of C compilers for comparison between toolchains, not just for one compiler. > They also have their test suites of programs for regression testing, > and any behavioural change in these programs that is visible in this > regression testing probably leads to applying the optimization in a > less aggressive way. > I would assume that they try to avoid UB in their test suite code (though of course gcc developers can have bugs and mistakes like anyone else). Sometimes test suite code is fixed when new bugs are found in it. > How do tests get added into the regression test suite? Ideally, if > somebody reports a case where a program behaves in one way in an > earlier version of the same compiler and differently in a later > version, that program and its original behaviour should usually be > added to the test suite > <https://www.complang.tuwien.ac.at/papers/ertl17kps.pdf>, but in gcc > this does not happen (see the bug reports linked to above). In what bizarre world would that be "ideal" ? If you want gcc 4.8 without tree optimisations, you can get it. If you want to use gcc 15 and not enable tree optimisations, that's fine too. If you want to write code that can be highly optimised with automatic generation of vector instructions that only work on aligned data, don't faff around going out of your way to write bad C code that messes with pointer types to create unaligned accesses. It's your choice. Let the rest of us that get our data alignment correct (and you get that naturally in C - you only get the UB if you've played silly buggers with pointer casts to write "smart" code) get faster results. Examples can be added to the test suite if they are useful. They can be added to test new features - there is no point in a test to see if the compiler generates code that matches an old compiler version unless there is a specific new feature flag to give defined semantics matching the old behaviour. (An example of that would be the "-fno-delete-null-pointer-check" flag.) > Apparently gcc has some other criteria for adding programs to the test > suite. > > So, is C still usable when you do not maintain one of those programs > that are considered to be relevant by C compiler maintainers? My > experience is that the amount of breakage for the code I maintain has > been almost non-existent in the last 15 years. A big part of that is > that we use lots of flags to tell the compiler that certain behaviour > is defined even if the C standard does not define it. That sounds like you have a solution to your problem. > Currently we > try the following flags with the versions of gcc or clang that support > them: > > -fno-gcse -fcaller-saves -fno-defer-pop -fno-inline -fwrapv > -fchar-unsigned -fno-strict-aliasing -fno-cse-follow-jumps > -fno-reorder-blocks -fno-reorder-blocks-and-partition > -fno-toplevel-reorder -fno-trigraphs -falign-labels=1 -falign-loops=1 > -falign-jumps=1 -fno-delete-null-pointer-checks -fcf-protection=none > -fno-tree-vectorize -mllvm=--tail-dup-indirect-size=0 > That sounds like you have code that uses a great deal of UB and relies on a wide range of very specific code generation and semantics that are not defined anywhere, in the C standards or compiler documentation. Maybe that's what you need for your projects, and if it works for you, fine. But it is a very unusual situation, and cannot be extrapolated to a non-negligible amount of C code. (Some flags, such as "-fwrapv" and "-fno-strict-aliasing", are needed to counter unwarranted assumptions in a more significant body of existing C code.) > Some of these flags just disable certain transformations; in those > cases there is no flag for defining the language in the way that our > program relies on, but only the optimization transforms it in a way > that is contrary to our intentions. In other cases, in particular > -fno-tree-vectorize, using the flag just avoids slowdowns from the > "optimization". You know better than the solid majority of programmers that "optimisation" is as much an art as a science, and that getting the best from a combination of code, compiler and target processor is no simple task. Compilers enable optimisations in groups (-O1, -O2, -O3, etc.) based on what usually gives better results for a range of code bases and a range of target devices - there are no guarantees for any particular combination. > > Another big part of the lack of breakage experience is probably the > code in the regression tests of the compiler, whatever the criteria > are used for including this code. I.e., our code rides in the > slipstream of this code. > >> On the other hand, there's the python approach in which they deprecate and >> remove little used and crufty features, but old python code doesn't work any >> more unless you go back and update it every year or two. -John] > > Is it so bad with Python? From what I read, after the huge problems > that Python had with migrating the existing code base from Python2 to > Python3 (where Python3 was intentionally not backwards compatible with > Python2), they had decided not to make backwards-incompatible changes > to the language in the future. > IME there are only sometimes issues with new Python versions, but the Python 2 to 3 incompatibilities are still a widespread problem.
Back to comp.compilers | Previous | Next — Previous in thread | Next in thread | Find similar
Undefined behaviour in C23 Martin Ward <mwardgkc@gmail.com> - 2025-08-20 14:06 +0100
Re: Undefined behaviour in C23 Kaz Kylheku <643-408-1753@kylheku.com> - 2025-08-20 18:33 +0000
Re: Undefined behaviour in C23 David Brown <david.brown@hesbynett.no> - 2025-08-21 15:02 +0200
Re: Undefined behaviour in C23 Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-08-21 12:53 -0700
Re: Undefined behaviour in C23 David Brown <david.brown@hesbynett.no> - 2025-08-22 17:58 +0200
Re: Undefined behaviour in C23 anton@mips.complang.tuwien.ac.at - 2025-08-22 17:16 +0000
Re: Undefined behaviour in C23 Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-08-22 15:11 -0700
Re: Undefined behaviour in C23 David Brown <david.brown@hesbynett.no> - 2025-08-23 16:55 +0200
Re: Undefined behaviour in C23 Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-08-23 15:58 -0700
Re: Undefined behaviour in C23 James Kuyper <jameskuyper@alumni.caltech.edu> - 2025-08-25 22:13 -0400
Re: Undefined behaviour in C23 James Kuyper <jameskuyper@alumni.caltech.edu> - 2025-08-26 13:41 -0400
Re: Undefined behaviour in C23 Michael S <already5chosen@yahoo.com.dmarc.email> - 2025-08-26 22:28 +0300
Re: Undefined behaviour in C23 James Kuyper <jameskuyper@alumni.caltech.edu> - 2025-08-26 16:53 -0400
Re: Undefined behaviour in C23 anton@mips.complang.tuwien.ac.at - 2025-08-21 05:44 +0000
Re: Undefined behaviour in C23 David Brown <david.brown@hesbynett.no> - 2025-08-22 18:42 +0200
Re: Undefined behaviour in C23 anton@mips.complang.tuwien.ac.at - 2025-09-06 17:15 +0000
csiph-web