A compiler back end translates an intermediate representation into operations suitable for a target machine. Typical tasks include instruction selection, register allocation, instruction scheduling and emission of assembly or object code. It uses facts about the target's instructions, registers, calling conventions and data layout.[ref]
For example, a load from
base + 4*i might use one indexed-addressing instruction when the target supports that addressing mode, or require separate address arithmetic otherwise. If more values are live than registers are available, Register allocation may spill some values to memory. Those choices change performance while having to preserve the source program's specified observable behavior. A target-independent intermediate form is therefore useful, but does not erase target-specific constraints. New to topics? Read the docs here!