Optimization Techniques for Compiler Design: Intermediate Code & Local Optimizations, Study notes of Computer Science

Various optimization techniques used in compiler design, focusing on intermediate code, local optimizations, and peephole optimizations. It covers topics such as algebraic simplification, constant folding, common subexpression elimination, copy propagation, dead code elimination, and peephole optimizations on assembly code. The document also touches upon the importance of intermediate code and its role in optimization.

Typology: Study notes

Pre 2010

Uploaded on 08/05/2009

koofers-user-oze
koofers-user-oze 🇺🇸

5

(1)

10 documents

1 / 6

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
1
Optimizations…
intermediate code:
pros: machine independent, optimization
opportunities which will not need to be
retargeted for another platform
cons: yet another language
possible representations:
trees, three-address code (y := x op z) (or
quadruples), triple, polish notation…
Optimization seeks to improve a program’s
utilization of some resource
Execution time (most often)
Code size
Network messages sent
Battery power used, etc.
Optimization should not alter what the program
computes
The answer must still be the same
What to optimize:
cost/performance argument (opt-s hard to implement,
increase compilation time…)
code to consider based on number of: occurrences in
code, repetitions of execution, uses of compiled code
Optimization options
Apply local optimizations in basic blocks
single entry/exit point
preserve outcome of computation
select different representation for sequence in block
Global optimization across CFG (trace) of BBs
harder to prove
use flow analysis
Intra-procedural optimizations
Local optimizations
Algebraic simplification
Some statements can be deleted:
x := x + 0
x := x * 1
Some statements can be simplified:
x := x * 0 x := 0
y := y ** 2 y := y * y
x := x * 8 x := x << 3
x := x * 15 t := x << 4; x := t - x
Constant Folding
Operations on constants can be computed at
compile time
(algebraic simplifications)
In general, if there is a statement
x := y op z
And yand zare constants
Then yopzcan be computed at compile time
Example: x := 2 + 2 x := 4
Example: if 2 < 0 jump L can be deleted
In general –
values of expressions involving compiler time
constants – replace unary/binary tree with a
constant node with corr. value
operations involving constants as operand –
replace binary operation subtree with its non-
constant subtree
pf3
pf4
pf5

Partial preview of the text

Download Optimization Techniques for Compiler Design: Intermediate Code & Local Optimizations and more Study notes Computer Science in PDF only on Docsity!

Optimizations…

  • intermediate code:
    • pros: machine independent, optimization opportunities which will not need to be retargeted for another platform
    • cons: yet another language
    • possible representations:
      • trees, three-address code (y := x op z) (or quadruples), triple, polish notation… - Optimization seeks to improve a program’s utilization of some resource - Execution time (most often) - Code size - Network messages sent - Battery power used, etc. - Optimization should not alter what the program computes - The answer must still be the same - What to optimize: - cost/performance argument (opt-s hard to implement, increase compilation time…) - code to consider based on number of: occurrences in code, repetitions of execution, uses of compiled code

Optimization options

  • Apply local optimizations in basic blocks
    • single entry/exit point
    • preserve outcome of computation
    • select different representation for sequence in block
  • Global optimization – across CFG (trace) of BBs
    • harder to prove
    • use flow analysis
  • Intra-procedural optimizations

Local optimizations

  • Algebraic simplification
    • Some statements can be deleted:

x := x + 0

x := x * 1

  • Some statements can be simplified:

x := x * 0 ⇒ x := 0

y := y ** 2 ⇒ y := y * y

x := x * 8 ⇒ x := x << 3

x := x * 15 ⇒ t := x << 4; x := t - x

Constant Folding

  • Operations on constants can be computed at compile time - (algebraic simplifications)
  • In general, if there is a statement x := y op z - And y and z are constants - Then y op z can be computed at compile time
  • Example: x := 2 + 2 ⇒ x := 4
  • Example: if 2 < 0 jump L can be deleted
    • In general –
      • values of expressions involving compiler time constants – replace unary/binary tree with a constant node with corr. value
      • operations involving constants as operand – replace binary operation subtree with its non- constant subtree

Constants within blocks

  • traverse values from constant assignments within a basic block
  • when an assignment involves a constant rhs put the target in a “known vars” list (symbol table)
  • whenever a var is accessed, check to see if its in “known vars” list, and if constant, then replace node in AST
  • remove variables from the list when a non- constant assignment is encountered, or at the end of a basic block
  • can use “known list” to track accesses and delete useless variables

Constants across blocks

  • why does a block end:
    • entrance to selection/looping statement
    • exit from same
    • calls to procs/funcs
  • when can we retain value of variable?

Flow of Control Optimizations

  • Eliminating unreachable code:
    • Code that is unreachable in the control-flow graph
    • Basic blocks that are not the target of any jump or “fall through” from a conditional
    • Such basic blocks can be eliminated
  • Removing unreachable code makes the program smaller - And sometimes also faster - Due to memory cache effects (increased spatial locality)

Single Assignment Form

  • Some optimizations are simplified if each register occurs only once on the left-hand side of an assignment
  • Intermediate code can be rewritten to be in single assignment form x := z + y b := z + y a := x ⇒ a := b x := 2 * x x := 2 * b (b is a fresh register)
  • More complicated in general, due to loops

Common Subexpression

Elimination

  • Assume
    • Basic block is in single assignment form
    • A definition x := is the first use of x in a block
  • All assignments with same rhs compute the same value
  • Example: x := y + z x := y + z … ⇒ … w := y + z w := x (the values of x, y, and z do not change in the … code)

Copy Propagation

  • If w := x appears in a block, all subsequent uses of w can be replaced with uses of x
  • Example: b := z + y b := z + y a := b ⇒ a := b x := 2 * a x := 2 * b
  • This does not make the program smaller or faster but might enable other optimizations - Constant folding - Dead code elimination

An Example

  • Copy propagation: a := x * x b := 3 c := x d := c * c e := b << 1 f := a + d g := e * f

An Example

  • Copy propagation: a := x * x b := 3 c := x d := x * x e := 3 << 1 f := a + d g := e * f

An Example

  • Constant folding: a := x * x b := 3 c := x d := x * x e := 3 << 1 f := a + d g := e * f

An Example

  • Constant folding: a := x * x b := 3 c := x d := x * x e := 6 f := a + d g := e * f

An Example

  • Common subexpression elimination: a := x * x b := 3 c := x d := x * x e := 6 f := a + d g := e * f

An Example

  • Common subexpression elimination: a := x * x b := 3 c := x d := a e := 6 f := a + d g := e * f

An Example

  • Copy propagation: a := x * x b := 3 c := x d := a e := 6 f := a + d g := e * f

An Example

  • Copy propagation: a := x * x b := 3 c := x d := a e := 6 f := a + a g := 6 * f

An Example

  • Dead code elimination: a := x * x b := 3 c := x d := a e := 6 f := a + a g := 6 * f

An Example

  • Dead code elimination: a := x * x

f := a + a g := 6 * f

  • This is the final form

If statements (CJUMP)

  • if cond then e1 else e1 => e
  • if 0 then e1 else e2 => e
  • reorder e1/e2 to fall through on branch

(follow by false lable, do !cond if

necessary)

  • while 2<3 – dead code elimination
  • (last class slide)

Arrays and loops

  • subscript expressions
    • occur frequently – good code important
    • precompute whatever possible
    • occur often within loops =>…
  • `unroll loops’ (modulo unrolling)
    • amortize overhead of loop instructions over several loop executions
  • branches to branches
  • use of registers – e.g., loop index in reg.