【问题标题】:Why there is no effect of restrict pointer为什么限制指针没有效果
【发布时间】:2012-10-01 20:16:03
【问题描述】:

我看不出 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

file1.sfile2.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 版本不会重新读取ab 的地址,ab 的地址将在寄存器中递增并在最后写入内存。

我做错了什么吗?还是选例行不行?

我尝试使用不同的开关 -O0-O1-O2-O3-Ofast-fstrict-aliasing,两个文件的结果相同。

注意: gcc --version = gcc (GCC) 4.6.3 20120306 (Red Hat 4.6.3-2)

编辑代码已更改。

【问题讨论】:

    标签: c pointers restrict-qualifier


    【解决方案1】:

    您只是阅读其中一个指针,因此restrict 无关紧要。

    请参阅this example,这很重要,因为指针可能会为相同的数据起别名,并且数据是通过两个指针写入和读取的。

    【讨论】:

    • 我改了代码,你能看看新的吗?
    • 新版本在任何一种情况下都不会重新读取任何内存,因此,restrict 再次无效。即,每个int 被读取一次。它是指针指向的数据,而不是与restrict 有问题的指针本身。
    【解决方案2】:

    问题是下面的表达式:

        *c++ = *a++ + *b++;
    

    无论如何,几乎都需要在每次循环迭代中取消引用所有指针,因为指针在每次迭代中都会发生变化。使用restrict 没有任何好处。

    尝试将循环内的行更改为:

        *c++ = *a++ + *b;
    

    (您可能还需要启用优化,例如-O2)。

    您会看到,在restrict 的情况下,它会将*b 加载到寄存器中一次,而在没有限制的情况下,它需要在每次循环迭代中通过指针加载,因为它不知道是否c 曾经别名 b

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-02-07
      • 2021-11-11
      • 1970-01-01
      • 2017-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多