Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c99 __restrict and compiler optimization

typedef struct {
    void * field1;
} s1;

void func1(void) {
    s1 my_s1;
    s1 * __restrict my_s1_ptr = &my_s1;
    *((int*)((char*)my_s1_ptr->field1 + 4))  = 0;
    *((int*)((char*)my_s1_ptr->field1 + 8))  = 1;
    *((int*)((char*)my_s1_ptr->field1 + 12)) = 2;
    *((int*)((char*)my_s1_ptr->field1 + 16)) = 3;
}

It seems that for version 11.1 of the Intel compiler and version 4.6 of gcc that the compiler reloads my_s1_ptr->field1 for each of the last 4 statements. My understanding of __restrict would suggest to me that the last 3 loads should be redundant and could be eliminated. Yes, I know the code is weird but there is a reason it is structured this way. I would just like to be able to get the compiler to eliminate the redundant loads. Any idea how to convince it to do that?

like image 283
DrTodd13 Avatar asked Jun 08 '12 01:06

DrTodd13


People also ask

What does restrict mean C++?

restrict says that two pointers cannot point to overlapping memory regions. The most common usage is for function arguments. This restricts how the function can be called, but allows for more compile optimizations. If the caller does not follow the restrict contract, undefined behavior can occur.

What is const char restrict?

For example, char const * restrict is a type. Actually, it only applies to pointer types, i.e. T * restrict . So int restrict is invalid, but int * restrict is valid. In a function, a parameter T * restrict p means that the allocated object pointed at by p is only pointed at by p .

Which of the following keyword is used for restriction purpose?

In the C programming language (after 99 standard), a new keyword is introduced known as restrict. restrict keyword is mainly used in pointer declarations as a type qualifier for pointers. It doesn't add any new functionality.

What is pointer aliasing?

If a function has two pointers pa and pb , with the same value, we say the pointers alias each other. This introduces constraints on the order of instruction execution. If two write accesses that alias occur in program order, they must happen in the same order on the processor and cannot be re-ordered.


Video Answer


1 Answers

s1 * __restrict means that this is the only pointer to a particular s1, so no alias for that type. It doesn't mean that there will be no alias for other pointer types, like void*, int*, or char*.

Using a char* is especially troublesome for the compiler, because a char* is specifically allowed to be used to access the bytes of other types. (char also means byte, and can be used to access the underlying memory of other types).

If the compiler cannot prove that your assignment will never, ever change what's pointed to, it will have to reload the pointer each time. For example, how can it tell that void* field1 isn't pointing to itself?


And wouldn't something like this work without all the casts?

int* p = my_s1.field1;
p[1] = 0;
p[2] = 1;
p[3] = 2;
p[4] = 3;

Assuming an int is 4 bytes, and that field1 actually points to an array of those.

like image 144
Bo Persson Avatar answered Sep 17 '22 04:09

Bo Persson