如何提供 memcpy 的实现

Tim*_*mmm 37 c gcc memset

我正在尝试编写一些带有memset-style 循环的裸机代码:

for (int i = 0; i < N; ++i) {
  arr[i] = 0;
}
Run Code Online (Sandbox Code Playgroud)

它是用 GCC 编译的,GCC 足够聪明,可以将其转换为对memset(). 不幸的是,因为它是裸机,我没有memset()(通常在 libc 中)所以我收到链接错误。

 undefined reference to `memset'
Run Code Online (Sandbox Code Playgroud)

似乎进行这种转换的优化是-ftree-loop-distribute-patterns

执行可以通过调用库生成代码的模式的循环分布。默认情况下,此标志在 -O2 及更高级别以及由-fprofile-use和启用-fauto-profile

所以一个人的解决方案是降低优化级别。不是很满意。

我还发现这真的有用的网页,说明这-ffreestanding是不足以让GCC没有做到这一点,而且也根本没有选择,只能提供自己的实现memcpymemmovememsetmemcmp。我很乐意这样做,但是怎么做?

如果我只是编写memset编译器将检测其中的循环并将其转换为对 memset 的调用!事实上,在我使用的 CPU 供应商提供的代码中,我发现了这条评论:

/*
// This is commented out because the assembly code that the compiler generates appears to be
// wrong.  The code would recursively call the memset function and eventually overruns the
// stack space.
void * memset(void *dest, int ch, size_t count)
...
Run Code Online (Sandbox Code Playgroud)

所以我认为这就是他们遇到的问题。

我如何提供 C 实现memset而不需要编译器将其优化为对自身的调用并且不禁用该优化?

Tim*_*mmm 31

啊哈我检查了 glibc 代码,有一个inhibit_loop_to_libcall修饰符听起来应该这样做。它是这样定义的

/* Add the compiler optimization to inhibit loop transformation to library
   calls.  This is used to avoid recursive calls in memset and memmove
   default implementations.  */
#ifdef HAVE_CC_INHIBIT_LOOP_TO_LIBCALL
# define inhibit_loop_to_libcall \
    __attribute__ ((__optimize__ ("-fno-tree-loop-distribute-patterns")))
#else
# define inhibit_loop_to_libcall
#endif
Run Code Online (Sandbox Code Playgroud)

  • @伦丁下摆。这*是*解决方案,即 Timmmm *自己的*定义的 `memset` 等的 `__attribute__ ((__optimize__ ("-fno-tree-loop-distribute-patterns")))` 修饰符。 (7认同)
  • 我没有使用任何 libc 实现。我想你可能误解了这个问题。 (6认同)