2015-07-20 61 views
5

所以,我最近感興趣的是編譯器(gcc (GCC) 4.8.3是否是有問題的)在優化指針和指針方面的表現。編譯器何時會對指針解引用優化保守?

最初我創建了一個簡單的整數和一個整數指針,並且實現了 操作,所以我可以打印出來。正如預期的那樣,硬編碼的所有操作 都是通過取消引用指針來優化的。

call __main 
leaq .LC0(%rip), %rcx 
movl $1, %edx 
call printf 

甚至創建一個函數,它在一個int指針, 取消引用它,改變它,它仍然是完全optmized後。

call __main 
leaq .LC0(%rip), %rcx 
movl $-1, %edx 
call printf 

現在,當我處理我的指針爲無效,鑄造它爲char和提領它所做的更改 ,它實際上仍optmized 完美(一個「額外」的MOV呼叫,因爲我最初把它作爲一個8字節 值,然後作爲指針廢棄1個字節值)

call __main 
movl $4, 44(%rsp) 
movb $2, 44(%rsp) 
leaq .LC0(%rip), %rcx 
movl 44(%rsp), %eax 
leal 1(%rax), %edx 
call printf 

所以到我的問題(S):

  1. 關於指針取消引用的編譯器優化的一致性如何?在某些情況下,它會選擇保守?

  2. 如果項目中的所有指針都是用restrict關鍵字聲明的,我可以相信它會像'完全沒有指針被使用'一樣優化嗎?

(假設沒有volatile例)

Ps¹:我知道,編譯器一般不工作不夠好,那一個 程序員擔心在不重要的優化幫助編譯器,在 一般來說,非生產性的(因爲很多關於優化的問題在關於 問題的答案中指出)。然而,我仍然對此事有好奇心。

Ps².: gcc -O3 -S -c main.c是用於生成彙編代碼

C代碼的命令:(如需要)

1:

#include <stdio.h> 

int main (void) 
{ 
    int a = 4; 
    int *ap = &a; 

    *ap = 0; 
    a += 1; 

    printf("%d\n", a); 
    return 0; 
} 

2:

#include <stdio.h> 

void change(int *p) { 
    *p -= 2; 
} 

int main (void) 
{ 
    int a = 4; 
    int *ap = &a; 

    *ap = 0; 
    change(ap); 
    a += 1; 

    printf("%d\n", a); 
    return 0; 
} 

3:

#include <stdio.h> 

void change(void *p) { 
    *((char*)p) += 2; 
} 

int main (void) 
{ 
    int a = 4; 
    void *ap = (void*) &a; 

    *((char*)(ap)) = 0; 
    change(ap); 
    a += 1; 

    printf("%d\n", a); 
    return 0; 
} 
+3

'restrict'和'const'是程序員的保證,而不是編譯器。如果你違反合同,不要驚訝地調用UB – Olaf

+0

爲什麼不包括C代碼,你得到了你發佈的結果彙編? –

+0

@JimBuck我將它們附加到問題中。 – SSWilks

回答

1

作爲優化分析的一部分,LLVM和GCC都發出靜態單分配表單代碼。 SSA代碼的一個有用屬性是精確地顯示了賦值影響的流程 - 也就是說,它知道哪些賦值導致了其他賦值,因此可以檢測哪些值可以影響其他賦值。

第一影響鏈看起來像

一個 - >常數(0) - > AP - >一個

第二種: 一個 - >常數( 0) - > ap - > p - > a

第三個與第二個非常相似。 (對不起,這個表示法已經很多了,但我希望它能夠說明我的觀點)。

因爲證明ap對ap的影響是確定性的,所以它可以自由地解除引用'early'並將這些指令組合成一個(儘管在前兩種情況下,這不是最準確的陳述,因爲該常數會覆蓋原始參考,並且讓編譯器證明原始分配不會流到代碼的末尾

使編譯器對解引用更加保守會涉及到足夠複雜以避免編譯器的理解(我認爲在靜態程序中很難)或者更可能導致編譯器在SSA過程中調用phi函數(以外行人員的名義,到c使用該作業受以前的多個作業影響)以非確定性方式進行。

restrict關鍵字的目的是暗示編譯器兩個指針是不同的。如果生成該指針的代碼仍然具有非確定性源代碼(例如,如果運行時創建的數據影響了取消引用值的選擇,我認爲這會在序列化時發生這種情況,這不會限制在運行時使用解除引用指針從外部源發送到程序中?)