这是两个 peephole linter,给土豆级硬件用的:扫一遍汇编,指出哪些地方有更划算的写法。
目标 ISA 都不再新,却还有机器在跑 —— 而编译器的默认调优早已不是为它们做的。
一个扫 ARMv5TE 汇编,一个扫 Pentium 与 pre-P6(P5、Cyrix、K6)以及 Pentium 4 的 x86 汇编。
它们找的是在目标 CPU 上划不来的序列。只要划不来就值得看一眼,指令条数多少不是重点。
判据不靠个人经验,全部锚在 gcc 的权威源上,分三类:
- gcc 明确写下的怪癖。
gcc/config/i386/x86-tune.def里的X86_TUNE_*标志,那些「避开某条指令」的条目。 - cost table 对比。一条指令在目标 CPU 上的开销,对比 Pentium II(x86)或 Cortex-A8(ARMv7-A)这两个基线。
- 原理上该避免的行为。长流水线上分支预测代价这一类行为谓词。
为什么是 census 而不是 gate
工具输出一份清单,不直接判定失败。
同一条指令在目标 CPU 上更贵,不等于这段代码就该改。改写要证明的东西在工具看不到的地方:改完之后原来被依赖的标志位是不是已经死了,对齐是不是还成立,时序有没有被别的指令补上。这些只有读代码的人能证明。
所以两个 linter 都是普查,不是闸门。报告「看这里」,判断留给读的人。
例外有两处,都在 ARM 那个里:--isa 是 ISA 门,-a 里的 Extended Asm 契约检查也算。这两处不存在权衡。指令集里没有的指令,或者写错的约束契约,就是错,没有可商量的余地。
构成
每个 linter 自成项目,彼此不共享代码。Python,加一张模式规则表,加两组测试:单元测试用合成的指令序列,集成测试用真实反汇编夹具。各自带 Makefile 与 pyproject.toml。
两个脚本各自在自己的目录里跑:
1 | python3 armv5telint.py arm.dis |
两个目录各自 make test,跑全部模块的测试。
项目在 https://github.com/lunzima/potatolint,许可 MIT。代码与文档里出现的处理器、架构与设备名称是各自所有者的商标。
评论
点击下面的按钮加载评论框。评论提交后需经确认,不会立即显示。
已提交,确认后会显示。