GCC 怎么把 switch 变成跳转表:偏移、稀疏度与阈值
来源:xoranth.net — 2024-01-14
📋 概述
这篇文章拆开 GCC 的 switch lowering。范围连续的小 case 直接变成 jmp [.L4 + rax*8] 式的跳转表,越界走 default;case 值整体偏移一个常数(97 到 101)时,先 lea eax,[rdi-97] 把基址拉回零,避免为稀疏区间分配大表;再稀疏就要权衡了,实测 GCC 的阈值大约是“每个 case 分摊 8 个表项”。除 bitset lowering 外,这些优化在 Clang 上也成立。
🔑 核心要点
- 连续 case 被编译成函数指针跳转表,与手写数组写法一一对应。
- case 值有常数偏移时,先 lea 减掉偏移再查表,省掉无用的低位空洞。
- 稀疏度决定值不值:实测阈值约为每个 case label 摊 8 个表项。
- 文中全部结论基于 -O3,且除 bitset lowering 外同样适用于 Clang。
- 作者为讲解简化了 GCC 源码、删掉了若干断言,读代码时要注意这点。
💡 金句
Our intuition suggests that the more sparse the values, the less advantageous the jump table conversion is.
👍 0
👎 0
← 返回 Lobsters 首页