Live data from Hacker News

Clang vs. Clang

blog.cr.yp.to

181–190 of 405 posts

Re: Clang vs. Clang

#181
post #175

Earlier quoted context omitted.

> Except that compiler writers essentially decide what's UB. No, the C/C++ standards specify what is UB. So, as long as you don't switch targeted standard versions, the brokenness of your code never changes. Compilers may happen to previously have never made optimizations around some specific UB, but, unless you read in the compiler's documentation that it won't, code relying on it was always broken. It's a bog stand…

> No, the C/C++ standards specify what is UB. And the compiler writers have a stranglehold on the standards bodies. They hold more than 50% of the voting power last time I checked. So yeah, compiler writers decide what's UB.

The vast majority of UB usually considered problematic has been in the standards for decades, long before compilers took as much advantage of it as they do now (and the reasons for including said UB back then were actual hardware differences, not appeasing compiler developers).

Are there even that many UB additions? The only thing I can remember is realloc with size zero going from implementation-defined to undefined in C23.

Re: Clang vs. Clang

#182
post #181

Earlier quoted context omitted.

> No, the C/C++ standards specify what is UB. And the compiler writers have a stranglehold on the standards bodies. They hold more than 50% of the voting power last time I checked. So yeah, compiler writers decide what's UB.

The vast majority of UB usually considered problematic has been in the standards for decades, long before compilers took as much advantage of it as they do now (and the reasons for including said UB back then were actual hardware differences, not appeasing compiler developers). Are there even that many UB additions? The only thing I can remember is realloc with size zero going from implementation-defined to undefined…

Yes, but that does not change the fact that compilers writers have control of the standard, have had that control since probably C99, and have introduced new UB along with pushing the 00UB worldview.

Re: Clang vs. Clang

#183

Earlier quoted context omitted.

I think this is a point of view that seems sensible, but probably hasn't really thought through how this works. For example some_array[i] What should the compiler emit here? Should it emit a bounds check? In the event the bounds check fails, what should it do? It is only through the practice of undefined behavior that the compiler can consistently generate code that avoids the bounds check. (We don't need it, because…

> What should the compiler emit here? It should emit an instruction to access memory location some_array + i. That's all most people that complain about optimizations on undefined behavior want. Sometimes there are questions that are hard to answer, but in a situation like this, the answer is "Try it and hope it doesn't corrupt memory." The behavior that's not wanted is for the compiler to wildly change behavior on p…

I think the "do the normal" thing is very easy to say and very hard to do in general. Should every case of `a / b` inject a `(b != 0) && ((a != INT_MAX && b != -1))`? If that evaluates to `true` then what should the program do? Or: should the compiler assume this can't happen. Languages with rich runtimes get around this by having an agreed upon way to signal errors, at the expense of runtime checking. An example directly stolen from the linked blog post:

  int stupid (int a) {
    return (a+1) > a;
  }
What should the compiler emit for this? Should it check for overflow, or should it emit the asm equivalent of `return 1`? If your answer is check for overflow: then should the compiler be forced to check for overflow every time it increments an integer in a for loop? If your answer is don't check: then how do you explain this function behaving completely weird in the overflow case? The point I'm trying to get at is that "do the obvious thing" is completely dependent on context.

Re: Clang vs. Clang

#184
post #94

I like Bernstein but sometimes he flies off the handle in the wrong direction. This is a good example, which he even half-heartedly acknowledges at the end! A big chunk of the essay is about a side point — how good the gains of optimization might be, which, even with data, would be a use-case dependent decision. But the bulk of his complaint is that C compilers fail to take into account semantics that cannot be expre…

Yep. DJB fell flat here. There were a lot of elitist religious opinions espoused without evidence.

Re: Clang vs. Clang

#185
post #134

> compiler writers refuse to take responsibility for the bugs they introduced, even though the compiled code worked fine before the "optimizations". The excuse for not taking responsibility is that there are "language standards" saying that these bugs should be blamed on millions of programmers writing code that bumps into "undefined behavior" But that's not an excuse for having a bug; it's the exact evidence that it…

There are only two models of UB that are useful to compiler users: 1) This is a bad idea and refuse to compile. 2) Do something sensible and stable. Silently fail and generate impossible to predict code is a third model that is only of use to compiler writers. Hiding behind the spec benefits no actual user.

If something is good for compiler developers, it is good for compiler users, in the sense that it makes it easier for the compiler developers to make the compilers we need.

Re: Clang vs. Clang

#186

> compiler writers refuse to take responsibility for the bugs they introduced, even though the compiled code worked fine before the "optimizations". The excuse for not taking responsibility is that there are "language standards" saying that these bugs should be blamed on millions of programmers writing code that bumps into "undefined behavior" But that's not an excuse for having a bug; it's the exact evidence that it…

Calling the compiler buggy for not doing what you want when you commit Undefined Behavior is like calling dd buggy for destroying your data when you call it with the wrong arguments. No, it's like calling dd buggy for deliberately zeroing all your drives when you call it with no arguments. How did we let pedantic brainless "but muh holy standards!!!1" religious brigading triumph over common sense? The standards left…

> The good thing about FOSS is that those in power can easily be changed. Perhaps it's time to fork, fix, and fight back.

Huzzah! Lead on, then.

Re: Clang vs. Clang

#187
post #158
post #134

Earlier quoted context omitted.

There are only two models of UB that are useful to compiler users: 1) This is a bad idea and refuse to compile. 2) Do something sensible and stable. Silently fail and generate impossible to predict code is a third model that is only of use to compiler writers. Hiding behind the spec benefits no actual user.

> Silently fail and generate impossible to predict code is a third model that is only of use to compiler writers. Hiding behind the spec benefits no actual user. A significant issue is that compiler "optimizations" aren't gaining a lot of general benefit anymore, and yet they are imposing a very significant cost on many people. Lots of people still are working on C/C++ compiler optimizations, but nobody is asking if…

What data?

Re: Clang vs. Clang

#188
post #181

Earlier quoted context omitted.

The vast majority of UB usually considered problematic has been in the standards for decades, long before compilers took as much advantage of it as they do now (and the reasons for including said UB back then were actual hardware differences, not appeasing compiler developers). Are there even that many UB additions? The only thing I can remember is realloc with size zero going from implementation-defined to undefined…

Yes, but that does not change the fact that compilers writers have control of the standard, have had that control since probably C99, and have introduced new UB along with pushing the 00UB worldview.

What introduced UB are you thinking of? I'll admit I don't know how much has changed, but the usually-complained-about things (signed overflow, null pointer dereferencing, strict aliasing) are clearly listed as UB in some C89 draft I found.

C23's introduced stdc_trailing_zeros & co don't even UB on 0, even though baseline x86-64's equivalent instructions are literally specified to leave their destination undefined on such!

00UB is something one can argue about, but I can't think of a meaningful way to define UB that doesn't impose significant restrictions on even basic compilers, without precisely defining how UB-result values are allowed to propagate.

e.g. one might expect that 'someFloat == (float)(int8_t)someFloat' give false on an input of 1000, but guaranteeing that takes intentional effort - namely, on hardware whose int↔float conversions only operate on ≥32-bit integers (i.e. everything - x86, ARM, RISC-V), there'd need to be an explicit 8-to-32-bit sign-extend, and the most basic compiler just emitting the two f32→i32 & i32→f32 instructions would fail (but is imo pretty clearly within "ignoring the situation completely with unpredictable results" that the C89 draft contains). Sure it doesn't summon cthulhu, but it'll quite likely break things very badly anyway. (whether it'd be useful to not have UB here in the first place is a separate question)

Even for 'x+100 < x' one can imagine a similar case where the native addition & comparison instructions operate on inputs wider than int; using such for assuming-no-signed-wrap addition always works, but would mean that the comparison wouldn't detect overflow. Though here x86-64, aarch64, and RISC-V all do provide instructions for 32-bit arith, matching their int. This would be a bigger thing if it were possible to have sub-int-sized arith.

Re: Clang vs. Clang

#189
post #181

Earlier quoted context omitted.

The vast majority of UB usually considered problematic has been in the standards for decades, long before compilers took as much advantage of it as they do now (and the reasons for including said UB back then were actual hardware differences, not appeasing compiler developers). Are there even that many UB additions? The only thing I can remember is realloc with size zero going from implementation-defined to undefined…

Yes, but that does not change the fact that compilers writers have control of the standard, have had that control since probably C99, and have introduced new UB along with pushing the 00UB worldview.

Which UB upsets you? Can you be specific so we can revert it?

Re: Clang vs. Clang

#190
post #71
post #18

Earlier quoted context omitted.

"The optimize attribute should be used for debugging purposes only. It is not suitable in production code. " https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attribute...

That's an interesting note. I wonder why they claim this. As far as I know, `[[gnu::optimize("-fno-tree-loop-distribute-patterns")]]` (or the equivalent #pragma) is required for implementing a memcpy function in C unless you do something funky with the build system.

Because these optimizations are not supposed to be a part of the user interface. They're internal passes and may one day go away or be merged or subsumed etc.
Post reply on HN