Align Registers to by Power of 2 Value with or/inc
Say you want to aligned a pointer for a load. I.e saying aligning for xmm
load:
This is a pretty common idiom:
addq $16, %rdi // 4b
andq $-16, %rdi // 4b
A cheaper way:
orq $15, %rdi // 4b
incq %rdi // 3b
If your pointer is in RAX, the special 2-byte op al, imm8
no-modrm encoding is useful. Writing a byte or word register leaves the upper bytes untouched. On older Intel CPUs (before Sandybridge) this can cause a partial-register stall, but even for performance it's safe on modern CPUs.
or $0xf, %al // 2b (leave upper bytes untouched)
inc %rax // 3b (carry into the upper bytes is possible)
or $0xf, %dl // 3b
inc %rdx // 3b
or $0xf, %dil // 4b REX + opcode + modrm + imm8
inc %rdi // 3b no savings
Also works with and $0xf0, %al
to round down to the previous alignment boundary.
Also worth noting the or
alone will round to value minus 1 so it can be used to keep address offsets in imm8
short encoding range i.e:
andq $-16, %rdi
// Stuff on (%rdi)[0, 79]
vmovdqa 80(%rdi), %xmm0
vs.
orq $15, %rdi
// Stuff on -15(%rdi)[0, 79]
vmovdqa 65(%rdi), %xmm0
# vmovdqa 80 - 15(%rdi), %xmm0 # same thing, but with the -15 in the asm source