#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
menjelaskan tanda tangan fungsi (mengambil argumen bilangan bulat bertanda 32-bit dan mengembalikan nilai bilangan bulat bertanda 32-bit) dan argumen fungsi N
yang akan menjadi variabel lokal bertipe bilangan bulat bertanda 64-bit;
string
mendeskripsikan data dalam bentuk string Cexport
menjelaskan fungsi modul atau data yang terlihat di luar modul saat iniimport
menjelaskan fungsi modul atau data yang harus didefinisikan dalam modul MIR lainnyaproto
menjelaskan prototipe fungsi. Sintaksnya sama dengan sintaks func
call
adalah instruksi MIR untuk memanggil fungsi MIR_load_external
m1
dan m2
adalah modul m_sieve
dan m_e100
, func
adalah fungsi ex100
, sieve
adalah fungsi 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
Biner mir-bin-run
disiapkan untuk digunakan dari binfmt_misc
dengan baris berikut (contoh):
line=:mir:M::MIR::/usr/local/bin/mir-bin-run:P
echo $line > /proc/sys/fs/binfmt_misc/register
Sesuaikan jalur biner mir-bin-run ke sistem Anda, yang merupakan jalur default
Dan jalankan dengan
c2m your-file.c -o your-file
chmod +x your-file
./your-file your args
Eksekusinya "dapat dikonfigurasi" dengan variabel lingkungan:
MIR_TYPE
menyetel antarmuka untuk eksekusi kode: interp
(untuk interpretasi), jit
(untuk pembuatan) dan lazy
(untuk pembuatan lambat, default);MIR_LIBS
(daftar dipisahkan titik dua) mendefinisikan daftar perpustakaan tambahan untuk dimuat;MIR_LIB_DIRS
atau LD_LIBRARY_PATH
(daftar dipisahkan titik dua) mendefinisikan daftar direktori tambahan untuk mencari perpustakaan.Karena sifat terikat
mir-bin-run
denganbinfmt_misc
, mungkin agak aneh untuk memanggilmir-bin-run
secara langsung. BenderaP
pada binfmt_misc meneruskan argumen tambahan dengan path lengkap ke biner MIR.
Jalur pengoptimalan yang sangat pendek untuk kecepatan dan ringan
Hanya penggunaan pengoptimalan yang paling berharga :
Tingkat pengoptimalan yang berbeda untuk menyesuaikan kecepatan kompilasi vs kinerja kode yang dihasilkan
Bentuk SSA dari MIR digunakan sebelum alokasi register
Kesederhanaan penerapan pengoptimalan dibandingkan kinerja kode yang dihasilkan secara ekstrem
Detail selengkapnya tentang pipeline kompiler JIT lengkap :
Sederhanakan : menurunkan MIR
Inline : menyejajarkan panggilan MIR
Build CFG : membangun Grafik Aliran Kontrol (blok dasar dan tepi CFG)
Bangun SSA : Membuat Formulir Penugasan Statis Tunggal dengan menambahkan node phi dan tepi SSA ke operan
Transformasi Alamat : menghapus atau mengubah instruksi MIR ADDR
Penomoran Nilai Global : menghapus penginapan yang berlebihan melalui GVN. Hal ini mencakup propagasi konstan dan penghapusan beban berlebihan
Copy Propagation : Propagasi salinan SSA dan menghapus instruksi ekstensi yang berlebihan
Penghapusan penyimpanan mati : menghapus penyimpanan yang berlebihan
Penghapusan Kode Mati : menghapus insns dengan output yang tidak terpakai
Pelepas tekanan : memindahkan insns untuk menurunkan tekanan register
SSA menggabungkan : menggabungkan alamat dan pasangan instruksi perbandingan dan cabang
Keluar dari SSA : Menghapus node phi dan tepi SSA
Opsi lompat : Optimasi lompatan yang berbeda
Machinize : menjalankan kode yang bergantung pada mesin yang mengubah MIR untuk panggilan ABI, insns 2-op, dll
Temukan Loop : menemukan loop alami dan membangun pohon loop
Build Live Info : menghitung live in dan live out untuk blok dasar
Build Register Conflicts : membangun matriks konflik untuk register yang terlibat dalam perpindahan. Ini digunakan untuk penggabungan register
Coalesce : penggabungan register yang agresif
Register Allocator (RA) : RA pemindaian linier berbasis prioritas dengan pemisahan jangkauan langsung
Bangun Rentang Langsung : menghitung rentang titik program untuk register
Tetapkan : RA cepat untuk -O0
atau RA pemindaian linier berbasis prioritas untuk -O1
dan lebih tinggi
Tulis ulang : ubah MIR sesuai dengan penetapannya menggunakan hard reg yang dicadangkan
Gabungkan (pemilihan kode): menggabungkan insn yang bergantung pada data menjadi satu
Penghapusan Kode Mati : menghapus insns dengan output yang tidak terpakai
Hasilkan Mesin Inns : menjalankan kode yang bergantung pada mesin yang membuat mesin insns
c2m
. Lihat README.mdmir.h
dan mir.c
berisi kode API utama termasuk input/output biner MIR dan representasi teks MIRmir-dlist.h
, mir-mp.h
, mir-varr.h
, mir-bitmap.h
, mir-hash.h
, mir-htab.h
, mir-reduce.h
berisi kode generik yang sesuai untuk tautan ganda daftar, kumpulan memori, array panjang variabel, bitmap, perhitungan hash, tabel hash, dan kompresi/dekompresi data. File mir-hash.h
adalah fungsi hash umum, sederhana, dan berkualitas tinggi yang digunakan oleh tabel hashmir-interp.c
berisi kode untuk interpretasi kode MIR. Itu disertakan dalam mir.c
dan tidak pernah dikompilasi secara terpisahmir-gen.h
, mir-gen.c
, mir-gen-x86_64.c
, mir-gen-aarch64.c
, mir-gen-ppc64.c
, mir-gen-s390x.c
, dan mir-gen-riscv64.c
berisi kode untuk kompiler MIR JITmir-gen-x86_64.c
, mir-gen-aarch64.c
, mir-gen-ppc64.c
, mir-gen-s390x.c
, dan mir-gen-riscv64.c
adalah kode yang bergantung pada mesin dari kompiler JITmir-.c
berisi kode sederhana yang bergantung pada mesin yang umum untuk juru bahasa dan kompiler JITmir-.h
berisi deklarasi umum untuk interpreter dan compiler JITmir2c/mir2c.h
dan mir2c/mir2c.c
berisi kode untuk kompiler MIR ke C. Kode yang dihasilkan mungkin tidak portabelc2mir/c2mir.h
, c2mir/c2mir.c
, c2mir/c2mir-driver.c
, dan c2mir/mirc.h
berisi kode untuk kompiler C ke MIR. File dalam direktori c2mir/x86_64
dan c2mir/aarch64
, c2mir/ppc64
, c2mir/s390x
, dan c2mir/riscv64
berisi x86_64, aarch64, ppc64le, s390x, dan kode yang bergantung pada mesin riscv untuk compiler C ke MIRmir-bin-run.c
berisi kode untuk mir-bin-run
yang dijelaskan di atasmir-bin-driver.c
dengan utilitas b2ctab
dapat digunakan untuk cara portabel untuk menghasilkan biner dari file biner MIRmir-utils
berisi utilitas berbeda untuk bekerja dengan MIR, misalnya mengubah MIR biner menjadi MIR tekstual dan sebaliknyaadt-tests
, mir-tests
, c-tests
, dan c-benchmarks
berisi kode untuk pengujian dan benchmarking MIR dan c2m
make bench
dan make test
Intel i5-13600K dengan memori 64GB di bawah FC37 dengan GCC-12.3.1
Generator MIR | Penerjemah MIR | gcc-O2 | gcc -O0 | |
---|---|---|---|---|
kompilasi [1] | 1.0 (249us) | 0,09 (22us) | 109 (27,1 mdtk) | 105 (26,1 mdtk) |
eksekusi [2] | 1,0 (1,74 detik) | 13,7 (23,8 detik) | 0,92 (1,6 detik) | 2,28 (3,97 detik) |
ukuran kode [3] | 1.0 (557 KB) | 0,43 (240 KB) | 58 (32,2MB) | 58 (32,2MB) |
LOK [4] | 1.0 (23.4K) | 0,48 (11,3K) | 103 (2420K) | 103 (2402K) |
[1] didasarkan pada waktu dinding kompilasi kode saringan C (tanpa file apa pun yang disertakan dan dengan menggunakan sistem file memori untuk GCC) dan kode saringan MIR yang sesuai oleh penerjemah MIR dan generator MIR dengan level optimasi 2
[2] didasarkan pada waktu dinding terbaik sebanyak 10 kali berjalan dengan menggunakan optimasi generator MIR level 2
[3] didasarkan pada ukuran cc1 yang dilucuti untuk inti GCC dan MIR serta juru bahasa atau generator untuk MIR
[4] perkiraan saya hanya berdasarkan file yang diperlukan untuk kompiler GNU C x86-64 dan file MIR untuk program minimal untuk membuat dan menjalankan kode MIR
Intel i5-13600K dengan memori 64GB di bawah FC37 dengan GCC-12.3.1
c2m -O2 -misalnya (generator) | c2m -ei (penerjemah) | gcc-O2 | gcc -O0 | |
---|---|---|---|---|
kompilasi [1] | 1.0 (336us) | 1.0 (337us) | 80 (27,1 mdtk) | 77 (26,1 mdtk) |
eksekusi [2] | 1,0 (1,74 detik) | 13,7 (23,8 detik) | 0,92 (1,6 detik) | 2,28 (3,97 detik) |
ukuran kode [3] | 1.0 (961 KB) | 1.0 (961 KB) | 34 (32,2MB) | 34 (32,2MB) |
LOK [4] | 1.0 (54.8K) | 1.0 (54.8K) | 44 (2420K) | 44 (2420K) |
[1] didasarkan pada waktu dinding kompilasi kode saringan C (tanpa file apa pun yang disertakan dan dengan menggunakan sistem file memori untuk GCC)
[2] didasarkan pada waktu dinding terbaik sebanyak 10 kali berjalan dengan menggunakan optimasi generator MIR level 2
[3] didasarkan pada ukuran cc1 yang dilucuti untuk GCC dan C2MIR, inti MIR, juru bahasa, dan generator untuk MIR
[4] didasarkan pada semua file sumber kecuali pengujian
Berikut adalah kinerja kode yang dihasilkan terkait dengan GCC -O2 untuk kompiler C yang berbeda pada 15 benchmark C kecil (dari direktori c-benchmarks
) pada mesin yang sama di mana
Rata-rata | Geomean | |
---|---|---|
gcc-O2 | 1,00 | 1,00 |
gcc -O0 | 0,63 | 0,57 |
c2m -mis | 0,96 | 0,91 |
c2m -eb | 0,92 | 0,85 |
chibicc | 0,38 | 0,30 |
dentang -O2 | 1.12 | 1.09 |
cparser -O3 | 1.02 | 0,98 |
cproc | 0,68 | 0,65 |
lacc -O3 | 0,47 | 0,39 |
pcc-O | 0,80 | 0,78 |
tcc | 0,54 | 0,50 |
emcc -O2/wasmer | 0,60 | 0,55 |
wasi -O2/wasmer cranelift | 0,60 | 0,54 |
wasi -O2/wasmer LLVM | 0,78 | 0,72 |
wasi -O2/wasmer singlepass | 0,45 | 0,36 |
wasi -O2/waktu basah | 0,92 | 0,87 |
c2m
) ke target lain selama 1-2 bulan