noalias
Microsoft 專有的
noalias表示函式呼叫不會未修改,或參考看得見的全域狀態,並且僅修改所指到的記憶體directly指標參數 (第一層間接取值)。
如果函式附註為noalias,最佳化器可以假設除了本身的參數,只會將第一層間接取值的指標參數所參考或修改的函式。看得見的全域狀態是一組的所有資料,未定義或參考外部的編譯範圍中,並不會採取它們的位址。編譯範圍是所有的原始程式檔 (/LTCG (連結時間產生程式碼)建置) 或單一原始程式檔 (非-/LTCG建置)。
範例
下列範例會示範如何使用__declspec(restrict)和__declspec(noalias)。一般情況下,記憶體所傳回的malloc是restrict和noalias因為 CRT 標頭已適當裝飾。
不過,在這個範例中,指標mempool和memptr 是全域的所以編譯器確定能夠獲得記憶體不會受制於別名沒有保證。傳回與指標的函式的裝飾__declspec(restrict)會告訴編譯器所傳回的值所指的記憶體不是別名。
裝飾函式在範例中所存取的記憶體__declspec(noalias)告知編譯器這個函式不會干擾全域狀態除了透過其參數清單中的指標。
// declspec_noalias.c
#include <stdio.h>
#include <stdlib.h>
#define M 800
#define N 600
#define P 700
float * mempool, * memptr;
__declspec(restrict) float * ma(int size)
{
float * retval;
retval = memptr;
memptr += size;
return retval;
}
__declspec(restrict) float * init(int m, int n)
{
float * a;
int i, j;
int k=1;
a = ma(m * n);
if (!a) exit(1);
for (i=0; i<m; i++)
for (j=0; j<n; j++)
a[i*n+j] = 0.1/k++;
return a;
}
__declspec(noalias) void multiply(float * a, float * b, float * c)
{
int i, j, k;
for (j=0; j<P; j++)
for (i=0; i<M; i++)
for (k=0; k<N; k++)
c[i * P + j] =
a[i * N + k] *
b[k * P + j];
}
int main()
{
float * a, * b, * c;
mempool = (float *) malloc(sizeof(float) * (M*N + N*P + M*P));
if (!mempool)
{
puts("ERROR: Malloc returned null");
exit(1);
}
memptr = mempool;
a = init(M, N);
b = init(N, P);
c = init(M, P);
multiply(a, b, c);
}