Yes.  I co-founded a startup building optimizing compilers for high-performance telecommunications processors in the early 2000s (acquired by Intel).  In any complex software system, building powerful, composable and modular abstractions is critical for managing complexity.  Having many composable passes is exactly that.  We were a small team (6 people) and a modular architecture maximized our productivity and made it possible to complete with teams many times our size.  We used a unified IR throughout the compiler so it had a consistent semantics, but the IR could support various canonical forms or constraints that were managed explicitly by the compiler.  Instruction formation involved three steps: fragment selection by tree covering (think of load with post increment or a SIMD instruction as multiple fragments), grouping of fragments into instructions, and grouping of instructions into issue slots in the scheduler (several of our targets were VLIW).  In addition to constraint, we had properties like SSA vs multiple assignment, structured control flow vs basic blocks, certain kinds of cleanup, etc.  A pass could declare its requirements (SSA, structured control flow, pre-fragment) and the compiler would check the properties, possibly running passes to create them (e.g. put in SSA form).  Having separate cleanup passes meant transformations didn&#x27;t have to clean up after themselves, often making things vastly simpler.  Analysis passes (dataflow, alias analysis, various abstraction interpretations) were independent of the properties because the IR had unified semantics.  That said, it is true our compiler didn&#x27;t have the fastest compile times (multiple times slower than gcc on targets we both supported), but we were a highly optimizing compiler and our generated code was significantly faster than the competing alternatives (if there were any).