C11标准添加了aligned_alloc分配未初始化的对齐内存的功能.该标准还包括calloc分配内存的功能,该内存初始化为零但仅将其与最大类型的大小对齐.
为什么C11标准不包含aligned_calloc分配零初始化的对齐内存的函数?
我知道你可以忘记结果以获得初始化的内存,但该calloc函数在某些操作系统上非常有用,因为内核提供的内存通常必须已初始化为零(并且与页面大小对齐)以确保安全性.
calloc可以利用这个并避免双重初始化.
另外,一些操作系统(如linux)以写时复制的方式提供存储器,同时calloc允许构造原始的稀疏数据结构.关于aligned_alloc破坏此属性的结果的初始化memset .
在我看来,这些优点虽然不便携,但应该足以具有第二个对齐的分配功能.
以下代码使用amd64上的gcc或clang编译:
// gcc -O2 file.c -c
int f(int a, int b, int c, int d)
{
return a & b & c & d;
}
Run Code Online (Sandbox Code Playgroud)
产生以下装配:
0000000000000000 <f>:
0: 89 d0 mov %edx,%eax
2: 21 c8 and %ecx,%eax
4: 21 f0 and %esi,%eax
6: 21 f8 and %edi,%eax
8: c3 retq
Run Code Online (Sandbox Code Playgroud)
由于按位and应该是关联的,人们会认为将成对方式累加到两个寄存器然后再and这两个寄存器会更有效.这将破坏依赖性并允许在具有多个ALU的cpu上并行执行.
由于编译器and为所有操作进入相同的寄存器,我假设它依赖于cpu能够进行寄存器重命名以打破依赖本身.
cpu的寄存器重命名功能是否没有成本,并且始终在amd64上可用,或者为什么编译器会像这样编译代码?
更新: 我发现如果为树关联宽度传递更高的值,gcc可以执行预期的依赖关系链断开:
--param tree-reassoc-width=2
Run Code Online (Sandbox Code Playgroud)