#define Size 819000
int sieve ( int N ) {
int64_t i , k , prime , count , n ; char flags [ Size ];
for ( n = 0 ; n < N ; n ++ ) {
count = 0 ;
for ( i = 0 ; i < Size ; i ++ )
flags [ i ] = 1 ;
for ( i = 0 ; i < Size ; i ++ )
if ( flags [ i ]) {
prime = i + i + 3 ;
for ( k = i + prime ; k < Size ; k += prime )
flags [ k ] = 0 ;
count ++ ;
}
}
return count ;
}
void ex100 ( void ) {
printf ("sieve (100) = %d", sieve (100));
}
m_sieve : module
export sieve
sieve : func i32, i32:N
local i64:iter, i64:count, i64:i, i64:k, i64:prime, i64:temp, i64:flags
alloca flags, 819000
mov iter, 0
loop : bge fin, iter, N
mov count, 0; mov i, 0
loop2 : bge fin2, i, 819000
mov u8:(flags, i), 1; add i, i, 1
jmp loop2
fin2 : mov i, 0
loop3 : bge fin3, i, 819000
beq cont3, u8:(flags,i), 0
add temp, i, i; add prime, temp, 3; add k, i, prime
loop4 : bge fin4, k, 819000
mov u8:(flags, k), 0; add k, k, prime
jmp loop4
fin4 : add count, count, 1
cont3 : add i, i, 1
jmp loop3
fin3 : add iter, iter, 1
jmp loop
fin : ret count
endfunc
endmodule
m_ex100 : module
format : string "sieve (10) = %dn"
p_printf : proto p:fmt, i32:result
p_sieve : proto i32, i32:iter
export ex100
import sieve, printf
ex100 : func v, 0
local i64:r
call p_sieve, sieve, r, 100
call p_printf, printf, format, r
endfunc
endmodule
func
描述函數的簽章(採用 32 位元有符號整數參數並傳回 32 位元有符號整數值)和函數參數N
,它將是 64 位元有符號整數類型的局部變量;
string
以C字串的形式描述數據export
描述當前模組外部可見的模組功能或數據import
描述了應該在其他 MIR 模組中定義的模組函數或數據proto
描述了函數原型。其語法與func
語法相同call
是呼叫函數的 MIR 指令MIR_load_external
載入外部 C 函數m1
和m2
是模組m_sieve
和m_e100
, func
是函數ex100
, sieve
是函數sieve
): /* ctx is a context created by MIR_init / MIR_init2 */
MIR_load_module ( ctx , m1 ); MIR_load_module ( ctx , m2 );
MIR_load_external ( ctx , "printf" , printf );
MIR_link ( ctx , MIR_set_interp_interface , import_resolver );
/* or use MIR_set_gen_interface to generate and use the machine code */
/* or use MIR_set_lazy_gen_interface to generate function code on its 1st call */
/* use MIR_gen (ctx, func) to explicitly generate the function machine code */
MIR_interp ( ctx , func , & result , 0 ); /* zero here is arguments number */
/* or ((void (*) (void)) func->addr) (); to call interpr. or gen. code through the interface */
binfmt_misc
在 Linux 上運行二進位 MIR 文件mir-bin-run
進位檔案已準備好透過binfmt_misc
使用下列行(範例):
line=:mir:M::MIR::/usr/local/bin/mir-bin-run:P
echo $line > /proc/sys/fs/binfmt_misc/register
請根據您的系統調整 mir-bin-run 二進位路徑,這是預設路徑
並運行
c2m your-file.c -o your-file
chmod +x your-file
./your-file your args
可執行檔可透過環境變數「配置」:
MIR_TYPE
設定程式碼執行的介面: interp
(用於解釋)、 jit
(用於生成)和lazy
(用於延遲生成,預設);MIR_LIBS
(冒號分隔清單)定義要載入的額外庫的清單;MIR_LIB_DIRS
或LD_LIBRARY_PATH
(冒號分隔清單)定義用於搜尋庫的額外目錄清單。由於
mir-bin-run
與binfmt_misc
的綁定性質,直接呼叫mir-bin-run
可能有點奇怪。 binfmt_misc 上的P
標誌傳遞一個額外的參數,其中包含 MIR 二進位檔案的完整路徑。
優化流程非常短,速度快且重量輕
僅最有價值的優化用途:
不同的最佳化等級可調整編譯速度與產生的程式碼效能
MIR 的SSA形式用於暫存器分配之前
針對極端生成程式碼效能的最佳化實施的簡單性
有關完整 JIT 編譯器管道的更多詳細資訊:
簡化:降低 MIR
Inline :內嵌 MIR 調用
Build CFG :建立控制流程圖(基本區塊和CFG邊)
建構 SSA :透過向運算元新增 phi 節點和 SSA 邊來建構單一靜態賦值形式
位址轉換:刪除或變更 MIR ADDR 指令
全球價值編號:透過 GVN 刪除冗餘 insn。這包括恆定傳播和冗餘負載消除
複製傳播:SSA複製傳播並刪除冗餘擴充指令
死店消除:刪除多餘的店
死程式碼消除:刪除具有未使用輸出的insn
壓力釋放:移動insns以降低套準壓力
SSA組合:組合位址以及比較和分支指令對
SSA 以外:刪除 phi 節點和 SSA 邊
Jump opts :不同的跳躍優化
Machinize :執行機器相關程式碼轉換 MIR 以呼叫 ABI、2-op insns 等
Find Loops :尋找自然循環並建立循環樹
建構活資訊:計算基本塊的活入與活出
建構寄存器衝突:為涉及移動的寄存器建立衝突矩陣。它用於寄存器合併
Coalesce :積極的暫存器合併
暫存器分配器 (RA) :基於優先權的線性掃描 RA,具有生命範圍分割
建構生命範圍:計算暫存器的程式點範圍
分配:用於-O0
的快速RA或用於-O1
及以上的基於優先順序的線性掃描RA
重寫:使用保留的硬暫存器根據分配轉換 MIR
組合(程式碼選擇):將資料依賴的insn合併為一個
死程式碼消除:刪除具有未使用輸出的insn
產生機器 Insns :執行與機器相關的程式碼建立機器 Insns
c2m
實作了一個小型 C11(2011 ANSI C 標準,帶有一些 GCC 擴充)。請參閱 README.mdmir.h
和mir.c
包含主要 API 程式碼,包括 MIR 二進位和 MIR 文字表示的輸入/輸出mir-dlist.h
、 mir-mp.h
、 mir-varr.h
、 mir-bitmap.h
、 mir-hash.h
、 mir-htab.h
、 mir-reduce.h
包含對應的雙連結通用程式碼列表、記憶體池、可變長度數組、點陣圖、哈希計算、哈希表以及壓縮/解壓縮資料。檔案mir-hash.h
是哈希表使用的通用、簡單、高品質的雜湊函數mir-interp.c
包含用於解釋 MIR 程式碼的程式碼。它包含在mir.c
中並且從不單獨編譯mir-gen.h
、 mir-gen.c
、 mir-gen-x86_64.c
、 mir-gen-aarch64.c
、 mir-gen-ppc64.c
、 mir-gen-s390x.c
和mir-gen-riscv64.c
包含 MIR JIT 編譯器的程式碼mir-gen-x86_64.c
、 mir-gen-aarch64.c
、 mir-gen-ppc64.c
、 mir-gen-s390x.c
和mir-gen-riscv64.c
是 JIT 編譯器的機器相關程式碼mir-.c
包含解釋器和 JIT 編譯器常見的簡單機器相關程式碼mir-.h
包含解釋器和 JIT 編譯器通用的聲明mir2c/mir2c.h
和mir2c/mir2c.c
包含 MIR 到 C 編譯器的程式碼。產生的程式碼可能不可移植c2mir/c2mir.h
、 c2mir/c2mir.c
、 c2mir/c2mir-driver.c
和c2mir/mirc.h
包含 C 到 MIR 編譯器的程式碼。目錄c2mir/x86_64
和c2mir/aarch64
、 c2mir/ppc64
、 c2mir/s390x
和c2mir/riscv64
中的檔案對應包含用於 C 到 MIR 編譯器的 x86_64、aarch64、ppc64le、s390x 和 cvrismir-bin-run.c
包含上述mir-bin-run
的程式碼b2ctab
實用程式的檔案mir-bin-driver.c
可用於從 MIR 二進位檔案產生二進位檔案的便攜式方式mir-utils
包含使用 MIR 的不同實用程序,例如將二進位 MIR 轉換為文字 MIR,反之亦然adt-tests
、 mir-tests
、 c-tests
和c-benchmarks
包含用於測試和基準測試 MIR 和c2m
的程式碼make bench
和make test
來執行一些基準測試和測試Intel i5-13600K,FC37 下 64GB 內存,GCC-12.3.1
MIR 產生器 | MIR 解釋器 | 海合會-O2 | 海灣合作委員會-O0 | |
---|---|---|---|---|
編譯[1] | 1.0 (249 秒) | 0.09(22 微秒) | 109 (27.1 毫秒) | 105(26.1 毫秒) |
執行 [2] | 1.0 (1.74秒) | 13.7(23.8秒) | 0.92 (1.6秒) | 2.28(3.97 秒) |
代碼大小 [3] | 1.0 (557KB) | 0.43 (240KB) | 58 (32.2MB) | 58 (32.2MB) |
LOC [4] | 1.0 (23.4K) | 0.48(11.3K) | 103 (2420K) | 103 (2402K) |
[1] 基於 C 篩程式碼的編譯時間(沒有任何包含文件,並且使用 GCC 的記憶體檔案系統)以及由最佳化等級 2 的 MIR 解釋器和 MIR 產生器產生的相應 MIR 篩選程式碼
[2] 基於使用 MIR 生成器優化等級 2 的 10 次運行的最佳運行時間
[3] 基於 GCC 和 MIR 核心的 cc1 的剝離大小以及 MIR 的解釋器或產生器
[4] 我的估計僅基於 x86-64 GNU C 編譯器所需的文件和用於創建和運行 MIR 程式碼的最小程式的 MIR 文件
Intel i5-13600K,FC37 下 64GB 內存,GCC-12.3.1
c2m -O2 -eg(發電機) | c2m-ei(解譯者) | 海合會-O2 | 海灣合作委員會-O0 | |
---|---|---|---|---|
編譯[1] | 1.0 (336us) | 1.0(337 秒) | 80 (27.1 毫秒) | 77(26.1 毫秒) |
執行 [2] | 1.0 (1.74秒) | 13.7(23.8秒) | 0.92 (1.6秒) | 2.28(3.97 秒) |
代碼大小 [3] | 1.0 (961KB) | 1.0 (961KB) | 34 (32.2MB) | 34 (32.2MB) |
LOC [4] | 1.0 (54.8K) | 1.0 (54.8K) | 44 (2420K) | 44 (2420K) |
[1] 基於 C sieve 程式碼的編譯時間(沒有任何包含檔案並使用 GCC 記憶體檔案系統)
[2] 基於使用 MIR 生成器優化等級 2 的 10 次運行的最佳運行時間
[3] 基於 GCC 和 C2MIR、MIR 核心、解釋器和 MIR 生成器的 cc1 的剝離大小
[4] 基於測試以外的所有來源文件
以下是在同一台機器上針對不同 C 編譯器在 15 個小型 C 基準測試(來自目錄c-benchmarks
)上產生的與 GCC -O2 相關的程式碼效能,其中
平均的 | 幾何平均法 | |
---|---|---|
海合會-O2 | 1.00 | 1.00 |
海灣合作委員會-O0 | 0.63 | 0.57 |
c2m-eg | 0.96 | 0.91 |
c2m-eb | 0.92 | 0.85 |
奇比克 | 0.38 | 0.30 |
鏗鏘-O2 | 1.12 | 1.09 |
cparser-O3 | 1.02 | 0.98 |
行程 | 0.68 | 0.65 |
紫膠-O3 | 0.47 | 0.39 |
聚碳酸酯-O | 0.80 | 0.78 |
TCC | 0.54 | 0.50 |
emcc-O2/wasmer | 0.60 | 0.55 |
wasi -O2/wasmer 起重機 | 0.60 | 0.54 |
wasi-O2/wasmer LLVM | 0.78 | 0.72 |
wasi-O2/wasmer 單通道 | 0.45 | 0.36 |
瓦西-O2/wasmtime | 0.92 | 0.87 |
c2m
)移植到另一個目標 1-2 個月