Optimizing Shared Caches in Chip Multiprocessors