L
LLVM Blog
blog.llvm.org · Company blog · on HN since 2009
The LLVM project's blog, with posts on Clang, optimization, link-time optimization, and compiler behavior from its developers.
What HN saysHN links it mainly for the undefined behavior series, which commenters use to explain how compilers exploit it. Clang on Windows also comes up.
226HN people shared it
145linked it in comments
130stories submitted
5.3Kstory points
6 months agolast shared
2009people per year2026
Most-shared posts
- 1What Every C Programmer Should Know About Undefined Behavior #1/368 people · 280 points · first shared 2011 · 18 comments on HN
- 2What Every C Programmer Should Know About Undefined Behavior #2/333 people · 301 points · first shared 2011 · 61 comments on HN
- 3What Every C Programmer Should Know About Undefined Behavior #3/320 people · 166 points · first shared 2011 · 10 comments on HN
- 4Amazing feats of Clang Error Recovery8 people · 113 points · first shared 2010 · 18 comments on HN
- 5What Every C Programmer Should Know About Undefined Behavior (2011)7 people · 93 points · first shared 2015 · 65 comments on HN
- 6LLVM's New Versioning Scheme6 people · 101 points · first shared 2016 · 83 comments on HN
- 7Closing the gap: cross-language LTO between Rust and C/C++5 people · 268 points · first shared 2019 · 66 comments on HN
- 8The Glasgow Haskell Compiler and LLVM5 people · 139 points · first shared 2010 · 7 comments on HN
- 9ThinLTO: Scalable and Incremental Link-Time Optimization for LLVM5 people · 117 points · first shared 2016 · 18 comments on HN
- 10Interactive C++ with Cling5 people · 10 points · first shared 2021 · discussion on HN
- 11Clang Is Now Used to Build Chrome for Windows4 people · 398 points · first shared 2018 · 100 comments on HN
- 12Devirtualization in LLVM and Clang4 people · 65 points · first shared 2017 · 24 comments on HN
- 13The new Clang _ExtInt feature provides exact bitwidth integer types3 people · 199 points · first shared 2020 · 157 comments on HN
- 14Intro to the LLVM MC Project3 people · 56 points · first shared 2010 · 5 comments on HN
- 15Byte Type: Supporting Raw Data Copies in the LLVM IR3 people · 25 points · first shared 2025 · 5 comments on HN
What HN people wrote when they linked it
gtani · 2015-06-14
since you got no response:
- scrapers, spider/crawler and content extractor for NLP analysis
- analyze your hard drive for old, duplicate etc files
- Arduino/raspberry pi (challenging, very little RAM, can't use c++11, stdlib, etc
- CUDA
_____________
also you want to look at VC++, clang and gnu toolsets, e.g. "#pragma once" and the C++14 refinements. Meyers Modern Effective and Effective 3rd ed books are great for that. Also Lippman et al's primer
_________________
compiler blogs: http://blogs.msdn.com/b/vcblog/
http://blog.llvm.org/
http://developerblog.redhat.com/tag/c/
nkurz · 2022-01-21
Are you familiar with this classic example? http://blog.llvm.org/2011/05/what-every-c-programmer-should-know_14.ht…
The problem (if I understand it right) is that "Redundant Null Check Elimination" might be run first, and will get rid of the safety return. But then the "Dead Code Elimination" can be run, which gets rid of the unused read, and thus removes the crash. Which means that rather than being logically equivalent, you can end up with a situation where /* do real stuff */ (aka /* launch missiles */) can be run despite the programmer's clear intentions.
vlovich123 · 2021-09-14
The article is from 2010 (missing tag) so the author likely is talking about 32 bit x86 machines. Also compilers from that era were less likely to exploit UB if at all. Certainly knowledge about it had only started trickling out in the general industry at the time as compilers started exploiting it with Chris Partner’s blog about it following about a year later [1].
[1] http://blog.llvm.org/2011/05/what-every-c-programmer-should-know_14.ht…
xvilka · 2021-07-20
It's surprising how so many people still use MSVC when there's clang-cl[1]. Both Google and Mozilla use it for producing binary releases for Windows for years already[2][3]. MSVC has poor track record on following standards and lacked ASAN etc support until recently. And Visual Studio now can integrate with it smoothly [4].
[1] https://clang.llvm.org/docs/MSVCCompatibility.html
[2] https://blog.llvm.org/2018/03/clang-is-now-used-to-build-chrome-for.ht…
[3] https://blog.mozilla.org/nfroyd/2019/04/25/an-unexpected-benefit-of-st…
[4] https://docs.microsoft.com/en-us/cpp/build/clang-support-msbuild?view=…
pjmlp · 2018-11-22
C seems simple.
http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html
http://blog.llvm.org/2011/05/what-every-c-programmer-should-know_14.ht…
http://blog.llvm.org/2011/05/what-every-c-programmer-should-know_21.ht…
What about advocating best practices to write proper code to those still using C89 + compiler extensions without any kind of analyzers?
radarsat1 · 2017-09-21
Your comment surprised me as clang is regarded to be pretty competitive these days (compared to gcc). I don't know the current state of things but a quick search revealed at least one sentence, http://llvm.org/docs/Vectorizers.html, "the loop below will be vectorized on Intel x86 if the SSE4.1 roundps instruction is available." So it seems SSE4 is supported by LLVM?
I was going to say maybe it's a new thing, but the following post also talks about SSE4 and is from 2011: http://blog.llvm.org/2011/12/llvm-31-vector-changes.html
Maybe it only supports a subset of SSE4? Do you know the details, compared to other compilers?
pcwalton · 2017-06-30
Just for what it's worth, the way I'd fix that problem in the compiler would be to implement dead store elimination via global value numbering. With trivial alias analysis, the compiler would be able to detect that the result of the "duffzero" instruction (which I assume is a memset) is always killed by the "duffcopy" instructions and would eliminate it.
See this article for how it's done in LLVM: http://blog.llvm.org/2009/12/introduction-to-load-elimination-in-gvn.h…
pgvoorhees · 2017-04-10
Code for Airplanes (and cars and other safety critical applications) follows a special set of rules in order to eliminate wonkiness that tends to crop up in complied programs (usually the result of undefined behavior, not always the programmers direct fault).
See:
http://blog.regehr.org/archives/213 (particularly part 3)
http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html
laughinghan · 2017-04-01
> are there important projects that do this intentionally?
Expecting integer overflow to be two's complement is so common that successors like Java, Go, and Rust all standardized on it, used by hashing algorithms and more: https://github.com/rust-lang/rfcs/pull/560
> In any case, compiler authors are going to follow the C standards, not you hypothetical "C-in-practice" standards
"The optimizer does go to some effort to "do the right thing" when it is obvious what the programmer meant (such as code that does "* (int *)P" when P is a pointer to float)." --blogpost by the second most widely used C compiler, clang/llvm: http://blog.llvm.org/2011/05/what-every-c-programmer-should-know_21.ht…
AceJohnny2 · 2016-05-11
To add to the others noting the differences between C's behaviour and the underlying assembly, I recommend Chris Lattner's (the creator of LLVM) series of posts about Undefined Behaviour in C:
http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html
http://blog.llvm.org/2011/05/what-every-c-programmer-should-know_14.ht…
http://blog.llvm.org/2011/05/what-every-c-programmer-should-know_21.ht…
(HN truncates the text of the URL, but they're all different)
I've been coding C professionally for over a decade, as required for firmware/embedded development, and those posts have instilled the fear of god in me.
nostrademons · 2016-03-06
http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html
When behavior is undefined, the compiler can legally do anything up to and including formatting your hard drive or making your computer burst into flames. It's counterintuitive, but C compilers follow the C standard and not necessarily programmer's intuitions about C.
joosters · 2016-01-28
Whenever a story about UB comes up on hacker news, the comments usually fill with both the predictable "Don't use C" comments and also a lot of ill-informed ranting about how stupid all this UB is.
For the first group of commenters, please don't bother posting again, just search HN and you can find a lifetime's supply of C love/hate arguments.
For the second group of people, I'd recommend reading two fantastic guides to UB:
http://blog.regehr.org/archives/213
http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html
These should be enough to explain why UB is trickier than you think...
vinkelhake · 2014-06-27
Great article.
Articles like this and the three-part series about undefined behavior on the LLVM blog [0] ought to be required reading for anyone who still has the impression that C is "portable assembler".
[0] http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html
dreish · 2014-06-27
pascal_cuoq is correct. Here's an excellent introduction to the subject:
http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html
epsylon · 2013-10-10
In the debian fiasco it's mostly a case of "manual code elimination" [1].
However there are plenty of examples of compilers aggressively removing code that causes undefined behaviour. Basically, when the compiler encounters UB, it can do whatever it wants to code that triggers the UB, which means possibly removing it. Compilers exploit this fact a lot because UBs happen a lot in "normal code". See here [2] for examples and explanations; I also can't help but mention John Regehr's blog [3] if you're interested in compilers, security, testing, safety.
[1] http://research.swtch.com/openssl
[2] http://blog.llvm.org/2011/05/what-every-c-programmer-should-know_14.ht…
[3] http://blog.regehr.org/archives/213 is a great article for example.
mikeash · 2011-12-31
Bingo. Both returning NULL from alloc(0) and assuming that alloc() never returns NULL are correct behavior by the compiler. It's simply taking advantage of the nasal demons.
It seems that LLVM and Clang have generally been much more aggressive about taking advantage of undefined behavior, which has ended up breaking code that worked under gcc. For example, with some versions of Clang, if you try to write something like (int )0 = 0, it'll completely skip that line when generating code! Completely valid, since dereferencing NULL is undefined behavior, but not what one might expect after using a compiler that's more obedient.
There's a great post on undefined behavior in C, what it means for a compiler, and how LLVM and Clang deal with it here:
http://blog.llvm.org/2011/05/what-every-c-programmer-should-know_21.ht…
btilly · 2010-10-26
I think that http://blog.llvm.org/2010/04/amazing-feats-of-clang-error-recovery.htm… gives a number of nice features that clang brings to the table which could be very useful for kernel hackers.
xiongchiamiov · 2010-09-13
I'm not enough of a C programmer to say anything about the actual product GCC spits out, but I'm certainly glad of the work the clang team has put into improving error messages: http://blog.llvm.org/2010/04/amazing-feats-of-clang-error-recovery.htm…
pietrofmaggi · 2010-07-17
CLang Error recovery works like magics:
http://blog.llvm.org/2010/04/amazing-feats-of-clang-error-recovery.htm…
ryanpetrich · 2010-05-13
LLVM will attempt to guess the proper name of a misspelled identifier for you: http://blog.llvm.org/2010/04/amazing-feats-of-clang-error-recovery.htm…
obi1kenobi · 2022-11-28
Fortunately, this post includes a link to an excellent 45min talk on undefined behavior which does go into a fair bit of the detail you were looking for. I encourage you to click it -- it's right in the post's introduction.
The purpose of this post and other "falsehoods" posts is to shine a light on the existence of a misconception or set of misconceptions. By that point, there are usually plenty of other high-quality posts about "why / how / when" etc. but for a variety of social dynamics reasons those posts by themselves did not have the wide distribution and readership they deserved. After shining a light on the misconception, interested readers are generally able to continue the learning process both through the sparked discussion and through doing their own searching.
Here's a specific example of such a post with even more details:
https://blog.llvm.org/2011/05/what-every-c-programmer-should-know_14.h…
saagarjha · 2018-04-24
> if you think "You have violated something, for which we will give you no diagnostic, and therefore we feel free to crash you at some random other place in the program that has nothing to do with the place where the alleged violation took place, again with no diagnostics" is reasonable
No, I generally don't, which is why I use a safer language like Swift most of the time (well, that, and the fact that I can take advantage of a nicer standard library). You put "safer" in quotes, because I don't think you quite understand how compiler optimizations are supposed to work. I think Chris Lattner's three part series, "What Every C Programmer Should Know About Undefined Behavior"[1], is a great explanation from a compiler writer for why dangerous optimizations have to exist. It certainly helped me when I was in a similar place as you, not quite understanding why the optimizer did seemingly stupid things.
Really, the crux of the issue is that every language has tradeoffs: you can program in assembly and know exactly what your program is doing, but you lose the portability and convenience of higher level languages. Then you have the C family of languages, where you get access to some higher level concepts at the cost of ceding control to a compiler. The compiler's job is to generate assembly that matches what you are trying to do in the most efficient way possible. Of course, if it did so too literally it would be very slow to account for every single "stupid" thing you could have…
mschaef · 2018-01-11
> Both C and Make are decades-old technologies, but most people can read a C file without much experience and intuitively understand what is going on.
While they might think they know what's going on, I'm not convinced they actually do. C can be an incredibly subtle language to get right...
http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html
Regarding make, the thing to realize there is that it's just a DSL for specifying a dependency graph (and the way for satisfying dependencies). It's not a hard concept, but unless you come to the field with a bit of computer science background, it's not likely something you've been directly exposed to at the level required to understand make. But I don't know that this means make's choice of abstraction is necessarily a bad thing for its intended use cases. I also think this tends to put the lie to the notion that the difficulty is mainly around tabs... tabs may obscure the details, but switching to a clearer syntax won't solve the more fundamental gaps in understanding the mechanics of make.
I'll also argue that this is a potential problem with DSL's in general... because DSL's often don't use traditional imperative language semantics, there's always a bit of a learning curve that needs to be ascended. However, for make at least, there are a useful debugging tools to help understand what it's actually doing.
For me, at least, 'make -n' is great in that it instructs make to resolve the dependency graph based on…
dataking · 2017-04-14
SoftwareMaven · 2015-07-01
That's is not remove code due to undefined behavior, so is an apples/oranges comparison. If we keep your function, but the call looks like this:
int value1, value2;
value1 = compute_value_1()
ComputeStuff(value2) # oops, fat-fingered the '2'
Do you really think the author meant to not have ComputeStuff run? Since value2 isn't initialized, it could be optimized out.
Yes, in this case, you would get a warning, but it is illustrative of the kinds of things can cause optimizers to do very unexpected things to your code. And it is surprisingly easy to find the UB conditions.
It's worth reading through this three-part post called What Every C Programmer Should Know About Undefined Behavior[1] from the LLVM folks to see how UB can screw with you, including removing NULL checks, eliminating overflow checks, and making debugging incredibly difficult to follow. It also explains why they can't just generate errors while optimizing.
1. http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html
Someone · 2015-06-30
It also helps if your syntax supports error recovery. For example, if 'if' statements end with 'fi', 'do' statements end with 'od', and function definitions statements end with 'end', and you get 'if ... do ... fi', you can report that you are missing a 'od' in the program, and recover parsing after the 'fi'.
C is horrible in this respect; all nesting looks the same. Because of that it took clang lots of effort to get good error recovery, for example to correctly report a missing semicolon at the end of a header file instead of reporting an error in the file including it (http://blog.llvm.org/2010/04/amazing-feats-of-clang-error-recovery.htm… (NB: that page is 5 years old, and does not represent the current state of gcc))
gcc makes that job even harder by allowing nested function definitions. That means that accidentally forgetting a single '}', as in
void f( int i) {
if( i > 2) {
exit(EXIT_FAILURE);
}
void g() {}
[...]
void h() {}
will make the compiler think that g() and h() are nested function definitions. So, the error you get is a “missing closing brace" on the last line of your file. Without nested function support, the error would be reported on the 'void g() {}' line. Still incorrect, but potentially thousands of lines closer to the source.
The Algol compiler (helped by Algol's syntax) I used years ago was way better. It frequently gave errors of the form
"x undeclared. Assumed real"
(if, say, you call sin(x) without declaring x)…
pdkl95 · 2014-09-23
> fixing the C code, is in my experience, much easier
Really?
Did you account for the many very subtle ways you can run into what the C language defines as "undefined behavior"? I have only met a few programmers that truly understand that can of worms. Way too many don';t even know that compilers exploit these parts of the spec despite programming in C for many years.
http://blog.regehr.org/archives/213
http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html
That's just the cases where it it is totally legal for the compiler to output random noise - or output nothing at all - instead of what the C code says locally. These are some of the nastiest "gotchas" I've seen in any language.[1] Even the best C programmers are occasionally bit by this class of bug.
I still like C (a lot), but it is not easy. It's just so very annoying and time consuming to track down a bug happening in "foo.c" that is actually caused by a variable in "bar.c" didn't get updated waaaaaay earlier because some bit of code in "quux.c" was skipped over due to undefined behavior. Especially it becomes a heisenbug due to that particular optimization being turned off when in in debug builds.[2]
Bourne [Again] shell has its own share of quirks and "gotchas", but they are usually easy to investigate, and they are generally easy to avoid once you've written a couple scripts.
[1] There are other important classes of bug; I'm just using undefined behavior as an example because of how amazingly…
cliffbean · 2012-06-04
> 1. To give compilers some leeway when optimizing stuff (for examples, see http://blog.llvm.org/2011/05/what-every-c-programmer-should-...)
I'm curious about this. See below.
> 2. To make C usable for those worried about erroneous overflows in their code.
I think you're saying that the rule allows compilers to implement -fwrapv if they choose, which sounds reasonable.
> 3. To make it easier to write C compilers for CPUs that trap on integer overflow.
> 4. To allow for performant C compilers on CPUs that use one's complement arithmetic.
I wonder how much these matter nowadays.
For optimization, the blog post you cite describes the following examples:
- "X+1 > X" to true
- "X*2/2" to "X"
- "<= loops" and "int" induction variables
On the first two, presumably these usually only come up after macro expansion and inlining, however they're still suspicious. If a function is scaling its return value and its caller is de-scaling it, it's usually a sign that the API isn't designed quite right. I'd be curious to know how often these come up.
Code using "int" induction variables to step through arrays on 64-bit targets is often sloppy. Such code won't handle very large arrays properly, due to the limited range of "int", which is a bug that may not be quickly noticed.
And for the "<= loop" itself:
for (i = 0; i <= N; ++i) { ... }
it's really unlikely that the code is actually intended to be an infinite loop in the case where N happens to be INT_MAX. Code…
kenferry · 2011-07-21
Yes… let's talk macros first. Actually, first first you should look at multi-dimensional analog literals if you haven't seen it, http://weegen.home.xs4all.nl/eelis/analogliterals.xhtml. Awesome/yikes.
Okay, back. What are the reasons to consider macros? Probably, compile time checking and ability to directly use variables that are in scope (e.g., fooButton for some button).
The goal of compile time checking is really debugging, to make it easy to find and fix mistakes. Now, in a format string, we don't have compile time checking, but we can have really good, descriptive error messages. Our diagnostics were inspired by those in clang, http://blog.llvm.org/2010/04/amazing-feats-of-clang-error-recovery.htm… right down to the carat pointing at the problem within the code. Maybe we could have done that with macros? I guess I didn't really try that hard, but usually if you mess up a macro, you're going to get something really cryptic from the compiler. Also, it's wayyyy easier for the client to grok and feel comfortable with a format string than with a crazy macro system. You know how we're parsing the string. You could implement it yourself if you had to. It's understandable, and you can see that there won't be side effects. Now consider that multi-dimensional analog literals link above. Does it work? Heck yeah! Do you want black magic like that in your code, with behavior you don't understand (at least without way more investment in understanding than we want…