2011년 4월 4일 월요일

strict keyword in C99

C99 표준부터 쓸 수 있는 keyword인 'restrict'는 나도 몰랐었다.
결론적으로 instruction 한두개를 절약하는데 매우 유용하다.

void updatePtrs(size_t *restrict ptrA, size_t *restrict ptrB, size_t *restrict val)
{
*ptrA += *val;
    *ptrB += *val; 
} 
 
이렇게 pointer앞에 restrict를 넣어주면, 
함수내에서 포인터 aliasing이 일어나지 않는다는 것을
compiler에게 알려준다. 또한, 서로 같은 포인터를 가리키지 않는다는 것을 알려준다.
그럼으로 compiler가 불필요한 instruction을 생성하지 않아도 되게 한다.
 
A. 다음은 restrict를 하지 않았을때의 instruction들이다.
---------------------------------------------- 
load R1 ← *val  ; Load the value of val pointer
load R2 ← *ptrA ; Load the value of ptrA pointer
add  R2 += R1   ; Perform Addition
set  R2 → *ptrA ; Update the value of ptrA pointer
; Similarly for ptrB, note that val is loaded twice, 
; because ptrA may be equal to val.
load R1 ← *val  
load R2 ← *ptrB
add  R2 += R1
set  R2 → *ptrB
---------------------------------------------- 
 
B. 다음은 restrict를 넣었을때의 instruction들이다.
----------------------------------------------  
load R1 ← *val 
load R2 ← *ptrA
add  R2 += R1
set  R2 → *ptrA
; Note that val is not reloaded,
; because the compiler knows it is unchanged
load R2 ← *ptrB
add  R2 += R1
set  R2 → *ptrB 
----------------------------------------------

B에서는 *val의 포인터 값이 바뀌지 않는 다는 것을 알기 때문에, 
val을 R1레지스터에 reload하지 않았다.
(위의 설명은 위키에서 가져왔다. http://en.wikipedia.org/wiki/Restrict )
 
이런 케이스가 얼마나 될꺼냐고?
nedtrie의 소스를 보다가 쓰고 있는 현장을 목격했다. ㅎ
 http://www.nedprod.com/programs/portable/nedtries/
여기를 보면 더 자세한 설명이 되어 있다.
GCC의 strict_aliasing flag을 켜는 것에 대해 써 있는데,
모두 켜도 되는지 확실해야 한다. 아마도 확신하기 쉽지 않기 때문에, 
개별적으로 써야 할 듯 하다.
http://cellperformance.beyond3d.com/articles/2006/05/demystifying-the-restrict-keyword.html
도움이 되셨다면, 광고 클릭을 ㅎㅎ ^^