






#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
endmodulefunc描述函数的签名(采用 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-<target>.c包含解释器和 JIT 编译器常见的简单机器相关代码mir-<target>.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 和 riscv 机器相关代码mir-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 个月