\section{Optimizations} MLRISC assumes that all high level optimizations (target independent) have already been performed. This includes things like inlining, array dependence analysis, and array bounds check elimination. The target dependent optimizations that remain include register allocation, scheduling and traditional optimizations to support scheduling. \subsection{Register allocation} MLRISC includes a state-of-the-art graph-coloring based register allocator that has an aggressive algorithm for copy-propagation. The latter guarantees to eliminate copy instructions without introducing spills. Spills in the register allocator are under the control of the client via call-backs to the front end. Where to spill registers and the associated information that must be maintained is client specific and varies with the compiler. \subsection{Scheduling for Superscalar Architectures} Several algorithms for acyclic global scheduling are provided. These include: \begin{itemize} \item Superblock, \item a variant of Bernstein/Rodeh, and \item Percolation based scheduling. \end{itemize} These algorithms tend to be quite complex and require a large number of support data structures and analysis. These include data structures such as: \begin{itemize} \item dominator/post dominator trees, \item loop nesting tree, \item control dependency graphs, and \item data dependency graphs. \end{itemize} Support analysis and optimization include: \begin{itemize} \item constant propagation, \item global value numbering, \item global code motion, and \item loop invariant hoisting. \end{itemize} \subsection{VLIW Compilation} MLRISC also contains a framework for the compilation of predicated VLIW architectures. Currently, the following algorithms have been implemented. \begin{itemize} \item hyperblock formation \item hyperblock scheduling \item modulo scheduling \end{itemize}