diff --git a/Jenkinsfile b/Jenkinsfile index 8d0ccb1808..a8ee043964 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,5 +1,5 @@ #!groovy dependenciesRevision='36a2a0d6a9da5e506439ffcb8dcf49d3e8f0e175-1185' strategy='EQUAL' -allowedCD=272 +allowedCD=270 allowedF=4 diff --git a/runtime/helpers/basic_math.h b/runtime/helpers/basic_math.h index b3ae5d26c0..cb5451741b 100644 --- a/runtime/helpers/basic_math.h +++ b/runtime/helpers/basic_math.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017-2018 Intel Corporation + * Copyright (C) 2017-2019 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -20,7 +20,7 @@ namespace OCLRT { namespace Math { -inline uint32_t nextPowerOfTwo(uint32_t value) { +constexpr uint32_t nextPowerOfTwo(uint32_t value) { --value; value |= value >> 1; value |= value >> 2; @@ -31,12 +31,34 @@ inline uint32_t nextPowerOfTwo(uint32_t value) { return value; } -inline uint32_t prevPowerOfTwo(uint32_t value) { +constexpr uint64_t nextPowerOfTwo(uint64_t value) { + --value; value |= value >> 1; value |= value >> 2; value |= value >> 4; value |= value >> 8; value |= value >> 16; + value |= value >> 32; + ++value; + return value; +} + +constexpr uint32_t prevPowerOfTwo(uint32_t value) { + value |= value >> 1; + value |= value >> 2; + value |= value >> 4; + value |= value >> 8; + value |= value >> 16; + return (value - (value >> 1)); +} + +constexpr uint64_t prevPowerOfTwo(uint64_t value) { + value |= value >> 1; + value |= value >> 2; + value |= value >> 4; + value |= value >> 8; + value |= value >> 16; + value |= value >> 32; return (value - (value >> 1)); } @@ -49,7 +71,7 @@ inline uint32_t getMinLsbSet(uint32_t value) { return multiplyDeBruijnBitPosition[static_cast(value * 0x077CB531U) >> 27]; } -inline uint32_t log2(uint32_t value) { +constexpr uint32_t log2(uint32_t value) { uint32_t exponent = 0u; uint32_t startVal = value; if (value == 0) { @@ -65,7 +87,7 @@ inline uint32_t log2(uint32_t value) { return exponent; } -inline uint64_t log2(uint64_t value) { +constexpr uint64_t log2(uint64_t value) { uint64_t exponent = 0; uint64_t startVal = value; if (value == 0) { @@ -141,7 +163,7 @@ inline bool isDivisableByPowerOfTwoDivisor(uint32_t number, uint32_t divisor) { return false; } -inline size_t computeTotalElementsCount(const Vec3 &inputVector) { +constexpr size_t computeTotalElementsCount(const Vec3 &inputVector) { size_t minElementCount = 1; auto xDim = std::max(minElementCount, inputVector.x); auto yDim = std::max(minElementCount, inputVector.y); @@ -150,7 +172,7 @@ inline size_t computeTotalElementsCount(const Vec3 &inputVector) { } template -bool isPow2(T val) { +constexpr bool isPow2(T val) { if (val != 0) { if ((val & (val - 1)) == 0) { return true; @@ -159,5 +181,20 @@ bool isPow2(T val) { return false; } +template +constexpr T ffs(T v) { + if (v == 0) { + return std::numeric_limits::max(); + } + + for (T i = 0; i < sizeof(T) * 8; ++i) { + if (0 != (v & (1ULL << i))) { + return i; + } + } + + UNREACHABLE("Either v==0 or any of bits is set"); +} + } // namespace Math } // namespace OCLRT diff --git a/runtime/helpers/debug_helpers.h b/runtime/helpers/debug_helpers.h index ecec84ba80..dbac3f4c95 100644 --- a/runtime/helpers/debug_helpers.h +++ b/runtime/helpers/debug_helpers.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017-2018 Intel Corporation + * Copyright (C) 2017-2019 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -14,6 +14,8 @@ OCLRT::abortUnrecoverable(__LINE__, __FILE__); \ } +#define UNREACHABLE(...) std::abort() + #ifndef DEBUG_BREAK_IF #ifdef _DEBUG #define DEBUG_BREAK_IF(expression) \ diff --git a/unit_tests/helpers/basic_math_tests.cpp b/unit_tests/helpers/basic_math_tests.cpp index c463592a8c..097399f0cf 100644 --- a/unit_tests/helpers/basic_math_tests.cpp +++ b/unit_tests/helpers/basic_math_tests.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017-2018 Intel Corporation + * Copyright (C) 2017-2019 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -12,19 +12,22 @@ using namespace OCLRT::Math; using namespace OCLRT; TEST(NextPowerOfTwo, aFewCases) { - EXPECT_EQ(1u, nextPowerOfTwo(1)); - EXPECT_EQ(2u, nextPowerOfTwo(2)); - EXPECT_EQ(4u, nextPowerOfTwo(3)); - EXPECT_EQ(32u, nextPowerOfTwo(31)); - EXPECT_EQ(32u, nextPowerOfTwo(32)); - EXPECT_EQ(64u, nextPowerOfTwo(33)); - EXPECT_EQ(1u << 31, nextPowerOfTwo((1u << 30) + 1)); - EXPECT_EQ(1u << 31, nextPowerOfTwo(1u << 31)); + EXPECT_EQ(1u, nextPowerOfTwo(1U)); + EXPECT_EQ(2u, nextPowerOfTwo(2U)); + EXPECT_EQ(4u, nextPowerOfTwo(3U)); + EXPECT_EQ(32u, nextPowerOfTwo(31U)); + EXPECT_EQ(32u, nextPowerOfTwo(32U)); + EXPECT_EQ(64u, nextPowerOfTwo(33U)); + EXPECT_EQ(1u << 31, nextPowerOfTwo((1u << 30U) + 1)); + EXPECT_EQ(1u << 31, nextPowerOfTwo(1u << 31U)); + + EXPECT_EQ(1ULL << 32, nextPowerOfTwo(static_cast((1ULL << 31ULL) + 1))); + EXPECT_EQ(1ULL << 32, nextPowerOfTwo(static_cast(1ULL << 32ULL))); } TEST(PrevPowerOfTwo, aroundPowers) { - EXPECT_EQ(0u, prevPowerOfTwo(0)); - EXPECT_EQ(1u, prevPowerOfTwo(1)); + EXPECT_EQ(0u, prevPowerOfTwo(0U)); + EXPECT_EQ(1u, prevPowerOfTwo(1U)); for (uint32_t i = 1; i < 32; i++) { uint32_t b = 1 << i; @@ -32,6 +35,9 @@ TEST(PrevPowerOfTwo, aroundPowers) { EXPECT_EQ(b, prevPowerOfTwo(b)); EXPECT_EQ(b, prevPowerOfTwo(b + 1)); } + + EXPECT_EQ(1ULL << 32, prevPowerOfTwo(static_cast(1ULL << 32ULL))); + EXPECT_EQ(1ULL << 32, prevPowerOfTwo(static_cast((1ULL << 32ULL) + 7))); } TEST(getMinLsbSet, basicValues) { @@ -193,3 +199,18 @@ TEST(isPow2Test, WhenArgPow2ThenReturnTrue) { EXPECT_TRUE(isPow2(128u)); EXPECT_TRUE(isPow2(4096u)); } + +TEST(ffs, givenZeroReturnMaxRange) { + EXPECT_EQ(std::numeric_limits::max(), ffs(0U)); +} + +TEST(ffs, givenNonZeroReturnFirstSetBitIndex) { + EXPECT_EQ(0U, ffs(0b1U)); + EXPECT_EQ(0U, ffs(0b11U)); + EXPECT_EQ(1U, ffs(0b10U)); + EXPECT_EQ(3U, ffs(0b1001000U)); + EXPECT_EQ(31U, ffs(1U << 31U)); + EXPECT_EQ(16U, ffs((1U << 31U) | (1U << 31U) | (1U << 16U))); + EXPECT_EQ(16ULL, ffs((1ULL << 63ULL) | (1ULL << 32ULL) | (1ULL << 16ULL))); + EXPECT_EQ(63ULL, ffs(1ULL << 63ULL)); +}