为什么restrict指针没有效果
-
12-12-2019 - |
题
我看不出 gcc 的限制指针代码有任何差异。
文件1
void test (int *a, int *b, int *c)
{
while (*a)
{
*c++ = *a++ + *b++;
}
}
文件2
void test (int *restrict a, int *restrict b, int *restrict c)
{
while (*a)
{
*c++ = *a++ + *b++;
}
}
编译用
gcc -S -std=c99 -masm=intel file1.c
gcc -S -std=c99 -masm=intel file2.c
文件1.s 和 文件2.s 两者相同,除了 .file
行,它告诉文件名:
.file "file1.c"
.text
.globl test
.type test, @function
test:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movq %rdi, -8(%rbp)
movq %rsi, -16(%rbp)
movq %rdx, -24(%rbp)
jmp .L2
.L3:
movq -8(%rbp), %rax
movl (%rax), %edx
movq -16(%rbp), %rax
movl (%rax), %eax
addl %eax, %edx
movq -24(%rbp), %rax
movl %edx, (%rax)
addq $4, -24(%rbp)
addq $4, -8(%rbp)
addq $4, -16(%rbp)
.L2:
movq -8(%rbp), %rax
movl (%rax), %eax
testl %eax, %eax
jne .L3
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size test, .-test
.ident "GCC: (GNU) 4.6.3 20120306 (Red Hat 4.6.3-2)"
.section .note.GNU-stack,"",@progbits
这两个代码都从内存中读取,然后分配指向的内存位置 a
到 b
. 。我所期望的 restrict
版本不会重新读取地址 a
和 b
, ,以及地址 a
和 b
将在寄存器中递增并最终写入内存。
我做错了什么吗?或者例子的选择是否合适?
我尝试过不同的开关 -O0
, -O1
, -O2
, -O3
, -Ofast
, , 和 -fstrict-aliasing
两个文件的结果相同。
笔记: gcc --version = gcc (GCC) 4.6.3 20120306(红帽 4.6.3-2)
编辑 代码已更改。
解决方案
问题是下面的表达式:
*c++ = *a++ + *b++;
无论如何,几乎需要在每次循环迭代中取消引用所有指针,因为指针在每次迭代中都会发生变化。使用没有任何好处 restrict
.
尝试将循环内的行更改为:
*c++ = *a++ + *b;
(您可能还需要启用优化,例如 -O2
).
你会在 restrict
加载案例 *b
一次进入寄存器,而在没有限制的情况下,它需要在每次循环迭代中通过指针加载,因为它不知道是否 c
曾经的别名 b
.
其他提示
您只阅读了其中一个指针,因此 restrict
没关系。
看 这个例子 这确实很重要,因为指针可能会为相同的数据指定别名,并且数据是通过两个指针写入和读取的。
不隶属于 StackOverflow