State of the art C compiler optimization tricks

A survey about state of the art C compiler optimization tricks, Felix von Leitner, Linux Kongress 2009.

The introduction and the conclusion is quite well put:

  • Optimizing == important.
  • But often: Readable code == more important
  • Learn what your compiler does

    Then let the compiler do it.

  • If you do an optimization, test it on real world data.
  • If it’s not drastically faster but makes the code less readable: undo it.

That's certainly something that I agree with 110%. And really, that's why a good compilers course is so important, even if the vast majority of students never write a compiler outside of class.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

And why all software

And why all software engineering/design courses should teach about profilers, and mandate their use.

There have been "teaching &

There have been "teaching & learning" style academic papers that have advocated showing students how parsers and interpreters translate to machine code in the past, visually. What I think is missing is the ability for the student to see how something like a BURS graph optimizer transforms a tree and then yields faster execution code. It also makes you realize how hard the compiler must work to understand you to tune something for you.

This idea is sort of like how CMU teaches grade school algebra to kids.

Also pays to recheck what the hardware is doing over time

Last time I worked on the nether end of a native compiler (targeting x86), when it came time to see what constants it was worth not-multiplying by (i.e., converting to shifts and adds), it turned out to be precious few (*). The amount of compute-ahead that some chips will perform (i.e., if you can avoiding doing anything data-dependent in your code) is astonishing, too.

So, just for example, you might be better off in some cases doing "complicated arithmetic" instead of "cheap table lookups".

(*) The exact multiply delay was almost certainly dependent on other factors, but it's relatively much faster than in the past.

And really, that's why a

And really, that's why a good compilers course is so important, even if the vast majority of students never write a compiler outside of class.

Or, another take we've had: teach students about compilers they would be writing. Most won't work for Sun to make the next Java. I don't think low-level optimizations are super important to most of them (though they should understand it a little). There's a myth that language design is hard: while true in the general case, as soon as you're in a specialized domain, there might be 'good enough'. Lex/Yacc-style tools were big steps here, and the community has rediscovered it a bit with Ruby DSLs. So, for example, teach students about source-to-source translators: let LLVM or JavaScript do the rest of the work.

In the beginning of our course, students wrote a quick Greasemonkey script to interpret webpages a little differently. Then, after going over parsing, they implemented one of google's little languages (unit conversion). Closer to the end (though as a worse example), they added classes, type checking, and FRP to the not-really-evolving JavaScript language through simple source-to-source translators.

Why not present compilers in a way students would more likely use them? It's less effective for students who will move on to language/compiler design, but they wouldn't be getting much out of such a class anyways.

As for the article itself -- it's interesting how it balances on the fence of architectural differences. E.g., when you tune, you tune for a particular architecture. I actually misread the article title before reading it: I've been looking for good books on modern static and dynamic language implementation.

edit: cleared up the list of examples. For this year's version (I'm not involved, but much is still in place since our changes): cs164. Unfortunately, there is no undergrad PL course, just a compilers one, which makes it a little random.

Und dann ...?

Then, after going over parsing, they implemented one of google's little languages (unit conversion) and then, near the end (though as a worse example).

I was very interested by the examples you were giving, but then I ran into the period! Is it possible that you some words out?

Fixed and added more

Fixed and added more context. I'm not the best storyteller :)

Nah! Given a choice... skip the compiler course!

If the choice is a course on benchmarking and profiling vs a course on compilers.... teach/learn benchmarking / profiling.

And if you think there is not enough to be taught in such a course... well, you obviously need one yourself!

There is no such course in

There is no such course in any major program I know about.

Closest would be Computer Systems course at CMU, based on Bryant's textbook.

Depends

To be honest, it very much depends on the quality of the compilers course. I've taken two, at different institutions, and they were at the opposite extremes of quality.

Tail recursion example is wrong

The author gives a non-tail-recursive version of factorial and says that msvc doesn't turn it into a loop. I've seen msvc turn tail recursive functions into loops. I use that feature pretty heavily when writing algorithmic code because the compiler is also smart enough to warn if a tail recursive call will result in an infinite loop, which you don't get if you write complex for/while iterations.


long fact(long x) {
if (x<=0) return 1;
return x*fact(x-1);
}

It is interesting that gcc turns this into a loop, although it isn't tail recursive.

Integer multiplications and additions are associative

GCC uses the associative property to transform the operation.

From tree-tailcall.c:

In addition to the standard tail recursion elimination, we handle the most
trivial cases of making the call tail recursive by creating accumulators.
For example the following function

int sum (int n)
{
if (n > 0)
return n + sum (n - 1);
else
return 0;
}

is transformed into

int sum (int n)
{
int acc = 0;

while (n > 0)
acc += n--;

return acc;
}

This is really COOL

I don't comment too often, but just wanted to offer kudos.

In general, I'd love more straight ahead papers/book that really explain current practice/state of the art.

-- Scott

The author gives a

The author gives a non-tail-recursive version of factorial and says that msvc doesn't turn it into a loop. I've seen msvc turn tail recursive functions into loops. I use that feature pretty heavily when writing algorithmic code because the compiler is also smart enough to warn if a tail recursive call will result in an infinite loop, which you don't get if you write complex for/while iterations.

long fact(long x) {
if (x return x*fact(x-1);
}

It is interesting that gcc turns this into a loop, although it isn't tail recursive.

[spam signature delete by admin]