From 2380d0ad1dd583b773d8b321636ac1f190b1cc1b Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Thu, 21 Aug 2025 17:07:34 +1000 Subject: [PATCH] [orc-rt] Add preliminary math.h header and basic operations. The initial operations, isPowerOf2 and nextPowerOf2 will be used in an upcoming patch to add support for bitmask-enums. --- orc-rt/include/CMakeLists.txt | 1 + orc-rt/include/orc-rt/math.h | 35 +++++++++++++++ orc-rt/unittests/CMakeLists.txt | 1 + orc-rt/unittests/math-test.cpp | 78 +++++++++++++++++++++++++++++++++ 4 files changed, 115 insertions(+) create mode 100644 orc-rt/include/orc-rt/math.h create mode 100644 orc-rt/unittests/math-test.cpp diff --git a/orc-rt/include/CMakeLists.txt b/orc-rt/include/CMakeLists.txt index eb24f29b1469..e2096a80404b 100644 --- a/orc-rt/include/CMakeLists.txt +++ b/orc-rt/include/CMakeLists.txt @@ -1,5 +1,6 @@ set(ORC_RT_HEADERS orc-rt-c/orc-rt.h + orc-rt/math.h orc-rt/span.h ) diff --git a/orc-rt/include/orc-rt/math.h b/orc-rt/include/orc-rt/math.h new file mode 100644 index 000000000000..4dd6ddd9e506 --- /dev/null +++ b/orc-rt/include/orc-rt/math.h @@ -0,0 +1,35 @@ +//===--------- math.h - Math helpers for the ORC runtime --------*- 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 +// +//===----------------------------------------------------------------------===// +// +// Math helper functions for the ORC runtime. +// +//===----------------------------------------------------------------------===// + +#ifndef ORC_RT_MATH_H +#define ORC_RT_MATH_H + +#include +#include + +namespace orc_rt { + +/// Test whether the given value is a power of 2. +template constexpr bool isPowerOf2(T Val) noexcept { + return Val != 0 && (Val & (Val - 1)) == 0; +} + +/// Calculates the next power of 2. +template constexpr T nextPowerOf2(T Val) noexcept { + for (size_t I = 1; I < std::numeric_limits::digits; I <<= 1) + Val |= (Val >> I); + return Val + 1; +} + +} // namespace orc_rt + +#endif // ORC_RT_MATH_H diff --git a/orc-rt/unittests/CMakeLists.txt b/orc-rt/unittests/CMakeLists.txt index 98c28c9664c2..51cd23304fc6 100644 --- a/orc-rt/unittests/CMakeLists.txt +++ b/orc-rt/unittests/CMakeLists.txt @@ -12,6 +12,7 @@ function(add_orc_rt_unittest test_dirname) endfunction() add_orc_rt_unittest(CoreTests + math-test.cpp span-test.cpp DISABLE_LLVM_LINK_LLVM_DYLIB ) diff --git a/orc-rt/unittests/math-test.cpp b/orc-rt/unittests/math-test.cpp new file mode 100644 index 000000000000..491bbd8baa6e --- /dev/null +++ b/orc-rt/unittests/math-test.cpp @@ -0,0 +1,78 @@ +//===- math-test.cpp ------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// Tests for orc-rt's math.h APIs. +// +//===----------------------------------------------------------------------===// + +#include "orc-rt/math.h" +#include "gtest/gtest.h" + +using namespace orc_rt; + +TEST(STLExtrasTest, isPowerOf2) { + // Test [0..16] + EXPECT_FALSE(isPowerOf2(0x00)); + EXPECT_TRUE(isPowerOf2(0x01)); + EXPECT_TRUE(isPowerOf2(0x02)); + EXPECT_FALSE(isPowerOf2(0x03)); + EXPECT_TRUE(isPowerOf2(0x04)); + EXPECT_FALSE(isPowerOf2(0x05)); + EXPECT_FALSE(isPowerOf2(0x06)); + EXPECT_FALSE(isPowerOf2(0x07)); + EXPECT_TRUE(isPowerOf2(0x08)); + EXPECT_FALSE(isPowerOf2(0x09)); + EXPECT_FALSE(isPowerOf2(0x0A)); + EXPECT_FALSE(isPowerOf2(0x0B)); + EXPECT_FALSE(isPowerOf2(0x0C)); + EXPECT_FALSE(isPowerOf2(0x0D)); + EXPECT_FALSE(isPowerOf2(0x0E)); + EXPECT_FALSE(isPowerOf2(0x0F)); + EXPECT_TRUE(isPowerOf2(0x10)); + + // Test some higher powers of two and their adjacent values. + EXPECT_FALSE(isPowerOf2(0x1F)); + EXPECT_TRUE(isPowerOf2(0x20)); + EXPECT_FALSE(isPowerOf2(0x21)); + + EXPECT_FALSE(isPowerOf2(0x3F)); + EXPECT_TRUE(isPowerOf2(0x40)); + EXPECT_FALSE(isPowerOf2(0x41)); + + EXPECT_FALSE(isPowerOf2(0x7F)); + EXPECT_TRUE(isPowerOf2(0x80)); + EXPECT_FALSE(isPowerOf2(0x81)); + + // Test larger values. + EXPECT_FALSE(isPowerOf2(0x3fffffff)); + EXPECT_TRUE(isPowerOf2(0x40000000)); + EXPECT_FALSE(isPowerOf2(0x40000001)); + + // Test negatives. + EXPECT_FALSE(isPowerOf2(-1)); +} + +TEST(STLExtrasTest, nextPowerOf2) { + EXPECT_EQ(nextPowerOf2(0x00), (1 << 0)); + EXPECT_EQ(nextPowerOf2(0x01), (1 << 1)); + EXPECT_EQ(nextPowerOf2(0x02), (1 << 2)); + EXPECT_EQ(nextPowerOf2(0x03), (1 << 2)); + EXPECT_EQ(nextPowerOf2(0x04), (1 << 3)); + EXPECT_EQ(nextPowerOf2(0x05), (1 << 3)); + EXPECT_EQ(nextPowerOf2(0x06), (1 << 3)); + EXPECT_EQ(nextPowerOf2(0x07), (1 << 3)); + EXPECT_EQ(nextPowerOf2(0x08), (1 << 4)); + EXPECT_EQ(nextPowerOf2(0x09), (1 << 4)); + EXPECT_EQ(nextPowerOf2(0x0a), (1 << 4)); + EXPECT_EQ(nextPowerOf2(0x0b), (1 << 4)); + EXPECT_EQ(nextPowerOf2(0x0c), (1 << 4)); + EXPECT_EQ(nextPowerOf2(0x0d), (1 << 4)); + EXPECT_EQ(nextPowerOf2(0x0e), (1 << 4)); + EXPECT_EQ(nextPowerOf2(0x0f), (1 << 4)); + EXPECT_EQ(nextPowerOf2(0x10), (1 << 5)); +}