Optimizing Compilers for Modern Architectures: A Dependence-Based Approach

Although there are many commonalities between register reuse and cache reuse, there are significant differences as well. First, there is a difference in the atomicity of storage. A register contains exactly one word, while caches are organized into blocks (or lines) that usually contain multiple words. Thus, reuse in registers arises from subsequent accesses to the same data item. This kind of reuse, often referred to as temporal reuse, also helps in cache management. On the other hand, when a cache block is loaded, misses are not required for accesses to different items in the same block. This kind of reuse of items located close enough to one another to occupy the same cache block is called spatial reuse.
A second class of differences between enhancing register and cache reuse arises because of the way caches are implemented. For example, on most caches, a store into an uncached block generates a miss, forcing the referenced block to be loaded into cache before the store can complete. A store into a register requires no such load. An immediate consequence of this property is that antidependences are important for enhancing cache reuse if the use can be brought close enough to the subsequent store, the cache miss on store may be avoided.
Finally, cache operations were originally intended to be synchronous; that is, the processor stalled while waiting for a miss to be serviced. This severely degraded performance when several misses occurred in sequence. These performance problems led machine designers...