如何提供memcpy的实现

如何提供memcpy的实现,c,gcc,memset,C,Gcc,Memset,我正在尝试编写一些裸机代码,其中包含memset样式的循环: for (int i = 0; i < N; ++i) { arr[i] = 0; } 实现这一转变的优化似乎是: 执行模式的循环分发,这些模式可以通过调用库生成代码。默认情况下,此标志在-O2和更高级别启用,并由-fprofile use和-fauto profile启用 因此,我们只是降低了优化水平。不太令人满意 我还发现这解释了-f重建不足以让GCC不这样做,而且基本上没有选择,只能提供自己的memcpy、memmo

我正在尝试编写一些裸机代码,其中包含
memset
样式的循环:

for (int i = 0; i < N; ++i) {
  arr[i] = 0;
}
实现这一转变的优化似乎是:

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

因此,我们只是降低了优化水平。不太令人满意

我还发现这解释了
-f重建
不足以让GCC不这样做,而且基本上没有选择,只能提供自己的
memcpy
memmove
memset
memcmp
实现。我很乐意这么做,但是怎么做呢

如果我只写
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)
...
所以我想这就是他们遇到的问题

如何提供
memset
的C实现,而不让编译器对其自身进行优化,也不禁用该优化?

啊哈,我签了名,有一个
禁止循环到libcall
修饰符,听起来它应该这样做。它是:

/*添加编译器优化以禁止循环转换到库
电话。这用于避免在memset和memmove中进行递归调用
默认实现*/
#ifdef有_CC_INHIBIT_LOOP_TO_LIBCALL
#定义禁止循环到libcall\
__属性(优化树循环分布模式)
#否则
#定义禁止循环到libcall
#恩迪夫

您在问题中提到:

似乎实现这一转变的优化是


关闭此优化只需将
-fno树循环分发模式
传递给编译器即可。这将全局关闭优化。

这是否回答了您的问题?奇怪,
-f重新理解
@Lundin:我不明白你为什么需要了解目标系统。我想你误解了。@EricPostpischil事实证明编译器在初始化/复制时确实插入了
memset
memcpy
调用,即使在
-f重新理解时也是如此。这一点在:
GCC需要独立的环境提供memcpy、memmove、memset和memcmp。
@supercat我认为这里提供的答案是“正确”的,因为glibc是这样做的(而且他们与GCC携手工作)。不,你不可能在裸机系统上运行glibc。我认为还有其他尝试为Linux风格的系统提供更合适的LIB,例如。“我自己没用过,所以我不能担保。”伦丁·海姆。这就是解决方案,即对Timmmm自己定义的依赖于gcc目标端口的
memset
等@AnttiHaapala进行修改。另外,如果您正在推出自己的std-lib替代品,那么您不应该同时使用另一个std-lib,显然……我没有使用任何libc实现。我想你可能误解了这个问题。@Lundin,这里的要点是,既然
glibc
提供了
memset
的一个实现,它需要有一些方法来抑制GCC的“用调用
memset
来替换此代码”优化,在不降低全局优化级别的情况下。这比我的答案更糟糕,我的答案只是将
memset
@timmm关闭这是你想要的答案,而不是你认为你想要的答案;假设您的
memset
与朴素的C实现没有任何不同,那么它可能比让编译器在代码中简单地生成一个循环要慢。编译器实际上只生成对
memset
的调用,因为它假设
memset
比它自己生成的任何东西都要快(在大多数情况下都是正确的)。这是一个好的观点,但您的解决方案总体上仍然不起作用,因为即使使用此标志,编译器仍然可以生成对
memset()
的调用。请参阅。@Timm您的答案使用了相同的标志,因此这是一个没有意义的点。我只使用特定函数的标志,这些函数不做任何其他事情来触发GCC对
memset()
/
memcpy()
的调用。
/*
// 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)
...