2016-07-03 3 views
9

모든 함수가 오류가없는 경우 0이고 오류 값이 0이 아닌 오류 코드를 반환하는 API를 가정합니다.C 정적 인라인 매개 변수 평가 최적화

int foo(...); 
int bar(...); 

이 API 함수하자. 이 있으라 수 foobar항상 호출해야 순서 및 foo는 바에서 호출 할 필요가있는 코드 조각에 관계없이 이전 오류의하지만 먼저 즉, 0이 아닌 에러 코드가 전파 될

을 반환
int foobar(...) 
{ 
    int rc = 0, rc_; 
    /* ... */ 
    rc_ = foo(...); rc = rc ? rc : rc_; 
    rc_ = bar(...); rc = rc ? rc : rc_; 
    return rc; 
} 

rc를 쓰면 rc_ multiplexing은 지루하고 오류가 발생하기 쉽습니다 (세 번째 연산자 인 if/else 또는 다른 것이 사용 되더라도 상관 없습니다).

수있다 에러 전파 도우미 함수

이이

int foobar(...) 
{ 
    int rc = 0; 
    /* ... */ 
    rc = rc_propagate(foo(...), rc); 
    rc = rc_propagate(bar(...), rc); 
    return rc; 
} 

같이 foobar에서 사용될 수

static inline 
int rc_propagate(int r, int p){ return p ? p : r; } 

C 표준의 제 파라미터의 평가를 당김으로써 최적화 할 수 있는가하자 rc_propagate, 정적 인라인 함수를 세 번째로 입력하여 두 번째 매개 변수 이 0이 아닌 경우 삼항 연산자 평가 규칙으로 인해 실행되지 않을 수 있습니다.

+1

하지만, 사람이 인용을 위해 기다릴 것 표준의 관련 부분. – immibis

+0

@ 2501 :이 경우에는 외부 기능이 아니고 정적 인라인입니다.내 의심은 전적으로 정적 인라인에 관한 것입니다. 특히 LLVM 개발자의 몇 가지 블로그 항목과 정적 인라인 함수 호출과 관련된 가능한 최적화를 읽었습니다. – datenwolf

+0

참고로,'rc = rc? rc : foo (...);'문제를 모두 피할 수 있습니까? – 2501

답변

3

컴파일러 (또는 관련 하드웨어)는 프로그램이 동일하게 유지되는 한 최적화 할 수 있습니다. 즉, 실행 한 프로그램이 작성한 프로그램과 다르다는 것을 증명할 수 없습니다.

이 경우, 작성한 프로그램은 평가되지 않을 수있는 삼항 연산자에 없으므로 항상 외부 함수를 호출합니다. 이 함수는 다른 흥미로운 부작용을 가질 수 있으며 컴파일러가 알지 못합니다. 즉, 최적화 된 버전의 프로그램은 해당 동작을 유지하기 위해 외부 함수를 호출해야합니다 (코드를 재정렬 할 수 있음).

이것이 사실이 아니라면 실행 한 프로그램이 작성한 프로그램과 같지 않다는 것을 증명할 수 있습니다. 이렇게하는 것이 쉽습니다. 외부 함수 호출에 printf (또는 동등한) 명령.을 넣으십시오.

1. 생성 된 기계 코드 또는 실행 파일이 아니라 실행될 때 존재하는 추상 프로그램의 개념.

GCC 버전 4.9.2, 5.3, 또는 6.1 : 기관에서 인수를 사용는


, 당신은 어떤 컴파일러는 실제로 foo는() 호출과 바() 출력을 최적화하지 않습니다 것을 알 수 있습니다 -O2 :

foobar(): 
pushq %rbx  
call foo()  
movl %eax, %ebx  
call bar()  
testl %ebx, %ebx  
cmove %eax, %ebx  
movl %ebx, %eax  
popq %rbx  
ret 

연타 버전 3.7.1 또는 -O2와 3.8 :

foobar():       
pushq %rbx  
callq foo()  
movl %eax, %ebx  
callq bar()  
testl %ebx, %ebx  
cmovnel %ebx, %eax  
popq %rbx  
나는 아무 생각
+0

글쎄, 내 충고는'정적 인라인 (static inline) '이고 부작용이없는 전달 함수에 관한 것이므로이 경우 컴파일러는 내부에서 일어나는 일을 알고있다. 그 중 하나가 오류를 반환하더라도 체인 *의 모든 함수가 호출 될 것입니다. 'rc_propagate'를 외부로 만드는 것은 확실하게 트릭을 할 것입니다. 그러나'정적 인라인'은 어떨까요? 나중에 컴파일러는 거기에 무슨 일이 일어나고 있는지에 대한 종합적인 지식을 제공합니다. – datenwolf

+0

@datenwolf 정적 인라인에서도 호출됩니다. 참고 : 외부 함수는 정적 함수가 아니라 알 수 없으므로 호출해야합니다. – 2501