From 40b236bb18e37a32dfe7c876ebd1b5187b805689 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Fri, 2 Aug 2024 17:04:20 +0200 Subject: [PATCH] hashlib: interface WIP --- frontends/ast/ast.h | 4 +- kernel/bitpattern.h | 8 +-- kernel/cellaigs.cc | 12 ++-- kernel/cellaigs.h | 4 +- kernel/hashlib.h | 121 +++++++++++++++++++++++++++--------- kernel/modtools.h | 27 +++++--- kernel/rtlil.cc | 2 +- kernel/rtlil.h | 82 ++++++++++++------------ kernel/scopeinfo.h | 4 +- kernel/sigtools.h | 8 ++- kernel/timinginfo.h | 4 +- kernel/yosys_common.h | 3 +- passes/opt/opt_merge.cc | 2 + passes/sat/recover_names.cc | 2 +- 14 files changed, 185 insertions(+), 98 deletions(-) diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 6c4a1e15a65..3f5ef22db8c 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -173,11 +173,11 @@ namespace AST std::string type2str(AstNodeType type); // The AST is built using instances of this struct - struct AstNode + struct AstNode : public Hashable { // for dict<> and pool<> unsigned int hashidx_; - unsigned int hash() const { return hashidx_; } + hash_t hash_acc(hash_t h) const final { return mkhash(h, hashidx_); } // this nodes type AstNodeType type; diff --git a/kernel/bitpattern.h b/kernel/bitpattern.h index 7a8eb39f9f2..ed570450ecf 100644 --- a/kernel/bitpattern.h +++ b/kernel/bitpattern.h @@ -25,12 +25,12 @@ YOSYS_NAMESPACE_BEGIN -struct BitPatternPool +struct BitPatternPool : public Hashable { int width; struct bits_t { std::vector bitdata; - mutable unsigned int cached_hash; + mutable hash_t cached_hash; bits_t(int width = 0) : bitdata(width), cached_hash(0) { } RTLIL::State &operator[](int index) { return bitdata[index]; @@ -43,10 +43,10 @@ struct BitPatternPool return false; return bitdata == other.bitdata; } - unsigned int hash() const { + hash_t hash_acc(hash_t h) const final { if (!cached_hash) cached_hash = hash_ops>::hash(bitdata); - return cached_hash; + return mkhash(h, cached_hash); } }; pool database; diff --git a/kernel/cellaigs.cc b/kernel/cellaigs.cc index 5dda4503fdd..d6aae855062 100644 --- a/kernel/cellaigs.cc +++ b/kernel/cellaigs.cc @@ -39,13 +39,13 @@ bool AigNode::operator==(const AigNode &other) const return true; } -unsigned int AigNode::hash() const +hash_t AigNode::hash_acc(hash_t h) const { - unsigned int h = mkhash_init; - h = mkhash(portname.hash(), portbit); - h = mkhash(h, inverter); - h = mkhash(h, left_parent); - h = mkhash(h, right_parent); + h = portname.hash_acc(h); + h = mkhash(portbit, h); + h = mkhash(inverter, h); + h = mkhash(left_parent, h); + h = mkhash(right_parent, h); return h; } diff --git a/kernel/cellaigs.h b/kernel/cellaigs.h index 8f6d69ba62b..de34b0125f4 100644 --- a/kernel/cellaigs.h +++ b/kernel/cellaigs.h @@ -24,7 +24,7 @@ YOSYS_NAMESPACE_BEGIN -struct AigNode +struct AigNode : public Hashable { IdString portname; int portbit; @@ -34,7 +34,7 @@ struct AigNode AigNode(); bool operator==(const AigNode &other) const; - unsigned int hash() const; + hash_t hash_acc(hash_t h) const final; }; struct Aig diff --git a/kernel/hashlib.h b/kernel/hashlib.h index 6b880f3a666..f5e03b5b187 100644 --- a/kernel/hashlib.h +++ b/kernel/hashlib.h @@ -32,10 +32,24 @@ inline unsigned int mkhash(unsigned int a, unsigned int b) { // traditionally 5381 is used as starting value for the djb2 hash const unsigned int mkhash_init = 5381; -// The ADD version of DJB2 -// (use this version for cache locality in b) +// TODO ifdef this +typedef uint64_t hash_t; +// typedef hash_t acc_t; + +struct Hashable { + virtual ~Hashable() = 0; + public: + [[nodiscard]] + virtual hash_t hash_acc(hash_t acc) const = 0; + [[nodiscard]] + hash_t hash() const { + return hash_acc(mkhash_init); + } +}; + +[[deprecated]] inline unsigned int mkhash_add(unsigned int a, unsigned int b) { - return ((a << 5) + a) + b; + return mkhash(a, b); } inline unsigned int mkhash_xorshift(unsigned int a) { @@ -52,11 +66,17 @@ inline unsigned int mkhash_xorshift(unsigned int a) { return a; } -template struct hash_ops { + + +template +struct hash_ops: std::false_type {}; + +template +struct hash_ops>> { static inline bool cmp(const T &a, const T &b) { return a == b; } - static inline unsigned int hash(const T &a) { + static inline hash_t hash(const T &a) { return a.hash(); } }; @@ -70,31 +90,31 @@ struct hash_int_ops { template<> struct hash_ops : hash_int_ops { - static inline unsigned int hash(bool a) { + static inline hash_t hash(bool a) { return a ? 1 : 0; } }; template<> struct hash_ops : hash_int_ops { - static inline unsigned int hash(int32_t a) { + static inline hash_t hash(int32_t a) { return a; } }; template<> struct hash_ops : hash_int_ops { - static inline unsigned int hash(int64_t a) { + static inline hash_t hash(int64_t a) { return mkhash((unsigned int)(a), (unsigned int)(a >> 32)); } }; template<> struct hash_ops : hash_int_ops { - static inline unsigned int hash(uint32_t a) { + static inline hash_t hash(uint32_t a) { return a; } }; template<> struct hash_ops : hash_int_ops { - static inline unsigned int hash(uint64_t a) { + static inline hash_t hash(uint64_t a) { return mkhash((unsigned int)(a), (unsigned int)(a >> 32)); } }; @@ -103,7 +123,7 @@ template<> struct hash_ops { static inline bool cmp(const std::string &a, const std::string &b) { return a == b; } - static inline unsigned int hash(const std::string &a) { + static inline hash_t hash(const std::string &a) { unsigned int v = 0; for (auto c : a) v = mkhash(v, c); @@ -115,7 +135,7 @@ template struct hash_ops> { static inline bool cmp(std::pair a, std::pair b) { return a == b; } - static inline unsigned int hash(std::pair a) { + static inline hash_t hash(std::pair a) { return mkhash(hash_ops

::hash(a.first), hash_ops::hash(a.second)); } }; @@ -139,7 +159,7 @@ template struct hash_ops> { static inline bool cmp(std::vector a, std::vector b) { return a == b; } - static inline unsigned int hash(std::vector a) { + static inline hash_t hash(std::vector a) { unsigned int h = mkhash_init; for (auto k : a) h = mkhash(h, hash_ops::hash(k)); @@ -154,19 +174,21 @@ struct hash_cstr_ops { return false; return true; } - static inline unsigned int hash(const char *a) { - unsigned int hash = mkhash_init; + static inline hash_t hash(const char *a) { + hash_t hash = mkhash_init; while (*a) hash = mkhash(hash, *(a++)); return hash; } }; +template <> struct hash_ops : hash_cstr_ops {}; + struct hash_ptr_ops { static inline bool cmp(const void *a, const void *b) { return a == b; } - static inline unsigned int hash(const void *a) { + static inline hash_t hash(const void *a) { return (uintptr_t)a; } }; @@ -176,11 +198,53 @@ struct hash_obj_ops { return a == b; } template - static inline unsigned int hash(const T *a) { - return a ? a->hash() : 0; + static inline hash_t hash(const T *a) { + return a ? a->hash_acc(mkhash_init) : 0; } }; +// Primary template +template +struct is_hashable : std::false_type {}; + +// Helper to check if hash_ops exists for a type U +template +struct has_hash_ops : std::false_type {}; + +template +struct has_hash_ops::hash(std::declval())), + decltype(hash_ops::cmp(std::declval(), std::declval())) +>> : std::true_type {}; + +// Helper to check if T is convertible to U and U has hash_ops +template +struct is_convertible_and_hashable : + std::conjunction< + std::is_convertible, + has_hash_ops + > {}; + +// Helper to check convertibility to a list of types +template +struct is_convertible_to_any_hashable : + std::disjunction< + is_convertible_and_hashable... + > {}; + +// Specialization that checks for direct hash_ops or convertibility to hashable types +template +struct is_hashable::value || + is_convertible_to_any_hashable::value + > +> : std::true_type {}; + template inline unsigned int mkhash(const T &v) { return hash_ops().hash(v); @@ -220,8 +284,8 @@ template> class pool; template> class mfp; template -class dict -{ +class dict : public Hashable { + // static_assert(is_hashable::value, "Key type must be derived from Hashable"); struct entry_t { std::pair udata; @@ -247,7 +311,7 @@ class dict int do_hash(const K &key) const { - unsigned int hash = 0; + hash_t hash = 0; if (!hashtable.empty()) hash = ops.hash(key) % (unsigned int)(hashtable.size()); return hash; @@ -651,8 +715,7 @@ class dict return !operator==(other); } - unsigned int hash() const { - unsigned int h = mkhash_init; + hash_t hash_acc(hash_t h) const final { for (auto &entry : entries) { h ^= hash_ops::hash(entry.udata.first); h ^= hash_ops::hash(entry.udata.second); @@ -675,8 +738,9 @@ class dict }; template -class pool +class pool : public Hashable { + // static_assert(is_hashable::value, "Key type must be derived from Hashable"); template friend class idict; protected: @@ -704,7 +768,7 @@ class pool int do_hash(const K &key) const { - unsigned int hash = 0; + hash_t hash = 0; if (!hashtable.empty()) hash = ops.hash(key) % (unsigned int)(hashtable.size()); return hash; @@ -1019,11 +1083,10 @@ class pool return !operator==(other); } - unsigned int hash() const { - unsigned int hashval = mkhash_init; + hash_t hash_acc(hash_t h) const final { for (auto &it : entries) - hashval ^= ops.hash(it.udata); - return hashval; + h ^= ops.hash(it.udata); + return h; } void reserve(size_t n) { entries.reserve(n); } diff --git a/kernel/modtools.h b/kernel/modtools.h index 34a23b37981..5bee2795804 100644 --- a/kernel/modtools.h +++ b/kernel/modtools.h @@ -28,7 +28,7 @@ YOSYS_NAMESPACE_BEGIN struct ModIndex : public RTLIL::Monitor { - struct PortInfo { + struct PortInfo : public Hashable { RTLIL::Cell* cell; RTLIL::IdString port; int offset; @@ -48,8 +48,14 @@ struct ModIndex : public RTLIL::Monitor return cell == other.cell && port == other.port && offset == other.offset; } - unsigned int hash() const { - return mkhash_add(mkhash(cell->name.hash(), port.hash()), offset); + // unsigned int hash() const { + // return mkhash(mkhash(cell->name.hash(), port.hash()), offset); + // } + hash_t hash_acc(hash_t acc) const { + acc = cell->name.hash_acc(acc); + acc = port.hash_acc(acc); + acc = mkhash(offset, acc); + return acc; } }; @@ -57,6 +63,8 @@ struct ModIndex : public RTLIL::Monitor { bool is_input, is_output; pool ports; + // SigBitInfo() : SigBitInfo{} {} + // SigBitInfo& operator=(const SigBitInfo&) = default; SigBitInfo() : is_input(false), is_output(false) { } @@ -299,11 +307,13 @@ struct ModIndex : public RTLIL::Monitor struct ModWalker { - struct PortBit + struct PortBit : public Hashable { RTLIL::Cell *cell; RTLIL::IdString port; int offset; + PortBit(Cell* c, IdString p, int o) : cell(c), port(p), offset(o) {} + // PortBit& operator=(const PortBit&) = default; bool operator<(const PortBit &other) const { if (cell != other.cell) @@ -317,8 +327,11 @@ struct ModWalker return cell == other.cell && port == other.port && offset == other.offset; } - unsigned int hash() const { - return mkhash_add(mkhash(cell->name.hash(), port.hash()), offset); + hash_t hash_acc(hash_t h) const final { + h = cell->name.hash_acc(h); + h = port.hash_acc(h); + h = mkhash(offset, h); + return h; } }; @@ -355,7 +368,7 @@ struct ModWalker { for (int i = 0; i < int(bits.size()); i++) if (bits[i].wire != NULL) { - PortBit pbit = { cell, port, i }; + PortBit pbit {cell, port, i}; if (is_output) { signal_drivers[bits[i]].insert(pbit); cell_outputs[cell].insert(bits[i]); diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index d3946a620de..93fcb821b74 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -33,7 +33,7 @@ YOSYS_NAMESPACE_BEGIN bool RTLIL::IdString::destruct_guard_ok = false; RTLIL::IdString::destruct_guard_t RTLIL::IdString::destruct_guard; std::vector RTLIL::IdString::global_id_storage_; -dict RTLIL::IdString::global_id_index_; +dict RTLIL::IdString::global_id_index_; #ifndef YOSYS_NO_IDS_REFCNT std::vector RTLIL::IdString::global_refcount_storage_; std::vector RTLIL::IdString::global_free_idx_list_; diff --git a/kernel/rtlil.h b/kernel/rtlil.h index f9da2949508..812b6fd756e 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -77,7 +77,7 @@ namespace RTLIL typedef std::pair SigSig; - struct IdString + struct IdString : public Hashable { #undef YOSYS_XTRACE_GET_PUT #undef YOSYS_SORT_ID_FREE_LIST @@ -93,7 +93,7 @@ namespace RTLIL } destruct_guard; static std::vector global_id_storage_; - static dict global_id_index_; + static dict global_id_index_; #ifndef YOSYS_NO_IDS_REFCNT static std::vector global_refcount_storage_; static std::vector global_free_idx_list_; @@ -358,8 +358,8 @@ namespace RTLIL *this = IdString(); } - unsigned int hash() const { - return index_; + hash_t hash_acc(hash_t h) const final { + return mkhash(index_, h); } // The following is a helper key_compare class. Instead of for example std::set @@ -655,7 +655,7 @@ namespace RTLIL }; }; -struct RTLIL::Const +struct RTLIL::Const : public Hashable { int flags; std::vector bits; @@ -710,8 +710,7 @@ struct RTLIL::Const bits.resize(width, bits.empty() ? RTLIL::State::Sx : bits.back()); } - inline unsigned int hash() const { - unsigned int h = mkhash_init; + inline hash_t hash_acc(hash_t h) const final { for (auto b : bits) h = mkhash(h, b); return h; @@ -777,7 +776,7 @@ struct RTLIL::SigChunk bool operator !=(const RTLIL::SigChunk &other) const; }; -struct RTLIL::SigBit +struct RTLIL::SigBit : public Hashable { RTLIL::Wire *wire; union { @@ -801,7 +800,7 @@ struct RTLIL::SigBit bool operator <(const RTLIL::SigBit &other) const; bool operator ==(const RTLIL::SigBit &other) const; bool operator !=(const RTLIL::SigBit &other) const; - unsigned int hash() const; + hash_t hash_acc(hash_t h) const final; }; struct RTLIL::SigSpecIterator @@ -838,11 +837,11 @@ struct RTLIL::SigSpecConstIterator inline void operator++() { index++; } }; -struct RTLIL::SigSpec +struct RTLIL::SigSpec : public Hashable { private: int width_; - unsigned long hash_; + hash_t hash_; std::vector chunks_; // LSB at index 0 std::vector bits_; // LSB at index 0 @@ -883,9 +882,10 @@ struct RTLIL::SigSpec SigSpec(const std::set &bits); explicit SigSpec(bool bit); + [[deprecated]] size_t get_hash() const { - if (!hash_) hash(); - return hash_; + log_assert(false && "deprecated"); + return 0; } inline const std::vector &chunks() const { pack(); return chunks_; } @@ -994,7 +994,7 @@ struct RTLIL::SigSpec operator std::vector() const { return bits(); } const RTLIL::SigBit &at(int offset, const RTLIL::SigBit &defval) { return offset < width_ ? (*this)[offset] : defval; } - unsigned int hash() const { if (!hash_) updhash(); return hash_; }; + hash_t hash_acc(hash_t h) const final { if (!hash_) updhash(); return mkhash(h, hash_); } #ifndef NDEBUG void check(Module *mod = nullptr) const; @@ -1033,10 +1033,10 @@ struct RTLIL::Selection } }; -struct RTLIL::Monitor +struct RTLIL::Monitor : public Hashable { - unsigned int hashidx_; - unsigned int hash() const { return hashidx_; } + hash_t hashidx_; + hash_t hash_acc(hash_t h) const final { return mkhash(h, hashidx_); } Monitor() { static unsigned int hashidx_count = 123456789; @@ -1056,10 +1056,10 @@ struct RTLIL::Monitor // Forward declaration; defined in preproc.h. struct define_map_t; -struct RTLIL::Design +struct RTLIL::Design : public Hashable { - unsigned int hashidx_; - unsigned int hash() const { return hashidx_; } + hash_t hashidx_; + hash_t hash_acc(hash_t h) const final { return mkhash(h, hashidx_); } pool monitors; dict scratchpad; @@ -1158,10 +1158,10 @@ struct RTLIL::Design #endif }; -struct RTLIL::Module : public RTLIL::AttrObject +struct RTLIL::Module : public RTLIL::AttrObject, public Hashable { - unsigned int hashidx_; - unsigned int hash() const { return hashidx_; } + hash_t hashidx_; + hash_t hash_acc(hash_t h) const final { return mkhash(h, hashidx_); } protected: void add(RTLIL::Wire *wire); @@ -1500,10 +1500,10 @@ struct RTLIL::Module : public RTLIL::AttrObject #endif }; -struct RTLIL::Wire : public RTLIL::AttrObject +struct RTLIL::Wire : public RTLIL::AttrObject, public Hashable { - unsigned int hashidx_; - unsigned int hash() const { return hashidx_; } + hash_t hashidx_; + hash_t hash_acc(hash_t h) const final { return mkhash(h, hashidx_); } protected: // use module->addWire() and module->remove() to create or destroy wires @@ -1530,10 +1530,10 @@ inline int GetSize(RTLIL::Wire *wire) { return wire->width; } -struct RTLIL::Memory : public RTLIL::AttrObject +struct RTLIL::Memory : public RTLIL::AttrObject, public Hashable { - unsigned int hashidx_; - unsigned int hash() const { return hashidx_; } + hash_t hashidx_; + hash_t hash_acc(hash_t h) const final { return mkhash(h, hashidx_); } Memory(); @@ -1545,10 +1545,10 @@ struct RTLIL::Memory : public RTLIL::AttrObject #endif }; -struct RTLIL::Cell : public RTLIL::AttrObject +struct RTLIL::Cell : public RTLIL::AttrObject, public Hashable { - unsigned int hashidx_; - unsigned int hash() const { return hashidx_; } + hash_t hashidx_; + hash_t hash_acc(hash_t h) const final { return mkhash(h, hashidx_); } protected: // use module->addCell() and module->remove() to create or destroy cells @@ -1655,10 +1655,10 @@ struct RTLIL::SyncRule RTLIL::SyncRule *clone() const; }; -struct RTLIL::Process : public RTLIL::AttrObject +struct RTLIL::Process : public RTLIL::AttrObject, public Hashable { - unsigned int hashidx_; - unsigned int hash() const { return hashidx_; } + hash_t hashidx_; + hash_t hash_acc(hash_t h) const final { return mkhash(h, hashidx_); } protected: // use module->addProcess() and module->remove() to create or destroy processes @@ -1702,10 +1702,14 @@ inline bool RTLIL::SigBit::operator!=(const RTLIL::SigBit &other) const { return (wire != other.wire) || (wire ? (offset != other.offset) : (data != other.data)); } -inline unsigned int RTLIL::SigBit::hash() const { - if (wire) - return mkhash_add(wire->name.hash(), offset); - return data; +inline hash_t RTLIL::SigBit::hash_acc(hash_t h) const { + if (wire) { + h = wire->name.hash_acc(h); + h = mkhash(offset, h); + return h; + } + h = mkhash(data, h); + return h; } inline RTLIL::SigBit &RTLIL::SigSpecIterator::operator*() const { diff --git a/kernel/scopeinfo.h b/kernel/scopeinfo.h index 71af70344ce..b479549f85a 100644 --- a/kernel/scopeinfo.h +++ b/kernel/scopeinfo.h @@ -300,7 +300,7 @@ class IdTree }; -struct ModuleItem { +struct ModuleItem : public Hashable { enum class Type { Wire, Cell, @@ -318,7 +318,7 @@ struct ModuleItem { Cell *cell() const { return type == Type::Cell ? static_cast(ptr) : nullptr; } bool operator==(const ModuleItem &other) const { return ptr == other.ptr && type == other.type; } - unsigned int hash() const { return (uintptr_t)ptr; } + hash_t hash_acc(hash_t h) const final { return mkhash((hash_t)ptr, h); } }; static inline void log_dump_val_worker(typename IdTree::Cursor cursor ) { log("%p %s", cursor.target, log_id(cursor.scope_name)); } diff --git a/kernel/sigtools.h b/kernel/sigtools.h index 63f1b51ec84..00ad2b8e633 100644 --- a/kernel/sigtools.h +++ b/kernel/sigtools.h @@ -26,10 +26,14 @@ YOSYS_NAMESPACE_BEGIN struct SigPool { - struct bitDef_t : public std::pair { + struct bitDef_t : public std::pair, public Hashable { bitDef_t() : std::pair(NULL, 0) { } bitDef_t(const RTLIL::SigBit &bit) : std::pair(bit.wire, bit.offset) { } - unsigned int hash() const { return first->name.hash() + second; } + hash_t hash_acc(hash_t h) const final { + h = first->name.hash_acc(h); + h = mkhash(second, h); + return h; + } }; pool bits; diff --git a/kernel/timinginfo.h b/kernel/timinginfo.h index e7e4eab6e2e..012a3f35491 100644 --- a/kernel/timinginfo.h +++ b/kernel/timinginfo.h @@ -36,7 +36,7 @@ struct TimingInfo explicit NameBit(const RTLIL::SigBit &b) : name(b.wire->name), offset(b.offset) {} bool operator==(const NameBit& nb) const { return nb.name == name && nb.offset == offset; } bool operator!=(const NameBit& nb) const { return !operator==(nb); } - unsigned int hash() const { return mkhash_add(name.hash(), offset); } + unsigned int hash() const { return mkhash(name.hash(), offset); } }; struct BitBit { @@ -44,7 +44,7 @@ struct TimingInfo BitBit(const NameBit &first, const NameBit &second) : first(first), second(second) {} BitBit(const SigBit &first, const SigBit &second) : first(first), second(second) {} bool operator==(const BitBit& bb) const { return bb.first == first && bb.second == second; } - unsigned int hash() const { return mkhash_add(first.hash(), second.hash()); } + unsigned int hash() const { return mkhash(first.hash(), second.hash()); } }; struct ModuleTiming diff --git a/kernel/yosys_common.h b/kernel/yosys_common.h index 56d2356b102..bc95875a62e 100644 --- a/kernel/yosys_common.h +++ b/kernel/yosys_common.h @@ -186,7 +186,8 @@ struct shared_str { using hashlib::mkhash; using hashlib::mkhash_init; -using hashlib::mkhash_add; +using hashlib::Hashable; +using hashlib::hash_t; using hashlib::mkhash_xorshift; using hashlib::hash_ops; using hashlib::hash_cstr_ops; diff --git a/passes/opt/opt_merge.cc b/passes/opt/opt_merge.cc index eb3aa462e01..07bed9bfd04 100644 --- a/passes/opt/opt_merge.cc +++ b/passes/opt/opt_merge.cc @@ -148,6 +148,7 @@ struct OptMergeWorker for (auto it : hash_conn_strings) hash_string += it; + log("hashed string %s\n", hash_string.c_str()); return std::hash{}(hash_string); } @@ -276,6 +277,7 @@ struct OptMergeWorker continue; uint64_t hash = hash_cell_parameters_and_connections(cell); + log("cell %s: hash %lX\n", cell->name.c_str(), hash); auto r = sharemap.insert(std::make_pair(hash, cell)); if (!r.second) { if (compare_cell_parameters_and_connections(cell, r.first->second)) { diff --git a/passes/sat/recover_names.cc b/passes/sat/recover_names.cc index 4870e2cac19..c7451d72647 100644 --- a/passes/sat/recover_names.cc +++ b/passes/sat/recover_names.cc @@ -48,7 +48,7 @@ struct IdBit { bool operator!=(const IdBit &other) const { return name != other.name || bit != other.bit; }; unsigned hash() const { - return mkhash_add(name.hash(), bit); + return mkhash(name.hash(), bit); } IdString name;