Index: src/CodeTools/DeclStats.cc
===================================================================
--- src/CodeTools/DeclStats.cc	(revision 9bb90a86e8103e3d4b363220e7618cf60fb1ba50)
+++ src/CodeTools/DeclStats.cc	(revision 35cd219b623c29a73cc06498fd38845d6799afd4)
@@ -18,4 +18,5 @@
 #include <iostream>
 #include <map>
+#include <sstream>
 #include <string>
 #include <unordered_map>
@@ -71,25 +72,4 @@
 				return *this;
 			}
-
-			/// Update based on a declaration list
-			ArgPackStats& operator+= ( std::list<DeclarationWithType*>& decls ) {
-				unsigned nn = 0;
-				unsigned nn_basic = 0;
-				unsigned nn_poly = 0;
-				for ( auto decl : decls ) {
-					nn += decl->get_type()->size();
-					if ( dynamic_cast<BasicType*>( decl->get_type() ) ) ++nn_basic;
-					else if ( GenPoly::hasPolyBase( decl->get_type() ) ) ++nn_poly;
-				}
-				++n.at( nn );
-				++n_basic.at( nn_basic );
-				++n_poly.at( nn_poly );
-				if ( nn > 0 ) {
-					++p_basic[ nn_basic*100/nn ];
-					++p_poly[ nn_poly*100/nn ];
-				}
-				
-				return *this;
-			}
 		};
 		
@@ -100,4 +80,8 @@
 			/// Count of declarations with each name
 			std::unordered_map<std::string, unsigned> by_name;
+			/// Count of uses of each basic type
+			std::unordered_map<std::string, unsigned> basic_type_names;
+			/// Count of uses of each non-basic type
+			std::unordered_map<std::string, unsigned> compound_type_names;
 			/// Stats for the parameter list
 			ArgPackStats params;
@@ -112,5 +96,5 @@
 			ArgPackStats assn_returns;
 			
-			Stats() : n_decls(0), n_type_params(), by_name(), params(), returns(), n_assns(), assn_params(), assn_returns() {}
+			Stats() : n_decls(0), n_type_params(), by_name(), basic_type_names(), compound_type_names(), params(), returns(), n_assns(), assn_params(), assn_returns() {}
 
 		public:
@@ -119,4 +103,6 @@
 				sum( n_type_params, o.n_type_params );
 				sum( by_name, o.by_name );
+				sum( basic_type_names, o.basic_type_names );
+				sum( compound_type_names, o.compound_type_names );
 				sum( params, o.params );
 				sum( returns, o.returns );
@@ -133,7 +119,36 @@
 		Stats total;
 
-		void analyzeFunc( FunctionType* fnTy, ArgPackStats& params, ArgPackStats& returns ) {
-			params += fnTy->get_parameters();
-			returns += fnTy->get_returnVals();
+		/// Update arg pack stats based on a declaration list
+		void analyze( Stats& stats, ArgPackStats& pstats, std::list<DeclarationWithType*>& decls ) {
+			unsigned n = 0;
+			unsigned n_basic = 0;
+			unsigned n_poly = 0;
+			for ( auto decl : decls ) {
+				n += decl->get_type()->size();
+				if ( BasicType* bt = dynamic_cast<BasicType*>( decl->get_type() ) ) {
+					++n_basic;
+					std::stringstream ss;
+					bt->print( ss );
+					++stats.basic_type_names[ ss.str() ];
+				} else if ( GenPoly::hasPolyBase( decl->get_type() ) ) {
+					++n_poly;
+				} else {
+					std::stringstream ss;
+					decl->get_type()->print( ss );
+					++stats.compound_type_names[ ss.str() ];
+				}
+			}
+			++pstats.n.at( n );
+			++pstats.n_basic.at( n_basic );
+			++pstats.n_poly.at( n_poly );
+			if ( n > 0 ) {
+				++pstats.p_basic[ n_basic*100/n ];
+				++pstats.p_poly[ n_poly*100/n ];
+			}
+		}
+		
+		void analyzeFunc( FunctionType* fnTy, Stats& stats, ArgPackStats& params, ArgPackStats& returns ) {
+			analyze( stats, params, fnTy->get_parameters() );
+			analyze( stats, returns, fnTy->get_returnVals() );
 		}
 
@@ -164,5 +179,5 @@
 						assnTy = assnDecl->get_functionType();
 					}
-					if ( assnTy ) analyzeFunc( assnTy, stats.assn_params, stats.assn_returns );
+					if ( assnTy ) analyzeFunc( assnTy, stats, stats.assn_params, stats.assn_returns );
 				}
 			}
@@ -171,5 +186,5 @@
 			++stats.by_name[ decl->get_name() ];
 
-			analyzeFunc( fnTy, stats.params, stats.returns );
+			analyzeFunc( fnTy, stats, stats.params, stats.returns );
 		}
 
@@ -266,4 +281,8 @@
 			printAll("unique_names", [](const Stats& stats) { return stats.by_name.size(); });
 			printAllSparseHisto("overloads", [](const Stats& stats) { return stats.by_name; });
+			printAll("basic_type_names", [](const Stats& stats) { return stats.basic_type_names.size(); });
+			printAllSparseHisto("basic_type_uses", [](const Stats& stats) { return stats.basic_type_names; });
+			printAll("compound_type_names", [](const Stats& stats) { return stats.compound_type_names.size(); });
+			printAllSparseHisto("compound_type_uses", [](const Stats& stats) { return stats.compound_type_names; });
 			printAllPack("params", [](const Stats& stats) { return stats.params; });
 			printAllPack("returns", [](const Stats& stats) { return stats.returns; });
Index: src/Common/ScopedMap.h
===================================================================
--- src/Common/ScopedMap.h	(revision 9bb90a86e8103e3d4b363220e7618cf60fb1ba50)
+++ src/Common/ScopedMap.h	(revision 35cd219b623c29a73cc06498fd38845d6799afd4)
@@ -230,4 +230,14 @@
 	}
 
+	/// Finds the given key in the provided scope; returns end() for none such
+	iterator findAt( size_type scope, const Key& key ) {
+		typename Scope::iterator val = scopes[scope].find( key );
+		if ( val != scopes[scope].end() ) return iterator( scopes, val, scope );
+		return end();
+	}
+	const_iterator findAt( size_type scope, const Key& key ) const {
+		return const_iterator( const_cast< ScopedMap< Key, Value >* >(this)->findAt( scope, key ) );
+	}
+
 	/// Finds the given key in the outermost scope inside the given scope where it occurs
 	iterator findNext( const_iterator &it, const Key &key ) {
Index: src/Common/VectorMap.h
===================================================================
--- src/Common/VectorMap.h	(revision 9bb90a86e8103e3d4b363220e7618cf60fb1ba50)
+++ src/Common/VectorMap.h	(revision 35cd219b623c29a73cc06498fd38845d6799afd4)
@@ -38,9 +38,9 @@
 	typedef const const_value_type* const_pointer;
 	
-	class iterator : public std::iterator< std::bidirectional_iterator_tag,
+	class iterator : public std::iterator< std::random_access_iterator_tag,
 	                                       value_type,
-										    difference_type,
-											pointer,
-											reference > {
+										   difference_type,
+										   pointer,
+										   reference > {
 	friend class VectorMap;
 	friend class const_iterator;
@@ -74,8 +74,40 @@
 		iterator operator-- (int) { iterator tmp = *this; --(*this); return tmp; }
 
+		iterator& operator+= (difference_type i) {
+			// SHENANIGANS: same reasons as operator++
+			new(&data) value_type{ (data.first + i), *(&data.second + i) };
+			return *this;
+		}
+
+		iterator operator+ (difference_type i) const { iterator tmp = *this; return tmp += i; }
+
+		iterator& operator-= (difference_type i) {
+			// SHENANIGANS: same reasons as operator++
+			new(&data) value_type{ (data.first - i), *(&data.second - i) };
+			return *this;
+		}
+
+		iterator operator- (difference_type i) const { iterator tmp = *this; return tmp -= i; }
+
+		difference_type operator- (const iterator& o) const { return data.first - o.data.first; }
+
+		value_type operator[] (difference_type i) const {
+			// SHENANIGANS: same reasons as operator++
+			return value_type{ (data.first + i), *(&data.second + i) };
+		}
+
 		bool operator== (const iterator& o) const {
 			return data.first == o.data.first && &data.second == &o.data.second;
 		}
+		
 		bool operator!= (const iterator& that) const { return !(*this == that); }
+
+		bool operator< (const iterator& o) const { return data.first < o.data.first; }
+
+		bool operator> (const iterator& o) const { return data.first > o.data.first; }
+
+		bool operator<= (const iterator& o) const { return data.first <= o.data.first; }
+
+		bool operator>= (const iterator& o) const { return data.first >= o.data.first; }
 	};
 
@@ -118,8 +150,46 @@
 		const_iterator operator-- (int) { const_iterator tmp = *this; --(*this); return tmp; }
 
+		const_iterator& operator+= (difference_type i) {
+			// SHENANIGANS: same reasons as iterator::operator++
+			new(&data) const_value_type{ (data.first + i), *(&data.second + i) };
+			return *this;
+		}
+
+		const_iterator operator+ (difference_type i) const {
+			const_iterator tmp = *this; return tmp += i;
+		}
+
+		const_iterator& operator-= (difference_type i) {
+			// SHENANIGANS: same reasons as iterator::operator++
+			new(&data) const_value_type{ (data.first - i), *(&data.second - i) };
+			return *this;
+		}
+
+		const_iterator operator- (difference_type i) const {
+			const_iterator tmp = *this; return tmp -= i;
+		}
+
+		difference_type operator- (const const_iterator& o) const {
+			return data.first - o.data.first;
+		}
+
+		const_value_type operator[] (difference_type i) const {
+			// SHENANIGANS: same reasons as iterator::operator++
+			return const_value_type{ (data.first + i), *(&data.second + i) };
+		}
+
 		bool operator== (const const_iterator& o) const {
 			return data.first == o.data.first && &data.second == &o.data.second;
 		}
+		
 		bool operator!= (const const_iterator& that) const { return !(*this == that); }
+
+		bool operator< (const const_iterator& o) const { return data.first < o.data.first; }
+
+		bool operator> (const const_iterator& o) const { return data.first > o.data.first; }
+
+		bool operator<= (const const_iterator& o) const { return data.first <= o.data.first; }
+
+		bool operator>= (const const_iterator& o) const { return data.first >= o.data.first; }
 	};
 
@@ -163,4 +233,16 @@
 };
 
+template<typename T>
+typename VectorMap<T>::iterator operator+ (typename VectorMap<T>::difference_type i, 
+                                           const typename VectorMap<T>::iterator& it) {
+	return it + i;
+}
+
+template<typename T>
+typename VectorMap<T>::const_iterator operator+ (typename VectorMap<T>::difference_type i, 
+                                                 const typename VectorMap<T>::const_iterator& it) {
+	return it + i;
+}
+
 #endif // _VECTORMAP_H
 
Index: src/GenPoly/InstantiateGeneric.cc
===================================================================
--- src/GenPoly/InstantiateGeneric.cc	(revision 9bb90a86e8103e3d4b363220e7618cf60fb1ba50)
+++ src/GenPoly/InstantiateGeneric.cc	(revision 35cd219b623c29a73cc06498fd38845d6799afd4)
@@ -122,5 +122,10 @@
 		/// Adds a value for a (key, typeList) pair to the current scope
 		void insert( Key *key, const std::list< TypeExpr* > &params, Value *value ) {
-			instantiations[ key ].push_back( Instantiation( TypeList( params ), value ) );
+			auto it = instantiations.findAt( instantiations.currentScope(), key );
+			if ( it == instantiations.end() ) {
+				instantiations.insert( key, ValueList{ Instantiation{ TypeList( params ), value } } );
+			} else {
+				it->second.push_back( Instantiation{ TypeList( params ), value } );
+			}
 		}
 	};
