此循环优化称为什么,它如何工作?

时间:2018-08-07 08:58:57

标签: algorithm loops gcc optimization

我正在编译以下代码:

#include <stdio.h>
#include <string.h>

int main()
{
  char data[1024];
  scanf("%s", data);

  for (int i = 0; i < strlen(data); i++)
  {
    if (data[i] == 'a')
    {
      printf("%d.\n", i);
    }
  }
}

我正在将-O2优化级别用于GCC。当检查gdb在组装级别如何完成内部循环时,在scanf之后得到以下指令:

0x40055c:   48 89 e0    mov    %rsp,%rax

,然后是迭代代码:

0x40055f <main+47>      mov    (%rax),%ecx 
0x400561 <main+49>      add    $0x4,%rax
0x400565 <main+53>      lea    -0x1010101(%rcx),%edx
0x40056b <main+59>      not    %ecx
0x40056d <main+61>      and    %ecx,%edx
0x40056f <main+63>      and    $0x80808080,%edx
0x400575 <main+69>      je     0x40055f <main+47> 

我只是想问一下,这种优化如何称呼?因此我可以阅读有关它的文章,而不必尝试对汇编代码的工作方式进行反向工程。

P.S。我知道这个想法是一次移动4个字节而不是一个字节,所以它必须进行较少的迭代,但是它如何调用以及如何工作?

2 个答案:

答案 0 :(得分:1)

请注意,这是strlen,而不是循环。

这是一个基于SWAR包含零字节的技巧的优化,在其他地方找到here

#define haszero(v) (((v) - 0x01010101UL) & ~(v) & 0x80808080UL)

由于strlen是内在函数,因此这可能不是由任何著名的“命名优化”引起的,它是特定函数的特定技巧。

答案 1 :(得分:1)

您显示的汇编代码是strlen()的一部分,实际上一次移动了4个字节,在这种情况下,是找到零字节。

有关算法的实现示例,请参见this