This class has a fair number of methods inherited from Type that don't make sense here (e.g. IsUniformType(), GetBaseType(), LLVMType(), etc. Would be nice to refactor the inheritance hierarchy to move most of those interface methods to a sub-class of Type, which in turn all of the other Type implementations inherit from.
Currently, this only looks for all program instances going to the same location and all going to a linear sequence of locations in memory. There are a number of other cases that might make sense to look for, including things that could be handled with a vector load + shuffle or things that could be handled with hybrids of e.g. 2 4-wide vector loads with AVX, etc.
Is it worth working harder to find more of these? It starts to get tricky, since having an undef operand doesn't necessarily mean that the result will be undefined. (And for that matter, is there an LLVM call that will do this for us?)
Should we break function symbols into a separate FunctionSymbol class and then not have these members that are not applicable for function symbols (and vice versa, for non-function symbols)?