2013年3月23日 星期六

GCC 4.8 Release Note

隔了整整一年的 GCC 4.8註1 終於 Release 了!

以下大略整理一下此次更新的部份, 主要整理自官方 Release 頁面[1], 但由於個人偏好, 非ARM, C/C++ 將不會出現在下面:

一般性

  1. GCC 切換使用 C++ 實作, 回不去了, 但要注意 GCC 中目前政策是只使用 C++2003 的 subset, 禁止列表可參考 [3]
  2. GCC 現在採用更激烈(aggressive)註2的最佳化, 同時也增加 -fno-aggressive-loop-optimizations 這個選項來避免過激行為
  3. DWARF4 為預設產生的 Debug Info
  4. 新的選項 -Og 可以產生有最佳化但又方便 Debug 的 Code, 以後可以不用下 -O0 -g3 可以換下 -Og -g3 了
  5. 新的最佳化選項 -ftree-partial-pre , 預設開啟於 -O3
  6. Struct 及 Matrix 的 reorg 功能被拔掉了(-fipa-struct-reorg 及 -fipa-matrix-reorg), 因為有機率產生出爛掉的東西, 而且 lto 時會爛掉
  7. LTO 大幅改善
  8. AddressSanitizer 及 ThreadSanitize 正式加入, 分別使用 -fsanitize=address 及 -fsanitize=thread 來開啟, AddressSanitizer 功能簡介可參照[5]

語言相關

  1. 錯誤訊息會用 ^ 來標示出錯誤地點, 例如以下是少分號的範例
    #include<stdio.h>
    #include<stdlib.h>
    
    int main(){
      return 0
    }
    
    GCC 4.8 的錯誤訊息
    test.c: In function ‘main’:
    test.c:6:1: error: expected ‘;’ before ‘}’ token
     }
     ^
    
    但跟 clang 比起來似乎還是沒做的很好, clang 的輸出範例:
    test.c:5:11: error: expected ';' after return statement
      return 0
              ^
              ;
    
    更多比較可參考[6]
  2. 新的選項 -ftrack-macro-expansion= 可以在讓你在顯示錯誤訊息時展開 Marco N 層, 範例:
    #define MARCO_(a, b) a b
    #define MARCO(a, b) MARCO_(a, b)
    
    void f(int a, int b) {
      MARCO(a, b);
    }
    
    GCC 4.7.2 的錯誤訊息
    marco.c: In function ‘f’:
    marco.c:5:3: error: expected ‘;’ before ‘b’
    
    GCC 4.8 的錯誤訊息
    marco.c: In function ‘f’:
    marco.c:6:12: error: expected ‘;’ before ‘b’
       MARCO(a, b);
                ^
    marco.c:2:24: note: in definition of macro 'MARCO_'
     #define MARCO_(a, b) a b
                            ^
    marco.c:6:3: note: in expansion of macro 'MARCO'
       MARCO(a, b);
       ^
    
    clang 的錯誤訊息
    marco.c:6:12: error: expected ';' after expression
      MARCO(a, b);
               ^
    marco.c:3:31: note: expanded from macro 'MARCO'
    #define MARCO(a, b) MARCO_(a, b)
                                  ^
    marco.c:2:24: note: expanded from macro 'MARCO_'
    #define MARCO_(a, b) a b
                           ^
    
  3. 新的警告 -Wsizeof-pointer-memaccess, 當該填 size 時你直接 sizeof(pointer) 就會跟你抱怨, 範例如下:
    #include <string.h>
    
    void f(int *p){
      memset(p, 1, sizeof(p));
    }
    
    然後開 -Wall 或 -Wsizeof-pointer-memaccess 會跟你抱怨
    memset.c: In function ‘f’:
    memset.c:4:22: warning: argument to ‘sizeof’ in ‘memset’ call is the same expression as the destination; did you mean to dereference it? [-Wsizeof-pointer-memaccess]
       memset(p, 1, sizeof(p));
                          ^
    
    不過還是要說一下 clang 吐出來的資訊比較清楚
    memset.c:4:23: warning: 'memset' call operates on objects of type 'int' while the size is based
          on a different type 'int *' [-Wsizeof-pointer-memaccess]
      memset(p, 1, sizeof(p));
             ~            ^
    memset.c:4:23: note: did you mean to dereference the argument to 'sizeof' (and multiply it by the
          number of elements)?
      memset(p, 1, sizeof(p));
                          ^
    

C++11專區

  1. thread_local 關鍵字實作了!
  2. 的 attribute 及 alignment 實作, 範例:
    [[noreturn]] void f();
    
    alignas(double) int i;
    

ARM

  1. AArch 64 支援
  2. ARM 的 AAPCS ABI 有稍微更動, 有關 vector types 部份的 ABI 將無法與舊的 GCC 產生的 Code 相容
  3. 現在 GCC 會想辦法產生 VFMA, VFMS, REVSH 及 REV16 指令
  4. 新的 Inst Scheduler 會考慮 Register Pressure, 不喜歡的話可透過 -fno-sched-pressure 關掉
  5. 支援 Marvell 的 iWMMX2 SIMD, 可透過指定 -mcpu=iwmmxt2 來開啟
註1: GCC 4.7 於 2012-03-22 Release 而 4.8 是 2013-03-22, 剛好一年
註2: Aggressive 這個字眼在 Compiler 領域中通常代表需要花較多時間分析及最佳化, 並且也有可能不會比較好(指 Code Size 或 Performance)

Reference

[1] GCC 4.8 Release 官方網頁
[2] C++ Conversion(GCC Wiki)
[3] http://gcc.gnu.org/wiki/CppConventions
[4] GCC and C vs C++ Speed, Measured
[5] Address-sanitizer : 新的 Android 快速記憶體錯誤偵測工具
[6] C++ Diagnostic Survey

沒有留言:

張貼留言