amount of arithmetic with less storage. Instruction scheduling Instruction scheduling is an important optimization for modern pipelined processors, which avoids stalls or bubbles in the pipeline by clustering instructions with no dependencies together, while being careful to preserve the original semantics. Rematerialization Rematerialization recalculates a value instead of loading it from memory, preventing a memory access. This is performed in tandem with register allocation to avoid spills. Code factoring If several sequences of code are identical, or can be parameterized or reordered to be identical, they can be replaced with calls to a shared subroutine. This can often share code for subroutine set-up and sometimes tail-recursion. Trampolines Many CPUs have smaller subroutine call instructions to access low memory. A compiler can save space by using these small calls in the main body of code. Jump instructions in low memory can access the routines at any address. This multiplies space savings from code factoring. Reordering computations Based on integer linear programming, restructuring compilers enhance data locality and expose more parallelism by reordering computations. Space-optimizing compilers may reorder code to lengthen sequences that can be factored into subroutines. Functional language optimizations Although many of these also apply to non-functional languages, they either originate in or are particularly critical in functional languages such as Lisp and ML. Tail-call optimization A function call consumes stack space and involves some overhead related to parameter passing and flushing the instruction cache. Tail-recursive algorithms can be converted to iteration through a process called tail-recursion elimination or tail-call optimization. Deforestation (data structure fusion) In languages where it is common for a sequence of transformations to be applied to a list, deforestation attempts to remove the construction of intermediate data structures. Partial evaluation Other optimizations Bounds-checking elimination Many languages, such as Java, enforce bounds checking of all array accesses. This is a severe performance bottleneck on certain applications such as scientific code. Bounds-checking elimination allows the compiler to safely remove bounds checking in many situations where it can determine that the index must fall within valid bounds; for example, if it is a simple loop variable. Branch-offset optimization (machine dependent) Choose the shortest branch displacement that reaches the target. Code-block reordering Code-block reordering alters the order of the basic blocks in a program in order to reduce conditional branches and improve locality of reference. Dead-code elimination Removes instructions that will not affect the behaviour of the program, for example