GCC使用#pragma GCC unroll时是否仅支持完全展开外层循环?
GCC循环展开行为解答
你观察到的现象并不代表GCC仅支持外层循环的完全展开,该结果是由GCC的pragma提示优先级、优化收益评估规则共同决定的:
#pragma GCC unroll n属于编译优化提示而非强制指令,编译器会综合评估展开后的性能收益、代码膨胀代价,最终决定是否按照提示执行展开。- 测试用例中外层循环总迭代次数为16,指定展开8次属于部分展开:展开后外层循环会变为2次迭代,单次迭代执行8份原循环体。由于外层循环的分支开销已经被内层512次迭代的执行开销完全掩盖,部分展开带来的分支减少收益几乎可以忽略,甚至代码膨胀还可能引入指令缓存命中率下降的副作用,因此编译器判定展开8次无收益,选择不执行展开。
- 指定展开16次属于完全展开,外层循环的分支会被完全消除,所有16次迭代的代码直接平铺,编译器判定该优化的收益远大于代码膨胀的代价,因此执行了完全展开。
如果要强制编译器执行部分展开,可以在编译参数中添加-funroll-all-loops,关闭编译器默认的展开收益阈值判断,即可看到指定展开次数的生成代码。
内容的提问来源于stack exchange,提问作者Cache
相关产品推荐
相关产品推荐

