forked from OSchip/llvm-project
[libc] Add nearest integer instructions to fputil.
Add round to nearest integer instructions to fputil. This will be used in sinf implementation https://reviews.llvm.org/D123154 Reviewed By: michaelrj Differential Revision: https://reviews.llvm.org/D129776
This commit is contained in:
parent
ecfaf4801c
commit
0f782b84cb
|
@ -69,4 +69,12 @@ add_header_library(
|
|||
.multiply_add
|
||||
)
|
||||
|
||||
add_header_library(
|
||||
nearest_integer
|
||||
HDRS
|
||||
nearest_integer.h
|
||||
DEPENDS
|
||||
libc.src.__support.common
|
||||
)
|
||||
|
||||
add_subdirectory(generic)
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
//===--- Round floating point to nearest integer on aarch64 -----*- 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_AARCH64_NEAREST_INTEGER_H
|
||||
#define LLVM_LIBC_SRC_SUPPORT_FPUTIL_AARCH64_NEAREST_INTEGER_H
|
||||
|
||||
#include "src/__support/architectures.h"
|
||||
|
||||
#if !defined(LLVM_LIBC_ARCH_AARCH64)
|
||||
#error "Invalid include"
|
||||
#endif
|
||||
|
||||
namespace __llvm_libc {
|
||||
namespace fputil {
|
||||
|
||||
static inline double nearest_integer(double x) {
|
||||
double result;
|
||||
__asm__ __volatile__("frintn %d0, %d1\n\t" : "=w"(result) : "w"(x));
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace fputil
|
||||
} // namespace __llvm_libc
|
||||
|
||||
#endif // LLVM_LIBC_SRC_SUPPORT_FPUTIL_AARCH64_NEAREST_INTEGER_H
|
|
@ -0,0 +1,51 @@
|
|||
//===-- Fast rounding to nearest integer for floating point -----*- 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_NEAREST_INTEGER_H
|
||||
#define LLVM_LIBC_SRC_SUPPORT_FPUTIL_NEAREST_INTEGER_H
|
||||
|
||||
#include "src/__support/architectures.h"
|
||||
#include "src/__support/common.h"
|
||||
|
||||
#if (defined(LLVM_LIBC_ARCH_X86_64) && defined(__SSE4_2__))
|
||||
#include "x86_64/nearest_integer.h"
|
||||
#elif defined(LLVM_LIBC_ARCH_AARCH64)
|
||||
#include "aarch64/nearest_integer.h"
|
||||
#else
|
||||
|
||||
namespace __llvm_libc {
|
||||
namespace fputil {
|
||||
|
||||
// This is a fast implementation for rounding to a nearest integer that, in case
|
||||
// of a tie, might pick a random one among 2 closest integers when the rounding
|
||||
// mode is not FE_TONEAREST.
|
||||
//
|
||||
// Notice that for AARCH64 and x86-64 with SSE4.2 support, we will use their
|
||||
// corresponding rounding instruction instead. And in those cases, the results
|
||||
// are rounded to the nearest integer, tie-to-even.
|
||||
static inline double nearest_integer(double x) {
|
||||
if (x < 0x1p53 && x > -0x1p53) {
|
||||
double r = x < 0 ? (x - 0x1.0p52) + 0x1.0p52 : (x + 0x1.0p52) - 0x1.0p52;
|
||||
double diff = x - r;
|
||||
// The expression above is correct for the default rounding mode, round-to-
|
||||
// nearest, tie-to-even. For other rounding modes, it might be off by 1,
|
||||
// which is corrected below.
|
||||
if (unlikely(diff > 0.5))
|
||||
return r + 1.0;
|
||||
if (unlikely(diff < -0.5))
|
||||
return r - 1.0;
|
||||
return r;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
} // namespace fputil
|
||||
} // namespace __llvm_libc
|
||||
|
||||
#endif
|
||||
#endif // LLVM_LIBC_SRC_SUPPORT_FPUTIL_NEAREST_INTEGER_H
|
|
@ -0,0 +1,37 @@
|
|||
//===--- Round floating point to nearest integer on x86-64 ------*- 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_NEAREST_INTEGER_H
|
||||
#define LLVM_LIBC_SRC_SUPPORT_FPUTIL_X86_64_NEAREST_INTEGER_H
|
||||
|
||||
#include "src/__support/architectures.h"
|
||||
|
||||
#if !defined(LLVM_LIBC_ARCH_X86_64)
|
||||
#error "Invalid include"
|
||||
#endif
|
||||
|
||||
#if !defined(__SSE4_2__)
|
||||
#error "SSE4.2 instruction set is not supported"
|
||||
#endif
|
||||
|
||||
#include <immintrin.h>
|
||||
|
||||
namespace __llvm_libc {
|
||||
namespace fputil {
|
||||
|
||||
static inline double nearest_integer(double x) {
|
||||
__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];
|
||||
}
|
||||
|
||||
} // namespace fputil
|
||||
} // namespace __llvm_libc
|
||||
|
||||
#endif // LLVM_LIBC_SRC_SUPPORT_FPUTIL_X86_64_NEAREST_INTEGER_H
|
|
@ -263,6 +263,28 @@ cc_library(
|
|||
],
|
||||
)
|
||||
|
||||
nearest_integer_common_hdrs = [
|
||||
"src/__support/FPUtil/nearest_integer.h",
|
||||
]
|
||||
|
||||
nearest_integer_platform_hdrs = [
|
||||
"src/__support/FPUtil/x86_64/nearest_integer.h",
|
||||
"src/__support/FPUtil/aarch64/nearest_integer.h",
|
||||
]
|
||||
|
||||
cc_library(
|
||||
name = "__support_fputil_nearest_integer",
|
||||
hdrs = nearest_integer_common_hdrs,
|
||||
# These are conditionally included and will #error out if the platform
|
||||
# doesn't support rounding instructions, so they can't be compiled on their
|
||||
# own.
|
||||
textual_hdrs = nearest_integer_platform_hdrs,
|
||||
deps = [
|
||||
":__support_common",
|
||||
":libc_root",
|
||||
],
|
||||
)
|
||||
|
||||
################################ fenv targets ################################
|
||||
|
||||
libc_function(
|
||||
|
|
Loading…
Reference in New Issue