【问题标题】:Useless jp / jnp assembly instruction on x86_64x86_64 上无用的 jp / jnp 汇编指令
【发布时间】:2015-03-26 19:07:06
【问题描述】:

我试图弄清楚 jp/jnp 指令在 LLVM 生成的 C 代码中的用途。示例:

int main(int argc, const char * argv[]) {
    double value = 1.5;

    if (value == 1.5) {
        value = 3.0;
    }

    return 0;
}

汇编输出:

Ltmp4:
    movsd   LCPI0_0(%rip), %xmm0
    movl    $0, -4(%rbp)
    movl    %edi, -8(%rbp)
    movq    %rsi, -16(%rbp)
Ltmp5:
    movsd   %xmm0, -24(%rbp)
Ltmp6:
    movsd   -24(%rbp), %xmm1
    ucomisd %xmm0, %xmm1
    jne LBB0_2
    jp  LBB0_2
## BB#1:
    movabsq $3, %rax
    cvtsi2sdq   %rax, %xmm0
Ltmp7:
    movsd   %xmm0, -24(%rbp)
Ltmp8:
LBB0_2:
    movl    $0, %eax
    popq    %rbp
    retq

jne 正在检查 value != 1.5 是否并跳过分配,但 jp 在这种情况下在做什么?

【问题讨论】:

  • 我想你告诉 llvm 不要制作优化代码之类的。编译器不可能发出 mov $0, %eax 而不是 xor %eax, %eax 任何级别的优化。该代码中还有其他令人讨厌的东西:movabsq $3, %rax 是 10 个字节,与 movl $3, %eax 相比,但效果完全相同。

标签: c assembly llvm x86-64 instructions


【解决方案1】:

jnejump if not equal,即如果未设置零标志则跳转。 jpjump if parity

ucomisd 被定义为比较两个doubles。它将表明它们是以下四种情况之一:无序、等于、大于或小于。

如果数字无序或相等,则设置零标志。所以jne 避免了剩余的大于或小于的情况。

仅当结果无序时才设置奇偶校验。 jp 抓住了这一点。

所以两者一起避免:无序、大于、小于。只留下第四种可能性,等价。

【讨论】:

  • 术语说明:“无序”表示两个参数没有相对顺序;也就是说,其中至少有一个是 NaN。如果它们是非 NaN 且相等,则不一样是“无序”。
  • @Tommy 很抱歉吹毛求疵,但我不同意 jp 是多余的。在尝试了 -Os-O3 之后,我没有看到任何证据支持您声称它已优化的说法。
  • 我的理解是ucomisd通过设置ZF=1PF=0表示两个数相等。如果两个标志都是1,则表示其中一个或两个数字都是NAN。只有当您知道ucomisd 的输入都不是NAN 时,您才能忽略PF。注意:我没有尝试“不安全的数学优化”选项,这可能会删除对 PF 的检查。
  • @user3386109 进一步检查,你是对的,我错了。答案经过大量修改并标记为社区 wiki,以记录称我为它的唯一所有者是不准确的(并且,为了记录,我的优化代码测试试图阻止条件被优化是有缺陷的)。跨度>
  • @Tommy Cheers,作为同事和科学家,我尊重你,因为科学家只寻求真正的知识,而政治家只寻求隐藏错误。
猜你喜欢
  • 2019-01-27
  • 1970-01-01
  • 1970-01-01
  • 2017-10-06
  • 2013-07-25
  • 1970-01-01
  • 1970-01-01
  • 2012-02-27
  • 2011-11-22
相关资源
最近更新 更多