如何告知编译器函数参数count永远不为零?
消除C函数中参数零值检查的冗余指令
示例代码
C函数
void Dummy(uint64* dest, const size_t count) { for (size_t ii = 0; ii < count; ii += 8) { *dest++ = (uint64)dest; } }
生成的汇编代码
观察编译器生成的汇编,第一条指令会检查count是否为零,若为零直接返回:
Dummy(unsigned long*, unsigned long): cbz x1, .LBB0_7 ... .LBB0_7: ret
问题
是否可以为count添加属性,表明该值永远不为零,从而省略此不必要的比较?是否有其他编码方式可以实现?
注:将for循环改为while循环等形式并无效果,编译器很智能!另外,我确实在意这一条微小的指令。
可行方案
1. 使用编译器内置假设(最直接有效)
在GCC、Clang等主流编译器中,可通过__builtin_assume向编译器传递参数约束,明确告知count永远不为零。修改后的代码如下:
void Dummy(uint64* dest, const size_t count) { __builtin_assume(count != 0); // 仅作为编译优化提示,无运行时代码 for (size_t ii = 0; ii < count; ii += 8) { *dest++ = (uint64)dest; } }
该指令不会生成运行时代码,仅用于指导编译器移除冗余的cbz零检查指令。
2. 使用函数参数属性(编译器扩展)
利用GCC/Clang的__attribute__((min(1)))标记参数最小值为1,向编译器传递参数非零的语义:
void Dummy(uint64* dest, const size_t count __attribute__((min(1)))) { for (size_t ii = 0; ii < count; ii += 8) { *dest++ = (uint64)dest; } }
此属性原本用于静态代码分析,部分编译器版本会据此优化零检查,可靠性略逊于内置假设指令。
3. 从接口语义上强制count非零
修改函数设计,通过参数语义确保非零。例如将参数改为count_minus_1,函数内部计算实际count为count_minus_1 + 1,调用方需传入实际count-1,从而保证count≥1:
// 调用时传入 实际count值 - 1 void Dummy(uint64* dest, const size_t count_minus_1) { const size_t count = count_minus_1 + 1; for (size_t ii = 0; ii < count; ii += 8) { *dest++ = (uint64)dest; } }
此方式需同步修改所有调用处,仅适合封闭场景的代码。
内容的提问来源于stack exchange,提问作者Lance E.T. Compte
相关产品推荐
相关产品推荐

