From befc22a61ee55d887a207153c1f5e85d0156c78b Mon Sep 17 00:00:00 2001
From: Wunkolo <Wunkolo@gmail.com>
Date: Thu, 23 Dec 2021 12:37:58 -0800
Subject: [PATCH] constant_pool: Use `unordered_map` rather than `map`

`map` is an ordinal structure with log(n) time searches.
`unordered_map` uses O(1) average-time searches and O(n) in the worst
case where a bucket has a to a colliding hash and has to start chaining.
The unordered version should speed up our general-case when looking up
constants.

I've added a trivial order-dependent(_(0,1) and (1,0) will return a
different hash_) hash to combine a 128-bit constant into a
64-bit hash that generally will not collide, using a bit-rotate to
preserve entropy.
---
 src/dynarmic/backend/x64/constant_pool.h | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/src/dynarmic/backend/x64/constant_pool.h b/src/dynarmic/backend/x64/constant_pool.h
index 16cdb236..1e4fb695 100644
--- a/src/dynarmic/backend/x64/constant_pool.h
+++ b/src/dynarmic/backend/x64/constant_pool.h
@@ -5,8 +5,9 @@
 
 #pragma once
 
-#include <map>
+#include <bit>
 #include <tuple>
+#include <unordered_map>
 
 #include <xbyak/xbyak.h>
 
@@ -29,7 +30,13 @@ public:
 private:
     static constexpr size_t align_size = 16;  // bytes
 
-    std::map<std::tuple<u64, u64>, void*> constant_info;
+    struct ConstantHash {
+        std::size_t operator()(const std::tuple<u64, u64>& constant) const {
+            return std::get<0>(constant) ^ std::rotl<u64>(std::get<1>(constant), 1);
+        }
+    };
+
+    std::unordered_map<std::tuple<u64, u64>, void*, ConstantHash> constant_info;
 
     BlockOfCode& code;
     size_t pool_size;