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 ?

Mat
  • 202,337
  • 40
  • 393
  • 406
san
  • 4,144
  • 6
  • 32
  • 50
  • 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 extension – Chris Dodd Aug 02 '12 at 20:25

4 Answers4

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.)

zwol
  • 135,547
  • 38
  • 252
  • 361
  • 2
    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... – davmac Sep 07 '11 at 04:27
  • IMHO both `restrict`s are necessary, since other pointers might otherwise exist outside of the scope of `foo`. – Johan Bezem Nov 05 '11 at 16:40
  • "What I want to convey to the compiler is that the pointers ... are not aliases of *each other*" – davmac Mar 15 '12 at 17:45
  • 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. – davmac Apr 25 '14 at 08:19
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.

davmac
  • 20,150
  • 1
  • 40
  • 68
  • Ah I see, I have to introduce new names. Thanks. – san Sep 07 '11 at 03:14
  • 1
    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). – davmac Sep 07 '11 at 03:17
  • 1
    You've got the '`restrict`' qualifiers on the wrong side of the '`*`'s here. – zwol Sep 07 '11 at 03:19
  • @davmac Do you mean something like `__restrict__ ptr = & (*iter)` ? Seems it will work, nice. Thanks. – san Sep 07 '11 at 03:24
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.

Mu Qiao
  • 6,941
  • 1
  • 31
  • 34
  • 1
    Pretty sure strict aliasing rules apply in `c` as well as `c++`. http://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule – Darren Engwirda Sep 07 '11 at 03:20
  • 1
    Yes, yes they do. Also, this answer does not tell the OP anything he or she did not already know. – zwol Sep 07 '11 at 03:25
  • 1
    The strict aliasing rules are more efficient in C++, because the parameters tend to be `std::vector&` and not `int*`. – Bo Persson Sep 07 '11 at 06:43
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.

sudo rm -rf slash
  • 1,156
  • 2
  • 16
  • 27