Sign in to follow this  
agottem

Restricted pointer question

Recommended Posts

I'm a little confused about the rules regarding restricted pointers. Maybe someone out there can help me out.


1. Is it legal to define nested restricted pointers as follows:


{
int* restrict a;
int* restrict b;

a = malloc(sizeof(int));

// b = a; <-- assignment here is illegal, needs to happen in child block
// *b = rand();

while(1)
{
b = a; // Is this legal? Assuming 'b' is not modified outside the while() block
*b = rand();
}
}




2. Is it legal to derive a restricted pointer value as follows:


{
int* restrict c;
int* restrict d;

c = malloc(sizeof(int*)*101);
d = c;

for(int i = 0; i < 100; i++)
{
*d = i;
d++;
}

c = d; // c is now set to the 101 element, is this legal assuming d isn't accessed?
*c = rand();
}



Thanks!
Andrew

Share this post


Link to post
Share on other sites
According to this restrict "is basically a promise to the compiler that for the scope of the pointer, the target of the pointer will only be accessed through that pointer (and pointers copied from it)."

Going by that definition I think both of your examples should be fine.

Also since you only write to memory, I think using restrict wouldn't make any difference to the code generation compared to not using it, so while it should work I wouldn't actually recommend using it in those cases.

It's more useful in code that looks like say:

int foo(int *a, int *b)
{
*a = 5;
*b = 7;
return *a + *b; // Without restrict, the compiler doesn't
// know if a == b, so it has to
// reload a before the add
}

Share this post


Link to post
Share on other sites
The was my thinking as well. Unfortunately, the c99 standard makes some claims about the declarations of restrict pointers. The standard has the example (http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf section 6.7.3.10) :


{
int * restrict p1;
int * restrict q1;
p1 = q1; // undefined behavior
{
int * restrict p2 = p1; // valid
int * restrict q2 = q1; // valid
p1 = q2; // undefined behavior
p2 = q2; // undefined behavior
}
}





Based on that example, it would seem that only restrict pointers declared in child blocks can be assigned restricted pointers. If that's the case, my two examples would be illegal, even though there technically isn't any aliasing.

Share this post


Link to post
Share on other sites
>> I'm a little confused about the rules regarding restricted pointers.

That is normal. See the comp.lang.c Usenet newsgroup for lots of examples.

They were added to fix a really annoying optimization problem, and misuse of the keyword can cause fatal errors.



It is similar to chemotherapy or acutely toxic poisons used for medicine. They should only be used if you demonstrate and actual need, only after careful diagnosis, only after you have tried less dangerous treatments. and if used, only used as sparingly as possible.


The general rule is: Don't use them.

The longer rule is: Only use them if you have already optimized your algorithm, looked at the optimized disassembly, and have direct knowledge that the compiler is generating a store/load pessimization. You have already tried to fix the problem with less severe means. In this situation, consider using a restrict qualification only within that section of code that suffers from the pessimization as an alternative to system-specific #pragmas.

Quote:
Original post by agottem
Based on that example, it would seem that only restrict pointers declared in child blocks can be assigned restricted pointers. If that's the case, my two examples would be illegal, even though there technically isn't any aliasing.

Yes they are illegal. And there is significant aliasing in your examples.


Your examples are illegal with their assignment:
(restrict qualified) a = malloc(...)

In this case your restrict qualified pointer is aliased with something else during that code block.

The restrict qualifier is much like the const qualifier; the restrict-qualified pointer should be initialized pointing to the associated object. Part of the guarantee is that you won't modify the pointer or the object.

A replacement of the pointed-to object is an illegal modification. Any expression that referenced the pointer must now be reloaded. Even though you didn't subsequently reference the pointer in your example, the expression is still invalid.



(restrict qualified) b = (restrict qualified) a;

This is illegal for the same reason, and is listed specifically in the language standard as ill-formed.



Neither example would actually benefit from the restrict keyword.

Your second example almost takes advantage of it, but doesn't quite. The whole purpose of the keyword is to prevent unnecessary store/load from reading a recently-written pointer. If your loop involved reading pointer d or *d after the assignment then restrict qualifications might have made sense. But it doesn't, so there is no point.



A great explanation of restrict sums it up this way: I promise that the pointer declared along with the restrict qualifier is not aliased. I certify that writes through this pointer will not effect the values read through any other pointer available in the same context which is also declared as restricted. Actual verification of this is usually much harder than it first seems. If it were easy then the compiler would have figured it out.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this