Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why there is no effect of restrict pointer

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.

like image 511
phoxis Avatar asked Oct 01 '12 20:10

phoxis


People also ask

Why is there no restrict in C++?

It has nothing to do with C++ because it's not a keyword or feature of C++, and if you use C header files in C++ you must remove the restrict keyword. Of course if you pass aliased pointers to a C function that declares them restricted (which you can do from either C++ or C) then it's undefined, but that's on you.

What is restrict qualified pointer?

In the C programming language, restrict is a keyword, introduced by the C99 standard, that can be used in pointer declarations. By adding this type qualifier, a programmer hints to the compiler that for the lifetime of the pointer, no other pointer will be used to access the object to which it points.

Does C++ have restrict keyword?

restrict is not supported by C++. It is a C only keyword.


2 Answers

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.

like image 70
Doug Currie Avatar answered Sep 16 '22 19:09

Doug Currie


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.

like image 22
Michael Burr Avatar answered Sep 17 '22 19:09

Michael Burr