Pointer-Aliasing a boon and curse in C/C++

What is pointer-Aliasing ?
One pointer is said to alias another pointer when both refer to the same location or object.
Example:
int var;
int *pint=&var;
If you change the value of *pint, the value referenced by var also changes because *pint aliases var, it’s just another name for the same thing.

What is the use of Pointer-Aliasing?
Variable var and pointer pint that points to the same thing as var. Many optimizations can be used if the compiler can assume that there is only one “name” for a given variable. For example, the compiler could keep all the member variables for var in registers during the loop, which obviously can’t be accessed through a memory pointer.
on gcc this optimization can be enabled by -O2 options.

So far so good :)

But this optimization can impact performance. Let’s write a sample code and analyze.

void
test_function(
int *x,
int *y,
int *z
)
{
*x += *z;
*y += *z;
}

int
main()
{
int a= 1;
int b = 2;
int c = 3;
test_function(&a, &b, &c);
printf("a=%d, b=%d,c=%d", a, b, c);
return 0;
}

Compile the code
[root@dhcppc4 pointer-aliasing]# gcc -O2 -ggdb -o pointer-alis pointer-alis.c

Now load the program in gdb and disassemble test_function code.
(gdb) disas test_function
Dump of assembler code for function test_function:
0x0000000000400560 : mov (%rdx),%eax #load value pointed by z to eax
0x0000000000400562 : add %eax,(%rdi)
0x0000000000400564 : mov (%rdx),%eax #load value pointed by z to eax
0x0000000000400566 : add %eax,(%rsi)
0x0000000000400568 : retq
End of assembler dump.

If you see above value pointed by pointer z is loaded twice in the register. Compiler doesn’t know that *z won’t also be *x, so loads it twice :(

So how can we solve this problem. Let modify our test_function a little
void
test_function(
int *x,
int *y,
int *z
)
{
int w = *z;
*x += w;
*y += w;
}

Let’s disassemble the test_function in gdb
(gdb) disas test_function
Dump of assembler code for function test_function:
0x0000000000400560 : mov (%rdx),%eax
0x0000000000400562 : add %eax,(%rdi)
0x0000000000400564 : add %eax,(%rsi)
0x0000000000400566 : retq
End of assembler dump.

After the change we can see value pointed by z is loaded into register only once :).

We can also use the keyword ‘restrict’ to overcome this problem.

We will discuss the restrict keyword and strict-aliasing rule in next article.

Follow

Get every new post delivered to your Inbox.

Join 575 other followers