在处理浮点数据的 C++ 代码中,从 float 到 int 的舍入转换相当频繁。例如,一种用途是生成转换表。
考虑一下这段代码:
// Convert a positive float value and round to the nearest integer
int RoundedIntValue = (int) (FloatValue + 0.5f);
C/C++ 语言将 (int) 强制转换定义为截断,因此必须添加 0.5f 以确保向上舍入到最接近的正整数(当输入为正数时)。对于上述内容,VS2015的编译器生成以下代码:
movss xmm9, DWORD PTR __real@3f000000 // 0.5f
addss xmm0, xmm9
cvttss2si eax, xmm0
上面的方法有效,但可能会更有效......
英特尔的设计人员显然认为这个问题足够重要,可以用一条指令来解决,该指令可以完成所需的工作:转换为最接近的整数值:cvtss2si(注意,助记符中只有一个“t”)。
如果 cvtss2si 替换上述序列中的 cvttss2si 指令,则将消除三个指令中的两个(就像使用额外的 xmm 寄存器一样,这可能会导致整体上更好的优化)。
那么我们如何编写 C++ 语句来使用一条 cvtss2si 指令完成这项简单的工作呢?
我一直在摸索,尝试类似以下的事情,但即使优化器正在执行任务,它也不会归结为可以/应该完成这项工作的一条机器指令:
int RoundedIntValue = _mm_cvt_ss2si(_mm_set_ss(FloatValue));
不幸的是,上面的内容似乎一心想要清除一整个永远不会使用的寄存器向量,而不是仅仅使用一个 32 位值。
movaps xmm1, xmm0
xorps xmm2, xmm2
movss xmm2, xmm1
cvtss2si eax, xmm2
也许我在这里错过了一个明显的方法。
您能否提供一组建议的 C++ 指令来最终生成单个 cvtss2si 指令?