182、NPU的编译器开发:代码覆盖率分析

182、NPU的编译器开发:代码覆盖率分析
NPU的编译器开发:代码覆盖率分析去年夏天,我在调试一个面向边缘设备的NPU编译器时,遇到了一个极其隐蔽的bug。模型在仿真器上跑得好好的,一上芯片就随机死机。折腾了三天,最后发现是编译器对某个特定形状的卷积操作生成了错误的地址偏移——而这个分支,在所有的单元测试里都没有覆盖到。那一刻,我盯着覆盖率报告上那个刺眼的红色区块,心里只有一个念头:代码覆盖率,不是用来给领导看的数字,是用来救命的。覆盖率不是“测了没”,而是“测了哪些”很多刚接触NPU编译器开发的工程师,会把代码覆盖率等同于“测试通过率”。这是两个完全不同的概念。测试通过率告诉你功能对不对,覆盖率告诉你还有哪些代码路径从来没被执行过。对于NPU编译器这种涉及指令调度、内存分配、硬件抽象层映射的复杂系统,未被执行的代码路径往往就是bug的温床。NPU编译器的代码结构通常包含几个关键层次:前端解析层(处理模型格式如ONNX/TFLite)、中间表示层(IR优化与变换)、后端代码生成层(生成NPU微码或指令序列)。每一层都有大量的条件分支、循环展开、特殊形状处理逻辑。覆盖率分析就是要确保这些分支都被“踩”过。行覆盖率、分支覆盖率、条件覆盖率——哪个更关键?在NPU编译器项目中,我一般会同时关注三种覆盖率指标,但优先级完全不同。行覆盖率是最基础的,告诉你哪些代码行被执行过。但行覆盖率有个坑:它无法区分if-else的两个分支是否都被执行。比如下面这段代码: