How to tell a C or a C++ compiler that pointers are not aliased
Asked Answered
F

4

8

I have function that receives an array of pointers like so:

void foo(int *ptrs[], int num, int size)
{ 
  /* The body is an example only  */
     for (int i = 0; i < size; ++i) { 
       for (int j = 0; j < num-1; ++j)
         ptrs[num-1][i] += ptrs[j][i];
     }
}

What I want to convey to the compiler is that the pointers ptrs[i] are not aliases of each other and that the arrays ptrs[i] do not overlap. How shall I do this ? My ulterior motive is to encourage automatic vectorization.

Also, is there a way to get the same effect as __restrict__ on an iterator of a std::vector ?

Frigorific answered 7/9, 2011 at 3:8 Comment(1)
Important note: The C++ standard does NOT support the restrict qualifier from C99 -- its not even a keyword. So any use of restrict in a C++ program is relying on an implementation extensionRetributive
B
9

restrict, unlike the more common const, is a property of the pointer rather than the data pointed to. It therefore belongs on the right side of the '*' declarator-modifier. [] in a parameter declaration is another way to write *. Putting these things together, you should be able to get the effect you want with this function prototype:

void foo(int *restrict *restrict ptrs, int num, int size)
{
   /* body */
}

and no need for new names. (Not tested. Your mileage may vary. restrict is a pure optimization hint and may not actually do anything constructive with your compiler.)

Brook answered 7/9, 2011 at 3:24 Comment(4)
Unless I'm mistaken, one of those "restrict" declarations is superfluous; there are no other "int **"-type variables around with which aliasing could occur. "int * restrict * ptrs" should do the job. And I wonder if "int * restrict ptrs[]" might do it also...Gastrolith
IMHO both restricts are necessary, since other pointers might otherwise exist outside of the scope of foo.Duna
"What I want to convey to the compiler is that the pointers ... are not aliases of each other"Gastrolith
Also, late comment, but semantics of pointers "outside of the scope of foo" are not affected by restrict qualifiers on parameters of foo. The second restrict is NOT necessary.Gastrolith
G
7

Something like:

void foo(int *ptrs[], int num, int size)
{ 
  /* The body is an example only  */
     for (int i = 0; i < size; ++i) { 
       for (int j = 0; j < num-1; ++j) {
         int * restrict a = ptrs[num-1];
         int * restrict b = ptrs[j];
         a[i] += b[i];
     }
}

... should do it, I think, in C99. I don't think there's any way in C++, but many C++ compilers also support restrict.

Gastrolith answered 7/9, 2011 at 3:13 Comment(4)
Ah I see, I have to introduce new names. Thanks.Frigorific
By the way, you can use a similar trick to mark the object reference by an iterator as unaliased (i.e. assign its address to a restricted pointer).Gastrolith
You've got the 'restrict' qualifiers on the wrong side of the '*'s here.Brook
@Gastrolith Do you mean something like __restrict__ ptr = & (*iter) ? Seems it will work, nice. Thanks.Frigorific
A
5

In C++, pointer arguments are assumed not to alias if they point to fundamentally different types ("strict aliasing" rules).

In C99, the "restrict" keyword specifies that a pointer argument does not alias any other pointer argument.

Argeliaargent answered 7/9, 2011 at 3:11 Comment(3)
Pretty sure strict aliasing rules apply in c as well as c++. #99150Guillermoguilloche
Yes, yes they do. Also, this answer does not tell the OP anything he or she did not already know.Brook
The strict aliasing rules are more efficient in C++, because the parameters tend to be std::vector<int>& and not int*.Verbenia
I
0

Call std::memcpy. Memcpy's definition will have restrict set up if your language/version and compiler support it, and most compilers will lower it into vector instructions if the size of the copied region is small.

Invoke answered 13/10, 2022 at 18:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.