FTZ/DAZ及-ffinite-math-only是否会破坏SIMD浮点位逻辑运算结果?
关于SSE浮点掩码与寄存器/编译器标志的问题
背景知识
32位浮点数格式回顾
32位浮点数的指数掩码为0x7F800000:
- 当且仅当指数部分全为0且尾数至少有一个非零位时,该数值为非正规数(denormal)
- 若指数部分全为1,则数值为
INF(尾数全0)或NaN(尾数含非零位)
FTZ与DAZ寄存器标志
FTZ(Flush-To-Zero)和DAZ(Denormals-Are-Zero)是CPU寄存器中的控制标志,设置后会改变浮点运算的运行时行为,同一二进制代码的表现会因标志状态不同而变化:
- FTZ:将浮点运算产生的非正规数直接截断为0
- DAZ:让CPU在运算过程中把遇到的非正规数视为0参与计算
目前尚未找到明确界定受这两个标志影响的运算类型的官方文档,若有相关资料欢迎补充。
-ffinite-math-only编译器标志
-ffinite-math-only是GCC和Clang中-ffast-math启用的子标志之一(MSVC的/fp:fast具备类似效果),它会触发仅在所有浮点数均为非INF、非NaN的前提下才正确的代码优化。
核心技术问题
_mm_cmpeq_ps()返回的如0x0000FFFF的掩码是否可能被清零?是否仅部分微架构存在这种情况?(已知DAZ会影响比较操作,将非正规数视为0参与比较,此处聚焦位逻辑运算相关的影响)- 当
0x0000FFFF这类掩码作为_mm_and_ps()的参数时,是否会被CPU视为0处理? - 严格来说
0xFFFF0000这类掩码属于NaN范畴,编译器是否会因优化导致生成的代码对这类掩码的处理失效?
潜在规避方案
若存在上述问题,位逻辑运算可改用对应指令的整数版本,但可能因CPU微架构差异产生跨执行域延迟;而比较指令无法直接套用此方案,需重新实现IEEE-754标准的比较逻辑,这一方案并不高效。目前期望寄存器标志与编译器标志的实现能保证逻辑正确性,但暂未找到相关官方说明。
内容的提问来源于stack exchange,提问作者Stefano Ariotta
相关产品推荐
相关产品推荐

