使用RAX / EAX / AX / AL / AH寄存器作为目标,是否可以更快地进位?

时间:2016-02-12 17:17:05

标签: c++ assembly intel inline-assembly

在英特尔文档中,我们有ADC的下一个定义:

Op / En操作数1操作数2 .....

RM ModRM:reg(r,w)ModRM:r / m(r)

MR ModRM:r / m(r,w)ModRM:reg(r)

MI ModRM:r / m(r,w)imm8

我是AL / AX / EAX / RAX imm8

现在是asm代码的一个小例子:

asm (         
    "adc    -Ox12(%rbp), %rax  \n\t"  //1
    "adc    -Ox12(%rbp), %rdx  \n\t"  //2
    "adc    -Ox12(%rbp), %r8   \n\t"  //3
    "adc    -Ox12(%rbp), %R11  \n\t"  //4

    "adc    %r8 , %rdx  \n\t"  //5
    "adc    %r8 , %rax  \n\t"  //6

    "adc    $3 , %rdx   \n\t"  //7
    "adc    $3 , %rax   \n\t"  //8
);

你能告诉我哪一组是每组中最快的指令吗?为什么? 我有这个问题,因为在英特尔他们引用%RAX寄存器。对方慢了吗?

2 个答案:

答案 0 :(得分:2)

Note: For everything below I'm assuming modern 80x86 (anything from the last 10 years or so).

For the first group; the first instruction has a (very slightly) increased chance of causing a cache miss or a dependency stall (caused by either RBP, RAX or the carry flag being modified by instructions leading up to it).

For all other instructions, there's a dependency on eflags (they have to wait until the carry flag from the previous instruction is known) and they will all suffer equally from that. More specifically I'd expect the "carry flag dependency" to limit execution to 1 cycle per instruction (with no instructions happening in parallel). That is the most likely bottleneck.

The registers used make no difference (other than dependencies on the previous use of the register).

答案 1 :(得分:2)

即使adc $3 , %rax也无法使用特殊的rax-only编码REX.W + 15 id ADC RAX, imm32

  • REX.W + 15 03 00 00 00是6个字节。 (adc rax, imm32
  • REX.W + 83 mod/rm 03是3个字节。 (adc r/m32, imm8,其中mod / rm字节将rax编码为目标,/2字段中的reg作为操作码的一部分.still-src操作共享操作)

The (16bit version of) both encodings were introduced with 8086。请参阅 wiki中的链接。显然,累加器预计会一直用于所有事情,和/或他们没有考虑将来的指令集扩展,所以他们认为值得在特殊al和{{上花费那么多操作码1}}所有ALU立即指令的版本。

如果查看双操作数整数ALU指令(axandorsub等),每个指令都有一个特殊的单字节 - testal / ax / eax目的地的短时编码,具有全尺寸立即操作数。 (即rax,而非imm32符号扩展为32或64b)。每个指令都有两个额外的操作码。

这仅影响x86代码大小。一旦指令被解码,它们的运行方式就没有进一步的区别。请参阅http://agner.org/optimize/以了解有关CPU内部的更多信息。

AMD64本可以将这些技术从64位模式中解放出来,从而释放出更多的编码空间,但他们对于杀死32位可能并不乐观。如果您希望指令在32和64位模式下工作,如果两种模式下的编码相同,则需要较少的解码器晶体管。不过,他们本可以使用imm8或其他东西的编码空间。不是新奇的SIMD功能,只是简单的一些基本指令。在标志设置操作之前,几乎不能在没有setcc r32的情况下使用setcc将完整寄存器归零。无论如何,AMD错过了从x86中删除一些错误的绝佳机会。