GCC使用memcpy和memset替换循环

8

我有一个简单的程序:

#define N 20
long c[N];
long a[N + N];

void f(void)
{
    long *s = c;
    long *p = a;
    while (p != a + N) *p++ = *s++;
    while (p != a + N + N) *p++ = 0;
}

我用以下方式进行编译:

/usr/gcc-arm-none-eabi-5_4-2016q3/bin/arm-none-eabi-gcc -mthumb -O3 -o main.o -c main.c

gcc可以方便地将循环分别替换为memcpymemset

00000000 <f>:
   0:   b570            push    {r4, r5, r6, lr}
   2:   4d07            ldr     r5, [pc, #28]   ; (20 <f+0x20>)
   4:   4c07            ldr     r4, [pc, #28]   ; (24 <f+0x24>)
   6:   002a            movs    r2, r5
   8:   4907            ldr     r1, [pc, #28]   ; (28 <f+0x28>)
   a:   0020            movs    r0, r4
   c:   f7ff fffe       bl      0 <memcpy>
  10:   1960            adds    r0, r4, r5
  12:   002a            movs    r2, r5
  14:   2100            movs    r1, #0
  16:   f7ff fffe       bl      0 <memset>
  1a:   bc70            pop     {r4, r5, r6}
  1c:   bc01            pop     {r0}
  1e:   4700            bx      r0

显然,gcc很聪明,并且决定库实现更加高效,但这在每种情况下可能是或不是正确的。我想知道,在例如速度不重要且不希望使用库调用的情况下,如何避免这种行为。


1
你已经通过使用 -O3 命令行选项明确告诉编译器要进行激进的优化 - 这不是默认设置。如果你想让编译器少一些激进,可以使用不同的优化设置,甚至不进行优化设置。 - Peter
这几乎是 https://dev59.com/TGw15IYBdhLWcg3wxugh#33818680 的副本。 - technosaurus
1
实际上是这样的。不幸的是,我在“memcpy循环”中找不到它。有很多关于“什么更快?”的帖子。谢谢。 - A.K.
可能是让GCC编译时不插入memcpy调用的方法的重复问题。 - vgru
这个回答解决了你的问题吗?如何提供memcpy的实现 - undefined
2个回答

11

好的,通过搜索https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html,找到了以下选项:

-ftree-loop-distribute-patterns

将可以通过调用库生成代码的模式进行循环分发。此标志在默认情况下启用 -O3。

指定 -fno-tree-loop-distribute-patterns 可避免触及标准库,而似乎不会影响其他优化。


很遗憾,-fno-tree-loop-distribute-patterns在Clang上无法工作。有人知道如何用Clang解决同样的问题吗? - cepstr

0

您正在使用标志-O3,它强制编译器运行所有可用的优化方法,请尝试较低的值,如-O2或-O。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接