I think this is a fundamental problem with C. Both of the language itself, but also of the C programming culture of insisting on very low levels of abstractions. Bugs and undefined behaviour is too easy for programmers to write when the level of abstraction is low. Too much boilerplate to get wrong. But too low a level is also bad for an optimizer. It cant assume it understand the programmers intention with the code.…
I don't think C is bad for optimizers. What language consistently generates faster machine code than C?
The Problem with Friendly C
81–90 of 174 posts
Re: The Problem with Friendly C
#82Earlier quoted context omitted.
But the standard already permits this. I'm just suggesting that rather than have compiler writers use these liberties to allow their compiler to remove code or make it do something peculiar, they could just allow it to do the natural thing for the target platform. (This is explicitly allowed by the standard. Consult its definition of undefined behaviour.) Why not create a compiler that does what your users want? Why…
Because the overwhelming majority of users of C compilers are compiling someone else's code that isn't narrowly targeted to the platform+compiler in question. So they get no benefit at all from specifying undefined behavior, but they do get a benefit from the performance gained by assuming away undefined behavior as dead cases.
I think this is a highly suspicious assumption. Programmers don't write code for no reason; they have a mental model of the current state of parameters and variables, and establish invariants as they write loops and conditionals. If you're going to start throwing out chunks of code the programmer wrote, you need to be certain - not merely unsure, but certain - that the code is dead. Infectious undefined values that propagate through data flow to break code flow isn't a sane programming environment.
Re: The Problem with Friendly C
#83Earlier quoted context omitted.
> But why can't it just produce something different on each system? It could. That is indeed how Rust, for example, defines it. But in C "unspecified values" have a way of turning into undefined behavior really quickly. Here's an actual bug we have in Rust [1]: let index = 1.04E+17 as u8; let array = vec![1, 2, 3, 4, 5]; println!("{}", array[index as usize]); // segfault Why does that segfault instead of emitting a s…
The problem here is, as you point out, the conversion of double to unsigned byte. More specifically, the problem is that processing this operation is not producing error; it instead propagates the problem and produces invalid code. That's a situation where nobody wins. I think we'd be better off if many undefined behaviours were instead implementation defined. If, instead, LLVM had converted the double to some intege…
I believe that you and others think that's an acceptable tradeoff. At the end of the day, though, most people want C compilers to produce the fastest code possible. Compiler authors are just responding to what users want. The example below is actually an excellent example of this.
> If it harms the performance of C++ vector iterators, for example, I don't care: strict aliasing rules are a worse cure than the disease of C++'s poorly thought out abstraction tools.
It's not just C++. Consider (from Chris Lattner's blog post):
float *array;
void zero_out() {
for (int i = 0; i
People saw compilers missing the optimization to compile this to a memset, and filed bugs against them. As a matter of fact, though, that is an illegal optimization to make unless the compiler is able to take advantage of strict aliasing. That's because, absent strict aliasing, array[0] could legally be a type-casted pointer back to "array" itself, even though almost nobody would actually write that code.The reason why compilers implemented strict aliasing rules is that their users demanded that they fix "optimizer bugs" like the one above. And, honestly, I can't blame either the compiler developers or the users. Strict aliasing ends up being one of the things that's often important for performance. The problem, if anything, lies with the C language.
Re: The Problem with Friendly C
#84Earlier quoted context omitted.
That would work if most applications spent all their time in a few hot spots. But, contrary to popular wisdom, that's usually not the case. Most applications have flat profiles (to steal a quote from DannyBee—but it matches my experience as well). They have flat profiles because people have spent a lot of time optimizing them. In this context—which is the norm—eliminating optimizations to save compile time and deferr…
I agree optimization is important. So important that it should be pushed down into the hardware. Binaries should look almost like source code. But that's just my vision for what it's worth.
Re: The Problem with Friendly C
#85Since, according to Chandler Carruth, the aim for Clang is to not do optimizations based on undefined behaviour without a corresponding instrument in ubsan[0], I don't see much traction on this well-defined/boring C effort. You know, in my experience, things would be great if people actually turned on warnings. I write all my new code with -Weverything with a few noise categories turned off. Everybody should build co…
Re: The Problem with Friendly C
#86Earlier quoted context omitted.
IMHO aggressive optimization at compile time is an example of premature optimization. Let the hardware have access to a straightforward representation. Once the run-time hot-spots are identified, the hardware (firmware, VM, whatever) can rewrite the binary code to execute faster. Excessive compiler optimization makes this difficult or impossible (too much information thrown away.) Compilers should be designed for fas…
It doesn't really seem like this solves the problem of optimizers introducing bugs and vulnerabilities. Take the canonical optimizer-created security hole: the hardware optimizer replaces a constant-time compare (which doesn't leak timing information) with a variable-time compare (which does). I don't think this solves the problem we're setting out to solve, ie. the optimizer introducing bugs.
Right now compiler writers are playing in a kind of local minimum (premature optimization as I said.) This may produce 3x-5x faster binary code today but also forces CPU manufacturers to retain backward compatibility causing them to also stay stuck in this local well. Eventually a new architecture is created (with 10x the registers etc.) and the cycle continues.
Re: The Problem with Friendly C
#87Since, according to Chandler Carruth, the aim for Clang is to not do optimizations based on undefined behaviour without a corresponding instrument in ubsan[0], I don't see much traction on this well-defined/boring C effort. You know, in my experience, things would be great if people actually turned on warnings. I write all my new code with -Weverything with a few noise categories turned off. Everybody should build co…
Re: The Problem with Friendly C
#88Earlier quoted context omitted.
The problem here is, as you point out, the conversion of double to unsigned byte. More specifically, the problem is that processing this operation is not producing error; it instead propagates the problem and produces invalid code. That's a situation where nobody wins. I think we'd be better off if many undefined behaviours were instead implementation defined. If, instead, LLVM had converted the double to some intege…
> On strict aliasing, I'm against it without explicit opt-in over a delimited subset of source code. I understand that using & is going to harm the performance of my code; I think that's an acceptable tradeoff for more predictable behaviour. I believe that you and others think that's an acceptable tradeoff. At the end of the day, though, most people want C compilers to produce the fastest code possible. Compiler auth…
I feel like a new systems language needs to come and make aliasing explicit in a way, so that it doesn't surprise programmers but still allows them to get the optimizations that they want. Tracking uniqueness like Rust is a good first step, but it doesn't work for unsafe code or anything with more subtle aliasing relationships.
Re: The Problem with Friendly C
#89Earlier quoted context omitted.
GCC has an intermediate representation. It's just not exercised as a separate project (like LLVM). It's far from "single pass"
You're right; to be clear, what I was talking about above was whether the passes are decoupled at an abstract level, not so much whether the implementation uses multiple phases. You can take LLVM "bitcode" as the product of clang, move it to another system with a different arch, and finish compiling the IR to a native binary on that system. This implies that the first step and second step don't share any state other…
Re: The Problem with Friendly C
#90Since, according to Chandler Carruth, the aim for Clang is to not do optimizations based on undefined behaviour without a corresponding instrument in ubsan[0], I don't see much traction on this well-defined/boring C effort. You know, in my experience, things would be great if people actually turned on warnings. I write all my new code with -Weverything with a few noise categories turned off. Everybody should build co…
At home, I turn on -Wall -Wextra for starters, enable about a dozen more for good measure, with -Werror as the pièce de réisistance.