diff --git a/kernel/celltypes.h b/kernel/celltypes.h
index cad505d9a..58c6907dc 100644
--- a/kernel/celltypes.h
+++ b/kernel/celltypes.h
@@ -56,7 +56,7 @@ struct CellTypes
 		setup_stdcells_mem();
 	}
 
-	void setup_type(RTLIL::IdString type, const pool<RTLIL::IdString> &inputs, const pool<RTLIL::IdString> &outputs, bool is_evaluable = false)
+	void setup_type(const RTLIL::IdString& type, const pool<RTLIL::IdString> &inputs, const pool<RTLIL::IdString> &outputs, bool is_evaluable = false)
 	{
 		CellType ct = {type, inputs, outputs, is_evaluable};
 		cell_types[ct.type] = ct;
@@ -298,24 +298,24 @@ struct CellTypes
 		cell_types.clear();
 	}
 
-	bool cell_known(RTLIL::IdString type) const
+	bool cell_known(const RTLIL::IdString& type) const
 	{
 		return cell_types.count(type) != 0;
 	}
 
-	bool cell_output(RTLIL::IdString type, RTLIL::IdString port) const
+	bool cell_output(const RTLIL::IdString& type, const RTLIL::IdString& port) const
 	{
 		auto it = cell_types.find(type);
 		return it != cell_types.end() && it->second.outputs.count(port) != 0;
 	}
 
-	bool cell_input(RTLIL::IdString type, RTLIL::IdString port) const
+	bool cell_input(const RTLIL::IdString& type, const RTLIL::IdString& port) const
 	{
 		auto it = cell_types.find(type);
 		return it != cell_types.end() && it->second.inputs.count(port) != 0;
 	}
 
-	bool cell_evaluable(RTLIL::IdString type) const
+	bool cell_evaluable(const RTLIL::IdString& type) const
 	{
 		auto it = cell_types.find(type);
 		return it != cell_types.end() && it->second.is_evaluable;
diff --git a/kernel/rtlil.h b/kernel/rtlil.h
index c50d75e90..f53d9df8c 100644
--- a/kernel/rtlil.h
+++ b/kernel/rtlil.h
@@ -308,10 +308,14 @@ namespace RTLIL
 		bool operator!=(const char *rhs) const { return strcmp(c_str(), rhs) != 0; }
 
 		char operator[](size_t i) const {
-			const char *p = c_str();
+                  const char *p = c_str();
+#ifndef NDEBUG
 			for (; i != 0; i--, p++)
 				log_assert(*p != 0);
 			return *p;
+#else
+			return *(p + i);
+#endif
 		}
 
 		std::string substr(size_t pos = 0, size_t len = std::string::npos) const {
diff --git a/passes/opt/opt_merge.cc b/passes/opt/opt_merge.cc
index e9d98cd43..4bcd5a189 100644
--- a/passes/opt/opt_merge.cc
+++ b/passes/opt/opt_merge.cc
@@ -41,7 +41,7 @@ struct OptMergeWorker
 
 	CellTypes ct;
 	int total_count;
-	SHA1 checksum;
+        using FingerPrint = std::hash<std::string>::result_type;
 
 	static void sort_pmux_conn(dict<RTLIL::IdString, RTLIL::SigSpec> &conn)
 	{
@@ -78,7 +78,7 @@ struct OptMergeWorker
 		return str;
 	}
 
-	std::string hash_cell_parameters_and_connections(const RTLIL::Cell *cell)
+        FingerPrint hash_cell_parameters_and_connections(const RTLIL::Cell *cell)
 	{
 		vector<string> hash_conn_strings;
 		std::string hash_string = cell->type.str() + "\n";
@@ -149,8 +149,7 @@ struct OptMergeWorker
 		for (auto it : hash_conn_strings)
 			hash_string += it;
 
-		checksum.update(hash_string);
-		return checksum.final();
+		return std::hash<std::string>{}(hash_string);
 	}
 
 	bool compare_cell_parameters_and_connections(const RTLIL::Cell *cell1, const RTLIL::Cell *cell2)
@@ -268,13 +267,13 @@ struct OptMergeWorker
 			}
 
 			did_something = false;
-			dict<std::string, RTLIL::Cell*> sharemap;
+                        std::unordered_map<FingerPrint, RTLIL::Cell*> sharemap;
 			for (auto cell : cells)
 			{
 				if ((!mode_share_all && !ct.cell_known(cell->type)) || !cell->known())
 					continue;
 
-				auto hash = hash_cell_parameters_and_connections(cell);
+				FingerPrint hash = hash_cell_parameters_and_connections(cell);
 				auto r = sharemap.insert(std::make_pair(hash, cell));
 				if (!r.second) {
 					if (compare_cell_parameters_and_connections(cell, r.first->second)) {