For this Assignment you will be continuing the implementation
of the JVM code optimizer jopt available in this archive. This includes some aspects of peephole
optimization and some aspects of global analysis of flow-of-control.
Note that your optimizer should be iterative. That is, it should apply all the optimizations below repeatedly until no more optimizations are possible. This will allow, for example, the second part of Questions 3 and 4 to happen without any extra work.
JasminOptimizer, every label encountered starts a new block. Modify the implementation to check if a label is ever the target of a jump instruction. If a label is not the target of a jump instruction and the last instruction of the previous block does not affect flow-of-control then merge the two blocks (and delete the label).
;; Begin Block 22 ... some instructions ; Block 22 exits to block 23 ;; End Block 22 ;; Begin Block 23 mylabel: ... some more instructions ;; End Block 23 |
==> |
;; Begin Block 22 ... some instructions ... some more instructions ;; End Block 22 |
fload 3 ldc 2.0 fmul |
==> |
fload 3 dup fadd |
ldc 1.0 ldc 2.0 fadd |
==> |
ldc 3.0 |
fadd, fsub,
fmul, and fdiv. Note that you get more
sophisticated optimizations for free when this optimization is iterated.
For example:
ldc 1.0 ldc 2.0 fadd ldc 5.0 fmul |
==> |
ldc 3.0 ldc 5.0 fmul |
==> |
ldc 15.0 |
ldc 5.0 ldc 1.0 ldc 2.0 fadd fmul |
==> |
ldc 5.0 ldc 3.0 fmul |
==> |
ldc 15.0 |
goto labelA ... ifxxx labelA ... labelA: goto labelB ... |
==> |
goto labelB ... ifxxx labelB ... labelA: goto labelB |
ifxxx labelA1 ... labelA1: goto labelA ... labelA: goto labelB ... |
==> |
ifxxx labelA ... labelA1: goto labelB ... labelA: goto labelB ... |
==> |
ifxxx labelB ... labelA1: goto labelB ... labelA: goto labelB ... |
jopt is
the removal of useless load/pop pairs.
However, the existence of any pop instruction indicates
that some useless information has been pushed onto the operand stack.
Generalize the current optimization by beginning at every
pop instruction and working backwards eliminating as many
useless instructions as possible. For example, a snippet of code like
fload 7 ldc 8.0 fmul fload 2 ldc 5.0 fadd fmul popshould simplify down to nothing.
CodeBlocks. These are any
CodeBlocks that do not contain any directives and for
which there is no execution path from the first block of the method in
which they are defined to themselves. (Hint: You may want to lookup
depth-first search in one of your algorithms or data structures
textbooks.)
istore,
fstore, and astore instructions. Such an
operation is useless if every execution path from that operation leads
to a dead-end (a block with no successors) or another
store of the same local variable before any
load operation on that variable. Once you have determined that a store instruction is useless you can replace it with a pop instruction.