[libc-commits] [llvm] [libc] [libc] Add mask functions to math_extras (PR #75169)
Guillaume Chatelet via libc-commits
libc-commits at lists.llvm.org
Tue Dec 12 03:59:22 PST 2023
https://github.com/gchatelet created https://github.com/llvm/llvm-project/pull/75169
None
>From ed45b069a3958aa9f20e850820622f3f58256e90 Mon Sep 17 00:00:00 2001
From: Guillaume Chatelet <gchatelet at google.com>
Date: Tue, 12 Dec 2023 11:58:56 +0000
Subject: [PATCH] [libc] Add mask functions to math_extras
---
libc/src/__support/FPUtil/CMakeLists.txt | 1 +
libc/src/__support/FPUtil/FloatProperties.h | 11 +----
libc/src/__support/math_extras.h | 40 ++++++++++++++++++-
libc/test/src/__support/math_extras_test.cpp | 25 +++++++++++-
.../llvm-project-overlay/libc/BUILD.bazel | 1 +
5 files changed, 65 insertions(+), 13 deletions(-)
diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt
index 3d6d712fc2058..1cb22536a1cf6 100644
--- a/libc/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/CMakeLists.txt
@@ -30,6 +30,7 @@ add_header_library(
DEPENDS
libc.src.__support.macros.properties.float
libc.src.__support.uint128
+ libc.src.__support.math_extras
)
add_header_library(
diff --git a/libc/src/__support/FPUtil/FloatProperties.h b/libc/src/__support/FPUtil/FloatProperties.h
index ef6a3cd403db6..360167a8c5011 100644
--- a/libc/src/__support/FPUtil/FloatProperties.h
+++ b/libc/src/__support/FPUtil/FloatProperties.h
@@ -12,6 +12,7 @@
#include "src/__support/UInt128.h"
#include "src/__support/macros/attributes.h" // LIBC_INLINE, LIBC_INLINE_VAR
#include "src/__support/macros/properties/float.h" // LIBC_COMPILER_HAS_FLOAT128
+#include "src/__support/math_extras.h" // mask_trailing_ones
#include <stdint.h>
@@ -80,16 +81,6 @@ template <> struct FPBaseProperties<FPType::X86_Binary80> {
FPEncoding::X86_ExtendedPrecision;
};
-// TODO: Move this utility elsewhere.
-template <typename T, size_t count> static constexpr T mask_trailing_ones() {
- static_assert(cpp::is_unsigned_v<T>);
- constexpr unsigned t_bits = CHAR_BIT * sizeof(T);
- static_assert(count <= t_bits && "Invalid bit index");
- // It's important not to initialize T with -1, since T may be BigInt which
- // will take -1 as a uint64_t and only initialize the low 64 bits.
- return count == 0 ? 0 : ((~T(0)) >> (t_bits - count));
-}
-
// Derives more properties from 'FPBaseProperties' above.
// This class serves as a halfway point between 'FPBaseProperties' and
// 'FPProperties' below.
diff --git a/libc/src/__support/math_extras.h b/libc/src/__support/math_extras.h
index 860cdda8586d1..571a3409e28bd 100644
--- a/libc/src/__support/math_extras.h
+++ b/libc/src/__support/math_extras.h
@@ -10,12 +10,50 @@
#ifndef LLVM_LIBC_SRC___SUPPORT_MATH_EXTRAS_H
#define LLVM_LIBC_SRC___SUPPORT_MATH_EXTRAS_H
-#include "src/__support/CPP/type_traits.h"
+#include "src/__support/CPP/type_traits.h" // is_unsigned_v
#include "src/__support/macros/attributes.h" // LIBC_INLINE
#include "src/__support/macros/config.h" // LIBC_HAS_BUILTIN
+#include <limits.h> // CHAR_BIT
+
namespace LIBC_NAMESPACE {
+// Create a bitmask with the count right-most bits set to 1, and all other bits
+// set to 0. Only unsigned types are allowed.
+template <typename T, size_t count>
+LIBC_INLINE constexpr T mask_trailing_ones() {
+ static_assert(cpp::is_unsigned_v<T>);
+ constexpr unsigned t_bits = CHAR_BIT * sizeof(T);
+ static_assert(count <= t_bits && "Invalid bit index");
+ // It's important not to initialize T with -1, since T may be BigInt which
+ // will take -1 as a uint64_t and only initialize the low 64 bits.
+ constexpr T all_zeroes(0);
+ constexpr T all_ones(~all_zeroes); // bitwise NOT performs integer promotion.
+ return count == 0 ? 0 : (all_ones >> (t_bits - count));
+}
+
+// Create a bitmask with the count left-most bits set to 1, and all other bits
+// set to 0. Only unsigned types are allowed.
+template <typename T, size_t count>
+LIBC_INLINE constexpr T mask_leading_ones() {
+ constexpr T mask(mask_trailing_ones<T, CHAR_BIT * sizeof(T) - count>());
+ return T(~mask); // bitwise NOT performs integer promotion.
+}
+
+// Create a bitmask with the count right-most bits set to 0, and all other bits
+// set to 1. Only unsigned types are allowed.
+template <typename T, size_t count>
+LIBC_INLINE constexpr T mask_trailing_zeros() {
+ return mask_leading_ones<T, CHAR_BIT * sizeof(T) - count>();
+}
+
+// Create a bitmask with the count left-most bits set to 0, and all other bits
+// set to 1. Only unsigned types are allowed.
+template <typename T, size_t count>
+LIBC_INLINE constexpr T mask_leading_zeros() {
+ return mask_trailing_ones<T, CHAR_BIT * sizeof(T) - count>();
+}
+
// Add with carry
template <typename T> struct SumCarry {
T sum;
diff --git a/libc/test/src/__support/math_extras_test.cpp b/libc/test/src/__support/math_extras_test.cpp
index 48c8fe95c689a..e55d995592cc1 100644
--- a/libc/test/src/__support/math_extras_test.cpp
+++ b/libc/test/src/__support/math_extras_test.cpp
@@ -11,8 +11,29 @@
namespace LIBC_NAMESPACE {
-TEST(LlvmLibcBlockMathExtrasTest, TODO) {
- // TODO Implement me.
+TEST(LlvmLibcBlockMathExtrasTest, mask_trailing_ones) {
+ EXPECT_EQ(uint8_t(0), (mask_leading_ones<uint8_t, 0>()));
+ EXPECT_EQ(uint8_t(0), (mask_trailing_ones<uint8_t, 0>()));
+ EXPECT_EQ(uint16_t(0), (mask_leading_ones<uint16_t, 0>()));
+ EXPECT_EQ(uint16_t(0), (mask_trailing_ones<uint16_t, 0>()));
+ EXPECT_EQ(uint32_t(0), (mask_leading_ones<uint32_t, 0>()));
+ EXPECT_EQ(uint32_t(0), (mask_trailing_ones<uint32_t, 0>()));
+ EXPECT_EQ(uint64_t(0), (mask_leading_ones<uint64_t, 0>()));
+ EXPECT_EQ(uint64_t(0), (mask_trailing_ones<uint64_t, 0>()));
+
+ EXPECT_EQ(uint32_t(0x00000003), (mask_trailing_ones<uint32_t, 2>()));
+ EXPECT_EQ(uint32_t(0xC0000000), (mask_leading_ones<uint32_t, 2>()));
+
+ EXPECT_EQ(uint32_t(0x000007FF), (mask_trailing_ones<uint32_t, 11>()));
+ EXPECT_EQ(uint32_t(0xFFE00000), (mask_leading_ones<uint32_t, 11>()));
+
+ EXPECT_EQ(uint32_t(0xFFFFFFFF), (mask_trailing_ones<uint32_t, 32>()));
+ EXPECT_EQ(uint32_t(0xFFFFFFFF), (mask_leading_ones<uint32_t, 32>()));
+ EXPECT_EQ(uint64_t(0xFFFFFFFFFFFFFFFF), (mask_trailing_ones<uint64_t, 64>()));
+ EXPECT_EQ(uint64_t(0xFFFFFFFFFFFFFFFF), (mask_leading_ones<uint64_t, 64>()));
+
+ EXPECT_EQ(uint64_t(0x0000FFFFFFFFFFFF), (mask_trailing_ones<uint64_t, 48>()));
+ EXPECT_EQ(uint64_t(0xFFFFFFFFFFFF0000), (mask_leading_ones<uint64_t, 48>()));
}
} // namespace LIBC_NAMESPACE
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index 95d6f9d220c25..b9bdb8f7c6d3e 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -664,6 +664,7 @@ libc_support_library(
deps = [
":__support_macros_attributes",
":__support_macros_properties_float",
+ ":__support_math_extras",
":__support_uint128",
],
)
More information about the libc-commits
mailing list