[libc] [llvm] [libc][fenv] Refactor x86 fenv implementations to make it work for various fenv_t. (PR #165015)
James Y Knight via llvm-commits
llvm-commits at lists.llvm.org
Fri Nov 7 09:49:18 PST 2025
================
@@ -0,0 +1,261 @@
+//===-- x87 floating point env manipulation functions -----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_X86_64_FENV_X86_COMMON_H
+#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_X86_64_FENV_X86_COMMON_H
+
+#include <stdbool.h>
+
+#include "hdr/stdint_proxy.h"
+#include "hdr/types/fenv_t.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/architectures.h"
+#include "src/__support/macros/properties/compiler.h"
+#include "src/__support/macros/properties/cpu_features.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace fputil {
+
+namespace internal {
+
+// Default order of floating point exception flags in x87 and mxcsr registers:
+// - Bit 0: Invalid Operations
+// - Bit 1: Denormal
+// - Bit 2: Divide-by-zero
+// - Bit 3: Overflow
+// - Bit 4: Underflow
+// - Bit 5: Inexact
+struct ExceptionFlags {
+ static constexpr uint16_t INVALID_F = 0x1;
+ // Some libcs define __FE_DENORM corresponding to the denormal input
+ // exception and include it in FE_ALL_EXCEPTS. We define and use it to
+ // support compiling against headers provided by such libcs.
+ static constexpr uint16_t DENORMAL_F = 0x2;
+ static constexpr uint16_t DIV_BY_ZERO_F = 0x4;
+ static constexpr uint16_t OVERFLOW_F = 0x8;
+ static constexpr uint16_t UNDERFLOW_F = 0x10;
+ static constexpr uint16_t INEXACT_F = 0x20;
+ static constexpr uint16_t ALL_F =
+ static_cast<uint16_t>(INVALID_F | DENORMAL_F | DIV_BY_ZERO_F |
+ OVERFLOW_F | UNDERFLOW_F | INEXACT_F);
+ static constexpr unsigned MXCSR_EXCEPTION_MASK_BIT_POSITION = 7;
+};
+
+LIBC_INLINE static constexpr bool fenv_exceptions_match_x86() {
+ return (FE_INVALID == ExceptionFlags::INVALID_F) &&
+#ifdef __FE_DENORM
+ (__FE_DENORM == ExceptionFlags::DENORMAL_F) &&
+#elif defined(FE_DENORM)
+ (FE_DENORM == ExceptionFlags::DENORMAL_F) &&
+#endif // __FE_DENORM
+ (FE_DIVBYZERO == ExceptionFlags::DIV_BY_ZERO_F) &&
+ (FE_OVERFLOW == ExceptionFlags::OVERFLOW_F) &&
+ (FE_UNDERFLOW == ExceptionFlags::UNDERFLOW_F) &&
+ (FE_INEXACT == ExceptionFlags::INEXACT_F);
+}
+
+// The rounding control values in the x87 control register and the MXCSR
+// register have the same 2-bit enoding but have different bit positions.
+// See below for the bit positions.
+struct RoundingControl {
+ static constexpr uint16_t TO_NEAREST = 0x0;
+ static constexpr uint16_t DOWNWARD = 0x1;
+ static constexpr uint16_t UPWARD = 0x2;
+ static constexpr uint16_t TOWARD_ZERO = 0x3;
+ static constexpr uint16_t ROUNDING_MASK = 0x3;
+ static constexpr unsigned X87_BIT_POSITION = 10;
+ static constexpr unsigned MXCSR_BIT_POSITION = 13;
+ static constexpr uint16_t X87_ROUNDING_MASK = ROUNDING_MASK
+ << X87_BIT_POSITION;
+ static constexpr uint16_t MXCSR_ROUNDING_MASK = ROUNDING_MASK
+ << MXCSR_BIT_POSITION;
+ static constexpr uint16_t ERROR = 0xFFFF;
+};
+
+static constexpr uint16_t MXCSR_ROUNDING_CONTROL_BIT_POSITION = 13;
+
+// Exception flags are individual bits in the corresponding registers.
+// So, we just OR the bit values to get the full set of exceptions.
+LIBC_INLINE static uint16_t get_status_value_from_except(int excepts) {
+ if constexpr (fenv_exceptions_match_x86()) {
+ return static_cast<uint16_t>(excepts & ExceptionFlags::ALL_F);
+ } else {
+ // We will make use of the fact that exception control bits are single
----------------
jyknight wrote:
I think this else clause would compile to essentially the above if the bits match anyways, so maybe the fenv_exceptions_match_x86 is unnecessary?
https://github.com/llvm/llvm-project/pull/165015
More information about the llvm-commits
mailing list