• Code optimization: – A transformation to a program to make it run faster and/or take up less space – Optimization should be safe, preserve the meaning of a program. – Code optimization is an important component in a compiler – Example: peephole optimization. • Peephole: a small moving window in the instruction sequence • Technique: examine a short sequence of target instructions (peephole) and try to replace it with a faster or shorter sequence • Peephole optimization: • • • • Redundant instruction elimination Flow of control optimization Algebraic simplifications Instruction selection • Examples: – Redundant loads and stores MOV R0, a MOV a, R0 – Unreachable code If debug = 1 goto L1 Goto L2 L1: print debugging info L2: – Examples: • Flow of control optimization: goto L1 goto L2 … … L1: goto L2 L1: goto L2 if a < b goto L1 if a<b goto L2 … … L1: goto L2 L1: goto L2 goto L1 … L1: if a < b goto L2 if a < b goto L2 goto L3 … L1: L3: • Algebraic simplification: x : = x+0 x := x*1 == nop • Reduction in strength X^2 x * x X * 4 x << 2 • Instruction selection Sometimes some hardware instructions can implement certain operation efficiently. • Code optimization can either be high level or low level: – High level code optimizations: • Loop unrolling, loop fusion, procedure inlining – Low level code optimizations: • Instruction selection, register allocation – Some optimization can be done in both levels: • Common subexpression elimination, strength reduction, etc. – Flow graph is a common intermediate representation for code optimization. • Basic block: a sequence of consecutive statements with exactly 1 entry and 1 exit. • Flow graph: a directed graph where the nodes are basic blocks and block B1 block B2 if and only if B2 can be executed immediately after B1: • Algorithm to construct flow graph: – Finding leaders of the basic blocks: • The first statement is a leader • Any statement that is the target of a conditional or unconditional goto is a leader • Any statement that immediately follows a goto or conditional goto statement is a leader – For each leader, its basic block consists all statements up to the next leader. – B1B2 if and only if B2 can be executed immediately after B1. • Example: 100: 101: 102: 103: 104: 105: 106: 107: sum = 0 j=0 goto 107 t1 = j << 2 t2 = addr(a) t3 = t2[t1] sum = sum + t3 if j < n goto 103 • Optimizations within a basic block is called local optimization. • Optimizations across basic blocks is called global optimization. • Some common optimizations: – – – – – – – – – – – – – – Instruction selection Register allocation Common subexpression elimination Code motion Strength reduction Induction variable elimination Dead code elimination Branch chaining Jump elimination Instruction scheduling Procedure inlining Loop unrolling Loop fusing Code hoisting • Instruction selection: – Using a more efficient instruction to replace a sequence of instructions (space and speed). – Example: Mov R2, (R3) Add R2, #1, R2 Mov (R3), R2 Add (R3), 1, (R3) • Register allocation: allocate variables to registers (speed) • Example: M[R13+sum] = 0 M[R13+j] = 0 GOTO L18 L19: R0 = M[R13+j] * 4 M[R13+sum] = M[R13+sum] +M[R0+_a] M[R13+j] = M[R13+j]+1 L18: NZ = M[R13+j] - M[_n] if NZ < 0 goto L19 R2 = 0 R1 = 0 GOTO L18 L19: R0 = R1 * 4 R2 = R2+M[R0+_a] R1 = R1+1 L18: NZ = R1 - M[_n] if NZ < 0 goto L19 • Code motion: move a loop invariant computation before the loop • Example: R2 = 0 R1 = 0 GOTO L18 R2 = 0 R1 = 0 R4 = M[_n] GOTO L18 L19: R0 = R1 * 4 R2 = R2+M[R0+_a] R1 = R1+1 L19: R4 = M[_n] NZ = R1 – R4 if NZ < 0 goto L19 L18: R0 = R1 * 4 R2 = R2+M[R0+_a] R1 = R1+1 L18: NZ = R1 – R4 if NZ < 0 goto L19 • Strength reduction: replace expensive operation by equivalent cheaper operations • Example: R2 = 0 R1 = 0 R4 = M[_n] GOTO L18 R2 = 0 R1 = 0 R4 = M[_n] R3 = _a GOTO L18 L19: R0 = R1 * 4 R2 = R2+M[R0+_a] R1 = R1+1 L19: NZ = R1 – R4 if NZ < 0 goto L19 L18: R2 = R2+M[R3] R3 = R3 + 4 R1 = R1+1 L18: NZ = R1 – R4 if NZ < 0 goto L19 • Induction variable elimination: can induce value from another variable. • Example: R2 = 0 R1 = 0 R4 = M[_n] R3 = _a GOTO L18 R2 = 0 R4 = M[_n] << 2 R3 = _a GOTO L18 L19: L19: R2 = R2+M[R3] R3 = R3 + 4 R1 = R1+1 L18: NZ = R1 – R4 if NZ < 0 goto L19 R2 = R2+M[R3] R3 = R3 + 4 L18: NZ = R3 – R4 if NZ < 0 goto L19 • Common subexpression elimination:an expression was previously calculated and the variables in the expression have not changed. Can avoid recomputing the expression. • Example: R1 = M[R13+I] << 2 R1 = M[R1+_b] R2 = M[R13+I] << 2; R2 = M[R2+_b] R1=M[R13+I] << 2 R1 = M[R1+_b] R2 = R1