簡體   English   中英

基於整數溢出的GCC優化

[英]GCC optimizations based on integer overflow

最近,我有一個關於有人想要檢查帶符號的int溢出的討論,例如if (A + B < 2 * max(A, B)) 讓我們先忽略一下邏輯本身是錯誤的,然后在C / C ++的上下文中討論有符號整數溢出。 (我相信這完全是從C繼承了標准的這一部分)。

當前的GCC將優化哪些需要帶符號整數溢出的檢查,而哪些不會呢?

由於原始文本的格式不夠好,並且似乎存在爭議,因此我決定對問題進行一些更改,但將原始文本保留在下面。

下面使用的所有示例均已通過gcc版本4.7.2 (Debian 4.7.2-5)並使用-O3編譯

即,它是未定義的,並且GCC臭名昭著地使用它來執行一些分支簡化。 我想到的第一個例子是

int i = 1;
while (i > 0){
    i *= 2;
}

產生無限循環。 這種優化開始的另一種情況是

if (A + 2 < A){
    /* Handle potential overflow */
}

假設A是帶符號整數類型,則溢出分支將被完全刪除。

更有趣的是,一些容易證明的整數溢出的情況沒有受到影響,例如

if (INT_MAX + 1 < 0){
    /* You wouldn't write this explicitly, but after static analysis the program
       could be shown to contain something like this. */
}

這會觸發以二進制補碼表示的分支。 同樣,此代碼使條件分支保持不變

int C = abs(A);
if (A + C < 0){
    /* For this to be hit, overflow or underflow had to happen. */
}

現在,對於這個問題,是否存在一種看起來像if (A + B < C)if (A + B < c)將被優化掉? 當我在寫這篇文章之前四處搜尋時,似乎應該對最后一個代碼片段進行優化,但是我無法在沒有顯式使用常量的溢出檢查中重現這種錯誤。

許多編譯器會將涉及帶符號整數或指針的表達式替換為“ false”,例如

a + 1 < a // signed integer a
p + 1 < p // Pointer p

當表達式僅在未定義行為的情況下可以為真時。 另一方面,這允許

for (char* q = p; q < p + 2; ++q) ...

內聯,不用任何檢查就用q = p和q = p + 1代替,所以這是一件好事。

if (A + abs (A) < 0)

對於許多編譯器來說可能太復雜了。 請注意,對於無符號整數,沒有未定義的行為。 結果,使用無符號32位整數和64位指針的循環會比必要的慢,因為必須考慮回繞行為。 對於無符號的32位整數和64位指針,可能

&p [i] > &p [i+1]

沒有未定義的行為(不帶有64位整數或32位指針)。

如果我可以解釋您的問題,我相信這是在問這樣的事情。

是否有一個編譯器如此積極地優化有符號整數表達式,使其准備對此類表達式的某些類別進行詳細分析,以便確定在可range of representable values for the type的整個可range of representable values for the type從屬條件為真(或假)。表達式的結果,並以此方式刪除條件測試?

您提供的編譯器是GCC的特定版本,並且您提供的表達式范圍很窄,但是我想您也希望了解其他編譯器或緊密相關的表達式。

答案是現在我還不知道,但這可能只是時間問題。

現有的編譯器會對包含常量或某些可識別模式的表達式進行過早評估,如果在此評估期間遇到不確定的行為,通常會避免優化表達式。 他們沒有義務這樣做。

數據流分析需要占用大量CPU和內存,並且傾向於在有很大好處的地方使用。 最終,C ++標准將停止更改(太多),並且編譯器編寫者將有很多時間在手。 編譯器讀取質數篩程序並將其優化為單個打印語句時,我們還有一天的時間,但是它會來的。

我的回答的重點是指出這實際上是關於編譯器技術的問題,與C ++標准關系不大。 也許您應該直接向GCC小組詢問。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM