Configure player

Close

WWDC Index does not host video files

If you have access to video files, you can configure a URL pattern to be used in a video player.

URL pattern

preview

Use any of these variables in your URL pattern, the pattern is stored in your browsers' local storage.

$id
ID of session: wwdc2009-402
$eventId
ID of event: wwdc2009
$eventContentId
ID of session without event part: 402
$eventShortId
Shortened ID of event: wwdc09
$year
Year of session: 2009
$extension
Extension of original filename: m4v
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: [2009] [Session 402] Compiler Ov...

WWDC09 • Session 402

Compiler Overview

iPhone • 1:01:35

Catch up on the latest innovations in Apple's rapidly advancing compiler technologies. See how to use GCC and LLVM in your own projects to maximize application performance. Understand the innovations in LLVM-GCC and find out how you can use it in your own testing and development.

Speakers: Chris Lattner, Evan Cheng

Unlisted on Apple Developer site

Downloads from Apple

SD Video (120.8 MB)

Transcript

This transcript has potential transcription errors. We are working on an improved version.

[Chris Lattner]

My name is Chris Lattner and I'm here to start out the beginning of this talk. So before we get started I want to talk about where we're coming from because this is not the first WWDC and we've been shipping tools for a long time now of course and so we-- you can really split the tools that we ship into 4 different categories. If you're on the iPhone it's very simple.

If you build for the 2.0 or the 2.x series of SDKs you build with GCC 4.0. If you build with the 3.0 series of SDKs you're building with CG 4.2 and that's the way it is. There's no choice, nothing to worry about, it just works. 4.2 has a lot of improvements over 4.0.

In particular support for the new iPhone 3G S. On the Mac side of things it's a little bit more complicated. So as of last WWDC we supported 3 compilers: GCC 4.0, 4.2 and LLVM-GCC. This year we support the same set of compilers with the addition of Clang. So I'm going to take you through some of the enhancements that we've done with these compilers and then take you through all the exciting things we're doing. So let's get started. Most of this talk I should say is specific to the Mac.

The iPhone is, since you have no choice you get to use the great compilers we have and you don't have to worry about it. But on the Mac there's a lot more different options that you have so we'll talk about that. So the one, the first great feature that I want to talk about before we go any farther is Blocks. So yesterday you heard a lot about Grand Central Dispatch.

Grand Central Dispatch is a great API and Blocks are one critical piece that fits into that. But Blocks are really not specific to Grand Central Dispatch. If you think about a lot of APIs they are callback based and with a lot of callback based APIs you pass pointers to functions around.

Well, you pass a pointer function around until you realize that you have some data that that function needs and then you end up passing void pointers and function pointers around, right? Well, this really quickly gets nasty and gross. Blocks solve that. A Block is also known as a closure or a lambda in other languages and the great feature they have is that you can write code inline in the middle of another function and it's an expression.

This means you can write your code and in addition to representing code that can be passed around you can refer to variables outside of that code and so here I have a little Block and this Block iterates over all of the elements in the array adding N to it and is defined outside the Block and the great thing about Blocks are the compiler handles the packing of all the data for you and so you don't have to pass around void *s that you then cast off structs and all that stuff right.

It just magically is done. So if you use this with Grand Central Dispatch you end up using it sort of like this. You end up saying hey I have a unit of work to do, pass into Dispatch Apply which is the GCD API and then Grand Central Dispatch handles executing that in parallel on all of your processors for you. So this is a really beautiful, natural language extension and this feature is supported in GCC 4.2, LLVM-GCC and Clang.

So there's a whole lot more to say about Blocks of course and I'm not going to go into it very much in this session but if you want to find out more go to the Programming With Blocks and the Grand Central Dispatch section and they'll tell you about it. If you want to there's also discussion about it in the various Objective-C sessions throughout the conference.

So Blocks I want to single out because they're the major new feature that we've added to GCC 4.2. If you look at the other enhancements to GCC we've made, GCC 4.0 has only had a small handful of critical bugs fixed over the last year. GCC 4.2 has had 3 features or 3 changes; Block support which we added. It has some bug fixes and it switched to 64-bit by default.

Well 64-bit by default means that if you run GCC on the command line on a 64-bit machine it will default to producing a 64-bit binary bdut if you're using Xcode or you're passing the -arch series of flags you won't see any change. Aside from that GCC hasn't really changed. So if it's OK with you guys I'd spend the rest of the time talking about LLVM and Clang.

Is that OK? [Applause] So let's dive in. So a quick recap. What is LLVM? LLVM is really about a new strategy for compilers. Right we've been using GCC for many years. We all know it. It works but it's just not great. So we're shipping compilers based on LLVM. These compilers are available along with GCC so you can use them if you want to but GCC is still there.

Another great thing about it is that LLVM is open source so you can actually join in the development that we do with LLVM at the website, mailing list, bug trackers all that kind of stuff there. You saw the cool new LLVM logo that we whipped up for the conference. So the the dragon comes back too. The dragon implies like Dragon Book and compilers and you know all of that stuff that fits together, in case you were wondering.

So, so that's what LLVM is. So why not just fix GCC, right? Well the real answer is that GCC doesn't really-- it's not a strong platform for the things we want to do in the future, right. GCC is a compiler. It does what it does. But getting it to do anything that it wasn't originally designed to do 20 years ago is really hard. And so LLVM is really the answer for that and we want to do something new, we want to push forward.

I think there's a huge amount of innovation that we can bring to compilers and we're just starting to do that now. So LLVM is all about redesigning how we build compilers. We build them as libraries. We build them as libraries so that we can use them in new ways, in different applications.

So we can reuse them. So we can use, you know, an x86 code generator in some way that you know we never would have thought about when we built it in the first place. So we're focusing on building something that's fast, flexible, performant, supports all these crazy features.

In case you haven't noticed GCC has a lot of features and so making all of that happen has taken some time but I'm really happy to say that we're to that point now. And so now that all that work has been done we can start building on doing new, exciting things with it. So of course LLVM as we talked about yesterday is not just used in traditional compilers.

OpenGL, OpenCL and, excitingly, the static analyzer built into Xcode are really great demonstrations of what you can do with compiler technology that most compiler people don't think about, right. The static analyzer is a great example of how the compiler's data flow analysis can really be used to solve interesting problems that you know aren't really related to making code go faster, which is really exciting but you know very different [laughter We also have LLVM-GCC and the Clang compiler. So to tell you about some of these applications I'd like to bring Evan Cheng up on stage and he'll tell you about what we're doing with LLVM here at Apple. Evan.

[Evan Cheng]

Thank you Chris. [Applause] Good afternoon, My name is Evan Cheng. I work here at Apple's Compiler Team. So here at Apple we've been doing a lot of very exciting things with LLVM. I just want to go through a few of them today. I hope you enjoy it. First, you've heard Chris talk about LLVM, GCC, LLVM-GCC, Clang.

You might be wondering, what are these things? What exactly is GCC? How are they related? So LLVM is a set of libraries of philosophy. It's a dragon. It's many things. So how does it fit? Well if you look at a static compiler like GCC you can roughly break it down into 3 parts.

You have the front end that's responsible for parsing your program. Then you have the optimizer that transform your program to make it go fast, then the code generator translates that into the machine language. Well, think of LLVM-GCC as taking the GCC front end technology and replace it-- the optimizer and code generator with kind of a turbo charged engine, the LLVM optimizer and code generator.

It looks, smells, tastes just like GCC but it's better and we want to take a-- with Clang we're taking a step further by replacing the front end as well and just completely do away with GCC technology to produce and kind of stitch the Clang front end with LLVM optimizer and code generator to produce a Clang opt-- compiler.

It's very exciting and Chris is going to talk to you all about Clang later. But for now let's focus on the LLVM. So again LLVM if you take a look at LLVM-GCC it's just a traditional static compiler. One of the major things was a static compiler, one of the common things with a static compiler is depending on other tools to kind of take the code that's generated by the compiler and produce an executable. So for example LLVM-GCC and GCC both produce assembly code and then requires assembler and linker to kind of produce executable. Well the other compilers out there right? Compile their embedding applications in the OS in many of the ways that they-- they compile code at the runtime.

We call these just-in-time compilers or dynamic compilers. So these are not new. The new thing with LLVM is we take the same optimizer and code generator and we produce static compiler but we can also use it to produce just-in-time compiler. So here at Apple we use this reusable components LLVM, we'll call it the LLVM back end, to produce a number of different applications, you know, different JITs imbedding as part of OpenGL and OpenCL.

Let's take a quick look at them. First OpenGL. You know OpenGL? This is a language for you to program your GPU to do 2D and 3D graphics animation. Well OpenGL is a very big standard. It has many, many features. Not every graphic card support all the features that's in OpenGL.

When that happens the OpenGL system will take the function you press and basically dynamically compile the code into-- into code that's executed on your host CPU. There are couple of ways to kind of support this, right? The older implementation used custom JITs and interpreter this to support this.

The problem with custom JITs is every different architecture you you have to have a different custom JIT for it. Well the problem with this is obvious, the higher engineering and maintenance cost and furthermore as OpenGL evolves and you add new features you required to have-- put in more optimizations to support these new features.

That's not that easy to do with a custom JIT framework. So one of the ways to deal with this problem, we can fall back into an interpreter that supports all the features, runs on all the platforms. The problem with interpreter is it can be over 100 times slower in some cases. So we have replaced OpenGL interpretation with one that's based on LLVM.

The great things with LLVM's code generator is it can target a variety of different architectures and a single optimizer, single code JIT that supports everything and it's because this general compilation framework is really, really easy to put in new optimizations, support the new functions that's in OpenGL. So the result is a more rigid, a more flexible framework OpenGL implementation and we have learned that turned out to be faster than the old implementation.

The next example is OpenCL. OpenCL is this new technology in Snow Leopard you heard a lot about. Well if you boil it down to is it's a new way for you to write C programs to tap in the computation power not only on your CPUs but on your GPU as well. This is a very powerful way of programming. Of course to support this you need a number-- kind of interesting technologies.

You need a C parser that's fast and a small memory footprint that can embed into the OpenCL system. You also need a back end compiler that is capable of targeting not only your CPUs or your GPU as well. Of course it's no surprise OpenCL is built on top of the Clang front end and LLVM backend technology. And not only that, the whole point of OpenCL is speed. You want to run your program fast.

So the compiler must produce great code and must compile really, really fast. Well, in Snow Leopard we have replaced a core image implementation from a custom JIT, a very well-tuned custom JIT implementation to one that's built on top of OpenCL and the result is 25% speed up. That shows how powerful the OpenG-- how powerful OpenCL is and how powerful the LLVM technology is.

If you're interested in learning more about OpenCL I encourage you to go to the Introduction to OpenCL talk on Thursday. So LLVM is a very exciting compilation technology. It's very powerful. For you developers you want to take advantage of it by compiling your code with Clang or LLVM-GCC. For the next part of the talk we're going to focus a little more on LLVM-GCC.

Why is it the worth the upgrade from GCC? When we designed LLVM-GCC we have a number of goals in mind. We wanted it to be a drop-in replacement for GCC. If you're compiling your code with GCC you should be able to you should be able to migrate your LLVM-GCC by selecting a different compiler. There's nothing else you need to do. So the first thing we want to support is 100% source and binary compatibility with GCC.

And of course there's a lot of GCC features you've come to rely upon. LLVM support every-- LLVM-GCC support all of the major features that GCC provides. And of course this is on top of LLVM so you expect it you expect it to be fast, compile code fast and generate fast code. So last year at WWDC we introduced LLVM-GCC as one of the compilers. We support-- it was a great release of LLVM-GCC.

It supported a majority of the GCC features but we left a few things out. But this year we added support for stack canaries, obviously a new Blocks feature, OpenMP and we really improved debugging support. So this year we're very happy to say LLVM-GCC now support all the major features of GCC. [Applause] Thank you.

Next let's turn to the things that make us compiler geeks really excited: Speed. So speed is 2 parts right? Compile times performance as well as speed of the generator code. So we have a different philosophy here. Because LLVM is going to be part of the runtime system it's build to be a JIT and part of the operating system. Compile-- compile time speed is very, very important to us. So we really worked very, very hard in this area.

We want to compare LLVM-GCC against GCC. Well the example I'm going to show you is AppKit which is a very, very large Objective-C framework and it's thousands of thousands of source files. We found, this is only one example but the results are pretty representative of everything we have tried. Let's look at compile time. So we're going to look at both release mode and debug mode. In release mode the default compilation option is -os. That means compile-- optimize for size but not at the expense of speed.

This turns out most optimizations. In debug mode it's -o0-g. That turns out just about all of the optimizations done and code generated really, really fast. So as you can expect, debug mode compiles really, really fast compared to release mode. Let's see how LLVM-GCC does. Well in release mode LLVM-GCC is 1.5 times faster, 35% faster than GCC.

What does that mean to you? Well I'm sorry to say we have shortened your coffee break by roughly 8 1/2 minutes here but-- for your productivity has just gone through the roof. And how about debugging-- how about debug bill Well last year when we released LLVM-GCC we noticed LLVM-GCC is doing way too much work at -O0. We still try to optimize your code even though you don't care about it. So it turns out LLVM-GCC was slower than GCC last year. Well this year we've put in a lot of work.

We're caught up and surpassed GCC by a bit. So you might be wondering why is it only 5% difference. Notice with optimization turned off majority of the compile time is in the front end; parsing time. Since we share the same front end technology as GCC there's not a whole lot we can do here. Of course that's the excuse, but we don't want to use that excuse. We want to do a lot better.

We'll talk about that later in the talk. So LLVM compile your code faster. Does it compile code-- does it make-- generate better code than GCC? We want to compare-- do the comparison across a number of benchmarks and focus on Intel performance for 32-bit and 64-bit. Let's see how we do. You have seen a number-- a different set-- a lot of numbers in the DT's State of the Union Talk. For this talk we're going to focus on a smaller set of benchmarks. First let's take a look at OpenSSL.

OpenSSL as you know is kind of open source cryptography library that a lot of applications are dependent upon. The data points here are different ciphers, different message digest systems. They all behave differently; have different reaction to compiler changes. So the speed up here as you can tell is across the board right. Some cases we do slightly better than GCC, 4%, 5%, but there are cases where we are over 20%, 30%, or over twice as fast than GCC. Think-- think about what that means to your application. That means a secure transfer goes much much quicker.

[Applause] Thank you. [Applause] In 64-bit the diffedrence is not quite as dramatic but again most of the cases we win-- LLVM-GCC wins. The difference could be small or could be over 20% faster. So at this point you may be wondering is there a way I can tell LLVM-GCC to work really, really hard? You know just give me the best you can do, forget about everything else. The answer is yes. Now LLVM-GCC provide you with a Link Time Optimization feature. What does Link Time Optimization do? Why can it can squeeze more performance out of your program.

Well Link Time Optimization is a way for LLVM to optimize your code by looking-- working across all the files at the same time. So traditionally when you compile you compile one source file at a time. The best the compiler can do is look at all the function in that single source file.

With Link Time Optimization you still compile one file at a time. For the linker at link time is going to take all of the source code and it's going to call back to the LLVM optimizer and code generator. So it will work on your complete set of source files at one time. It's going to do aggressive inter-procedure optimization.

For example it can inline one function in one source file into another function in a different source file. It can do all kinds of very aggressive optimization. What does that mean? It means it sometimes can squeeze out performance that even the programmer may not be able to do because it can work on such a big scope. Well let's see how what LTO can do.

Take a look at the OpenSSL example. Here we're looking at 2 data points. In one case LLVM-GCC already does quite well, it's 20% faster. In another case it's behind GCC by 1%. With Link Time Optimization turned on the first case got even faster; 5 additional percent. The second case got 10% faster.

It turns a slight loss into win. Thank you. [Applause] Here's another case: JPEG decoding. JPEG is such a well known compression standard. The decoder has been worked on over the years of being tuned and tuned and tuned. There's really not a lot of room for improvement. In fact LLVM-GCC doesOK. It can be 1% of performance benefit. Not interesting. With Link Time Optimization we're able to squeeze out 7% additional improvements.

Link Time optimizing is very powerful. It's also extremely easy to use. With our implementation of Link Time Optimization all you have to do is go into Xcode, change the configuration compile configuration and select Link Time Optimization. If your project's makefile-base-- makefile-based it's also really easy. Just add the -flto compile time option. Alternatively you can use -04 which is equivalent to -03 and -flto.

So we know LLVM-GCC is a great compiler. It's relatively young but it's also very mature. It's product, it's a production compiler. In the Snow Leopard you got, we already building several bits of the Snow Leopard with LLVM-GCC. CoreData, of course OpenSSL, but also Java HotSpot. I'm pointing out Java HotSpot you know because it's such huge cross-platform project.

It's millions of lines of C++ code. Used every trick in the book to get performance. If LLVM-GCC can compile Java HotSpot it can probably compile your C++ project. So to recap, how does LLVM-GCC compare to GCC 4.2? Well we got all the features that GCC provides. It will also give you Link Time Optimization.

And LLVM-GCC generate better code than GCC. And LLVM is also significantly faster in terms of compile time in release mode. In debug mode we are only slightly better. So we need to rethink the problem. We need a new front end technology, new parsing technology that's a significant faster, that's where Clang comes in. I'd like to ask Chris to talk to you about Clang.

[ Applause ]

[Chris Lattner]

A new front end technology. Why would we do that? I mean C's has been around for years. How could possibly improve a C compiler right? Well it turns out there's like a few ways [laughter]. So what is Clang? You've heard about this a few times already.

It seems like we like to overload terms here so LLVM means about 4 different things depending on what context you're asking. Clang also means several different things depending on who's asking and what they're asking about. The first Clang is a set of libraries, a set of libraries built just like LLVM is and so right now this implements a C and an a Objective-C front end and it follows the normal LLVM design approach so we go for modularity, readability and this is what allows us to build the static analyzer, right, which uses the front end but not the code generator LLVM.

Clang is also a compiler so you can pick it out of Xcode and use it to build your apps and this combines the strengths of the Clang front end with the power of the LLVM backend and optimizer. Finally Clang is also an open source project. Clang has a much better webpage than LLVM does [laughter] and you can find it on clang.llvm.org.

So why do we care, right? Well, the great thing about being a compiler person is that you know people make fun of you and-- oh wait, no, that's not the right thing. The great thing about being a compiler person is that you can build tools that you use yourself. Right and this is the same for all the developer tools. Right we build tools because we're programmers and we want programming to be fun.

We want-- we do this all the time. Let's make it great. And so that's why we care about things like fast compile times, fast generator code and great features. So Clang and LLVM going forward are really where we're investing this. We think we can make things a lot better than they are now. We can push forward and there's a lot of work to be done.

So I'm going to do the first ever compiler demo that I know of just to give you an idea of what this feels like. So here I have a simple objective CF called Blast F. This is a developer example that we showed before and you can download it from the webpage and like many applications this with builds with GCC.

And so if we build this guy with GCC you can see how this works. Just make sure it's all clean and we hit Build and we can see 1, 2, 3, 4, 5, 6, you know, roughly 6 seconds to build this in. Well switching to either LLVM-GCC or Clang is really easy.

You just go to either your target or your project settings in Xcode and you say Edit Active Target and you get a nice list of different options and you can search for compiler and then one of the options here is the compiler that we're using. Right and so here's GCC.

And so if you pick this guy you can pick a number of different options. You can pick Clang, you can pick LLVM-GCC and they all work really well. One nice thing about picking Clang out of Xcode is if you have a mixed project that has C++, Objective-C++ all mixed together in the same project that the C and Objective-C pieces will build with Clang and the C++ and Objective-C++ pieces will build with LLVM-GCC. So it's completely transparent. So now that we've picked that we're done. All we have to do is hit Build and you see 1, 2, 3, whoa-- OK.

Well [Applause] So so the reason I like to do this is not because it is, you know, a specific percent faster than GCC. That's really not the point. I mean I'll show you numbers later but the point is that Clang feels a lot faster. It's not just one of these theoretical numbers that you throw up on a chart. Just doing development with Clang it-- it-- it's a much nicer experience and I hope you agree. So if we come back to the slides and keep going.

[Background sounds]

[Chris Lattner]

So I gave you a brief introduction of what Clang is. I want to talk about several different topics related to Clang: compatibility, specifically GCC compatibility. This is the limiting factor of whether or not it will actually work with your code. Talk about compile times. Give you some more, more detailed numbers than you saw yesterday. Talk about some nice features that Clang has.

I think that you'll like some of these and then we'll wrap things up in the end. So the first thing that we want to talk about when it comes to compatibility is C++. Well I know that many of you are thinking, oh, Clang only supports C and Objective-C and I use C++ for everything or a big chunk of my stuff and therefore Clang's irrelevant. Well obviously C++ is a critical language for us. It's a critical language for Apple. It's a critical language for our developers and we're-- I'm happy to say that we're committed to implementing this.

It's a ridiculously huge language [applause] but we're gonna do it. Beyond just doing it we actually intend to do a really good job because one interesting factoid is that Clang itself and LLVM itself is all written in C++. So we have-- we have some motivation to do this. I've also noticed that C++ has-- C++ compilers seem to have some room for improvement too [laughter].

Maybe we'll be able to do some good things there. So that said Clang currently has no C++ support as we said before and so if you've tried to build an Xcode project using C++ we'll use LLVM G++ for you and your program will build just fine and you just won't get the benefit of Clang on the C++ code. So I'm happy to say that not only are we committed to doing it in some abstract theoretical way we've actually been working like crazy on this.

Right C++ is a big enough feature that you want to start early because it takes time to do and not only are we to the point where we can do things like you know references and you know bool and you know really exciting features like that we're to the point where last week we started implementing things like partial template specialization and other features that are actually you know real C++ things. The caveat being that C++ is a huge language and there's still a lot to be done. So if you're interesting in learning more we have a lot of details about C++ prog-- C++ progress on the webpage and you know patches welcome [laughter].

So command line compatibility; so continuing in our theme of compatibility, one of the the big things we wanted to make sure that you could do is take Clang and drop it in and build your code with it. Right and so because of this we've worked really hard to make Clang as compatible as possible with GCC even on the command line.

And so this means that all of your favorite or most hated command line options for GCC should work just fine. This means that if you have a makefile you can just set CC = Clang and it's in the Developer/usr/bin folder in most installations and it should just build just fine.

If you do this you don't get the auto fallback to LLVM G++ and so you usually set CXX and your makefile will do the right thing. It should be really easy to use. The next thing is source compatibility. So who here loves it when you upgrade your compiler and then it says, oh, you have an error that you didn't have before? Is that your favorite feature of compilers?

Yeah.

[Chris Lattner]

I'm not seeing a lot of hands here. Yeah, I've noticed that too and in fact any major-- any difference between compilers really prevents it from being adopted. Right because if you upgrade compilers and say, oh, I have 10,000 errors. Is it really worth it, right? That's going to take a lot of time to adapt, to change your code.

Well I'm really happy to say that we put a ridiculous amount of work in making Clang compatible with GCC. So not only do we support the C standard we also support a bunch of GCC extensions. So things like inline assembly is a obvious one that many people use.

We support a broad range of GCC extensions. We also support a broad range of interesting quirks you know that are dubious and then even some outright bugs that GCC has that that real code depends on and we're committed to doing things right and so if we have you know a bug or a quirk here depending on we'll have to put out a warning where GCC wouldn't-- the nice thing about that is you can decide whether or not you care about it and you can deal with it at your leisure. But this means that you can basically just pick up Clang, use it and it and it should work which is very powerful.

That said Clang still is a relatively new technology and when Clang builds your code you should have confidence that it does work but if you use a feature that we haven't implemented yet you'll get an error from Clang. And so if you use OpenMP for example Clang doesn't support that yet so your program in the case of OpenMP just won't be parallel.

If you use nested functions or the crazy underbar underbar label thing or a couple of other really similar levels of obscure features to GCC Clang will output an error and say hey I can't build this. For right now that means that you have to build your code with LLVM-GCC. Sorry [laughter].

That said we've run a ton of code through it and so we're pretty confident that the major bases are covered. So Objective-C is very similar so we also want to be extremely compatible with Objective-C. The only difference here is that there are a few things we intentionally decided to remove from Clang and these are things that are either wildly incorrect that we discovered in a new implementation of the language or some things that we're already deprecating in GCC.

I'll give you an example of these and I hope you agree they're pretty, pretty gross. So if you depend on these you're going to get an error message out of Clang and it should say, this is this is invalid and we don't plan to add it and so if you use these you should fix your code and there's 2 reasons to this. 1: We're moving to Clang and so you need to eventually get your code to build. A second big reason is that the stack analyzer uses the same parser as Clang.

Right, or it uses the Clang parser and so it won't work on your code either, and so fortunately these are pretty weird things [laughter]. Cast of Super is one example of that so Cast of Super is one of the instances I've seen have occurred when people were passing around instance variables and they change the call super instead and a cast remained.

Well in Objective-C super sends a message to you-- sends a message to your super class. Super is not supposed to be an expression, it's supposed to be a magic token in there and so we fixed this and usually it's just a matter of removing that cast from your code.

Cast of L-Value is another interesting example. Cast of L-Value is a crazy GCC feature that even they removed from their compiler but we had it accidentally enabled for Objective-C and so some of these guys snuck into some Objective-C code base-- code bases. So this was up and a warning already with GCC. So hopefully you've already fixed this.

Generally instead of assigning into a cast you cast the thing that you want to assign and it's a much better way to go. The third one is really interesting, so this is 64-bit specific and 64-bit we-- 64-bit Objective-C uses what's called the non-fragile ABI and this allows at link time you to add instance variables to your classes. Well that means that the size of an interface is only specified at runtime.

It's not specified at compile time and GCC lets you use sizeof, well what does sizeof give you? Well it gives you the size of the class when GCC saw it and that's not the same size as when you run your app which is a pretty scary situation. The fix for this is real easy. You just change your code to call the Objective-C runtime function, class_getInstanceSize, and that's all you have to do. So I hope you agree these are some pretty weird and pretty quirky things.

Most Objective-C code just builds just fine the first time. If you try Clang and you have any problems, you're welcome to come to the lab tomorrow morning and a fleet of compiler engineers will be happy to help you with the code [laughter]. So the last thing I want to say about compatibility is a gotcha. So the-- the trajectory of C has followed a couple of different steps.

You know before 1989 there was no standard in C, it was this weird soup of different implementations and nobody's compilers agreed. In 1989 the language was standardized and the Anzio and the ISO language standards and that gave us C89. 10 years later they had a new language standard called C99.

C99 adds a whole bunch of features to C. Well GCC is always defaulted to C89. And so now I'm happy to say that Clang is going to leap into the feature and default to a language that is only 1 decade old, not 2.

[ Laughter and applause ]

[Chris Lattner]

So C99 is pretty much a transparent extension to C89. There's only one minor thing and that's inline. So if you build your app with Clang and you specifically say the compiler should use its default compiler and you get some link errors you may find out that those are inline functions and so inline changed between C89 and C99.

The easy solution for this is just to change inline to static inline and it will work in both modes, it'll work with GCC, it works with Clang and everything is good. The other fix for this is you can explicitly say, hey, I want C89 and you can do that either in Xcode with the C language dialect setting or you can say -scd=C89 or gnu 89 on the command line.

It's really easy. And so if you don't tell Clang what language to use for C it will pick C99. Should be pretty straightforward. Those are the only compatibility gotchas that we really have to talk about. So we built it to be extremely compatible to GCC. You should just be able to drop it in and it just works.

If you're using a feature that Clang doesn't support it should tell you and if you're using something crazy that we intentionally removed it should tell you that, and there's a C99 thing. So it should be really, really straight forward to adopt. So compile time speed. Most of-- this one's interesting. Yesterday Andreas told you that Clang compiles code twice as fast as GCC. That's true but it's only part of the story. If you look at how much faster Clang is than GCC it's a lot more interesting.

So here we have a whole bunch of different applications. The ones on the left are a bunch of Apple applications like Mail and Automator and Dashcode and even Xcode. These guys are a couple of open source applications and these are some developer examples that we've shown. Just for a range of different source code. If you look at how much faster Clang is and how much faster the Clang compiler is than the GCC compiler it's actually pretty fast.

Right so [applause] I'll talk about why this is later but you can see in almost all cases, results vary of course, but in almost all cases Clang is almost 3 times as fast as GCC. That's a pretty big victory right there and well it's not an accident of course, this is because we've fought and fought really hard to make it happen but this is also in a debug configuration. So this is in the configuration where you're almost completely front end bound. Right so this means your -O0 compiles which is where we all do our development in should be a lot faster right.

So if the compiler speed is only part of the story and so the compiler being fast is good but when you do a build you do a lot of other things. You run the build system. You compile some NIB files, you copy files around, maybe you have some custom build scripts and other stuff in your project and so if you look at total build time there we see it's about twice as fast. And so Clang is about twice as fast when you include all of the other stuff that we haven't sped up. And so this is what you see when you when you do actually build from Xcode like I did before.

So that's great because this is what you care about right. An interesting note here is that that there are things that you can do that go wrong and so Dashcode, the interesting reason that it's a little bit slower is it uses a custom build step that uses a Java app to do some compression or something like that.

I'm not familiar with all of the details but if you do custom build steps of course the compiler can't help you. So I think that's-- that's-- those are some amazing results and the question is how do we do it? Well there's not one easy answer right. I mean it's not like we fixed one problem in GCC and magically got it dramatically faster.

If you boil it down there's you know thousands of specific engineering decisions we made or that, specific design decisions we made to to to achieve this. You know we can wave our hands and say it's better algorithms and less memory but I want to give you an example of of 2 things. One is this LLVM and Clang separation.

So GCC when it was implemented you know 20, 25 years ago was built as a C compiler you know for VAX or something. Where they brought up the code generator and they brought the C front at the same time and because they did this they got intertwined a little bit because it was easier. Well over time and over the next 20 years it got even worse and so it's this big intertangled mess.

Well the problem with that is that GCC spends a lot of time and even more memory doing things that don't matter. So specifically if you look at like a structure declaration, GCC saves space, memory for-- in a structure declaration for backend code generator stuff right. Well in our system we have huge headers with millions, well not millions, thousands of structure declarations and enum constants and all this stuff right. Well any 1 .m file doesn't use most of those and so if you spend memory on that you're just wasting it right because the code generator doesn't code gen stuff you're not using.

LLVM and Clang are very different I mean I think you'll believe me that LLVM doesn't depend on Clang because we've been using it for a long time before Clang even existed, that we've intentionally built Clang to be separate from LLVM as well. This is to allow things like the static analyzer and other things that don't use the code generator right? Well the good thing about this is that if we-- keeping them separate and unentangled really helps us both in purity and reusability and all that stuff. But it also means that we spend time and memory doing things that really matter. We only spend memory on stuff that-- for the code generator actually goes through the code generator.

This is not that novel of a concept but it's actually a pretty big design decision in GCC that would be almost impossible to reverse, right, and so this is an example of design and how it impacts performance and memory and all that kind of stuff. Another thing I want to talk about is precompiled headers.

Precompiled headers are what we use on the system to handle the fact that you have 10 MB of headers coming into your 100 line.m file right and so if you're not careful you spend all of your time parsing these header files, right So if we look at PCH we can look at how GCC and how Clang does it. Well there's 2 scenarios, generation and use, and you can see that here we're looking at memory use.

GCC spends takes almost 125 MB to generate a PCH file for say Cocoa.h but it only take 48 MB of memory when you use it. Well that's good because when you only generate once and then you use it a lot of times right. Well we've finally optimized our PCH implementation to be dramatically lazier. So instead of pulling in everything off the disk we only pull in the declarations and the types that you are using as you compile a file.

Because of this Clang uses substantially less memory and when we generate the PCH file this is head to head engineering difference right because of things like we talked about before and so you can see by just by engineering it differently or better it's twice as good. By-- but by being-- making it dramatically more lazy we really got a 4X reduction of memory use. Well this can really impact your build right.

If you have a laptop that doesn't have very much memory it's quite possible you're going to be swapping with GCC. Well going from a scenario from when you're swapping to not swapping is more than 2X speed difference right and this can be a huge, a huge difference in your build performance.

Well beyond just being faster or using less memory, PCH files are also dramatically smaller right and so if you're using network builds or other things where you're shipping PCH files around, this could be a huge impact. And so we've really put a lot of work into finally optimizing specific pieces of Clang that are used and really important in our scenarios right.

And the problem is that with GCC the GCC folks really care about building Unix apps and Unix apps typically are C files with you know a 10,000-line header file right. That's not the way our system works and so we're not getting a lot of support from the community to help improve GCC in this respect and you know at the end of the day the design would be very difficult to fix anyways and so that's why Clang is-- that's why we can push Clang forward and we can do the right things for our system and the results I think speak for themselves. [Cough] So--

[ Applause ]

[Chris Lattner]

So I've told you all about how we want to be exactly like GCC but faster right? Well I have a hard time being limited to doing exactly what GCC does because GCC really isn't that great at a lot of things. So can we do anything better than GCC? The answer is yes, right. So I won't talk about error and warning improvements. Andreas talked a little bit about this yesterday but I want to give you some more examples right.

Errors and warnings, what we call diagnostics are really important. It's not some glitzy feature, but errors and warnings are things we deal with all the time. If you can make me be 30% faster at getting to the problem and fixing it then that's, you know, multiplied by 100,000 bugs that I introduced in my own programs and that makes me a lot more productive, right? So we put a lot of time into this and this is something that really matters.

The problem of course is that GCC is just really not great at this. Here's a typical example. So here I have some apparently perfectly legal code and I compile this and I get this very insightful message from GCC, right. Yeah, so I've gotten to the point basically when I'm using GCC I don't even read the messages anymore.

I just find the line number; I go scrutinize the line and try to figure out what I did wrong, right. That's how bad it is. Well, with Clang we want to push this much further and we want to do a lot better and so of course, like I say, we are, right. So here's an example, same example and the difference between what GCC tells you and what Clang does, right.

Here Clang will tell you hey, I don't know what NSString is. Well obviously I forgot to include Cocoa.h right? Well that message doesn't tell me anything about what the compiler is thinking and it is legitimately a hard problem and it takes a lot of work because the compiler just knows something is wrong, it has to guess or infer what you did wrong and tell it to be able to explain in a way you understand. But this is a problem that's worth solving and so we've put a lot of effort into it.

And this isn't just isn't for Xcode. If you run Clang with a command line you can also see very nice looking output. In this case we actually print the error and the line of code that it occurs on to the command line which is really nice when you're doing command line development. Another example is range information, so here's here's a great example from yesterday where we have 4 plusess on the line and GCC tells us something is invalid right.

Well in Xcode it's beautiful, you get these awesome highlights of the subexpressions for these kinds of things and it says, hey, this subexpression is the problem. This is really useful when you have things that are like precedence issues and things like that. This is also really nice for saying, hey, this is supposed to match that, and the compiler can highlight those and say what's happening. The same thing also happens on the command line.

We, we underline the various pieces and we only print out one line so it's not quite as nice as Xcode but if you have errors that are standing thousands of lines anyways then hopefully you can fix it without that. But these are just 2 examples right. I want to tell you a couple more cute things. Let's look at macros. So macros are really interesting because often you don't know something is a macro.

Here I'm just calling MAX right and I include the definition of MAX just so you can see it but I didn't-- I get some error message from the compiler saying hey I have invalid operands, right, which is the generic message saying there's something wrong. I didn't write a greater than. I don't even know that's a macro and I'm getting something from the compiler that doesn't make any sense to me right. Well with Clang it's really nice because the front end has been designed to keep track of this information.

Not only does Clang tell you that you have that error it actually unwinds all of the macro instantiations that are involved in that and it tells you the different levels and highlights and so here you can say that is the greater than, that's the problem and here's where it came from. In Xcode in the build results window you can click on the instantiated from line there and it will jump right to the macro definition so you can look at it. It's really powerful and really really nice.

[ Applause ]

[Chris Lattner]

But that's not all [laughter]. So there's a lot of other things we've-- a lot of other improvements we put into this. How about warnings? You get a warning out of your compiler. The compiler inevitably has some flag that controls that warning but how do you figure out what it is? Well Clang tells you. It says hey here's a warning, if you don't want this warning that's the flag that controls it. I'll talk more about controlling warnings later. It's a very simple thing right. If you design it in so that you have a database of warnings, right. Well one more example.

So this is a little picky but this is the kind of thing that has always irritated us which is here I have forgotten a semicolon and GCC tells me that it's on the curly brace line. Well that's not where you put a semicolon. What's it talking about right. I mean Clang will actually tell you you're supposed to put it there if you click on this in Xcode or you click on the build results window it will actually go to the right place so you can hit semicolon instead of going to the wrong line right.

I mean this is little details like this but this kind of stuff adds up over time. And coming back to C++ a lot of the improvements we made for Clang for diagnostics are important and useful in C but I think that C++ is where a lot of it will pay off.

So C++ has things like type defs. Right, well Clang is very good at preserving type def information and the idea being that if you get a error about SGG string you get an error about SGG string instead of SGG basic string, you know, all that kind of stuff right. So we put a lot of effort into making this great.

I think that-- I think that you will like it. You should play with it. Talking about warnings. Warnings are really interesting right because there is a lot of ways that you can control them So you can control them with the -Wfoo flag for the foo warning. You can also turn it off with Wno-foo.

You can also turn it into an error with -Werror=foo. But one of the things that I've talked to and maybe I hang out with some very pedantic people but a lot of people like building with Werror right and if you build with Werror [applause] if you build with Werror you get one warning, you're dead. How do I get rid of it? Maybe I can't change my code right? Well I'm happy to say that you can actually turn off specific warnings.

You can even turn specific warnings back into warnings in Werror mode and so if you build with Werror-Wno-error=foo this says I want all my warnings to be errors except that one right there and you can either make it a warning or you can make it just completely ignored and so this is really nice.

This lets you do things. But there's a little bit more right because this lets you control on a per-file basis. Wouldn't it be nice if you could actually have a little bit more control over this? Well something that people have suggested to us for years that's very difficult to pull off is controlling warnings within the file right. I have a specific warning I want to get rid of. Stop it now! [Laughter] Well with Clang you can use a simple fragment to control this.

You can say ignore this warning at this point or turn into an error at this point. Right this is really great if you have something like Bison producing C file and you know Bison injects all of this code that does all of these horrible things and you know produces warnings. I love Bison, Bison is great. [Laughter] But I mean you can use this for a lot of different things. Combine this with the fact that Clang tells you what warning flags control various warnings and suddenly you have full control over what's happening in your compiler.

Amazing right. So--

[ Applause ]

So so we put a lot of effort into making this really nice and really powerful and one other nice thing about using pragmas is that you can use this in your code and GCC will just silently ignore them and so you don't have to do if defs or any other weird things, this is just-- you can just use this in your code and there's no problem with that. Let's talk about something else. So we explain that OpenCL uses vectors or OpenCL uses Clang right.

And OpenCL is all about performance and one thing that is really important for performance is vectors. Well Clang has a lot of really nice vector extensions that you can use directly in your code even if you're building applications, you're not using OpenCL. So here I show you the kind of gross horrible syntax for defining a vector type. This-- with this definition I get a new flip 4 and this says I have a vector of 4 floats. With this I can now declare some vectors. Now GCC has a vector extension that is similar to this.

They call it the generic vector extension. Clang also supports that extension. But while you can declare vectors and you can do basic operations with the GCC vectors. You can do things like loading them, storing them, multiplying them, element wise, adding them, stuff like that. There's no way to get to the elements of the vector. If you want to get element 4 you have to make it a union with an array and then use the array to get the element of that vector.

That's horrible. I mean the whole reason you're doing this is for performance right? Now you're going to memory? Why are we doing this? I mean that's bad. Well Clang has a lot of really nice syntax for doing this. If you want to get to element 3 of your vector you use subscript 3.

This is where you guess. This is amazing technology.

[ Applause ]

It also has a number of nice things from OpenCL like access to all of the even or the odd elements of a vector. If you're doing things with complex numbers for example this is a really nice way to extract out all the real or the imaginary components. It also supports GLSL-style swizzling operations so you can say v.xxxxx to get a splat of all of the X elements. We even have a built-in that you can use to do a fully general permutation of any 2 vectors.

In this case I'm taking one element out of the 1 and 3 elements out of V2 and doing my own custom mix right and because this uses the LLVM backend you can be sure you're getting really good code out of that and this is how OpenCL works and it's-- it's a very powerful set of extensions.

It lets you write really portable and really powerful code. So if you want to learn more about the syntax, the Introduction to OpenCL session can tell you all about that-- all about this. I only have one slide on that. So the the question now is can I actually use Clang right? So I told you hopefully why Clang is really cool, why you should want to use it. So now can you actually in fact use it? Well I'm happy to say that yes in fact actually Clang does actually work.

It might be hard to believe [applause] so we've been working on Clang for a long time now, 2 1/2, 3 years, something like that and Clang, remember, is building on the LLVM code generator and optimizer so it's using the exact same well tested optimization code generation technology LLVM-GCC is using and as I told you before if it sees something it doesn't understand it doesn't hope for the best and keep going and output code and it might work. It actually says no I do not understand this.

Sorry, right? Well beyond design philosophies and principles we've also done a huge amount of testing and Clang again is an open source project. We've had a huge input from open source people building little apps. Little apps you know like the FreeBSD kernel and FreeBSD userspace and at Apple we've done a huge amount of testing on internal apps.

I mean you saw the big list of apps up above. So we've done a huge amount of testing on this and you know the FreeBSD kernel of course it not only builds, it actually does work and boot and do all of that great stuff right. So this isn't a theoretical exercise. So Clang really does work. Beyond that of course we told you yesterday that Clang is being used to build applications in Snow Leopard.

So not only we-- you know doing tests and see if they build we're actually building applications, mastering them on the DVD and shipping them to you. So when you run Automator or Interface Builder or Dashcode or Property List Editor you're actually running Clang compiled code right. We're serious about this. Beyond that we're actually building Xcode. Well just so you have an idea of what Xcode entails right.

Xcode is not a small app. Xcode is 2 apps with 18 frameworks and 20 plug-ins. The source space is built out of 17 Xcode projects and it's over 2 1/2 million lines of code. This is a major real-world app. This is this is the real deal. Now full disclosure, about 5% of that is Objective-C++ and so this is exercising the ability of the Xcode, Xcode's ability to fall back to LLVM and C++ to build that but that's still a heck of a lot of code right and Xcode works great and particularly in Snow Leopard.

So this is a real compiler. [Applause] So for me one of the great things about actually building applications and shipping them is not just you know the-- you know-- chalk it up 1, yay, compiler you actually work, it's actually getting people to live on the compiler. Right so we've had these teams living on this compiler and doing their daily development with it and it's really exciting to talk to these people because they have very interesting quotes. Apparently not all of them have been thrilled with GCC either.

This is a great quote from Chris Espinoza. He says, "I've never seen a transition to a new compiler go as smoothly as this," and Chris adds, "When I say never, it's somewhat authoritative," having started in the garage you know 25 years ago, 30 years ago, sorry Chris. So--

[applause]

[Chris Lattner]

So it's-- it's been really exciting to see people use it and and so far from what I can tell people seem to love it and this is just the first of things to come I hope. We have a lot of-- a lot of ideas for the future.

So to wrap things up I want to talk briefly about the Static Analyzer right because compilers are boring right we learned that yesterday [laughter]. Let's talk about the new cool stuff. Well the the new cool stuff is the integration of the Static Analyzer with Xcode and the Xcode team has done an amazing job of making this accessible and really useful and so we you saw a couple of demos that show you how the data flow information and the control flow information from Clang is rendered in Xcode in a way that's truly beautiful. It's really fun to use too if you haven't tried it yet. This works with both the Mac and the iPhone. It's easy to use often-- often-- stuff.

If you want to learn more about this we have a session right after this in North Beach and the session Ted Kremenek, the Chief Architect will tell you all about it and so it's a great session, I highly encourage you to go there. So at this point you may be wondering, I've learned about all these different compilers, well, which one should I actually use, right? Well, there's many different ones to choose from. So let's talk about their virtues. With Clang, building with Clang is a great option if it works for you because you have fast compiles, you get great generated code using the LLVM optimizer and backend and you get a great user experience.

Use Clang! However if you're using a feature that Clang doesn't support yet like method functions is one example, or you really care about OpenMP, then LLVM-GCC is a really good answer. Now OpenMP-- the LLVM-GCC supports all the same features that GCC does and it's not as fast as Clang when building in debug mode but it's really fast for optimized compiles and the LLVM optimizer is substantially faster than the GCC optimizer.

You get fast generated code and you get really good compatibility with GCC, including C++ and Objective-C++. Now if you want the minimum possible delta from our tools release last year, GCC 4.2 is a good answer. This is a stable compiler from last year with a few bug fixes and the Blocks feature.

So we haven't done anything crazy, this is for people who are in the middle of their development cycle and aren't ready to switch up to a different compiler. Finally, if you're still using GCC 4.0, please stop. [Laughter] GCC 4.0 was a great compiler but it's really-- it's really time to move forward.

Both on the Mac and the iPhone GCC 4.2 is really the compiler you should be using at the least. And so this is the compiler landscape and I hope that you'll, you know, have some fun with your compilers and start expecting more. So if you're interested in learning more information about compilers or you have questions feel free to contact Michael Jurewitz, he's our Developer Tools Evangelist.