One of the things this person misses is a lot of these are undefined with the explicit goal to let compiler authors take advantage of them.
So his real argument is with the C committee for not defining these things the way he wants them. His claim that the behavior of what should happen is obvious is pretty strange (IE "it should do exactly whatever the compiler is trying to prove it doesn't")
It's essentially a complaint that compiler authors should follow a mystical spirit of C that he seems to have in his head.
(Plus, you know, he's kind of a dick about it all)
I read things like "We had plans to turn this optimization into a production feature, but eventually
realized that the GCC maintainers only care about certain benchmarks
and treat production programmers as adversaries that deserve getting their code
broken.
...
The current GCC and Clang maintainers suggest that we should convert
programs to “C”. How would that turn out for Gforth?"
I was intrigued, so i went looking for the mailing list discussion where the gcc or clang people suggested this or where any of this happened.
I can't find it.
On either set of mailing lists.
I searched for gforth, i searched for anton, etc
Nothing.
> lot of these are undefined with the explicit goal to let compiler authors take advantage of them.
Constructs should be undefined because the current landscape of C implementations is surveyed, and those constructs are found to be nonportable to such an extent that their behavior cannot be even "implementation-defined" or "unspecified".
That's the beginning and end of it, period.
That's why certain thing were undefined or unspecified in the first ANSI C standard. For instance, different compilers had different evaluation order for function arguments, without documenting which, or guaranteeing that it would always be the way it is.
The committee didn't sit there and decide "let's make evaluation orders undefined for the sake of blazing speed, even though all C compilers today are doing it left to right. Let's have it so that after 1989, they can use whatever order they want!"
It was, "Ooops, we can't codify a specific evaluation order, because looking at what's out there, there isn't one. If we were to codify an order, implementations not having the order that we codify would have to be modified to conform with our standardized language."
As time goes on, these stupid things should be tightened. Over the course of thirty years, it's okay to codify some gratuitous lack of definedness in a language area and make everyone straighten it out in their implementations.
While his tone may be unwarranted, I think his claims are more reasonable than you suggest. I'm not sure where the actual bug reports are, but here's a long but excellent thread on comp.arch where Anton makes his point more fully: http://compgroups.net/comp.arch/if-it-were-easy/2993157
Edit: In another comment, you say "The whole thing is like complaining that people follow the law, instead of the spirit of the law." I think that might be accurate. Impractical as it may be, there are many (including me and presumably Anton) who believe that society benefits if individuals hold themselves to a higher standard than obeying the letter of the law and flaunting the spirit.
> So his real argument is with the C committee for not defining these things the way he wants them.
To some extent yes. But if you take it to that extreme – where you really have to understand the standard at the language lawyer level –, C becomes an unreasonably complicated language where you can only trust experts to have a deep enough understanding to write correct code.
I'm a compiler writer. I'm not actually unsympathetic to these points, and agree that compilers intended for practical use had better have strong justification for surprising behavior.
But the pervasively nasty tone of the paper is not going to make many friends among the people whose work the authors are trying to influence.
I agree about the unpleasant tone of the paper, putting "facts" and "optimizations" in quotes, implying they are not real, and talking about "claims" of GCC maintainers, and cracks about psychic powers.
But there is a good underlying point to the paper, and one I tend to agree with - a compiler's behavior should give considerable weight to how the language is used more than taking a literal view of what the words mean in the spec.
Taking things to an absurd extreme to make the point, "undefined behavior" implies that a compiler writer can insert code to reformat the hard disk if it encountered such code. Granted, the point of a spec is to define things so that compiler writers don't have to divine intent, but perfection is never attained and hence compiler writers have to use their judgment.
I know in my compiler work, I have backed out some optimizations that were allowed by the spec, but broke too many programs. The inconsequential speed improvement was just not worth it.
I can't currently say that I am a compiler writer, since I'm working on static analysis tools, but I have been a compiler writer for more of my career than I have been anything else, and I was thoroughly amused by the tone of the paper. It's not particularly professional, and it's not likely to change minds among the people he is excoriating, but I don't think that's the point. Instead, I think he's trying to shift the "Overton window", to embolden people uncomfortable with the status quo, so that they can argue for what they want instead of accepting the opinions of compiler writers as some kind of unchangeable holy writ.
int d[16];
int SATD (void)
{
int satd = 0, dd, k;
for (dd=d[k=0]; k<16; dd=d[++k]) {
satd += (dd < 0 ? -dd : dd);
}
return satd;
}
This gets optimized into an infinite loop, and the paper says that this is incorrect. I'm on the side of the compiler. This code is broken, if you do an out-of-bounds access then an infinite loop is the least of your worries.
Independent of undefined behavior: Who writes such god-awful code?
There:
for (k=0; k < 16; k++)
{
dd = d[k];
satd += (dd < 0 ? -dd : dd);
}
Just one more line, less error-prone, idiomatic for-loop and variable accesses (therefore easier and faster to comprehend), and best of all: no undefined behavior.
("But if my code is simple, how will other people know what a genius I am?")
There's no way I would accept the code from that benchmark in a code review.
On a reasonable machine (e.g., x86, x86_64, ARM, ARM64), in a reasonable context (i.e., not the very tippy top stack frame), the one-past-the-end read is harmless. The value is unused, and the read itself is not going to segfault because it's going to read the frame pointer or return address out of the stack frame.
Even with buggy code, you want the behavior of the generated code to reflect the behavior of the source code, or debugging becomes an exercise in frustration (especially, but not only on platforms where running a debugger is not an option).
Yeah, this is undefined behaviour and should not be expected to work, 100% agreed.
Wouldn't it be faster to remove that costly ternary conditional operator by zeroing out the first bit? Well, there's one degenerate case, for minvalue of int, but that is degenerate either way.
The author doesn't understand the market demands for a compiler:
1) Customers who want their text-size to be as small as possible so they can shave $0.0015 off their BOM by using smaller ROM parts
2) Chip vendors who have 7 figure sales that will fall-through if they can't show a 0.7% higher Dhrystone MIPS (yes Dhrystone, the benchmark that was obsolete 20 years ago).
3) Managers who make buying decisions purely based on a set of their own pet benchmarks, with no regard to anything in this paper.
Damn right a compiler will take advantage of every optimization opportunity afforded by the standard. Good compilers will have ways of being much less aggressive about optimizations; I bet with gcc and clang each you have some -f flags that will disable certain optimizations (not to mention just good old -O0); I know most commercial compilers do.
[edit]
I would like to see some less-optimizable C standard catch on, so that there could be a mode common to multiple compilers that makes programmers happy. Unfortunately attempts to create such a dialect have failed to get off the ground.
[edit2]
Part of this is because there is less of a consensus on what are optimizations* and "optimizations" than the author would believe.
As for the market demands on compilers, I hope that this paper influences that in more reasonable directions. In the meantime, I have nothing against having an option (or more) for "optimizations". Enabling new "optimizations" by default however has the effect of miscompiling existing programs and is not such a good idea. At the very least there should be one flag for disabling "optimizations" without disabling optimizations.
Concerning what are optimizations: If the observable behaviour does not change (even when there is undefined behaviour), it's an optimization. Also, register allocation and rearranging stuff in memory is an optimization (because programs that rely on that not changing break on maintenance). Other transformations are, at best, "optimizations". If you have any questions about specific transformations, please ask.
Optimizations based on undefined behavior are actually based on the belief that the code in question doesn't have undefined behavior (that the programmer is taking care of any possibility of undefined behavior, where that possibility exists).
This assumption should be made only if the programmer who wrote that code is a machine: a machine translating something which itself doesn't have undefined behavior, into C that doesn't have undefined behavior.
That assumption should not be made when the programmer is a person. Or, if the assumption is used, it should be accompanied by a diagnostic. "I'm expressing what appears to be your intent using a more efficient approach, which breaks in a surprising way if you made a mistake."
For instance, consider
int compare(int x, unsigned char y)
{
return x + y > x;
}
This is always true, or else the behavior is undefined. So it can be replaced with:
int compare(int x, unsigned char y)
{
(void) x; /* somewhat accepted de facto idiom for ignoring arguments */
(void) y;
return 1;
}
And GCC does turn it into "return 1". But why the hell would a human write a complicated function in place of just constant 1?
If a machine generated this due to following a template of code, that is understandable, and making it return 1 is helpful --- assuming that the generator is carefully written to avoid relying on undefined behavior.
Even if the generator actually relies on undefined behavior, the issue can be fixed in the generator, which can be run to regenerate all the code; but there is no such easy band-aid for human-written code. (A code generator can even have a catalog of what version of what compiler brand supports what undefined behavior in what way, and tune its output accordingly to what compiler is used in the subsequent pass.)
What is unhelpful on the part of compiler writers is supporting some undefined behavior as a de facto extension for many years, and then backpedaling on it.
One day your code that depends on signed integers having two's complement "odometer wraparound semantics" stops working after years or decades because of some compiler cowboy who was in millennial kindergarten when that code was written.
What I think many people fail to realize is that a large part of the code as a C compiler sees it is machine-generated. While I certainly do not tend to literally write out `if (1 != 0)` conditionals in my code, these and other similarly trivial expressions, will be introduced en-masse after macro expansion and aggressive inlining.
And in this context, macro-expanded, inlined code, exploiting the assumption of no undefined behavior occurring starts making a lot more sense. Sure, if you consider something like
int x = *ptr;
if (ptr != NULL) {
*ptr = 1;
}
you may not unreasonably say that, as there is an explicit ptr != NULL check in there, probably that's what the programmer intended -- so we should not replace ptr != NULL with a constant 0 because that pointer was already dereferenced.
However if the real code is
int x = *ptr;
do_something_with_ptr(ptr)
and the do_something_with_ptr() function just happens to contain a NULL-check at some point (because it is written for a more generic purpose and not use in just this place), then not dropping that NULL-check becomes a very significant missed optimization opportunity.
If the compiler wouldn't optimize that out of consideration for the possibility of the former hand-written code, that would incur costs on the programmer. He might have to split do_something_with_ptr() into two functions, one doing NULL checks and one not doing it. He may have to add explicit compiler assumption / unreachability annotations.
The whole argument goes both ways, performing optimizations that break broken code has a cost (people have to fix it) and not performing those optimizations for working code (people have to manually optimize it).
Out of all ridiculous claims in that .pdf, many pointed out by others I find this especially entertaining:
But do “optimizations” actually produce speedups for benchmarks? Despite
frequent claims by compiler maintainers that they do, they rarely present numbers
to support these claims. E.g., Chris Lattner (from Clang) wrote a three-part
blog posting8 about undefined behavior, with most of the first part devoted to
“optimizations”, yet does not provide any speedup numbers. On the GCC side,
when asked for numbers, one developer presented numbers he had from some
unnamed source from IBM’s XLC compiler, not GCC; these numbers show a
speedup factor 1.24 for SPECint from assuming that signed overflow does not
happen (i.e., corresponding to the difference between -fwrapv and the default
on GCC and Clang).
Fortunately, Wang et al. [WCC+12] performed their own experiments compiling
SPECint 2006 for AMD64 with both gcc-4.7 and clang-3.1 with default
“optimizations” and with those “optimizations” disabled that they could identify,
and running the results on a on a Core i7-980. They found speed differences
on two out of the twelve SPECint benchmarks: 456.hmmer exhibits a speedup
by 1.072 (GCC) or 1.09 (Clang) from assuming that signed overflow does not
happen. For 462.libquantum there is a speedup by 1.063 (GCC) or 1.118 (Clang)
from assuming that pointers to different types don’t alias. If the other benchmarks
don’t show a speed difference, this is an overall SPECint improvement by
a factor 1.011 (GCC) or 1.017 (Clang) from “optimizations”.
I mean, the speed-up of 7.2%, 9%, 6.3%, 11.8% for specific cases is huge. It will make real time and money difference for people.
He is advocating against having that just because he thinks what signed integer overflow should do is obvious. Entitlement, ignorance, incompetence. I am not sure which one is it. It takes 1 minute to figure out that signed integer overflow is undefined and act accordingly.
Developer time is a zero sum game. If one of these optimizations bites me and I spend one day figuring out what happened, I don't spend one day doing optimization somewhere else, where a much greater speedup can be achieved. Or, to out it in your money difference terms, I could be adding value to the program somewhere else, adding or polishing features.
It's a balancing game. Looking at it through the lens of % speedup, ignoring everything else is just stupid. In a perfect world we'd make decisions based on numbers. He provided his. Where are yours?
I half expected the document to present statistical evidence about how programmers tend to behave, and use that to generate advice for compiler writers.
The article is a nice read (and doesn't present that kind of statistical evidence), but I'm still wondering, has anyone done a significant study of how programmers work? I would be really fascinated to read an analysis of, say, data taken from full-time software engineers at a given company where all of their actions are recorded (key-strokes, compiler runs, error messages, etc.). Similar to how online competitive gamers have their actions recorded to the microsecond to identify weak points.
It would even be interesting to know, e.g., what is the net average number of lines of code created/deleted per day?
The average doesn't matter, specific problems are reported on the mailinglists, for example. You wouldn't sway everyone's writing style with some statistical evidence, not in a giant ecosystem like C/unix and it's not a democracy either where 51% would just ignore the other 49% existence.
What? "tested and production" programs might be conforming according to the C standard, but that's only because it's a largely useless term: [a] conforming program is one that is acceptable to a conforming implementation. [C99, 4]
If the implementation is conforming (which might not be the case) and has accepted the program (which could be chock full of cruft), then the program is conforming. The "conforming" designation simply doesn't assure us of any measure of quality, other than that the program isn't so bad that it doesn't compile and link (with that one toolchain which produced its executable).
If the program is tested and in production using a compiler that is operated in a nonconforming mode (often the default on many compilers), then acceptance of the program doesn't speak to its conformance at all.
This kind of twaddle in the abstract is a very bad way to start out a paper. (And I'm one of the "converted" people, you don't have to work hard to convince me about the dangers of optimizing based on "no UB" ssumptions, without a single diagnostic squawk.)
"Conforming program" may be a largely useless term, but it's one of the two conformance levels for programs that the C standard defines. The other is "strictly conforming program", and it does not include any terminating C program, so it's also a largely useless term.
Now C compiler maintainers justify "optimizations" with the C standard, and indeed, a compiler that behaves like that is a "conforming implementation" (the only conformance level that the C standard defines for compilers). Is that a useful term?
Yes, we should be exploring the fringes of the C standard (in particular, "optimizations") less, because that is not useful territory; instead, we should orient ourselves by looking at the C programs that are out there.
But anyway, my thinking when I wrote that was: if somebody comes at you with the frequent stance of "your program is non-standard crap full of bugs", when it worked as intended with all previous versions of the compiler, you can shoot back at them with "it's a conforming program". Of course, if the other side is a language lawyer, that approach will not help, as you demonstrate, but if not, maybe you can get the other side to take a more productive stance.
The diagram on page 13 has linear interpolation plotted between the datapoints. That's one step away from fitting an arbitrary polynomial for the points. Don't do it, implying measurements between point releases isn't very sensible.
[+] [-] DannyBee|10 years ago|reply
So his real argument is with the C committee for not defining these things the way he wants them. His claim that the behavior of what should happen is obvious is pretty strange (IE "it should do exactly whatever the compiler is trying to prove it doesn't")
It's essentially a complaint that compiler authors should follow a mystical spirit of C that he seems to have in his head.
(Plus, you know, he's kind of a dick about it all)
I read things like "We had plans to turn this optimization into a production feature, but eventually realized that the GCC maintainers only care about certain benchmarks and treat production programmers as adversaries that deserve getting their code broken. ... The current GCC and Clang maintainers suggest that we should convert programs to “C”. How would that turn out for Gforth?"
I was intrigued, so i went looking for the mailing list discussion where the gcc or clang people suggested this or where any of this happened.
I can't find it. On either set of mailing lists. I searched for gforth, i searched for anton, etc Nothing.
[+] [-] kazinator|10 years ago|reply
Constructs should be undefined because the current landscape of C implementations is surveyed, and those constructs are found to be nonportable to such an extent that their behavior cannot be even "implementation-defined" or "unspecified".
That's the beginning and end of it, period.
That's why certain thing were undefined or unspecified in the first ANSI C standard. For instance, different compilers had different evaluation order for function arguments, without documenting which, or guaranteeing that it would always be the way it is.
The committee didn't sit there and decide "let's make evaluation orders undefined for the sake of blazing speed, even though all C compilers today are doing it left to right. Let's have it so that after 1989, they can use whatever order they want!"
It was, "Ooops, we can't codify a specific evaluation order, because looking at what's out there, there isn't one. If we were to codify an order, implementations not having the order that we codify would have to be modified to conform with our standardized language."
As time goes on, these stupid things should be tightened. Over the course of thirty years, it's okay to codify some gratuitous lack of definedness in a language area and make everyone straighten it out in their implementations.
[+] [-] nkurz|10 years ago|reply
Edit: In another comment, you say "The whole thing is like complaining that people follow the law, instead of the spirit of the law." I think that might be accurate. Impractical as it may be, there are many (including me and presumably Anton) who believe that society benefits if individuals hold themselves to a higher standard than obeying the letter of the law and flaunting the spirit.
[+] [-] 95014_refugee|10 years ago|reply
... where you conveniently leave out the part where the 'C committee' is stuffed with compiler vendors.
"Plus, you know, he's kind of a dick about it all"
If you had been on the receiving end of what these people call 'optimisations' for more than a few years, you'd think he was being pretty civilised.
[+] [-] rbehrends|10 years ago|reply
To some extent yes. But if you take it to that extreme – where you really have to understand the standard at the language lawyer level –, C becomes an unreasonably complicated language where you can only trust experts to have a deep enough understanding to write correct code.
[+] [-] unknown|10 years ago|reply
[deleted]
[+] [-] conceit|10 years ago|reply
It's called tongue in cheek. Like so: you dick :P
[+] [-] pklausler|10 years ago|reply
But the pervasively nasty tone of the paper is not going to make many friends among the people whose work the authors are trying to influence.
[+] [-] WalterBright|10 years ago|reply
But there is a good underlying point to the paper, and one I tend to agree with - a compiler's behavior should give considerable weight to how the language is used more than taking a literal view of what the words mean in the spec.
Taking things to an absurd extreme to make the point, "undefined behavior" implies that a compiler writer can insert code to reformat the hard disk if it encountered such code. Granted, the point of a spec is to define things so that compiler writers don't have to divine intent, but perfection is never attained and hence compiler writers have to use their judgment.
I know in my compiler work, I have backed out some optimizations that were allowed by the spec, but broke too many programs. The inconsequential speed improvement was just not worth it.
[+] [-] marssaxman|10 years ago|reply
[+] [-] anon4|10 years ago|reply
[deleted]
[+] [-] AndyKelley|10 years ago|reply
[+] [-] adwn|10 years ago|reply
There:
Just one more line, less error-prone, idiomatic for-loop and variable accesses (therefore easier and faster to comprehend), and best of all: no undefined behavior.("But if my code is simple, how will other people know what a genius I am?")
There's no way I would accept the code from that benchmark in a code review.
[+] [-] ursus_bonum|10 years ago|reply
[+] [-] swolchok|10 years ago|reply
[+] [-] rbehrends|10 years ago|reply
[+] [-] Kenji|10 years ago|reply
Wouldn't it be faster to remove that costly ternary conditional operator by zeroing out the first bit? Well, there's one degenerate case, for minvalue of int, but that is degenerate either way.
[+] [-] unknown|10 years ago|reply
[deleted]
[+] [-] unknown|10 years ago|reply
[deleted]
[+] [-] ori_b|10 years ago|reply
[+] [-] kzhahou|10 years ago|reply
(disclaimer: I am a programmer, not a compiler)
[+] [-] unknown|10 years ago|reply
[deleted]
[+] [-] aidenn0|10 years ago|reply
1) Customers who want their text-size to be as small as possible so they can shave $0.0015 off their BOM by using smaller ROM parts
2) Chip vendors who have 7 figure sales that will fall-through if they can't show a 0.7% higher Dhrystone MIPS (yes Dhrystone, the benchmark that was obsolete 20 years ago).
3) Managers who make buying decisions purely based on a set of their own pet benchmarks, with no regard to anything in this paper.
Damn right a compiler will take advantage of every optimization opportunity afforded by the standard. Good compilers will have ways of being much less aggressive about optimizations; I bet with gcc and clang each you have some -f flags that will disable certain optimizations (not to mention just good old -O0); I know most commercial compilers do.
[edit]
I would like to see some less-optimizable C standard catch on, so that there could be a mode common to multiple compilers that makes programmers happy. Unfortunately attempts to create such a dialect have failed to get off the ground.
[edit2]
Part of this is because there is less of a consensus on what are optimizations* and "optimizations" than the author would believe.
[+] [-] AntonErtl|10 years ago|reply
Concerning what are optimizations: If the observable behaviour does not change (even when there is undefined behaviour), it's an optimization. Also, register allocation and rearranging stuff in memory is an optimization (because programs that rely on that not changing break on maintenance). Other transformations are, at best, "optimizations". If you have any questions about specific transformations, please ask.
[+] [-] kazinator|10 years ago|reply
This assumption should be made only if the programmer who wrote that code is a machine: a machine translating something which itself doesn't have undefined behavior, into C that doesn't have undefined behavior.
That assumption should not be made when the programmer is a person. Or, if the assumption is used, it should be accompanied by a diagnostic. "I'm expressing what appears to be your intent using a more efficient approach, which breaks in a surprising way if you made a mistake."
For instance, consider
This is always true, or else the behavior is undefined. So it can be replaced with: And GCC does turn it into "return 1". But why the hell would a human write a complicated function in place of just constant 1?If a machine generated this due to following a template of code, that is understandable, and making it return 1 is helpful --- assuming that the generator is carefully written to avoid relying on undefined behavior.
Even if the generator actually relies on undefined behavior, the issue can be fixed in the generator, which can be run to regenerate all the code; but there is no such easy band-aid for human-written code. (A code generator can even have a catalog of what version of what compiler brand supports what undefined behavior in what way, and tune its output accordingly to what compiler is used in the subsequent pass.)
What is unhelpful on the part of compiler writers is supporting some undefined behavior as a de facto extension for many years, and then backpedaling on it.
One day your code that depends on signed integers having two's complement "odometer wraparound semantics" stops working after years or decades because of some compiler cowboy who was in millennial kindergarten when that code was written.
[+] [-] nikic|10 years ago|reply
And in this context, macro-expanded, inlined code, exploiting the assumption of no undefined behavior occurring starts making a lot more sense. Sure, if you consider something like
you may not unreasonably say that, as there is an explicit ptr != NULL check in there, probably that's what the programmer intended -- so we should not replace ptr != NULL with a constant 0 because that pointer was already dereferenced.However if the real code is
and the do_something_with_ptr() function just happens to contain a NULL-check at some point (because it is written for a more generic purpose and not use in just this place), then not dropping that NULL-check becomes a very significant missed optimization opportunity.If the compiler wouldn't optimize that out of consideration for the possibility of the former hand-written code, that would incur costs on the programmer. He might have to split do_something_with_ptr() into two functions, one doing NULL checks and one not doing it. He may have to add explicit compiler assumption / unreachability annotations.
The whole argument goes both ways, performing optimizations that break broken code has a cost (people have to fix it) and not performing those optimizations for working code (people have to manually optimize it).
[+] [-] rcfox|10 years ago|reply
[+] [-] bluecalm|10 years ago|reply
But do “optimizations” actually produce speedups for benchmarks? Despite frequent claims by compiler maintainers that they do, they rarely present numbers to support these claims. E.g., Chris Lattner (from Clang) wrote a three-part blog posting8 about undefined behavior, with most of the first part devoted to “optimizations”, yet does not provide any speedup numbers. On the GCC side, when asked for numbers, one developer presented numbers he had from some unnamed source from IBM’s XLC compiler, not GCC; these numbers show a speedup factor 1.24 for SPECint from assuming that signed overflow does not happen (i.e., corresponding to the difference between -fwrapv and the default on GCC and Clang). Fortunately, Wang et al. [WCC+12] performed their own experiments compiling SPECint 2006 for AMD64 with both gcc-4.7 and clang-3.1 with default “optimizations” and with those “optimizations” disabled that they could identify, and running the results on a on a Core i7-980. They found speed differences on two out of the twelve SPECint benchmarks: 456.hmmer exhibits a speedup by 1.072 (GCC) or 1.09 (Clang) from assuming that signed overflow does not happen. For 462.libquantum there is a speedup by 1.063 (GCC) or 1.118 (Clang) from assuming that pointers to different types don’t alias. If the other benchmarks don’t show a speed difference, this is an overall SPECint improvement by a factor 1.011 (GCC) or 1.017 (Clang) from “optimizations”.
I mean, the speed-up of 7.2%, 9%, 6.3%, 11.8% for specific cases is huge. It will make real time and money difference for people. He is advocating against having that just because he thinks what signed integer overflow should do is obvious. Entitlement, ignorance, incompetence. I am not sure which one is it. It takes 1 minute to figure out that signed integer overflow is undefined and act accordingly.
[+] [-] DominikD|10 years ago|reply
It's a balancing game. Looking at it through the lens of % speedup, ignoring everything else is just stupid. In a perfect world we'd make decisions based on numbers. He provided his. Where are yours?
[+] [-] abecedarius|10 years ago|reply
[+] [-] j2kun|10 years ago|reply
The article is a nice read (and doesn't present that kind of statistical evidence), but I'm still wondering, has anyone done a significant study of how programmers work? I would be really fascinated to read an analysis of, say, data taken from full-time software engineers at a given company where all of their actions are recorded (key-strokes, compiler runs, error messages, etc.). Similar to how online competitive gamers have their actions recorded to the microsecond to identify weak points.
It would even be interesting to know, e.g., what is the net average number of lines of code created/deleted per day?
[+] [-] conceit|10 years ago|reply
[+] [-] kazinator|10 years ago|reply
If the implementation is conforming (which might not be the case) and has accepted the program (which could be chock full of cruft), then the program is conforming. The "conforming" designation simply doesn't assure us of any measure of quality, other than that the program isn't so bad that it doesn't compile and link (with that one toolchain which produced its executable).
If the program is tested and in production using a compiler that is operated in a nonconforming mode (often the default on many compilers), then acceptance of the program doesn't speak to its conformance at all.
This kind of twaddle in the abstract is a very bad way to start out a paper. (And I'm one of the "converted" people, you don't have to work hard to convince me about the dangers of optimizing based on "no UB" ssumptions, without a single diagnostic squawk.)
[+] [-] AntonErtl|10 years ago|reply
Now C compiler maintainers justify "optimizations" with the C standard, and indeed, a compiler that behaves like that is a "conforming implementation" (the only conformance level that the C standard defines for compilers). Is that a useful term?
Yes, we should be exploring the fringes of the C standard (in particular, "optimizations") less, because that is not useful territory; instead, we should orient ourselves by looking at the C programs that are out there.
But anyway, my thinking when I wrote that was: if somebody comes at you with the frequent stance of "your program is non-standard crap full of bugs", when it worked as intended with all previous versions of the compiler, you can shoot back at them with "it's a conforming program". Of course, if the other side is a language lawyer, that approach will not help, as you demonstrate, but if not, maybe you can get the other side to take a more productive stance.
[+] [-] conceit|10 years ago|reply
[+] [-] Dylan16807|10 years ago|reply
[+] [-] wirrbel|10 years ago|reply