Merge pull request #5356 from lioncash/clz
common/bit_util: Replace CLZ/CTZ operations with standardized ones
This commit is contained in:
commit
5b9aedfc21
10 changed files with 17 additions and 113 deletions
|
@ -21,82 +21,6 @@ template <typename T>
|
||||||
return sizeof(T) * CHAR_BIT;
|
return sizeof(T) * CHAR_BIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
[[nodiscard]] inline u32 CountLeadingZeroes32(u32 value) {
|
|
||||||
unsigned long leading_zero = 0;
|
|
||||||
|
|
||||||
if (_BitScanReverse(&leading_zero, value) != 0) {
|
|
||||||
return 31 - leading_zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] inline u32 CountLeadingZeroes64(u64 value) {
|
|
||||||
unsigned long leading_zero = 0;
|
|
||||||
|
|
||||||
if (_BitScanReverse64(&leading_zero, value) != 0) {
|
|
||||||
return 63 - leading_zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 64;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
[[nodiscard]] inline u32 CountLeadingZeroes32(u32 value) {
|
|
||||||
if (value == 0) {
|
|
||||||
return 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
return static_cast<u32>(__builtin_clz(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] inline u32 CountLeadingZeroes64(u64 value) {
|
|
||||||
if (value == 0) {
|
|
||||||
return 64;
|
|
||||||
}
|
|
||||||
|
|
||||||
return static_cast<u32>(__builtin_clzll(value));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
[[nodiscard]] inline u32 CountTrailingZeroes32(u32 value) {
|
|
||||||
unsigned long trailing_zero = 0;
|
|
||||||
|
|
||||||
if (_BitScanForward(&trailing_zero, value) != 0) {
|
|
||||||
return trailing_zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] inline u32 CountTrailingZeroes64(u64 value) {
|
|
||||||
unsigned long trailing_zero = 0;
|
|
||||||
|
|
||||||
if (_BitScanForward64(&trailing_zero, value) != 0) {
|
|
||||||
return trailing_zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 64;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
[[nodiscard]] inline u32 CountTrailingZeroes32(u32 value) {
|
|
||||||
if (value == 0) {
|
|
||||||
return 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
return static_cast<u32>(__builtin_ctz(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] inline u32 CountTrailingZeroes64(u64 value) {
|
|
||||||
if (value == 0) {
|
|
||||||
return 64;
|
|
||||||
}
|
|
||||||
|
|
||||||
return static_cast<u32>(__builtin_ctzll(value));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
|
||||||
[[nodiscard]] inline u32 MostSignificantBit32(const u32 value) {
|
[[nodiscard]] inline u32 MostSignificantBit32(const u32 value) {
|
||||||
|
|
|
@ -8,11 +8,11 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <bit>
|
||||||
#include <concepts>
|
#include <concepts>
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/bit_set.h"
|
#include "common/bit_set.h"
|
||||||
#include "common/bit_util.h"
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/concepts.h"
|
#include "common/concepts.h"
|
||||||
|
|
||||||
|
@ -268,7 +268,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr s32 GetNextCore(u64& affinity) {
|
constexpr s32 GetNextCore(u64& affinity) {
|
||||||
const s32 core = Common::CountTrailingZeroes64(affinity);
|
const s32 core = std::countr_zero(affinity);
|
||||||
ClearAffinityBit(affinity, core);
|
ClearAffinityBit(affinity, core);
|
||||||
return core;
|
return core;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
// This file references various implementation details from Atmosphere, an open-source firmware for
|
// This file references various implementation details from Atmosphere, an open-source firmware for
|
||||||
// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
|
// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
|
||||||
|
|
||||||
|
#include <bit>
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/bit_util.h"
|
#include "common/bit_util.h"
|
||||||
#include "common/fiber.h"
|
#include "common/fiber.h"
|
||||||
|
@ -31,12 +33,12 @@ static void IncrementScheduledCount(Kernel::Thread* thread) {
|
||||||
|
|
||||||
void KScheduler::RescheduleCores(KernelCore& kernel, u64 cores_pending_reschedule,
|
void KScheduler::RescheduleCores(KernelCore& kernel, u64 cores_pending_reschedule,
|
||||||
Core::EmuThreadHandle global_thread) {
|
Core::EmuThreadHandle global_thread) {
|
||||||
u32 current_core = global_thread.host_handle;
|
const u32 current_core = global_thread.host_handle;
|
||||||
bool must_context_switch = global_thread.guest_handle != InvalidHandle &&
|
bool must_context_switch = global_thread.guest_handle != InvalidHandle &&
|
||||||
(current_core < Core::Hardware::NUM_CPU_CORES);
|
(current_core < Core::Hardware::NUM_CPU_CORES);
|
||||||
|
|
||||||
while (cores_pending_reschedule != 0) {
|
while (cores_pending_reschedule != 0) {
|
||||||
u32 core = Common::CountTrailingZeroes64(cores_pending_reschedule);
|
const auto core = static_cast<u32>(std::countr_zero(cores_pending_reschedule));
|
||||||
ASSERT(core < Core::Hardware::NUM_CPU_CORES);
|
ASSERT(core < Core::Hardware::NUM_CPU_CORES);
|
||||||
if (!must_context_switch || core != current_core) {
|
if (!must_context_switch || core != current_core) {
|
||||||
auto& phys_core = kernel.PhysicalCore(core);
|
auto& phys_core = kernel.PhysicalCore(core);
|
||||||
|
@ -109,7 +111,7 @@ u64 KScheduler::UpdateHighestPriorityThreadsImpl(KernelCore& kernel) {
|
||||||
|
|
||||||
// Idle cores are bad. We're going to try to migrate threads to each idle core in turn.
|
// Idle cores are bad. We're going to try to migrate threads to each idle core in turn.
|
||||||
while (idle_cores != 0) {
|
while (idle_cores != 0) {
|
||||||
u32 core_id = Common::CountTrailingZeroes64(idle_cores);
|
const auto core_id = static_cast<u32>(std::countr_zero(idle_cores));
|
||||||
if (Thread* suggested = priority_queue.GetSuggestedFront(core_id); suggested != nullptr) {
|
if (Thread* suggested = priority_queue.GetSuggestedFront(core_id); suggested != nullptr) {
|
||||||
s32 migration_candidates[Core::Hardware::NUM_CPU_CORES];
|
s32 migration_candidates[Core::Hardware::NUM_CPU_CORES];
|
||||||
size_t num_candidates = 0;
|
size_t num_candidates = 0;
|
||||||
|
|
|
@ -8,11 +8,11 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <bit>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "common/alignment.h"
|
#include "common/alignment.h"
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/bit_util.h"
|
|
||||||
#include "common/common_funcs.h"
|
#include "common/common_funcs.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/hle/kernel/memory/memory_types.h"
|
#include "core/hle/kernel/memory/memory_types.h"
|
||||||
|
@ -105,7 +105,7 @@ private:
|
||||||
ASSERT(depth == 0);
|
ASSERT(depth == 0);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
offset = offset * 64 + Common::CountTrailingZeroes64(v);
|
offset = offset * 64 + static_cast<u32>(std::countr_zero(v));
|
||||||
++depth;
|
++depth;
|
||||||
} while (depth < static_cast<s32>(used_depths));
|
} while (depth < static_cast<s32>(used_depths));
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <bit>
|
||||||
|
|
||||||
#include "common/bit_util.h"
|
#include "common/bit_util.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "core/hle/kernel/errors.h"
|
#include "core/hle/kernel/errors.h"
|
||||||
|
@ -60,7 +62,7 @@ constexpr CapabilityType GetCapabilityType(u32 value) {
|
||||||
|
|
||||||
u32 GetFlagBitOffset(CapabilityType type) {
|
u32 GetFlagBitOffset(CapabilityType type) {
|
||||||
const auto value = static_cast<u32>(type);
|
const auto value = static_cast<u32>(type);
|
||||||
return static_cast<u32>(Common::BitSize<u32>() - Common::CountLeadingZeroes32(value));
|
return static_cast<u32>(Common::BitSize<u32>() - static_cast<u32>(std::countl_zero(value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
add_executable(tests
|
add_executable(tests
|
||||||
common/bit_field.cpp
|
common/bit_field.cpp
|
||||||
common/bit_utils.cpp
|
|
||||||
common/fibers.cpp
|
common/fibers.cpp
|
||||||
common/param_package.cpp
|
common/param_package.cpp
|
||||||
common/ring_buffer.cpp
|
common/ring_buffer.cpp
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
// Copyright 2017 Citra Emulator Project
|
|
||||||
// Licensed under GPLv2 or any later version
|
|
||||||
// Refer to the license.txt file included.
|
|
||||||
|
|
||||||
#include <catch2/catch.hpp>
|
|
||||||
#include <math.h>
|
|
||||||
#include "common/bit_util.h"
|
|
||||||
|
|
||||||
namespace Common {
|
|
||||||
|
|
||||||
TEST_CASE("BitUtils::CountTrailingZeroes", "[common]") {
|
|
||||||
REQUIRE(Common::CountTrailingZeroes32(0) == 32);
|
|
||||||
REQUIRE(Common::CountTrailingZeroes64(0) == 64);
|
|
||||||
REQUIRE(Common::CountTrailingZeroes32(9) == 0);
|
|
||||||
REQUIRE(Common::CountTrailingZeroes32(8) == 3);
|
|
||||||
REQUIRE(Common::CountTrailingZeroes32(0x801000) == 12);
|
|
||||||
REQUIRE(Common::CountTrailingZeroes64(9) == 0);
|
|
||||||
REQUIRE(Common::CountTrailingZeroes64(8) == 3);
|
|
||||||
REQUIRE(Common::CountTrailingZeroes64(0x801000) == 12);
|
|
||||||
REQUIRE(Common::CountTrailingZeroes64(0x801000000000UL) == 36);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Common
|
|
|
@ -18,10 +18,10 @@
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include <bit>
|
||||||
#include "command_classes/host1x.h"
|
#include "command_classes/host1x.h"
|
||||||
#include "command_classes/nvdec.h"
|
#include "command_classes/nvdec.h"
|
||||||
#include "command_classes/vic.h"
|
#include "command_classes/vic.h"
|
||||||
#include "common/bit_util.h"
|
|
||||||
#include "video_core/cdma_pusher.h"
|
#include "video_core/cdma_pusher.h"
|
||||||
#include "video_core/command_classes/nvdec_common.h"
|
#include "video_core/command_classes/nvdec_common.h"
|
||||||
#include "video_core/engines/maxwell_3d.h"
|
#include "video_core/engines/maxwell_3d.h"
|
||||||
|
@ -56,7 +56,7 @@ void CDmaPusher::Step() {
|
||||||
|
|
||||||
for (const u32 value : values) {
|
for (const u32 value : values) {
|
||||||
if (mask != 0) {
|
if (mask != 0) {
|
||||||
const u32 lbs = Common::CountTrailingZeroes32(mask);
|
const auto lbs = static_cast<u32>(std::countr_zero(mask));
|
||||||
mask &= ~(1U << lbs);
|
mask &= ~(1U << lbs);
|
||||||
ExecuteCommand(static_cast<u32>(offset + lbs), value);
|
ExecuteCommand(static_cast<u32>(offset + lbs), value);
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -126,7 +126,7 @@ private:
|
||||||
|
|
||||||
s32 count{};
|
s32 count{};
|
||||||
s32 offset{};
|
s32 offset{};
|
||||||
s32 mask{};
|
u32 mask{};
|
||||||
bool incrementing{};
|
bool incrementing{};
|
||||||
|
|
||||||
// Queue of command lists to be processed
|
// Queue of command lists to be processed
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include "common/bit_util.h"
|
#include <bit>
|
||||||
#include "video_core/command_classes/codecs/h264.h"
|
#include "video_core/command_classes/codecs/h264.h"
|
||||||
#include "video_core/gpu.h"
|
#include "video_core/gpu.h"
|
||||||
#include "video_core/memory_manager.h"
|
#include "video_core/memory_manager.h"
|
||||||
|
@ -266,7 +266,7 @@ void H264BitWriter::WriteExpGolombCodedInt(s32 value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void H264BitWriter::WriteExpGolombCodedUInt(u32 value) {
|
void H264BitWriter::WriteExpGolombCodedUInt(u32 value) {
|
||||||
const s32 size = 32 - Common::CountLeadingZeroes32(static_cast<s32>(value + 1));
|
const s32 size = 32 - std::countl_zero(value + 1);
|
||||||
WriteBits(1, size);
|
WriteBits(1, size);
|
||||||
|
|
||||||
value -= (1U << (size - 1)) - 1;
|
value -= (1U << (size - 1)) - 1;
|
||||||
|
|
Loading…
Reference in a new issue