当前位置:  开发笔记 > 编程语言 > 正文

为什么icc无法以合理的方式处理编译时分支提示?

如何解决《为什么icc无法以合理的方式处理编译时分支提示?》经验,为你挑选了0个好方法。

开发人员可以使用__builtin_expect 内置函数来帮助编译器了解分支可能走向哪个方向.

将来,我们可能会为此目的获得一个标准属性,但截至今天至少全部clang,iccgcc支持非标准属性__builtin_expect.

但是,icc当你使用它时,似乎会生成奇怪的代码1.也就是说,无论使用哪个方向进行预测,使用内置函数的代码都严格地比没有内置代码的代码更糟糕.

以下面的玩具功能为例:

int foo(int a, int b)
{
  do {
     a *= 77;
  } while (b-- > 0);  
  return a * 77;
}

在三个编译器中,icc唯一一个将其编译为3个指令的最佳标量循环:

foo(int, int):
..B1.2:                         # Preds ..B1.2 ..B1.1
        imul      edi, edi, 77                                  #4.6
        dec       esi                                           #5.12
        jns       ..B1.2        # Prob 82%                      #5.18
        imul      eax, edi, 77                                  #6.14
        ret          

无论GCC和Clang的管理无缘简单的解决方案,并使用5条指令.

另一方面,当你在循环条件下使用likelyunlikely宏时,icc完全是脑死亡:

#define likely(x)   __builtin_expect((x), 1)
#define unlikely(x) __builtin_expect((x), 0)

int foo(int a, int b)
{

   do {
     a *= 77;
  } while (likely(b-- > 0));  

   return a * 77;
}

这个循环在功能上等同于前一个循环(因为__builtin_expect只返回它的第一个参数),但icc会产生一些可怕的代码:

foo(int, int):
        mov       eax, 1                                        #9.12
..B1.2:                         # Preds ..B1.2 ..B1.1
        xor       edx, edx                                      #9.12
        test      esi, esi                                      #9.12
        cmovg     edx, eax                                      #9.12
        dec       esi                                           #9.12
        imul      edi, edi, 77                                  #8.6
        test      edx, edx                                      #9.12
        jne       ..B1.2        # Prob 95%                      #9.12
        imul      eax, edi, 77                                  #11.15
        ret                                                     #11.15

该函数的大小增加了一倍,达到10条指令,并且(更糟糕的是!)关键循环的数量增加了一倍多,达到7条指令,其中一条长关键依赖链涉及一个cmov奇怪的东西.

如果您使用unlikely提示,并且也使用Godbolt支持的所有icc版本(13,14,17),情况也是如此.因此,无论提示如何,代码生成都严格地更糟,并且无论实际的运行时行为如何.

使用提示时,既gcc不会clang降低也不会有任何降级.

那是怎么回事?


1至少在我试过的第一个和后续的例子中.

推荐阅读
360691894_8a5c48
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有