将变量/参数打包进结构体/联合体是否存在意外性能损耗?
关于GCC对单字节参数的SWAR优化疑问
本文讨论的并非结构体填充/打包(为对齐目的插入结构体中的未命名字节)相关问题。
现有如下函数:
#include <stdint.h> uint8_t get_index(const uint8_t xs, const uint8_t zs, const uint8_t ys, const uint8_t l) { return (xs >> l & 1) | (zs >> l & 2) | (ys >> l & 4); }
令人惊讶的是,即使开启优化,GCC也未对该函数应用SWAR优化,生成了多条and和sar指令。
但通过以下方式可轻松实现SWAR优化:
#include <stdint.h> union Arg { uint8_t b[3]; uint32_t u; }; uint8_t get_index(union Arg arg, const uint8_t l) { static const union Arg mask = {.b = {1, 2, 4}}; /* 使用该方式而非整数常量可避免依赖字节序,最终仍会被优化为对应整数常量。 */ arg.u = arg.u >> l & mask.u; return arg.b[0] | arg.b[1] | arg.b[2]; }
该版本生成的汇编代码更短,不同测试版本结果一致。
现提出以下疑问:
- 为何GCC无法将前者优化为后者?是存在特定技术限制还是仅为遗漏的优化项?
- 单个字节参数与联合体中的字节访问方式是否存在差异?若有,原因是什么?直觉上两者无差异,因为它们都位于当前栈帧的已知位置。
- 采用打包入联合体的传参方式是否会比单独传参更慢?
此前已查阅《传递多个变量 vs 传递结构体》相关问题,但该问题聚焦于远大于CPU字长的大型结构体,未涉及字内单个字节的访问场景,与本文讨论内容不符。
内容的提问来源于stack exchange,提问作者CPlus
相关产品推荐
相关产品推荐

