I understand Control-Flow Graph (CFG) optimizations and that they typically operate on SSA Intermediate Representations (IR). I am wondering though if the compiler optimizes the AST in any way before the IR, or does any optimizations before the IR/CFG phase.
Yes, constant folding is an example of an optimization that can be performed very early, possibly even in AST node construction functions. On the other hand, performing constant folding on the AST may be undesirable if this would be detrimental to error messages. Some languages (e.g. Java) cannot perform constant folding in the syntactic phase as they must be able to resolve certain variables.
There is, of course, a huge variety of compiler architectures. LLVM with many passes that all use the same IR is an extreme variant, I think GCC uses multiple IRs at different stages. At the other extreme would be the Perl VM, which uses its opcode structures both as an AST and as bytecode.