簡體   English   中英

ARM GCC 在優化期間刪除所需的代碼

[英]ARM GCC removing required code during optimization

我有以下代碼,它執行從 16bpp 圖像到 1bpp 圖像的真正基本轉換,代碼按預期運行,直到我啟用編譯器優化,此時我只得到一個黑色圖像。

#define RSCALE 5014709
#define GSCALE 9848225
#define BSCALE 1912602

uint16_t _convertBufferTo1bit(uint8_t* buffer, uint16_t size)
{
    uint8_t* dst_ptr = buffer;
    uint8_t* end_ptr = buffer + size;
    uint16_t pos = 0;
    uint8_t r, g, b, i;
    uint32_t lum;

    while(buffer < end_ptr)
    {
        for(i = 8; i > 0; i--)
        {
            r = (*buffer & 0xF8);
            g = ((*buffer & 0x07) << 5);
            buffer += 1;
            g |= (*buffer & 0x03);
            b = ((*buffer & 0x1F) << 3);
            buffer += 1;

            lum = ((RSCALE * r) + (GSCALE * g) + (BSCALE * b));
            if(lum > 0x7FFFFFFF)
            {
                //White
                dst_ptr[pos] |= (1 << (i-1));
            }
            else
            {
                //black
                dst_ptr[pos] &= ~(1 << (i-1));
            }
        }
        pos++;
    }

    return pos;
}

查看反編譯的程序集時,我可以看到if(lum > 0x7FFFFFFF)語句和所有相關計算已被編譯器刪除。 有人可以幫我理解為什么嗎?

-O0 -std=c++17 -Wall -Wextra

https://godbolt.org/z/GhPezzh33

-O1 -std=c++17 -Wall -Wextra

https://godbolt.org/z/bn1M4319h

在這段代碼中:

lum = ((RSCALE * r) + (GSCALE * g) + (BSCALE * b));
if(lum > 0x7FFFFFFF)

RSCALEGSCALEBSCALE分別是501470998482251912602 假設int在正在使用的 C 實現中是 32 位,這些都是int常量。

rgb都是uint8_t類型,因此在乘法中它們被提升為int

然后((RSCALE * r) + (GSCALE * g) + (BSCALE * b))是一個完全使用int操作數產生int結果的計算。 因此編譯器可以看到lum被分配了一個int結果的值,並且它有權假設結果在INT_MININT_MAX的范圍內。 此外,它可以看到所有操作數都是非負數,因此不可能產生負數,將可能的范圍縮小到0INT_MAX 這排除了將負值分配給uint32_t將導致換行到高值的可能性。 所以編譯器可能會假設lum > 0x7FFFFFFF永遠不會是真的。

計算可能會溢出int ,然后行為未定義,並且仍然允許編譯器使用該假設。

要更正此問題,請將每個乘法的至少一個操作數更改為unsigned

暫無
暫無

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

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