Adding ffs and 64-bit prev/next pow2

Change-Id: Ie10731c16b65a4fd1f36fd4c9bbca9a6951583a1
This commit is contained in:
Chodor, Jaroslaw
2019-01-28 17:51:00 +01:00
committed by sys_ocldev
parent b11e0825c9
commit 22448ee265
4 changed files with 80 additions and 20 deletions

2
Jenkinsfile vendored
View File

@@ -1,5 +1,5 @@
#!groovy #!groovy
dependenciesRevision='36a2a0d6a9da5e506439ffcb8dcf49d3e8f0e175-1185' dependenciesRevision='36a2a0d6a9da5e506439ffcb8dcf49d3e8f0e175-1185'
strategy='EQUAL' strategy='EQUAL'
allowedCD=272 allowedCD=270
allowedF=4 allowedF=4

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2017-2018 Intel Corporation * Copyright (C) 2017-2019 Intel Corporation
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
* *
@@ -20,7 +20,7 @@
namespace OCLRT { namespace OCLRT {
namespace Math { namespace Math {
inline uint32_t nextPowerOfTwo(uint32_t value) { constexpr uint32_t nextPowerOfTwo(uint32_t value) {
--value; --value;
value |= value >> 1; value |= value >> 1;
value |= value >> 2; value |= value >> 2;
@@ -31,12 +31,34 @@ inline uint32_t nextPowerOfTwo(uint32_t value) {
return value; return value;
} }
inline uint32_t prevPowerOfTwo(uint32_t value) { constexpr uint64_t nextPowerOfTwo(uint64_t value) {
--value;
value |= value >> 1; value |= value >> 1;
value |= value >> 2; value |= value >> 2;
value |= value >> 4; value |= value >> 4;
value |= value >> 8; value |= value >> 8;
value |= value >> 16; 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)); return (value - (value >> 1));
} }
@@ -49,7 +71,7 @@ inline uint32_t getMinLsbSet(uint32_t value) {
return multiplyDeBruijnBitPosition[static_cast<uint32_t>(value * 0x077CB531U) >> 27]; return multiplyDeBruijnBitPosition[static_cast<uint32_t>(value * 0x077CB531U) >> 27];
} }
inline uint32_t log2(uint32_t value) { constexpr uint32_t log2(uint32_t value) {
uint32_t exponent = 0u; uint32_t exponent = 0u;
uint32_t startVal = value; uint32_t startVal = value;
if (value == 0) { if (value == 0) {
@@ -65,7 +87,7 @@ inline uint32_t log2(uint32_t value) {
return exponent; return exponent;
} }
inline uint64_t log2(uint64_t value) { constexpr uint64_t log2(uint64_t value) {
uint64_t exponent = 0; uint64_t exponent = 0;
uint64_t startVal = value; uint64_t startVal = value;
if (value == 0) { if (value == 0) {
@@ -141,7 +163,7 @@ inline bool isDivisableByPowerOfTwoDivisor(uint32_t number, uint32_t divisor) {
return false; return false;
} }
inline size_t computeTotalElementsCount(const Vec3<size_t> &inputVector) { constexpr size_t computeTotalElementsCount(const Vec3<size_t> &inputVector) {
size_t minElementCount = 1; size_t minElementCount = 1;
auto xDim = std::max(minElementCount, inputVector.x); auto xDim = std::max(minElementCount, inputVector.x);
auto yDim = std::max(minElementCount, inputVector.y); auto yDim = std::max(minElementCount, inputVector.y);
@@ -150,7 +172,7 @@ inline size_t computeTotalElementsCount(const Vec3<size_t> &inputVector) {
} }
template <typename T> template <typename T>
bool isPow2(T val) { constexpr bool isPow2(T val) {
if (val != 0) { if (val != 0) {
if ((val & (val - 1)) == 0) { if ((val & (val - 1)) == 0) {
return true; return true;
@@ -159,5 +181,20 @@ bool isPow2(T val) {
return false; return false;
} }
template <typename T>
constexpr T ffs(T v) {
if (v == 0) {
return std::numeric_limits<T>::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 Math
} // namespace OCLRT } // namespace OCLRT

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2017-2018 Intel Corporation * Copyright (C) 2017-2019 Intel Corporation
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
* *
@@ -14,6 +14,8 @@
OCLRT::abortUnrecoverable(__LINE__, __FILE__); \ OCLRT::abortUnrecoverable(__LINE__, __FILE__); \
} }
#define UNREACHABLE(...) std::abort()
#ifndef DEBUG_BREAK_IF #ifndef DEBUG_BREAK_IF
#ifdef _DEBUG #ifdef _DEBUG
#define DEBUG_BREAK_IF(expression) \ #define DEBUG_BREAK_IF(expression) \

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2017-2018 Intel Corporation * Copyright (C) 2017-2019 Intel Corporation
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
* *
@@ -12,19 +12,22 @@ using namespace OCLRT::Math;
using namespace OCLRT; using namespace OCLRT;
TEST(NextPowerOfTwo, aFewCases) { TEST(NextPowerOfTwo, aFewCases) {
EXPECT_EQ(1u, nextPowerOfTwo(1)); EXPECT_EQ(1u, nextPowerOfTwo(1U));
EXPECT_EQ(2u, nextPowerOfTwo(2)); EXPECT_EQ(2u, nextPowerOfTwo(2U));
EXPECT_EQ(4u, nextPowerOfTwo(3)); EXPECT_EQ(4u, nextPowerOfTwo(3U));
EXPECT_EQ(32u, nextPowerOfTwo(31)); EXPECT_EQ(32u, nextPowerOfTwo(31U));
EXPECT_EQ(32u, nextPowerOfTwo(32)); EXPECT_EQ(32u, nextPowerOfTwo(32U));
EXPECT_EQ(64u, nextPowerOfTwo(33)); EXPECT_EQ(64u, nextPowerOfTwo(33U));
EXPECT_EQ(1u << 31, nextPowerOfTwo((1u << 30) + 1)); EXPECT_EQ(1u << 31, nextPowerOfTwo((1u << 30U) + 1));
EXPECT_EQ(1u << 31, nextPowerOfTwo(1u << 31)); EXPECT_EQ(1u << 31, nextPowerOfTwo(1u << 31U));
EXPECT_EQ(1ULL << 32, nextPowerOfTwo(static_cast<uint64_t>((1ULL << 31ULL) + 1)));
EXPECT_EQ(1ULL << 32, nextPowerOfTwo(static_cast<uint64_t>(1ULL << 32ULL)));
} }
TEST(PrevPowerOfTwo, aroundPowers) { TEST(PrevPowerOfTwo, aroundPowers) {
EXPECT_EQ(0u, prevPowerOfTwo(0)); EXPECT_EQ(0u, prevPowerOfTwo(0U));
EXPECT_EQ(1u, prevPowerOfTwo(1)); EXPECT_EQ(1u, prevPowerOfTwo(1U));
for (uint32_t i = 1; i < 32; i++) { for (uint32_t i = 1; i < 32; i++) {
uint32_t b = 1 << i; uint32_t b = 1 << i;
@@ -32,6 +35,9 @@ TEST(PrevPowerOfTwo, aroundPowers) {
EXPECT_EQ(b, prevPowerOfTwo(b)); EXPECT_EQ(b, prevPowerOfTwo(b));
EXPECT_EQ(b, prevPowerOfTwo(b + 1)); EXPECT_EQ(b, prevPowerOfTwo(b + 1));
} }
EXPECT_EQ(1ULL << 32, prevPowerOfTwo(static_cast<uint64_t>(1ULL << 32ULL)));
EXPECT_EQ(1ULL << 32, prevPowerOfTwo(static_cast<uint64_t>((1ULL << 32ULL) + 7)));
} }
TEST(getMinLsbSet, basicValues) { TEST(getMinLsbSet, basicValues) {
@@ -193,3 +199,18 @@ TEST(isPow2Test, WhenArgPow2ThenReturnTrue) {
EXPECT_TRUE(isPow2(128u)); EXPECT_TRUE(isPow2(128u));
EXPECT_TRUE(isPow2(4096u)); EXPECT_TRUE(isPow2(4096u));
} }
TEST(ffs, givenZeroReturnMaxRange) {
EXPECT_EQ(std::numeric_limits<uint32_t>::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));
}