LLVM IR clang -O1 -S -emit-llvm
define i32 @f(i32 %0, i32 %1) {
  %3 = add nsw i32 %1, %0
  ret i32 %3
}
  • Every value carries a type, i32.
  • %0, %1 and %3 are virtual registers. There are as many as needed, and each is assigned once.
  • nsw means the signed add will not overflow. Optimization passes rely on facts like this.
  • Not tied to a CPU. The same IR goes to the x86 backend and the ARM backend.
x86-64 assembly clang -O1 -S -masm=intel
f:
  lea eax, [rdi + rsi]
  ret
  • No types. eax is 32 bits because the width is part of the register name.
  • rdi, rsi and eax are real registers, and x86-64 has only a fixed set of them.
  • The add became lea. One lea adds two registers into a third, while add would need a mov first. This trick is specific to x86.
  • Assembled, it is 8d 04 37 c3, valid only on x86-64.