Why do we use intermediate languages instead of AST?
abstract-syntax-tree, compiler-construction, gcc, optimization
Solution
GCC is using far more than just two intermediate representations, and far less than it should have used.
There is a compiler design methodology, known as "nanopass": a compiler is built of a sequence of very simple code rewrites, starting with an original AST produced by a parser and ending up in a low level code. Each transform is trivial, and difference between neighbouring intermediate languages is subtle.
This way it is easy to reason about each of the transforms, easy to comprehend the whole chain and easy to add new functionality. A rich language may have a lot of syntax sugar which can be expressed in terms of simpler language constructs before doing any type checking, for example.
Each of the languages in this chain is represented as an AST, of course, but usually only the very first one, which was produced by a parser, will be called an "AST", and all the others will be "intermediate languages". Of course, terminology might vary between different schools of thought. I personally prefer to use the term "AST" all the way through.
Problem
What is the difference between an intermediate language and an AST? As far as I can tell, they both offer flow analysis information which a compiler can use for optimization purposes. I know GCC uses two intermediate representations - an AST and an IL. What is the reason for this?