There are many small optimizations the assembler can perform before outputting MAR code. There should be an optional step right before outputting code which optimizes a list of IR lines.
Starting optimizations
A small list of initial optimizations that can be supported with this issue.
Note: A small rule that applies for all of these optimizations: Any optimization that would normally result in an instruction being removed CANNOT be performed if that instruction has a label.
Redundant MOV
Two MOV
instructions copying data to/from each other is redundant and the second MOV
can be omitted:
to:
Overwritten MOV
A sequential MOV
instruction which has the same destination as the MOV
instruction right before it makes the previous MOV
redundant:
MOV A, 0x0001
MOV A, 0x0002
to:
JMPs to the next instruction
A JMP
instruction which simply jumps to the instruction right after it can be omitted:
to:
Potentially unsafe optimizations
The following is a list of optimizations that can only be done assuming the user never intentionally reads memory below the stack pointer (SP
). These may need to be optional separately from the safe optimizations above (e.g. the assembler could have a flag --no-stack-optimizations
to disable these).
Condensed sequential PUSH & POP
Sequential PUSH
and POP
instructions can be condensed into a single MOV
:
to:
Omitting sequential PUSH & POP from & to same destination
Sequential PUSH
and POP
instructions to and from the same destination can be omitted entirely:
to:
PUSH overwritten by SP increment
A PUSH
instruction immediately succeeded by a an increment of the stack pointer (SP
) effectively "erases" the value pushed onto the stack:
PUSH 0x0001
ADD SP, 2 ; Second operand can be any value above 0
to:
ADD SP, 1 ; Second operand must be decremented to account for the missing PUSH!
- If the
ADD
specifically only adds 1 to the stack pointer, both instructions can be removed.
- This is only possible if the second operand of
ADD
is an immediate as we need to decrement the value.