This is an automated email from the ASF dual-hosted git repository.

tqchen pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm.git


The following commit(s) were added to refs/heads/main by this push:
     new 012d6a72f6 [IR] Platform-independent SHash (#14204)
012d6a72f6 is described below

commit 012d6a72f661113ae1ccfae38e5fc848296d76d8
Author: Junru Shao <[email protected]>
AuthorDate: Mon Mar 6 17:37:27 2023 -0800

    [IR] Platform-independent SHash (#14204)
    
    This PR introduces the necessary change to make structural-hash
    platform-independent. The change includes:
    - Explicitly require the hash type to be `uint64_t` rather than
      platform-dependent `size_t`.
    - Implement structural hash for POD types including `double`, `int`
      by unioning them with `uint64_t` explicitly.
    - Implement a platform-independent fast hashing algorithm for `std::string`
---
 include/tvm/node/reflection.h          |  2 +-
 include/tvm/node/structural_hash.h     | 74 ++++++++++++++++--------------
 include/tvm/runtime/container/string.h | 73 +++++++++++++++++++++++++++---
 src/node/structural_hash.cc            | 82 +++++++++++++++++-----------------
 src/relay/backend/utils.h              |  2 +-
 5 files changed, 151 insertions(+), 82 deletions(-)

diff --git a/include/tvm/node/reflection.h b/include/tvm/node/reflection.h
index f547b5a707..2cfb50e1a2 100644
--- a/include/tvm/node/reflection.h
+++ b/include/tvm/node/reflection.h
@@ -244,7 +244,7 @@ class ReflectionVTable::Registry {
  *    static constexpr const std::nullptr_t VisitAttrs = nullptr;
  *
  *    static void SHashReduce(const runtime::StringObj* key, SHashReducer 
hash_reduce) {
- *      
hash_reduce->SHashReduceHashedValue(runtime::String::HashBytes(key->data, 
key->size));
+ *      
hash_reduce->SHashReduceHashedValue(runtime::String::StableHashBytes(key->data, 
key->size));
  *    }
  *
  *    static bool SEqualReduce(const runtime::StringObj* lhs,
diff --git a/include/tvm/node/structural_hash.h 
b/include/tvm/node/structural_hash.h
index 8b8a403326..4d822e68d3 100644
--- a/include/tvm/node/structural_hash.h
+++ b/include/tvm/node/structural_hash.h
@@ -36,52 +36,60 @@ namespace tvm {
  * \brief Hash definition of base value classes.
  */
 class BaseValueHash {
- public:
-  size_t operator()(const double& key) const { return 
std::hash<double>()(key); }
-
-  size_t operator()(const int64_t& key) const { return 
std::hash<int64_t>()(key); }
-
-  size_t operator()(const uint64_t& key) const { return 
std::hash<uint64_t>()(key); }
-
-  size_t operator()(const int& key) const { return std::hash<int>()(key); }
-
-  size_t operator()(const bool& key) const { return std::hash<bool>()(key); }
-
-  size_t operator()(const std::string& key) const { return 
std::hash<std::string>()(key); }
-
-  size_t operator()(const runtime::DataType& key) const {
-    return std::hash<int32_t>()(static_cast<int32_t>(key.code()) |
-                                (static_cast<int32_t>(key.bits()) << 8) |
-                                (static_cast<int32_t>(key.lanes()) << 16));
+ protected:
+  template <typename T, typename U>
+  uint64_t Reinterpret(T value) const {
+    union Union {
+      T a;
+      U b;
+    } u;
+    static_assert(sizeof(Union) == sizeof(T), "sizeof(Union) != sizeof(T)");
+    static_assert(sizeof(Union) == sizeof(U), "sizeof(Union) != sizeof(U)");
+    u.b = 0;
+    u.a = value;
+    return u.b;
   }
 
+ public:
+  uint64_t operator()(const float& key) const { return Reinterpret<float, 
uint32_t>(key); }
+  uint64_t operator()(const double& key) const { return Reinterpret<double, 
uint64_t>(key); }
+  uint64_t operator()(const int64_t& key) const { return Reinterpret<int64_t, 
uint64_t>(key); }
+  uint64_t operator()(const uint64_t& key) const { return key; }
+  uint64_t operator()(const int& key) const { return Reinterpret<int, 
uint32_t>(key); }
+  uint64_t operator()(const bool& key) const { return key; }
+  uint64_t operator()(const runtime::DataType& key) const {
+    return Reinterpret<DLDataType, uint32_t>(key);
+  }
   template <typename ENum, typename = typename 
std::enable_if<std::is_enum<ENum>::value>::type>
-  bool operator()(const ENum& key) const {
-    return std::hash<size_t>()(static_cast<size_t>(key));
+  uint64_t operator()(const ENum& key) const {
+    return Reinterpret<int64_t, uint64_t>(static_cast<int64_t>(key));
+  }
+  uint64_t operator()(const std::string& key) const {
+    return runtime::String::StableHashBytes(key.data(), key.length());
   }
 };
 
 /*!
- * \brief Content-aware structural hasing.
+ * \brief Content-aware structural hashing.
  *
  *  The structural hash value is recursively defined in the DAG of IRNodes.
  *  There are two kinds of nodes:
  *
  *  - Normal node: the hash value is defined by its content and type only.
  *  - Graph node: each graph node will be assigned a unique index ordered by 
the
- *    first occurence during the visit. The hash value of a graph node is
+ *    first occurrence during the visit. The hash value of a graph node is
  *    combined from the hash values of its contents and the index.
  */
 class StructuralHash : public BaseValueHash {
  public:
-  // inheritate operator()
+  // inherit operator()
   using BaseValueHash::operator();
   /*!
    * \brief Compute structural hashing value for an object.
    * \param key The left operand.
    * \return The hash value.
    */
-  TVM_DLL size_t operator()(const ObjectRef& key) const;
+  TVM_DLL uint64_t operator()(const ObjectRef& key) const;
 };
 
 /*!
@@ -109,23 +117,23 @@ class SHashReducer {
      *
      * \param hashed_value The hashed value
      */
-    virtual void SHashReduceHashedValue(size_t hashed_value) = 0;
+    virtual void SHashReduceHashedValue(uint64_t hashed_value) = 0;
     /*!
      * \brief Append hash value of key to the current sequence of hashes.
      *
      * \param key The object to compute hash from.
-     * \param map_free_vars Whether to map free variables by their occurence 
number.
+     * \param map_free_vars Whether to map free variables by their occurrence 
number.
      */
     virtual void SHashReduce(const ObjectRef& key, bool map_free_vars) = 0;
     /*!
-     * \brief Apppend a hash value of free variable to the current sequence of 
hashes.
+     * \brief Append a hash value of free variable to the current sequence of 
hashes.
      *
      * \param var The var of interest.
-     * \param map_free_vars Whether to map free variables by their occurence 
number.
+     * \param map_free_vars Whether to map free variables by their occurrence 
number.
      *
      * \note If map_free_vars is set to be true,
      *       internally the handler can maintain a counter to encode free 
variables
-     *       by their order of occurence. This helps to resolve variable
+     *       by their order of occurrence. This helps to resolve variable
      *       mapping of function parameters and let binding variables.
      *
      *       If map_free_vars is set to be false, the address of the variable 
will be used.
@@ -139,7 +147,7 @@ class SHashReducer {
      *
      * \return Whether there is already a pre-computed hash value.
      */
-    virtual bool LookupHashedValue(const ObjectRef& key, size_t* hashed_value) 
= 0;
+    virtual bool LookupHashedValue(const ObjectRef& key, uint64_t* 
hashed_value) = 0;
     /*!
      * \brief Mark current comparison as graph node in hashing.
      *        Graph node hash will depends on the graph structure.
@@ -193,7 +201,7 @@ class SHashReducer {
   /*! \brief Internal class pointer. */
   Handler* handler_;
   /*!
-   * \brief Whether or not to map free variables by their occurence
+   * \brief Whether or not to map free variables by their occurrence
    *        If the flag is false, then free variables will be mapped
    *        by their in-memory address.
    */
@@ -210,10 +218,10 @@ class SHashHandlerDefault : public SHashReducer::Handler {
   SHashHandlerDefault();
   virtual ~SHashHandlerDefault();
 
-  void SHashReduceHashedValue(size_t hashed_value) override;
+  void SHashReduceHashedValue(uint64_t hashed_value) override;
   void SHashReduce(const ObjectRef& key, bool map_free_vars) override;
   void SHashReduceFreeVar(const runtime::Object* var, bool map_free_vars) 
override;
-  bool LookupHashedValue(const ObjectRef& key, size_t* hashed_value) override;
+  bool LookupHashedValue(const ObjectRef& key, uint64_t* hashed_value) 
override;
   void MarkGraphNode() override;
 
   /*!
@@ -222,7 +230,7 @@ class SHashHandlerDefault : public SHashReducer::Handler {
    * \param map_free_vars Whether or not to remap variables if possible.
    * \return The hash result.
    */
-  virtual size_t Hash(const ObjectRef& object, bool map_free_vars);
+  virtual uint64_t Hash(const ObjectRef& object, bool map_free_vars);
 
  protected:
   /*!
diff --git a/include/tvm/runtime/container/string.h 
b/include/tvm/runtime/container/string.h
index 5ecd89e9f5..c6382506b3 100644
--- a/include/tvm/runtime/container/string.h
+++ b/include/tvm/runtime/container/string.h
@@ -24,6 +24,7 @@
 #ifndef TVM_RUNTIME_CONTAINER_STRING_H_
 #define TVM_RUNTIME_CONTAINER_STRING_H_
 
+#include <dmlc/endian.h>
 #include <dmlc/logging.h>
 #include <tvm/runtime/container/base.h>
 #include <tvm/runtime/logging.h>
@@ -247,10 +248,70 @@ class String : public ObjectRef {
    * \param size The size of the bytes.
    * \return the hash value.
    */
-  static size_t HashBytes(const char* data, size_t size) {
-    // This function falls back to string copy with c++11 compiler and is
-    // recommended to be compiled with c++14
-    return std::hash<std::string_view>()(std::string_view(data, size));
+  static uint64_t StableHashBytes(const char* data, size_t size) {
+    const constexpr uint64_t kMultiplier = 1099511628211ULL;
+    const constexpr uint64_t kMod = 2147483647ULL;
+    union Union {
+      uint8_t a[8];
+      uint64_t b;
+    } u;
+    static_assert(sizeof(Union) == sizeof(uint64_t), "sizeof(Union) != 
sizeof(uint64_t)");
+    const char* it = data;
+    const char* end = it + size;
+    uint64_t result = 0;
+    for (; it + 8 <= end; it += 8) {
+      if (DMLC_IO_NO_ENDIAN_SWAP) {
+        u.a[0] = it[0];
+        u.a[1] = it[1];
+        u.a[2] = it[2];
+        u.a[3] = it[3];
+        u.a[4] = it[4];
+        u.a[5] = it[5];
+        u.a[6] = it[6];
+        u.a[7] = it[7];
+      } else {
+        u.a[0] = it[7];
+        u.a[1] = it[6];
+        u.a[2] = it[5];
+        u.a[3] = it[4];
+        u.a[4] = it[3];
+        u.a[5] = it[2];
+        u.a[6] = it[1];
+        u.a[7] = it[0];
+      }
+      result = (result * kMultiplier + u.b) % kMod;
+    }
+    if (it < end) {
+      u.b = 0;
+      uint8_t* a = u.a;
+      if (it + 4 <= end) {
+        a[0] = it[0];
+        a[1] = it[1];
+        a[2] = it[2];
+        a[3] = it[3];
+        it += 4;
+        a += 4;
+      }
+      if (it + 2 <= end) {
+        a[0] = it[0];
+        a[1] = it[1];
+        it += 2;
+        a += 2;
+      }
+      if (it + 1 <= end) {
+        a[0] = it[0];
+        it += 1;
+        a += 1;
+      }
+      if (!DMLC_IO_NO_ENDIAN_SWAP) {
+        std::swap(u.a[0], u.a[7]);
+        std::swap(u.a[1], u.a[6]);
+        std::swap(u.a[2], u.a[5]);
+        std::swap(u.a[3], u.a[4]);
+      }
+      result = (result * kMultiplier + u.b) % kMod;
+    }
+    return result;
   }
 
   TVM_DEFINE_NOTNULLABLE_OBJECT_REF_METHODS(String, ObjectRef, StringObj);
@@ -448,7 +509,7 @@ inline int String::memncmp(const char* lhs, const char* 
rhs, size_t lhs_count, s
 
 inline size_t ObjectHash::operator()(const ObjectRef& a) const {
   if (const auto* str = a.as<StringObj>()) {
-    return String::HashBytes(str->data, str->size);
+    return String::StableHashBytes(str->data, str->size);
   }
   return ObjectPtrHash()(a);
 }
@@ -476,7 +537,7 @@ namespace std {
 template <>
 struct hash<::tvm::runtime::String> {
   std::size_t operator()(const ::tvm::runtime::String& str) const {
-    return ::tvm::runtime::String::HashBytes(str.data(), str.size());
+    return ::tvm::runtime::String::StableHashBytes(str.data(), str.size());
   }
 };
 }  // namespace std
diff --git a/src/node/structural_hash.cc b/src/node/structural_hash.cc
index fa77b47bd2..6cf796d344 100644
--- a/src/node/structural_hash.cc
+++ b/src/node/structural_hash.cc
@@ -39,7 +39,7 @@
 
 namespace tvm {
 
-// Define the dispatch functio here since primary user is in this file.
+// Define the dispatch function here since primary user is in this file.
 void ReflectionVTable::SHashReduce(const Object* self, SHashReducer reducer) 
const {
   uint32_t tindex = self->type_index();
   if (tindex >= fshash_reduce_.size() || fshash_reduce_[tindex] == nullptr) {
@@ -50,7 +50,7 @@ void ReflectionVTable::SHashReduce(const Object* self, 
SHashReducer reducer) con
 }
 
 // Hash handler that handles free vars
-// by assigning an unique counter in the order of their ocurrence.
+// by assigning an unique counter in the order of their occurrence.
 //
 // This algorithm depends on the determinism of the traversal of SHash 
function.
 // In particular, when we traverse unordered_map, we should first sort
@@ -69,9 +69,9 @@ class SHashHandlerDefault::Impl {
      */
     ObjectRef object;
     /*! \brief The partially reduce hash value.*/
-    size_t reduced_hash;
+    uint64_t reduced_hash;
     /*! \brief The expected location in the result stack. */
-    size_t result_stack_index = std::numeric_limits<size_t>::max();
+    uint64_t result_stack_index = std::numeric_limits<uint64_t>::max();
     /*! \brief Whether the children has been expanded via SEqualReduce */
     bool children_expanded{false};
     /*! \brief Whether the node is graph node. */
@@ -80,7 +80,7 @@ class SHashHandlerDefault::Impl {
     bool map_free_vars;
 
     Task() = default;
-    explicit Task(ObjectRef object, size_t reduced_hash, bool map_free_vars)
+    explicit Task(ObjectRef object, uint64_t reduced_hash, bool map_free_vars)
         : object(object), reduced_hash(reduced_hash), 
map_free_vars(map_free_vars) {}
   };
 
@@ -90,7 +90,7 @@ class SHashHandlerDefault::Impl {
     task_stack_.back().graph_node_hash = true;
   }
 
-  bool LookupHashedValue(const ObjectRef& key, size_t* hash_value) {
+  bool LookupHashedValue(const ObjectRef& key, uint64_t* hash_value) {
     auto it = hash_memo_.find(key);
     if (it != hash_memo_.end()) {
       hash_value[0] = it->second;
@@ -99,7 +99,7 @@ class SHashHandlerDefault::Impl {
     return false;
   }
 
-  void SHashReduceHashedValue(size_t hashed_value) {
+  void SHashReduceHashedValue(uint64_t hashed_value) {
     pending_tasks_.emplace_back(Task(ObjectRef(nullptr), hashed_value, false));
   }
 
@@ -107,18 +107,18 @@ class SHashHandlerDefault::Impl {
     ICHECK(!hash_memo_.count(GetRef<ObjectRef>(var)));
     if (map_free_vars) {
       // use counter value.
-      size_t value = std::hash<size_t>()(free_var_counter_++);
+      uint64_t value = std::hash<uint64_t>()(free_var_counter_++);
       pending_tasks_.emplace_back(Task(ObjectRef(nullptr), value, false));
     } else {
       // use pointer hash
-      size_t value = std::hash<const runtime::Object*>()(var);
+      uint64_t value = std::hash<const runtime::Object*>()(var);
       pending_tasks_.emplace_back(Task(ObjectRef(nullptr), value, false));
     }
   }
 
   void SHashReduce(const ObjectRef& object, bool map_free_vars) {
     // Directly push the result
-    // Note: it is still important to push the result to pendng tasks
+    // Note: it is still important to push the result to pending tasks
     // so that the reduction order of hash values stays the same.
     if (!object.defined()) {
       pending_tasks_.emplace_back(Task(ObjectRef(nullptr), 0, false));
@@ -133,7 +133,7 @@ class SHashHandlerDefault::Impl {
     }
   }
 
-  size_t Hash(const ObjectRef& object, bool map_free_vars) {
+  uint64_t Hash(const ObjectRef& object, bool map_free_vars) {
     ICHECK_EQ(task_stack_.size(), 0U);
     ICHECK_EQ(pending_tasks_.size(), 0U);
     ICHECK_EQ(result_stack_.size(), 0U);
@@ -147,7 +147,7 @@ class SHashHandlerDefault::Impl {
     this->RunTasks();
 
     ICHECK_EQ(result_stack_.size(), 1U);
-    size_t ret = result_stack_.back();
+    uint64_t ret = result_stack_.back();
     result_stack_.pop_back();
     return ret;
   }
@@ -170,13 +170,13 @@ class SHashHandlerDefault::Impl {
    * \brief Compute the reduced hash value for the task.
    * \param task The indicated task.
    */
-  size_t ReduceHash(const Task& task) {
-    size_t stack_begin = task.result_stack_index;
+  uint64_t ReduceHash(const Task& task) {
+    uint64_t stack_begin = task.result_stack_index;
     ICHECK_LE(stack_begin, result_stack_.size());
 
     // combine in the reverse order of the stack.
-    size_t reduced_hash = task.reduced_hash;
-    for (size_t i = result_stack_.size(); i != stack_begin; --i) {
+    uint64_t reduced_hash = task.reduced_hash;
+    for (uint32_t i = result_stack_.size(); i != stack_begin; --i) {
       reduced_hash = support::HashCombine(reduced_hash, result_stack_[i - 1]);
     }
     result_stack_.resize(stack_begin);
@@ -201,7 +201,7 @@ class SHashHandlerDefault::Impl {
           // so that we can distinguish DAG from trees.
           if (entry.graph_node_hash) {
             entry.reduced_hash = support::HashCombine(entry.reduced_hash,
-                                                      
std::hash<size_t>()(graph_node_counter_++));
+                                                      
std::hash<uint64_t>()(graph_node_counter_++));
           }
           hash_memo_[entry.object] = entry.reduced_hash;
         }
@@ -241,27 +241,27 @@ class SHashHandlerDefault::Impl {
   // The owner of this impl
   SHashHandlerDefault* parent_;
   // free var counter.
-  size_t free_var_counter_{0};
+  uint32_t free_var_counter_{0};
   // graph node counter.
-  size_t graph_node_counter_{0};
+  uint32_t graph_node_counter_{0};
   // record current stack top
   bool allow_push_to_stack_{true};
   // list of pending tasks to be pushed to the stack.
   std::vector<Task> pending_tasks_;
   // Internal task stack to executed the task
   std::vector<Task> task_stack_;
-  // Internal stack to store the result poped from the task stack.
-  std::vector<size_t> result_stack_;
+  // Internal stack to store the result popped from the task stack.
+  std::vector<uint64_t> result_stack_;
   // reflection vtable
   ReflectionVTable* vtable_ = ReflectionVTable::Global();
   // map from lhs to rhs
-  std::unordered_map<ObjectRef, size_t, ObjectPtrHash, ObjectPtrEqual> 
hash_memo_;
+  std::unordered_map<ObjectRef, uint64_t, ObjectPtrHash, ObjectPtrEqual> 
hash_memo_;
 };
 
 SHashHandlerDefault::SHashHandlerDefault() { impl = new Impl(this); }
 SHashHandlerDefault::~SHashHandlerDefault() { delete impl; }
 
-void SHashHandlerDefault::SHashReduceHashedValue(size_t hashed_value) {
+void SHashHandlerDefault::SHashReduceHashedValue(uint64_t hashed_value) {
   return impl->SHashReduceHashedValue(hashed_value);
 }
 
@@ -273,13 +273,13 @@ void SHashHandlerDefault::SHashReduceFreeVar(const 
runtime::Object* var, bool ma
   impl->SHashReduceFreeVar(var, map_free_vars);
 }
 
-bool SHashHandlerDefault::LookupHashedValue(const ObjectRef& key, size_t* 
hashed_value) {
+bool SHashHandlerDefault::LookupHashedValue(const ObjectRef& key, uint64_t* 
hashed_value) {
   return impl->LookupHashedValue(key, hashed_value);
 }
 
 void SHashHandlerDefault::MarkGraphNode() { impl->MarkGraphNode(); }
 
-size_t SHashHandlerDefault::Hash(const ObjectRef& object, bool map_free_vars) {
+uint64_t SHashHandlerDefault::Hash(const ObjectRef& object, bool 
map_free_vars) {
   return impl->Hash(object, map_free_vars);
 }
 
@@ -289,11 +289,11 @@ void SHashHandlerDefault::DispatchSHash(const ObjectRef& 
key, bool map_free_vars
 
 TVM_REGISTER_GLOBAL("node.StructuralHash")
     .set_body_typed([](const ObjectRef& object, bool map_free_vars) -> int64_t 
{
-      size_t hashed_value = SHashHandlerDefault().Hash(object, map_free_vars);
+      uint64_t hashed_value = SHashHandlerDefault().Hash(object, 
map_free_vars);
       return static_cast<int64_t>(hashed_value);
     });
 
-size_t StructuralHash::operator()(const ObjectRef& object) const {
+uint64_t StructuralHash::operator()(const ObjectRef& object) const {
   return SHashHandlerDefault().Hash(object, false);
 }
 
@@ -302,7 +302,7 @@ struct StringObjTrait {
   static constexpr const std::nullptr_t VisitAttrs = nullptr;
 
   static void SHashReduce(const runtime::StringObj* key, SHashReducer 
hash_reduce) {
-    hash_reduce->SHashReduceHashedValue(runtime::String::HashBytes(key->data, 
key->size));
+    
hash_reduce->SHashReduceHashedValue(runtime::String::StableHashBytes(key->data, 
key->size));
   }
 
   static bool SEqualReduce(const runtime::StringObj* lhs, const 
runtime::StringObj* rhs,
@@ -371,7 +371,7 @@ void NDArrayHash(const runtime::NDArray::Container* arr, 
SHashReducer* hash_redu
   }
   if (hash_data) {
     (*hash_reduce)
-        ->SHashReduceHashedValue(runtime::String::HashBytes(
+        ->SHashReduceHashedValue(runtime::String::StableHashBytes(
             static_cast<const char*>(arr->dl_tensor.data), 
runtime::GetDataSize(arr->dl_tensor)));
   }
 }
@@ -405,7 +405,7 @@ struct ArrayNodeTrait {
 
   static void SHashReduce(const ArrayNode* key, SHashReducer hash_reduce) {
     hash_reduce(static_cast<uint64_t>(key->size()));
-    for (size_t i = 0; i < key->size(); ++i) {
+    for (uint32_t i = 0; i < key->size(); ++i) {
       hash_reduce(key->at(i));
     }
   }
@@ -416,7 +416,7 @@ struct ArrayNodeTrait {
     }
 
     if (lhs->size() != rhs->size()) return false;
-    for (size_t i = 0; i < lhs->size(); ++i) {
+    for (uint32_t i = 0; i < lhs->size(); ++i) {
       if (!equal(lhs->at(i), rhs->at(i))) return false;
     }
     return true;
@@ -425,10 +425,10 @@ struct ArrayNodeTrait {
  private:
   static bool SEqualReduceTraced(const ArrayNode* lhs, const ArrayNode* rhs,
                                  const SEqualReducer& equal) {
-    size_t min_size = std::min(lhs->size(), rhs->size());
+    uint32_t min_size = std::min(lhs->size(), rhs->size());
     const ObjectPathPair& array_paths = equal.GetCurrentObjectPaths();
 
-    for (size_t index = 0; index < min_size; ++index) {
+    for (uint32_t index = 0; index < min_size; ++index) {
       ObjectPathPair element_paths = {array_paths->lhs_path->ArrayIndex(index),
                                       
array_paths->rhs_path->ArrayIndex(index)};
       if (!equal(lhs->at(index), rhs->at(index), element_paths)) {
@@ -491,7 +491,7 @@ struct ShapeTupleObjTrait {
 
   static void SHashReduce(const ShapeTupleObj* self, SHashReducer hash_reduce) 
{
     hash_reduce(self->size);
-    for (size_t i = 0; i < self->size; ++i) {
+    for (uint32_t i = 0; i < self->size; ++i) {
       hash_reduce(self->data[i]);
     }
   }
@@ -499,7 +499,7 @@ struct ShapeTupleObjTrait {
   static bool SEqualReduce(const ShapeTupleObj* lhs, const ShapeTupleObj* rhs,
                            SEqualReducer equal) {
     if (lhs->size != rhs->size) return false;
-    for (size_t i = 0; i < lhs->size; ++i) {
+    for (uint32_t i = 0; i < lhs->size; ++i) {
       if (!equal(lhs->data[i], rhs->data[i])) return false;
     }
     return true;
@@ -539,10 +539,10 @@ struct MapNodeTrait {
     // This resolves common use cases where we want to store
     // Map<Var, Value> where Var is defined in the function
     // parameters.
-    using KV = std::pair<size_t, ObjectRef>;
+    using KV = std::pair<uint64_t, ObjectRef>;
     std::vector<KV> temp;
     for (const auto& kv : *key) {
-      size_t hashed_value;
+      uint64_t hashed_value;
       if (hash_reduce->LookupHashedValue(kv.first, &hashed_value)) {
         temp.emplace_back(hashed_value, kv.second);
       }
@@ -553,11 +553,11 @@ struct MapNodeTrait {
     // add size to the hash
     hash_reduce(static_cast<uint64_t>(key->size()));
     // hash the content
-    for (size_t i = 0; i < temp.size();) {
-      size_t k = i + 1;
+    for (uint32_t i = 0; i < temp.size();) {
+      uint32_t k = i + 1;
       for (; k < temp.size() && temp[k].first == temp[i].first; ++k) {
       }
-      // ties are rare, but we need to skip them to make the hash determinsitic
+      // ties are rare, but we need to skip them to make the hash deterministic
       if (k == i + 1) {
         hash_reduce->SHashReduceHashedValue(temp[i].first);
         hash_reduce(temp[i].second);
@@ -583,7 +583,7 @@ struct MapNodeTrait {
     // add size to the hash after sorting.
     hash_reduce(static_cast<uint64_t>(key->size()));
     // hash the content
-    for (size_t i = 0; i < temp.size(); ++i) {
+    for (uint32_t i = 0; i < temp.size(); ++i) {
       hash_reduce(temp[i].first);
       hash_reduce(temp[i].second);
     }
diff --git a/src/relay/backend/utils.h b/src/relay/backend/utils.h
index d5cf4baf72..acaea425d1 100644
--- a/src/relay/backend/utils.h
+++ b/src/relay/backend/utils.h
@@ -696,7 +696,7 @@ struct TargetStrHash {
    */
   size_t operator()(const Target& target) const {
     std::string s(target->kind->name);
-    return String::HashBytes(s.c_str(), s.size());
+    return String::StableHashBytes(s.c_str(), s.size());
   }
 };
 

Reply via email to