Optimizer

The optimizer will first focus on simple peephole optimizations.

replacing far jumps with local jumps

Since many instructions like brne, brlt, rcall, rjmp, ... can only jump +-64 words from the instruction pointer, it is required to generate sequences that negate a conditon like brlt and jump over a jmp instruction to perform the actual jump.
Since we do not know at that time if the brlt is sufficient for the range of the jump.
When the instructions have been selected, we can do peephole optimization to undo some of that redundant code and make the generated code smaller and more readable.

  brlt label_skip
  jmp label_actual_target
label_skip:
  ...
label_actual_target:
  nop
can be replaced by
  brge label_actual_target
label_skip:
  ...
label_actual_target:
  nop

redundant instruction elimination

eliminating instructions which overwrite the effects of the previous instruction

  cp    r2, r4
  cp    r3, r5
can be replaced by
  cp    r3, r5

combining multiple instructions

Sometimes there are special instructions that can do the work of multiple simple instructions.
We can then use these more powerful instructions, even if the neighboring instructions are not from the same statement in the IR.

  mov XL, r17
  mov XH, r18
can be written as
  movw XL:XH, r17:r18

redundant jump elimination

When generating code for a basic block, we do not necessarily know (or need to know) which block will follow afterwards in the assembly code. So they are connected by jumps. But when one block follows another, the redundant jump can be removed later.

  tst   r2
  brne  L5
  rjmp  L6

L6:
  mov   r17, YL
can be replaced by
  tst   r2
  brne  L5

L6:
  mov   r17, YL