Why there is no effect of restrict pointer
Asked Answered
P

2

8

I can't see any difference of code by gcc for restrict pointers.

file1

void test (int *a, int *b, int *c)
{
  while (*a)
  {
    *c++ = *a++ + *b++; 
  }
}

file2

void test (int *restrict a, int *restrict b, int *restrict c)
{
  while (*a)
  {
    *c++ = *a++ + *b++;
  }
}

compile with

  gcc -S -std=c99 -masm=intel file1.c
  gcc -S -std=c99 -masm=intel file2.c

file1.s and file2.s both are same, except the .file line, which tells the filename:

    .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

Both of these code read from the memory and then assign the memory location pointed to by a to b. Where i expected the restrict version will not re-read the addresses of a and b, and the addresses of a and b will be incremented in-register and at the end written to memory.

Is there anything wrong i am doing? Or is the selection of the example okay?

I have tried with different switches -O0, -O1, -O2, -O3, -Ofast, and -fstrict-aliasing with the same identical results for both of the files.

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

EDIT Code changed.

Palpable answered 1/10, 2012 at 20:16 Comment(0)
B
3

The thing is that the following expression:

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

pretty much needs to dereference all the pointers in each loop iteration anyway, since the pointers change in each iteration. There's no benefit to using restrict.

Try changing the line inside the loop to:

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

(you may need to also enable optimizations such as -O2).

You'll see that in the restrict case it loads *b into a register once, while in the case without restrict it needs to load through the pointer in each loop iteration because it doesn't know whether or not c ever aliases b.

Buntline answered 1/10, 2012 at 22:17 Comment(0)
L
7

You are only reading through one of the pointers, so restrict doesn't matter.

See this example where it does matter because the pointers may alias the same data, and the data are written and read through both pointers.

Loesceke answered 1/10, 2012 at 20:29 Comment(2)
I have changed the code, can you please have a look at the new one?Palpable
The new version does not re-read any memory in either case, so again, restrict has no effect. I.e., every int is read once. It the the data pointed to by the pointer, not the pointer itself that is at issue with restrict.Loesceke
B
3

The thing is that the following expression:

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

pretty much needs to dereference all the pointers in each loop iteration anyway, since the pointers change in each iteration. There's no benefit to using restrict.

Try changing the line inside the loop to:

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

(you may need to also enable optimizations such as -O2).

You'll see that in the restrict case it loads *b into a register once, while in the case without restrict it needs to load through the pointer in each loop iteration because it doesn't know whether or not c ever aliases b.

Buntline answered 1/10, 2012 at 22:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.