4 ms·
> According to the Intel optimization manual, using EBP, RBP, or R13 as the base address will make LEA slower. Now that's odd. What is special about those regi
by rwallace 7y ago
> According to the Intel optimization manual, using EBP, RBP, or R13 as the base address will make LEA slower.
Now that's odd. What is special about those registers, that code using them can end up slower than the others?
- magicalhippo 7y agoThe post explains it. LEA without those registers used as base can be computed in the address generation unit, which is separate from the regular arithmetic unit(s). Since x86 supports complex but useful addressing, the AGU was made fast so memory operations wouldn't be dog slow. The LEA exploits this resource for computation rather than "just" for addressing memory, for example: lea eax, [ecx+eax*2-30h] With normal arithmetic that would be three instructions that could not be done in parallel, but with LEA it's done in a single clock cycle[1]. More details here[2]. For some reason, the AGU seems incapable of dealing with those registers as base I guess. [1]: https://gmplib.org/~tege/x86-timing.pdf https://gmplib.org/~tege/x86-timing.pdf [2]: http://www.nynaeve.net/?p=64 http://www.nynaeve.net/?p=64 (point 3)
- BeeOnRope 7y agoThe article is wrong, AGU hasn't been used for LEA on mainstream Intel CPUs in a decade at least. LEAs are calculated on ALU execution units like other ALU ops. r13 and rbp are special because the usual way of encoding those registers in an indexed addressing mode without an offset was repurposed instead for another mode: offset only or RIP-relative in x86-64. This affected only ebp in x86-32 but also r13 in x86-64 because of the way the instruction was encoded. As a result, if you want to use rbp as a base, you need to use an explicit offset (which can be zero) and that ends of triggering the "three source rule" for slow LEA in the case of indexed addressing, even though you have included any offset in the assembly.
- magicalhippo 7y agoAlrighty then, time for me to never do any x86 asm programming again I see :) Thanks for the detailed correction.
- userbinator 7y agoIt's also why 3 operands with LEA is slower than 2 --- the microarchitectures thus far have no 3-input ALU, so it gets cracked into two (dependent) uops.
- pbsd 7y agoThe single-uop FMA instructions beg to differ. As well as ADC, SBB, CMOVcc, etc, since Broadwell: 1 uop, 3 inputs. LEA itself has consisted of 1 uop for a very long time...but the complex 3-input version gets sent to a different place than the simple one. The PBLENDVB case is interesting: the VEX-encoded variant takes 2 uops in every uarch, but 1 uops (since Skylake) in the non-VEX encoded variant that takes XMM0 as a hardcoded input.
- BeeOnRope 7y agoPBLENDVB is weird. My guess is that it wasn't an execution or rename limit, since PBLENDVB should be "just as hard", but a decode or (pre-rename) uop format limit: i.e., the uop format in the IDQ couldn't handle three variable inputs, but the implicit xmm0 is fine (doesn't take any space). Or the decoders couldn't handle it. Still, once 3-input stuff like FMA did appear I don't know why it wasn't fixed. Possibly FMA has special handling...