[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