簡體   English   中英

優化器可以省略從 64 位到 32 位整數類型的分配嗎?

[英]Can the optimizer elide assignment from 64bit to 32bit integer types?

鑒於這種:

uint64_t truncate(uint64_t num) {
    uint32_t lessBits = static_cast<uint32_t>(num);
    return static_cast<uint64_t>(lessBits);
}

編譯器是否允許優化靜態轉換並保留完整的 64 位值,還是必須保留 32 位“截斷”?

做一個快速的godbold檢查,它會出現一個mov eax , ...被使用,這意味着 32 位“截斷”沒有被優化掉。

語言如何涵蓋這種情況? 我目前的猜測是這只是整數轉換被完全定義並且編譯器觀察到這一點的情況,所以它不能省略分配/32位轉換。

由於優化絕不能影響已定義的程序行為的原則,以及為了允許優化,標准必須將其行為可能影響的所有操作表征為未定義行為的推論,沒有定義的情況下標准將允許實現進行您描述的那種替換。 如果一個實現作為“符合語言擴展”的一種形式,指定除除法/余數之外的整數計算永遠不會產生任何副作用,除了產生可能會或可能不會在其正常范圍內的可能被截斷的值類型,然后使用 32 位int和 64 位long這樣的實現,給出如下內容:

long test(int *arr, int count)
{
  long total = 0;
  int subtotal = 0;
  for (int i=0; i<count; i++)
  {
    subtotal += arr[i];
    total += subtotal;
  }
  return total;
}

可能會在閑暇時將小計保持為 32 位int並在每次循環時將其符號擴展到 64 位,然后再將其添加到total ,或者它可以在從arr[i]加載時對其進行符號擴展內存並將subtotal保持為 64 位值,並且在溢出的情況下可能會觀察到這種行為差異,因為實現的“符合語言擴展”。

請注意,遺憾的是沒有辦法邀請編譯器對小於int類型執行此類優化,因為實現需要記錄有關如何將intunsigned轉換為較小有符號類型的一致規則,因此不允許簡單地存儲較小的類型在 32 位寄存器中輸入類型而不截斷並允許讀取它們的整個值,即使這樣做比截斷更有效。

在 C 語言中,整數類型之間的轉換是強制性的(除了 as-if 規則,這意味着編譯器可以做任何它喜歡的事情,如果它沒有任何區別。所以如果函數的每個返回值都被忽略或分配給 32 位整數,則允許編譯器不進行轉換。)

浮點類型之間的轉換可能不是強制性的; 編譯器可以自由使用比要求更高的精度。 但是,由於強制轉換而導致的轉換或由於對變量賦值而導致的轉換是強制性的。 此外,還有一些預定義的宏可以讓您檢測編譯器的作用。

所以

float x = 3.1;
float y = 3.2;
double d = x * y;
double e = (float) (x * y);
float z = x * y;

必須將 3.1f 和 3.2f 分配給 x 和 y。 x * y 可以以浮點或雙精度計算,因此 d 可能有不同的結果。 e 和 z 不能。 (這是因為 double 的尾數位是浮點數的兩倍以上,因此以無限精度計算 x*y,先舍入為 double 再舍入浮點數,產生的結果與僅舍入為浮點數相同。如果涉及 long double,事情可能會有所不同)。

暫無
暫無

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

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