[libc-commits] [libc] c0bbd6f - [libc] Improve nearest_integer for non-AVX x86 targets. (#230529)
via libc-commits
libc-commits at lists.llvm.org
Mon Oct 12 11:06:06 PDT 2026
Author: lntue
Date: 2026-10-12T14:06:01-04:00
New Revision: c0bbd6fe4f1a2d0413d12b0ad4a16c8982ca154b
URL: https://github.com/llvm/llvm-project/commit/c0bbd6fe4f1a2d0413d12b0ad4a16c8982ca154b
DIFF: https://github.com/llvm/llvm-project/commit/c0bbd6fe4f1a2d0413d12b0ad4a16c8982ca154b.diff
LOG: [libc] Improve nearest_integer for non-AVX x86 targets. (#230529)
Without AVX, _mm_round_ss and _mm_round_sd introduce false dependency of
the upper lanes that causes significant regressions for non-AVX x86
targets.
We call roundss and roundsd directly with inline asm to prevent the
false dependency for such targets.
Added:
Modified:
libc/src/__support/FPUtil/x86_64/nearest_integer.h
Removed:
################################################################################
diff --git a/libc/src/__support/FPUtil/x86_64/nearest_integer.h b/libc/src/__support/FPUtil/x86_64/nearest_integer.h
index 4eae5ffe816b3..d57db0dacf013 100644
--- a/libc/src/__support/FPUtil/x86_64/nearest_integer.h
+++ b/libc/src/__support/FPUtil/x86_64/nearest_integer.h
@@ -26,18 +26,41 @@
namespace LIBC_NAMESPACE_DECL {
namespace fputil {
+// The legacy SSE4.1 `roundss` and `roundsd` are 2-operand instructions that
+// preserve the upper bits of the destination XMM register (unlike AVX's
+// 3-operand `vroundss` and `vroundsd`, where `_mm_round_ss(xmm, xmm, ...)`
+// explicitly passes `xmm` as the source for the upper bits). Without AVX,
+// because only lane 0 of `_mm_round_ss` / `_mm_round_sd` is used, the compiler
+// may allocate a
diff erent destination register than the source register,
+// creating a false dependency on the destination register's previous value
+// (see https://github.com/llvm/llvm-project/issues/230589). Using inline
+// assembly with `"+x"(x)` forces identical source and destination registers
+// without the extra lane-zeroing instructions required by `_mm_round_ps` /
+// `_mm_round_pd`.
LIBC_INLINE float nearest_integer(float x) {
+#ifdef __AVX__
__m128 xmm = _mm_set_ss(x); // NOLINT
__m128 ymm =
_mm_round_ss(xmm, xmm, _MM_ROUND_NEAREST | _MM_FROUND_NO_EXC); // NOLINT
return ymm[0];
+#else
+ LIBC_INLINE_ASM("roundss %1, %0, %0" : "+x"(x) : "i"(_MM_ROUND_NEAREST |
+ _MM_FROUND_NO_EXC));
+ return x;
+#endif
}
LIBC_INLINE double nearest_integer(double x) {
+#ifdef __AVX__
__m128d xmm = _mm_set_sd(x); // NOLINT
__m128d ymm =
_mm_round_sd(xmm, xmm, _MM_ROUND_NEAREST | _MM_FROUND_NO_EXC); // NOLINT
return ymm[0];
+#else
+ LIBC_INLINE_ASM("roundsd %1, %0, %0" : "+x"(x) : "i"(_MM_ROUND_NEAREST |
+ _MM_FROUND_NO_EXC));
+ return x;
+#endif
}
} // namespace fputil
More information about the libc-commits
mailing list