CS 6120: Advanced Compilers: The Self-Guided Online Course (2020)

1 day ago (cs.cornell.edu)

The section on dynamic compilers is more or less all about trace compilation. Generally, trace compilation is a dead end and has been abandoned repeatedly. The more important concepts here are type feedback and speculation and deoptimization, as well as making fast compilers and tiering.

The course overall looks good, and it's great that so much is available online, so well done, Adrian.

  • Thanks, Ben. I admit I mostly think tracing is just a mind-expanding concept to learn about, even if history has proven it’s not very practical as an organizing principle. But as you say, I’d love to offer more context on “what actually seems to work” industrially.

    • Yeah, it is conceptually interesting. I like giving students perspective and in 770 (https://www.cs.cmu.edu/~wasm/cs17-770/fall2025/) I might spend half or less of a lecture on tracing and I don't pull punches on how I think it ends up not really working well in real systems. It's a good opportunity to talk about program behavior and the cost/benefit of speculation.

      We spend a lot more time on type feedback, ICs, and deoptimization which are the more universal concepts that can be applied to multiple different compiler designs.

      1 reply →

  • I work on PyTorch torch.compile and it’s a tracing compiler as well. Perhaps this domain is very narrow though; it is also a very not conventional compiler, you’d probably be deeply offended by some of the stuff we do! ;)

  • > Generally, trace compilation is a dead end and has been abandoned repeatedly.

    JAX is a tracing compiler!

    (I know, I know, it sits in an extremely different part of the problem space than TraceMonkey or LuaJIT. Still.)

    • Interesting. I think numerical computing is a narrow enough domain where programs have very well-behaved control flow, which avoids most of the problems of trace compilation. Loops over branchy code, which are really common in general programs, are very difficult to make work well with tracing.

      Numerical programs being very stable in terms of control is what enables GPU parallelization and loop optimizations in the long tradition of Fortran compilers. Optimizations like loop tiling, interchange, strip mining, etc aren't going to be easy to do with trace compilation.

      Anyway my comment was more directed toward trace compilation in the context of dynamic languages, and there I think it's pretty well established it only works well for small programs.

      3 replies →

  • The TraceMonkey paper was on my qual reading list, and my quals happened to be around the time TraceMonkey was ripped out of SpiderMonkey. I was talking with one of the developers at the time (I think it was Jason Orendorff?), who said that tracing just doesn't work out, but there was limited circumstances where he thought it might work out... but I've completely forgotten what those circumstances were.

  • Trace compilation is NOT a dead end.

    LuaJIT works just fine. On big programs. On hundreds of millions of servers and devices.

    I find it deeply saddening that even scholars keep repeating this trope. Ignorance is bliss.

    • Hi Mike, I think your work on luajit is really cool. I worked on JavaScript for some time and among all of the JS engines out there, a lot of ideas were tried. TraceMonkey in particular did explore trace compilation for JavaScript and benefited from a lot of fundamental research into trace compilation from Michael Franz's group and others. I've talked to many of those people. It just didn't work out for JS as there are too many diverse programs out there that aren't well-behaved. It's not enough to get great performance on some programs (and hopefully good performance on average programs) if there are pathological cases that ruin user experience. The internet is the greatest VM fuzzer yet invented and produces some stunningly awful things that present constant challenges to speculative dynamic optimization. It's well accepted in the JS space that method JITs have more stable, understandable performance, though they too can get into trouble.

      Best of luck.

      2 replies →

I'm a bit confused about what makes this course "advanced." Most of the topics (dead code elimination, data flow, dominator analysis, SSA form) seem like they belong in a first course on compilers.

  • Well, course numbers are regular enough that you can look up what the "intro compilers" course is: https://www.cs.cornell.edu/courses/cs4120/2026sp/?schedule

    The short answer is that compilers is basically broken up into two courses, with the first course largely being the minimum necessary to build a compiler (lexing, parsing, codegen, register allocation), and the second course being how to build an optimizing compiler.

    • The academic literature on register allocation is scary.

      First is presented a linear time optimal algorithm for graph coloring then it is claimed better can be done by a O(N^2) algorithm that uses a heuristic.

      I do believe the dragon book got caught with the emperor's new register allocator and the literature hasn't really recovered yet.

      4 replies →

    • Looks like there is quite a bit of overlap with regards to the optimizing parts between these two courses. I guess it's switching from the dragon book to academic papers that makes it advanced.

    • I am actively opposed to this design for a first compiler. There is no need for a lexer with a recursive descent parser. Register allocation is also an unnecessary distraction. It is better for a first compiler to compile to a higher level language in which neither register assignment nor memory management are necessary.

      Optimizing compilers are suboptimal in that they waste enormous amount of time optimizing code that can't or needn't be optimized and even where the optimizations are helpful, they are opaque and at risk of unexpectedly regressing both due to small changes at the source code level or changes in the compiler optimizer, both of which are quite insidious.

      If instead of optimizing compilers, we had languages that allowed for seamless interop between low level and high level functions, then perhaps an llm becomes the optimizer (or you can invoke the compiler to optimize a specific function by source level rewrite). The benefit of this compared to a traditional optimizing compiler is that the optimization is done once per function and never repeated (until prompted) and the implementation is human readable and not buried in a binary. Moreover, and perhaps even more importantly, by not doing optimizations in the compiler, compilation times can be much faster, easily 100-1000x than state of the art optimizing compiler, while generating equivalent or even better runtime performance. As it has been said: premature optimization is the root of all evil.

      2 replies →

  • I have read TONS of material about it*, and none of that is part of the majority of that!

    In fact, the "backend" be compiler or interpreter is nearly always left as "exercise to reader".

    You can't imagine how much is left to be discovered, from how make a closure, track environment, do pattern matching, memory representation, etc.

    EVERYTHING interesting is something you need to look for.

    P.D: This only one of the years:https://gist.githubusercontent.com/mamcx/e1743571b9a1ea163a7...

  • I think a lot of the non-professionals start with parsing and do not get exposed to backend. I have read two books about interpreters/compilers and they don't touch the backend very much.

    Maybe this is introductory for backend?

    • That's part of it. I think another part is that it seems like the students are asked to read the papers behind a lot of the concepts, and academic literature is not generally very accessible to undergrads. (Not that they can't read it, but without someone guiding you through at least the first few papers, it can be a frustrating experience for many.)

  • What is advanced then? Good coverage of dce, data flow, ssa, intruction selection and reg alloc is actually like 98% of the backend.

    • Perhaps polyhedral optimization, tiling, scalar evolution, vectorization...

      I guess garbage collection is pretty advanced in the syllabus.

      1 reply →

Are there any other self-guided online university level CS courses like this?

  • There are dozens. Search "mooc". Also some professors will release their lectures and homework outside of a "mooc" framework. I've even had professors respond to questions in the comments. The Internet can still be pretty cool.

How does this compare to Nora Sandler's "Writing a C compiler" in terms of the potential gains for the reader?

  • I found that book to be basically useless as a passive reader.

    She basically writes "do this" and you are supposed to do it.

    This course is much more valuable because it actually gives a lot of information.

    It really feels like most text books on compilers have massive "black hole" sections that pull you in on the technicals that you are not even supposed to use in the end.

    I found that his course and the LLVM book by Quentin Colombet really useful because they both give easy to understand information that seems to be actually used in real large systems like LLVM/gcc etc.

    There are also book like SSA-based compiler design that seem to be great but I am not able to read because of lacking prior knowledge.

    Also thank you to Adrian if he is reading this, he is an amazing teacher and releasing this content is much appreciated

  • Her book sits closer to what you'd get from an undergraduate level compilers course, this course covers more advanced material than she does. If you're a novice or a dabbler, start with her book or something else at that level, then try out this course and fill in the gaps as needed.

Is there also a self guided course for "basic compilers", before stepping into an advanced level?

Saw a podcast that talked about the rust compiler, which apparently included machine learning algorithms at some points to determine whether or not you had code that could crash your system

  • I've never heard about that and I'm pretty sure it's incorrect (although "machine learning" is a wide term), do you have a source for that?

    • I've also never heard this before. The closest I can think of is fuzzing test suites used to find panics in various crates, but that's neither machine learning nor in the compiler itself.

      I know that datalog is used for the borrow checking logic, so I could also maybe imagine someone describing something like that in some hand wavy way like "proof by machine to detect up front whether the program is safe or might crash" and that getting misinterpreted, but that seems like a stretch

      2 replies →

I'm super curious what alexia massalin is up to these days, besides collecting microunity patent royalties