Optimizing Compilers for Modern Architectures: A Dependence-Based Approach

The original implementation of the strategies developed by Carr, Callahan, and Kennedy [55, 64, 65, 67] was carried out in the PFC system and later migrated to ParaScope. All of the effectiveness studies presented in Sections 8.3.8 and 8.4.3 were done within this infrastructure. The principal implementation concern was the inclusion of testing for input dependence. Although the testing itself is easy to do using a straightforward modification of dependence analysis, the total number of input dependences is likely to be large enough to cause problems for the compiler. Scalar dependences in particular can cause huge blowups in the size of the dependence graph because they can be carried at every level of a loop nest. In PFC, we ameliorated this problem by using a summary representation for scalar dependences that summarized all levels in a single edge representation. This strategy can be extended to summarize all the direction vectors quite easily. With these changes, the dependence graphs were still large, but the size was manageable.
Scalar replacement and the related transformations were particularly important on the original Ardent Titan because floating-point operations were carried out in the vector unit, which bypassed cache for all loads and stores. In other words, floating-point quantities were never cached, so it was critical to make effective use of registers. The compiler implemented a scalar replacement pass along the lines described in this chapter except that it did not construct input dependence, so it missed a substantive number of opportunities for...