common/bit_util: Replace CLZ/CTZ operations with standardized ones
Makes for less code that we need to maintain.
This commit is contained in:
		| @@ -21,82 +21,6 @@ template <typename T> | ||||
|     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 | ||||
|  | ||||
| [[nodiscard]] inline u32 MostSignificantBit32(const u32 value) { | ||||
|   | ||||
| @@ -8,11 +8,11 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <array> | ||||
| #include <bit> | ||||
| #include <concepts> | ||||
|  | ||||
| #include "common/assert.h" | ||||
| #include "common/bit_set.h" | ||||
| #include "common/bit_util.h" | ||||
| #include "common/common_types.h" | ||||
| #include "common/concepts.h" | ||||
|  | ||||
| @@ -268,7 +268,7 @@ private: | ||||
|     } | ||||
|  | ||||
|     constexpr s32 GetNextCore(u64& affinity) { | ||||
|         const s32 core = Common::CountTrailingZeroes64(affinity); | ||||
|         const s32 core = std::countr_zero(affinity); | ||||
|         ClearAffinityBit(affinity, core); | ||||
|         return core; | ||||
|     } | ||||
|   | ||||
| @@ -5,6 +5,8 @@ | ||||
| // This file references various implementation details from Atmosphere, an open-source firmware for | ||||
| // the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX. | ||||
|  | ||||
| #include <bit> | ||||
|  | ||||
| #include "common/assert.h" | ||||
| #include "common/bit_util.h" | ||||
| #include "common/fiber.h" | ||||
| @@ -31,12 +33,12 @@ static void IncrementScheduledCount(Kernel::Thread* thread) { | ||||
|  | ||||
| void KScheduler::RescheduleCores(KernelCore& kernel, u64 cores_pending_reschedule, | ||||
|                                  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 && | ||||
|                                (current_core < Core::Hardware::NUM_CPU_CORES); | ||||
|  | ||||
|     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); | ||||
|         if (!must_context_switch || core != current_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. | ||||
|     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) { | ||||
|             s32 migration_candidates[Core::Hardware::NUM_CPU_CORES]; | ||||
|             size_t num_candidates = 0; | ||||
|   | ||||
| @@ -8,11 +8,11 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <array> | ||||
| #include <bit> | ||||
| #include <vector> | ||||
|  | ||||
| #include "common/alignment.h" | ||||
| #include "common/assert.h" | ||||
| #include "common/bit_util.h" | ||||
| #include "common/common_funcs.h" | ||||
| #include "common/common_types.h" | ||||
| #include "core/hle/kernel/memory/memory_types.h" | ||||
| @@ -105,7 +105,7 @@ private: | ||||
|                         ASSERT(depth == 0); | ||||
|                         return -1; | ||||
|                     } | ||||
|                     offset = offset * 64 + Common::CountTrailingZeroes64(v); | ||||
|                     offset = offset * 64 + static_cast<u32>(std::countr_zero(v)); | ||||
|                     ++depth; | ||||
|                 } while (depth < static_cast<s32>(used_depths)); | ||||
|  | ||||
|   | ||||
| @@ -2,6 +2,8 @@ | ||||
| // Licensed under GPLv2 or any later version | ||||
| // Refer to the license.txt file included. | ||||
|  | ||||
| #include <bit> | ||||
|  | ||||
| #include "common/bit_util.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "core/hle/kernel/errors.h" | ||||
| @@ -60,7 +62,7 @@ constexpr CapabilityType GetCapabilityType(u32 value) { | ||||
|  | ||||
| u32 GetFlagBitOffset(CapabilityType 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 | ||||
|   | ||||
| @@ -1,6 +1,5 @@ | ||||
| add_executable(tests | ||||
|     common/bit_field.cpp | ||||
|     common/bit_utils.cpp | ||||
|     common/fibers.cpp | ||||
|     common/param_package.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. | ||||
| // | ||||
|  | ||||
| #include <bit> | ||||
| #include "command_classes/host1x.h" | ||||
| #include "command_classes/nvdec.h" | ||||
| #include "command_classes/vic.h" | ||||
| #include "common/bit_util.h" | ||||
| #include "video_core/cdma_pusher.h" | ||||
| #include "video_core/command_classes/nvdec_common.h" | ||||
| #include "video_core/engines/maxwell_3d.h" | ||||
| @@ -56,7 +56,7 @@ void CDmaPusher::Step() { | ||||
|  | ||||
|     for (const u32 value : values) { | ||||
|         if (mask != 0) { | ||||
|             const u32 lbs = Common::CountTrailingZeroes32(mask); | ||||
|             const auto lbs = static_cast<u32>(std::countr_zero(mask)); | ||||
|             mask &= ~(1U << lbs); | ||||
|             ExecuteCommand(static_cast<u32>(offset + lbs), value); | ||||
|             continue; | ||||
|   | ||||
| @@ -126,7 +126,7 @@ private: | ||||
|  | ||||
|     s32 count{}; | ||||
|     s32 offset{}; | ||||
|     s32 mask{}; | ||||
|     u32 mask{}; | ||||
|     bool incrementing{}; | ||||
|  | ||||
|     // Queue of command lists to be processed | ||||
|   | ||||
| @@ -19,7 +19,7 @@ | ||||
| // | ||||
|  | ||||
| #include <array> | ||||
| #include "common/bit_util.h" | ||||
| #include <bit> | ||||
| #include "video_core/command_classes/codecs/h264.h" | ||||
| #include "video_core/gpu.h" | ||||
| #include "video_core/memory_manager.h" | ||||
| @@ -266,7 +266,7 @@ void H264BitWriter::WriteExpGolombCodedInt(s32 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); | ||||
|  | ||||
|     value -= (1U << (size - 1)) - 1; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Lioncash
					Lioncash