Matt Godbolt's blog17 hours agohttp://xania.org/202512/13-licking-licm?utm_source=feed&utm_medium=rss编译器通过将循环外不变的代码(如大小计算)移出循环来优化循环,这被称为循环不变代码移动(LICM)。在一个string_view计数示例中,clang将get_range()调用移出循环,并使用setle/setge来避免分支。相信编译器,但使用Compiler Explorer等工具验证其输出,因为gcc可能无法对某些结构类型执行LICM。
Matt Godbolt's blog17 hours agohttp://xania.org/202512/14-licm-when-it-doesnt?utm_source=feed&utm_medium=rss循环不变代码外提(LICM)可以将像`strlen`这样的计算从循环中提取出来,以生成高效的汇编代码。在循环内部修改全局变量(例如`num_compares`)可能导致LICM失败。失败的原因是别名问题:`char*`被允许与任何类型别名,因此当全局变量被修改时,编译器无法证明字符串未改变。尽管有严格的别名规则,`char*`(以及`unsigned char*`、`std::byte*`)有一个特殊例外,允许它们与任何东西别名。在实践中,GCC、Clang和MSVC都无法对修改后的代码执行LICM。下一篇文章将探讨更多的别名问题以及如何帮助编译器优化此类代码。